package org.graalvm.component.installer.model;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.graalvm.component.installer.CommonConstants;
import org.graalvm.component.installer.SystemUtils;
import org.graalvm.component.installer.Version;
public final class ComponentInfo {
private final String id;
private final String versionString;
private final Version version;
private final String name;
private String infoPath;
private String licensePath;
private String licenseType;
private final Map<String, String> requiredGraalValues = new HashMap<>();
private final List<String> paths = new ArrayList<>();
private final Set<String> workingDirectories = new LinkedHashSet<>();
private final Map<String, Object> providedValues = new HashMap<>();
private URL remoteURL;
private boolean polyglotRebuild;
private byte[] shaDigest;
private String postinstMessage;
private boolean nativeComponent;
private String tag = "";
private Set<String> dependencies = Collections.emptySet();
private String origin;
private DistributionType distributionType = DistributionType.OPTIONAL;
private int priority;
private StabilityLevel stability = StabilityLevel.Undefined;
public ComponentInfo(String id, String name, String versionString, String tag) {
this.id = id;
this.versionString = versionString;
this.name = name;
this.version = Version.fromString(versionString);
this.tag = tag;
}
public ComponentInfo(String id, String name, String versionString) {
this(id, name, versionString, "");
}
public ComponentInfo(String id, String name, Version v) {
this.id = id;
this.versionString = v == null ? null : v.originalString();
this.name = name;
this.version = v == null ? Version.NO_VERSION : v;
}
public String getId() {
return id;
}
public String getVersionString() {
return versionString;
}
public String getName() {
return name;
}
public DistributionType getDistributionType() {
return distributionType;
}
public void setDistributionType(DistributionType distributionType) {
this.distributionType = distributionType;
}
public Map<String, String> getRequiredGraalValues() {
return Collections.unmodifiableMap(requiredGraalValues);
}
public void addRequiredValues(Map<String, String> vals) {
String os = vals.get(CommonConstants.CAP_OS_NAME);
String arch = vals.get(CommonConstants.CAP_OS_ARCH);
if (os != null) {
String nos = SystemUtils.normalizeOSName(os, arch);
if (!nos.equals(os)) {
vals.put(CommonConstants.CAP_OS_NAME, nos);
}
}
if (arch != null) {
String narch = SystemUtils.normalizeArchitecture(os, arch);
if (!narch.equals(os)) {
vals.put(CommonConstants.CAP_OS_ARCH, narch);
}
}
requiredGraalValues.putAll(vals);
}
public void addRequiredValue(String s, String val) {
if (val == null) {
requiredGraalValues.remove(s);
} else {
String v = val;
switch (s) {
case CommonConstants.CAP_OS_ARCH:
v = SystemUtils.normalizeArchitecture(null, val);
break;
case CommonConstants.CAP_OS_NAME:
v = SystemUtils.normalizeOSName(val, null);
break;
default:
break;
}
requiredGraalValues.put(s, v);
}
}
public void addPaths(List<String> filePaths) {
paths.addAll(filePaths);
}
public void setPaths(List<String> filePaths) {
paths.clear();
addPaths(filePaths);
}
public List<String> getPaths() {
return Collections.unmodifiableList(paths);
}
public String getInfoPath() {
return infoPath;
}
public void setInfoPath(String infoPath) {
this.infoPath = infoPath;
}
public String getLicensePath() {
return licensePath;
}
public void setLicensePath(String licensePath) {
this.licensePath = licensePath;
}
public URL getRemoteURL() {
return remoteURL;
}
public void setRemoteURL(URL remoteURL) {
this.remoteURL = remoteURL;
}
public byte[] getShaDigest() {
return shaDigest;
}
public void setShaDigest(byte[] shaDigest) {
this.shaDigest = shaDigest;
}
public boolean isPolyglotRebuild() {
return polyglotRebuild;
}
public void setPolyglotRebuild(boolean polyglotRebuild) {
this.polyglotRebuild = polyglotRebuild;
}
public Set<String> getWorkingDirectories() {
return workingDirectories;
}
public void addWorkingDirectories(Collection<String> dirs) {
workingDirectories.addAll(dirs);
}
public String getPostinstMessage() {
return postinstMessage;
}
public void setPostinstMessage(String postinstMessage) {
this.postinstMessage = postinstMessage;
}
public String getLicenseType() {
return licenseType;
}
public void setLicenseType(String licenseType) {
this.licenseType = licenseType;
}
@Override
public int hashCode() {
int hash = 5;
hash = 37 * hash + Objects.hashCode(this.id);
hash = 37 * hash + Objects.hashCode(this.version);
hash = 37 * hash + Objects.hashCode(this.tag);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ComponentInfo other = (ComponentInfo) obj;
if (!Objects.equals(this.id, other.id)) {
return false;
}
if (!Objects.equals(this.version, other.version)) {
return false;
}
if (!Objects.equals(this.tag, other.tag)) {
return false;
}
return true;
}
public Version getVersion() {
return version;
}
private static Comparator<ComponentInfo> editionComparator(String myEdition) {
return new Comparator<ComponentInfo>() {
@Override
public int compare(ComponentInfo o1, ComponentInfo o2) {
if (o1 == null) {
if (o2 == null) {
return 0;
} else {
return -1;
}
} else if (o2 == null) {
return 1;
}
String ed1 = o1.getRequiredGraalValues().get(CommonConstants.CAP_CATALOG_EDITION);
String ed2 = o2.getRequiredGraalValues().get(CommonConstants.CAP_CATALOG_EDITION);
boolean m1 = Objects.equals(ed1, myEdition);
boolean m2 = Objects.equals(ed2, myEdition);
if (m1) {
return m2 ? 0 : -1;
} else if (m2) {
return 1;
}
if (ed1 == null) {
ed1 = "";
}
if (ed2 == null) {
ed2 = "";
}
return ed1.compareToIgnoreCase(ed2);
}
};
}
private static final Comparator<ComponentInfo> COMPARATOR_VERSIONS = new Comparator<ComponentInfo>() {
@Override
public int compare(ComponentInfo o1, ComponentInfo o2) {
if (o1 == null) {
if (o2 == null) {
return 0;
} else {
return -1;
}
} else if (o2 == null) {
return 1;
}
int n = o1.getVersion().compareTo(o2.getVersion());
if (n == 0) {
return o1.getPriority() - o2.getPriority();
} else {
return n;
}
}
};
@Override
public String toString() {
return getId() + "[" + getVersion().toString() +
(tag.isEmpty() ? "" : "/" + tag) + "]";
}
public static Comparator<ComponentInfo> versionComparator() {
return COMPARATOR_VERSIONS;
}
public static Comparator<ComponentInfo> reverseVersionComparator(ComponentStorage target) {
String myEdition = target.loadGraalVersionInfo().get(CommonConstants.CAP_GRAALVM_VERSION);
return versionComparator().reversed().thenComparing(editionComparator(myEdition));
}
public static Comparator<ComponentInfo> versionComparator(ComponentStorage target) {
String myEdition = target.loadGraalVersionInfo().get(CommonConstants.CAP_GRAALVM_VERSION);
return versionComparator().thenComparing(editionComparator(myEdition));
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public boolean isNativeComponent() {
return nativeComponent;
}
public void setNativeComponent(boolean nativeComponent) {
this.nativeComponent = nativeComponent;
}
public <T> void provideValue(String k, T v) {
providedValues.put(k, v);
}
public <T> T getProvidedValue(String k, Class<T> type) {
Object o = providedValues.get(k);
if (!type.isInstance(o)) {
if (type != String.class || o == null) {
return null;
}
o = o.toString();
}
@SuppressWarnings("unchecked")
T ret = (T) o;
return ret;
}
public Map<String, Object> getProvidedValues() {
return Collections.unmodifiableMap(providedValues);
}
public void addProvidedValues(Map<String, Object> vals) {
for (String s : vals.keySet()) {
provideValue(s, vals.get(s));
}
}
public void setDependencies(Set<String> deps) {
this.dependencies = deps;
}
public Set<String> getDependencies() {
return Collections.unmodifiableSet(dependencies);
}
public boolean isInstalled() {
return infoPath != null;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public StabilityLevel getStability() {
return stability;
}
public void setStability(StabilityLevel stab) {
if (stab == null) {
this.stability = StabilityLevel.Undefined;
} else {
this.stability = stab;
}
}
}