From 48e7f27f7f83d9f4f07e6ea9e4f5197ce21c5efd Mon Sep 17 00:00:00 2001 From: Hannes Wellmann Date: Sun, 3 Sep 2023 14:38:38 +0200 Subject: [PATCH] Modernize internal p2 metadata Member classes This improves the Requirement.hashCode() method. --- .../internal/p2/metadata/ArtifactKey.java | 87 ++++------- .../internal/p2/metadata/InstallableUnit.java | 129 ++++++---------- .../p2/metadata/ProvidedCapability.java | 73 ++++----- .../p2/metadata/RequiredCapability.java | 51 +++---- .../internal/p2/metadata/Requirement.java | 54 +++---- .../p2/metadata/ResolvedInstallableUnit.java | 140 ++++++------------ .../equinox/p2/metadata/MetadataFactory.java | 2 +- .../artifact/spi/ArtifactDescriptor.java | 72 +++------ 8 files changed, 206 insertions(+), 402 deletions(-) diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ArtifactKey.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ArtifactKey.java index c41e984a58..cce083253a 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ArtifactKey.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ArtifactKey.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2017 IBM Corporation and others. + * Copyright (c) 2007, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -13,17 +13,16 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.metadata; -import java.util.ArrayList; -import java.util.StringTokenizer; +import java.util.Objects; import org.eclipse.core.runtime.Assert; import org.eclipse.equinox.p2.metadata.IArtifactKey; import org.eclipse.equinox.p2.metadata.Version; import org.eclipse.equinox.p2.metadata.expression.IMemberProvider; -/** +/** * The concrete type for representing IArtifactKey's. *

- * See {link IArtifact for a description of the lifecycle of artifact keys) + * See {link IArtifact for a description of the lifecycle of artifact keys) */ public class ArtifactKey implements IArtifactKey, IMemberProvider { private static final String SEPARATOR = ","; //$NON-NLS-1$ @@ -36,52 +35,33 @@ public class ArtifactKey implements IArtifactKey, IMemberProvider { private final String classifier; private final Version version; - private static String[] getArrayFromList(String stringList, String separator) { - if (stringList == null || stringList.trim().length() == 0) - return new String[0]; - ArrayList list = new ArrayList<>(); - boolean separatorSeen = true; - StringTokenizer tokens = new StringTokenizer(stringList, separator, true); - while (tokens.hasMoreTokens()) { - String token = tokens.nextToken().trim(); - if (token.equals(separator)) { - if (separatorSeen) - list.add(""); //$NON-NLS-1$ - separatorSeen = true; - } else { - separatorSeen = false; - if (token.length() != 0) - list.add(token); - } - } - if (separatorSeen) - list.add(""); //$NON-NLS-1$ - return list.toArray(new String[list.size()]); - } - public static IArtifactKey parse(String specification) { - String[] parts = getArrayFromList(specification, SEPARATOR); - if (parts.length < 2 || parts.length > 3) + String[] parts = specification.split(SEPARATOR, -1); + if (parts.length < 2 || parts.length > 3) { throw new IllegalArgumentException("Unexpected number of parts in artifact key: " + specification); //$NON-NLS-1$ + } Version version = Version.emptyVersion; - if (parts.length == 3 && parts[2].trim().length() > 0) + if (parts.length == 3 && !parts[2].isBlank()) { version = Version.parseVersion(parts[2]); + } try { return new ArtifactKey(parts[0], parts[1], version); } catch (IllegalArgumentException e) { - throw (IllegalArgumentException) new IllegalArgumentException("Wrong version syntax in artifact key: " + specification).initCause(e); //$NON-NLS-1$ + throw (IllegalArgumentException) new IllegalArgumentException( + "Wrong version syntax in artifact key: " + specification).initCause(e); //$NON-NLS-1$ } } public ArtifactKey(String classifier, String id, Version version) { - super(); Assert.isNotNull(classifier); Assert.isNotNull(id); Assert.isNotNull(version); - if (classifier.contains(SEPARATOR)) + if (classifier.contains(SEPARATOR)) { throw new IllegalArgumentException("comma not allowed in classifier"); //$NON-NLS-1$ - if (id.contains(SEPARATOR)) + } + if (id.contains(SEPARATOR)) { throw new IllegalArgumentException("comma not allowed in id"); //$NON-NLS-1$ + } this.classifier = classifier; this.id = id; this.version = version; @@ -105,10 +85,7 @@ public Version getVersion() { @Override public int hashCode() { - int hash = id.hashCode(); - hash = 17 * hash + getVersion().hashCode(); - hash = 17 * hash + classifier.hashCode(); - return hash; + return Objects.hash(id, getVersion(), classifier); } @Override @@ -118,10 +95,12 @@ public String toString() { @Override public boolean equals(Object obj) { - if (!(obj instanceof IArtifactKey)) - return false; - IArtifactKey ak = (IArtifactKey) obj; - return ak.getId().equals(id) && ak.getVersion().equals(getVersion()) && ak.getClassifier().equals(classifier); + if (this == obj) { + return true; + } + return obj instanceof IArtifactKey ak // + && ak.getId().equals(id) && ak.getVersion().equals(getVersion()) + && ak.getClassifier().equals(classifier); } @Override @@ -131,24 +110,16 @@ public String getId() { @Override public String toExternalForm() { - StringBuffer data = new StringBuffer(classifier).append(SEPARATOR); - data.append(id).append(SEPARATOR); - data.append(version.toString()); - return data.toString(); + return String.join(SEPARATOR, classifier, id, version.toString()); } @Override public Object getMember(String memberName) { - // It is OK to use identity comparisons here since - // a) All constant valued strings are always interned - // b) The Member constructor always interns the name - // - if (MEMBER_ID == memberName) - return id; - if (MEMBER_VERSION == memberName) - return version; - if (MEMBER_CLASSIFIER == memberName) - return classifier; - throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ + return switch (memberName) { + case MEMBER_ID -> id; + case MEMBER_VERSION -> version; + case MEMBER_CLASSIFIER -> classifier; + default -> throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ + }; } } diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/InstallableUnit.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/InstallableUnit.java index 7d49b306de..31d540a0f8 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/InstallableUnit.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/InstallableUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2018 IBM Corporation and others. + * Copyright (c) 2007, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -16,9 +16,11 @@ import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import org.eclipse.equinox.internal.p2.core.helpers.CollectionUtils; import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties; import org.eclipse.equinox.p2.metadata.IArtifactKey; @@ -108,9 +110,9 @@ public InstallableUnit() { public void addTouchpointData(ITouchpointData newData) { int tl = touchpointData.length; - if (tl == 0) + if (tl == 0) { touchpointData = new ITouchpointData[] { newData }; - else { + } else { ITouchpointData[] newDatas = new ITouchpointData[tl + 1]; System.arraycopy(touchpointData, 0, newDatas, 0, tl); newDatas[tl] = newData; @@ -118,34 +120,23 @@ public void addTouchpointData(ITouchpointData newData) { } } + static final Comparator ID_FIRST_THEN_VERSION = Comparator // + .comparing(IInstallableUnit::getId) // + .thenComparing(IInstallableUnit::getVersion); + @Override public int compareTo(IInstallableUnit other) { - int cmp = getId().compareTo(other.getId()); - if (cmp == 0) - cmp = getVersion().compareTo(other.getVersion()); - return cmp; + return ID_FIRST_THEN_VERSION.compare(this, other); } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) - return false; - if (!(obj instanceof IInstallableUnit)) - return false; - final IInstallableUnit other = (IInstallableUnit) obj; - if (id == null) { - if (other.getId() != null) - return false; - } else if (!id.equals(other.getId())) - return false; - if (getVersion() == null) { - if (other.getVersion() != null) - return false; - } else if (!getVersion().equals(other.getVersion())) - return false; - return true; + } + return obj instanceof IInstallableUnit unit // + && Objects.equals(getId(), unit.getId()) // + && Objects.equals(getVersion(), unit.getVersion()); } @Override @@ -183,10 +174,7 @@ public Map getProperties() { * Helper method to cache localized properties */ public String getLocalizedProperty(String key) { - String result = null; - if (localizedProperties != null) - result = localizedProperties.getProperty(key); - return result; + return localizedProperties != null ? localizedProperties.getProperty(key) : null; } @Override @@ -227,11 +215,7 @@ public Version getVersion() { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((getVersion() == null) ? 0 : getVersion().hashCode()); - return result; + return Objects.hash(id, getVersion()); } @Override @@ -245,21 +229,15 @@ public boolean isSingleton() { } private OrderedProperties properties() { - return (properties != null ? properties : NO_PROPERTIES); + return properties != null ? properties : NO_PROPERTIES; } public void setArtifacts(IArtifactKey[] value) { - if (value == null || value.length == 0) - artifacts = NO_ARTIFACTS; - else - artifacts = value; + artifacts = value == null || value.length == 0 ? NO_ARTIFACTS : value; } public void setCapabilities(IProvidedCapability[] newCapabilities) { - if (newCapabilities == null || newCapabilities.length == 0) - providedCapabilities = NO_PROVIDES; - else - providedCapabilities = newCapabilities; + providedCapabilities = newCapabilities == null || newCapabilities.length == 0 ? NO_PROVIDES : newCapabilities; } public void setFilter(IMatchExpression filter) { @@ -276,14 +254,14 @@ public void setId(String id) { public static IMatchExpression parseFilter(String filterStr) { IFilterExpression filter = ExpressionUtil.parseLDAP(filterStr); - if (filter == null) + if (filter == null) { return null; - + } synchronized (filterCache) { IMatchExpression matchExpr = filterCache.get(filter); - if (matchExpr != null) + if (matchExpr != null) { return matchExpr; - + } matchExpr = ExpressionUtil.getFactory().matchExpression(filterWrap, filter); filterCache.put(filter, matchExpr); return matchExpr; @@ -294,16 +272,19 @@ public static IMatchExpression parseFilter(String filterStr) { * Helper method to cache localized properties */ public String setLocalizedProperty(String key, String value) { - if (localizedProperties == null) + if (localizedProperties == null) { localizedProperties = new OrderedProperties(); + } return localizedProperties.put(key, value); } public String setProperty(String key, String value) { - if (value == null) + if (value == null) { return (properties != null ? (String) properties.remove(key) : null); - if (properties == null) + } + if (properties == null) { properties = new OrderedProperties(); + } return (String) properties.setProperty(key, value); } @@ -396,37 +377,22 @@ public void setMetaRequiredCapabilities(IRequirement[] metaReqs) { @Override public Object getMember(String memberName) { - // It is OK to use identity comparisons here since - // a) All constant valued strings are always interned - // b) The Member constructor always interns the name - // - if (MEMBER_PROVIDED_CAPABILITIES == memberName) - return providedCapabilities; - if (MEMBER_ID == memberName) - return id; - if (MEMBER_VERSION == memberName) - return version; - if (MEMBER_PROPERTIES == memberName) - return properties; - if (MEMBER_FILTER == memberName) - return filter; - if (MEMBER_ARTIFACTS == memberName) - return artifacts; - if (MEMBER_REQUIREMENTS == memberName) - return requires; - if (MEMBER_LICENSES == memberName) - return licenses; - if (MEMBER_COPYRIGHT == memberName) - return copyright; - if (MEMBER_TOUCHPOINT_DATA == memberName) - return touchpointData; - if (MEMBER_TOUCHPOINT_TYPE == memberName) - return touchpointType; - if (MEMBER_UPDATE_DESCRIPTOR == memberName) - return updateInfo; - if (MEMBER_SINGLETON == memberName) - return Boolean.valueOf(singleton); - throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ + return switch (memberName) { + case MEMBER_PROVIDED_CAPABILITIES -> providedCapabilities; + case MEMBER_ID -> id; + case MEMBER_VERSION -> version; + case MEMBER_PROPERTIES -> properties; + case MEMBER_FILTER -> filter; + case MEMBER_ARTIFACTS -> artifacts; + case MEMBER_REQUIREMENTS -> requires; + case MEMBER_LICENSES -> licenses; + case MEMBER_COPYRIGHT -> copyright; + case MEMBER_TOUCHPOINT_DATA -> touchpointData; + case MEMBER_TOUCHPOINT_TYPE -> touchpointType; + case MEMBER_UPDATE_DESCRIPTOR -> updateInfo; + case MEMBER_SINGLETON -> singleton; + default -> throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ + }; } public static IInstallableUnit contextIU(String ws, String os, String arch) { @@ -441,8 +407,7 @@ public static IInstallableUnit contextIU(String ws, String os, String arch) { public static IInstallableUnit contextIU(Map environment) { InstallableUnit ctxIU = new InstallableUnit(); ctxIU.setId("org.eclipse.equinox.p2.context.iu"); //$NON-NLS-1$ - for (Map.Entry entry : environment.entrySet()) - ctxIU.setProperty(entry.getKey(), entry.getValue()); + environment.forEach(ctxIU::setProperty); return ctxIU; } } diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java index 9c251928db..6d1edefb5a 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2017 IBM Corporation and others. + * Copyright (c) 2007, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -16,12 +16,13 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.metadata; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; +import java.util.stream.Stream; import org.eclipse.core.runtime.Assert; import org.eclipse.equinox.p2.metadata.IProvidedCapability; import org.eclipse.equinox.p2.metadata.Version; @@ -50,13 +51,13 @@ public ProvidedCapability(String namespace, Map props) { Assert.isNotNull(props); Assert.isTrue(!props.isEmpty()); - - assertValidPropertyTypes(props); + props.forEach(this::assertValidValueType); Map resolvedProps = new HashMap<>(props); // Verify the name - Assert.isTrue(resolvedProps.containsKey(namespace) && (resolvedProps.get(namespace) instanceof String), NLS.bind(Messages.provided_capability_name_not_defined, namespace)); + Assert.isTrue(resolvedProps.containsKey(namespace) && (resolvedProps.get(namespace) instanceof String), + NLS.bind(Messages.provided_capability_name_not_defined, namespace)); // Verify the version Object version = resolvedProps.get(PROPERTY_VERSION); @@ -73,11 +74,8 @@ public ProvidedCapability(String namespace, String name, Version version) { Assert.isNotNull(namespace, NLS.bind(Messages.provided_capability_namespace_not_defined, null)); Assert.isNotNull(name, NLS.bind(Messages.provided_capability_name_not_defined, namespace)); this.namespace = namespace; - - Map props = new HashMap<>(); - props.put(namespace, name); - props.put(PROPERTY_VERSION, version == null ? Version.emptyVersion : version); - this.properties = Collections.unmodifiableMap(props); + this.properties = Map.of(namespace, name, // + PROPERTY_VERSION, version == null ? Version.emptyVersion : version); } @Override @@ -98,7 +96,7 @@ public String toString() { @Override public int hashCode() { - return namespace.hashCode() * properties.hashCode(); + return Objects.hash(namespace, properties); } @Override @@ -106,22 +104,9 @@ public boolean equals(Object other) { if (other == null) { return false; } - - if (!(other instanceof IProvidedCapability)) { - return false; - } - - IProvidedCapability otherCapability = (IProvidedCapability) other; - - if (!(namespace.equals(otherCapability.getNamespace()))) { - return false; - } - - if (!(properties.equals(otherCapability.getProperties()))) { - return false; - } - - return true; + return other instanceof IProvidedCapability otherCapability // + && namespace.equals(otherCapability.getNamespace()) + && properties.equals(otherCapability.getProperties()); } @Override @@ -146,22 +131,13 @@ public Map getProperties() { @Override public Object getMember(String memberName) { - switch (memberName) { - case MEMBER_NAMESPACE : - return namespace; - case MEMBER_NAME : - return properties.get(namespace); - case MEMBER_VERSION : - return properties.get(PROPERTY_VERSION); - case MEMBER_PROPERTIES : - return properties; - default : - throw new IllegalArgumentException(String.format("No such member: %s", memberName)); //$NON-NLS-1$ - } - } - - private void assertValidPropertyTypes(Map props) { - props.forEach(this::assertValidValueType); + return switch (memberName) { + case MEMBER_NAMESPACE -> namespace; + case MEMBER_NAME -> properties.get(namespace); + case MEMBER_VERSION -> properties.get(PROPERTY_VERSION); + case MEMBER_PROPERTIES -> properties; + default -> throw new IllegalArgumentException(String.format("No such member: %s", memberName)); //$NON-NLS-1$ + }; } private void assertValidValueType(String key, Object prop) { @@ -176,10 +152,11 @@ private void assertValidValueType(String key, Object prop) { } private void assertValidScalarType(String key, Object scalar) { - Arrays.asList(Version.class, String.class, Long.class, Integer.class, Short.class, Byte.class, Double.class, Float.class, Boolean.class, Character.class) - .stream() - .filter(t -> t.isAssignableFrom(scalar.getClass())) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException(String.format("Invalid type %s of property %s", scalar.getClass(), key))); //$NON-NLS-1$ + Class clazz = scalar.getClass(); + Stream> supportedClasses = Stream.of(Version.class, String.class, Long.class, Integer.class, + Short.class, Byte.class, Double.class, Float.class, Boolean.class, Character.class); + if (supportedClasses.noneMatch(t -> t.isAssignableFrom(clazz))) { + throw new IllegalArgumentException(String.format("Invalid type %s of property %s", scalar.getClass(), key)); //$NON-NLS-1$ + } } } diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java index 66d7179a47..39f83cda54 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2017 IBM Corporation and others. + * Copyright (c) 2007, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -125,18 +125,11 @@ public VersionRange getRange() { @Override public String toString() { - StringBuilder result = new StringBuilder(); - - result.append(getNamespace()); - result.append("; "); //$NON-NLS-1$ - result.append(getName()); - result.append(" "); //$NON-NLS-1$ - result.append(getRange()); - - return result.toString(); + return getNamespace() + "; " + getName() + " " + getRange(); //$NON-NLS-1$ //$NON-NLS-2$ } - public static IMatchExpression createMatchExpressionFromRange(String namespace, String name, VersionRange range) { + public static IMatchExpression createMatchExpressionFromRange(String namespace, String name, + VersionRange range) { Assert.isNotNull(namespace); Assert.isNotNull(name); @@ -184,27 +177,23 @@ public static VersionRange extractRange(IMatchExpression match IExpression expr = ExpressionUtil.getOperand(matchExpression); Object[] params = matchExpression.getParameters(); - switch (params.length) { - // No version parameter - case 2 : - return emptyRange; - // One version parameter: strict or one of the open ranges - case 3 : - Version v = (Version) params[2]; - if (expr.equals(STRICT)) { - return new VersionRange(v, true, v, true); - } - return new VersionRange(v, expr.equals(OPEN_I), MAX_VERSION, true); - // Two version parameters: one of the closed ranges - default : - Version left = (Version) params[2]; - boolean leftInclusive = expr.equals(CLOSED_II) || expr.equals(CLOSED_IN); - - Version right = (Version) params[3]; - boolean rightInclusive = expr.equals(CLOSED_II) || expr.equals(CLOSED_NI); - - return new VersionRange(left, leftInclusive, right, rightInclusive); + return switch (params.length) { + case 2 -> emptyRange; // No version parameter + case 3 -> { // One version parameter: strict or one of the open ranges + Version v = (Version) params[2]; + if (expr.equals(STRICT)) { + yield new VersionRange(v, true, v, true); + } + yield new VersionRange(v, expr.equals(OPEN_I), MAX_VERSION, true); + } + default -> { // Two version parameters: one of the closed ranges + Version left = (Version) params[2]; + boolean leftInclusive = expr.equals(CLOSED_II) || expr.equals(CLOSED_IN); + Version right = (Version) params[3]; + boolean rightInclusive = expr.equals(CLOSED_II) || expr.equals(CLOSED_NI); + yield new VersionRange(left, leftInclusive, right, rightInclusive); } + }; } public static boolean isStrictVersionRequirement(IMatchExpression matchExpression) { diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Requirement.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Requirement.java index 0d9dfa202c..bc6f461b3d 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Requirement.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Requirement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2017 IBM Corporation and others. + * Copyright (c) 2007, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,6 +14,7 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.metadata; +import java.util.Objects; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.metadata.IProvidedCapability; import org.eclipse.equinox.p2.metadata.IRequirement; @@ -54,7 +55,8 @@ public class Requirement implements IRequirement, IMemberProvider { protected final int max; protected final String description; - public Requirement(IMatchExpression requirement, IMatchExpression filter, int min, int max, boolean greedy, String description) { + public Requirement(IMatchExpression requirement, IMatchExpression filter, + int min, int max, boolean greedy, String description) { this.matchExpression = requirement; this.filter = filter; this.min = min; @@ -88,11 +90,7 @@ public String toString() { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((filter == null) ? 0 : filter.hashCode()); - result = prime * result + matchExpression.hashCode(); - return result; + return Objects.hash(filter, matchExpression, min, max, greedy, matchExpression); } @Override @@ -100,21 +98,11 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - - if (!(obj instanceof IRequirement)) { - return false; - } - - IRequirement other = (IRequirement) obj; - if (filter == null) { - if (other.getFilter() != null) { - return false; - } - } else if (!filter.equals(other.getFilter())) { - return false; - } - - return min == other.getMin() && max == other.getMax() && greedy == other.isGreedy() && matchExpression.equals(other.getMatches()); + return obj instanceof IRequirement other // + && Objects.equals(filter, other.getFilter()) // + && min == other.getMin() && max == other.getMax() // + && greedy == other.isGreedy() // + && matchExpression.equals(other.getMatches()); } @Override @@ -154,19 +142,13 @@ public boolean isMatch(IInstallableUnit candidate) { @Override public Object getMember(String memberName) { - switch (memberName) { - case MEMBER_FILTER : - return filter; - case MEMBER_MIN : - return min; - case MEMBER_MAX : - return max; - case MEMBER_GREEDY : - return greedy; - case MEMBER_MATCH : - return matchExpression; - default : - throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ - } + return switch (memberName) { + case MEMBER_FILTER -> filter; + case MEMBER_MIN -> min; + case MEMBER_MAX -> max; + case MEMBER_GREEDY -> greedy; + case MEMBER_MATCH -> matchExpression; + default -> throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ + }; } } diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ResolvedInstallableUnit.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ResolvedInstallableUnit.java index f07c910756..d4c210bb51 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ResolvedInstallableUnit.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ResolvedInstallableUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2018 IBM Corporation and others. + * Copyright (c) 2007, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,10 +15,12 @@ package org.eclipse.equinox.internal.p2.metadata; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.equinox.p2.metadata.IArtifactKey; import org.eclipse.equinox.p2.metadata.ICopyright; import org.eclipse.equinox.p2.metadata.IInstallableUnit; @@ -34,37 +36,24 @@ import org.eclipse.equinox.p2.metadata.expression.IMemberProvider; public class ResolvedInstallableUnit implements IInstallableUnit, IMemberProvider { - private static IInstallableUnitFragment[] NO_IU = new IInstallableUnitFragment[0]; - - private final IInstallableUnitFragment[] fragments; + private final List fragments; protected final IInstallableUnit original; public static final String MEMBER_ORIGINAL = "original"; //$NON-NLS-1$ public static final String MEMBER_FRAGMENTS = "fragments"; //$NON-NLS-1$ public ResolvedInstallableUnit(IInstallableUnit resolved) { - this(resolved, null); + this(resolved, List.of()); } - public ResolvedInstallableUnit(IInstallableUnit resolved, IInstallableUnitFragment[] fragments) { + public ResolvedInstallableUnit(IInstallableUnit resolved, List fragments) { this.original = resolved; - this.fragments = fragments == null ? NO_IU : fragments; + this.fragments = fragments; } @Override public Collection getFragments() { - int fcount = fragments.length; - if (fcount == 0) - return Collections.emptyList(); - - ArrayList result = new ArrayList<>(fcount); - result.addAll(Arrays.asList(fragments)); - for (int i = 0; i < fcount; i++) { - IInstallableUnit fragment = fragments[i]; - if (fragment.isResolved()) - result.addAll(fragment.getFragments()); - } - return result; + return withFragmentElements(fragments, f -> f.isResolved() ? f.getFragments() : List.of()); } @Override @@ -99,54 +88,31 @@ public String getProperty(String key, String locale) { @Override public Collection getProvidedCapabilities() { - Collection originalCapabilities = original.getProvidedCapabilities(); - if (fragments.length == 0) - return originalCapabilities; - - ArrayList result = new ArrayList<>(originalCapabilities); - for (IInstallableUnitFragment fragment : fragments) { - result.addAll(fragment.getProvidedCapabilities()); - } - return result; + return withFragmentElements(original.getProvidedCapabilities(), IInstallableUnit::getProvidedCapabilities); } @Override public Collection getRequirements() { - Collection originalCapabilities = original.getRequirements(); - if (fragments.length == 0) - return originalCapabilities; - - ArrayList result = new ArrayList<>(originalCapabilities); - for (IInstallableUnitFragment fragment : fragments) { - result.addAll(fragment.getRequirements()); - } - return result; + return withFragmentElements(original.getRequirements(), IInstallableUnit::getRequirements); } @Override public Collection getMetaRequirements() { - Collection originalCapabilities = original.getMetaRequirements(); - if (fragments.length == 0) - return originalCapabilities; - - ArrayList result = new ArrayList<>(originalCapabilities); - for (IInstallableUnitFragment fragment : fragments) { - result.addAll(fragment.getMetaRequirements()); - } - return result; + return withFragmentElements(original.getMetaRequirements(), IInstallableUnit::getMetaRequirements); } @Override public Collection getTouchpointData() { - Collection originalTouchpointData = original.getTouchpointData(); - if (fragments.length == 0) - return originalTouchpointData; + return withFragmentElements(original.getTouchpointData(), IInstallableUnit::getTouchpointData); + } - ArrayList result = new ArrayList<>(originalTouchpointData); - for (IInstallableUnitFragment fragment : fragments) { - result.addAll(fragment.getTouchpointData()); + private Collection withFragmentElements(Collection elements, + Function> getter) { + if (fragments.isEmpty()) { + return elements; } - return result; + return Stream.concat(elements.stream(), fragments.stream().map(getter).flatMap(Collection::stream)) + .collect(Collectors.toCollection(ArrayList::new)); } @Override @@ -168,22 +134,20 @@ public boolean isSingleton() { public boolean equals(Object obj) { // TODO This is pretty ugly.... boolean result = original.equals(obj); - if (result) + if (result) { return true; - if (obj instanceof ResolvedInstallableUnit) - return original.equals(((ResolvedInstallableUnit) obj).original); - return false; + } + return obj instanceof ResolvedInstallableUnit unit && original.equals(unit.original); } @Override public int hashCode() { - // TODO Auto-generated method stub return original.hashCode(); } @Override public String toString() { - return "[R]" + original.toString(); //$NON-NLS-1$ + return "[R]" + original; //$NON-NLS-1$ } public IInstallableUnit getOriginal() { @@ -192,10 +156,7 @@ public IInstallableUnit getOriginal() { @Override public int compareTo(IInstallableUnit other) { - int cmp = getId().compareTo(other.getId()); - if (cmp == 0) - cmp = getVersion().compareTo(other.getVersion()); - return cmp; + return InstallableUnit.ID_FIRST_THEN_VERSION.compare(this, other); } @Override @@ -240,37 +201,24 @@ public boolean satisfies(IRequirement candidate) { @Override public Object getMember(String memberName) { - if (MEMBER_FRAGMENTS == memberName) - return fragments; - if (MEMBER_ORIGINAL == memberName) - return original; - if (InstallableUnit.MEMBER_PROVIDED_CAPABILITIES == memberName) - return getProvidedCapabilities(); - if (InstallableUnit.MEMBER_ID == memberName) - return getId(); - if (InstallableUnit.MEMBER_VERSION == memberName) - return getVersion(); - if (InstallableUnit.MEMBER_PROPERTIES == memberName) - return getProperties(); - if (InstallableUnit.MEMBER_FILTER == memberName) - return getFilter(); - if (InstallableUnit.MEMBER_ARTIFACTS == memberName) - return getArtifacts(); - if (InstallableUnit.MEMBER_REQUIREMENTS == memberName) - return getRequirements(); - if (InstallableUnit.MEMBER_LICENSES == memberName) - return getLicenses(); - if (InstallableUnit.MEMBER_COPYRIGHT == memberName) - return getCopyright(); - if (InstallableUnit.MEMBER_TOUCHPOINT_DATA == memberName) - return getTouchpointData(); - if (InstallableUnit.MEMBER_TOUCHPOINT_TYPE == memberName) - return getTouchpointType(); - if (InstallableUnit.MEMBER_UPDATE_DESCRIPTOR == memberName) - return getUpdateDescriptor(); - if (InstallableUnit.MEMBER_SINGLETON == memberName) - return Boolean.valueOf(isSingleton()); - throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ + return switch (memberName) { + case MEMBER_FRAGMENTS -> fragments.toArray(IInstallableUnitFragment[]::new); + case MEMBER_ORIGINAL -> original; + case InstallableUnit.MEMBER_PROVIDED_CAPABILITIES -> getProvidedCapabilities(); + case InstallableUnit.MEMBER_ID -> getId(); + case InstallableUnit.MEMBER_VERSION -> getVersion(); + case InstallableUnit.MEMBER_PROPERTIES -> getProperties(); + case InstallableUnit.MEMBER_FILTER -> getFilter(); + case InstallableUnit.MEMBER_ARTIFACTS -> getArtifacts(); + case InstallableUnit.MEMBER_REQUIREMENTS -> getRequirements(); + case InstallableUnit.MEMBER_LICENSES -> getLicenses(); + case InstallableUnit.MEMBER_COPYRIGHT -> getCopyright(); + case InstallableUnit.MEMBER_TOUCHPOINT_DATA -> getTouchpointData(); + case InstallableUnit.MEMBER_TOUCHPOINT_TYPE -> getTouchpointType(); + case InstallableUnit.MEMBER_UPDATE_DESCRIPTOR -> getUpdateDescriptor(); + case InstallableUnit.MEMBER_SINGLETON -> isSingleton(); + default -> throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ + }; } } diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java index 01747ba80c..b72fd4c3a8 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java @@ -764,7 +764,7 @@ public static IInstallableUnit createResolvedInstallableUnit(IInstallableUnit un return unit; Assert.isNotNull(unit); Assert.isNotNull(fragments); - return new ResolvedInstallableUnit(unit, fragments); + return new ResolvedInstallableUnit(unit, Arrays.asList(fragments)); } diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/ArtifactDescriptor.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/ArtifactDescriptor.java index 46106eb4d9..8cc00c5f9c 100644 --- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/ArtifactDescriptor.java +++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/ArtifactDescriptor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 IBM Corporation and others. + * Copyright (c) 2007, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,8 +14,7 @@ *******************************************************************************/ package org.eclipse.equinox.p2.repository.artifact.spi; -import java.util.Arrays; -import java.util.Map; +import java.util.*; import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties; import org.eclipse.equinox.p2.metadata.IArtifactKey; import org.eclipse.equinox.p2.metadata.expression.IMemberProvider; @@ -50,7 +49,6 @@ public class ArtifactDescriptor implements IArtifactDescriptor, IMemberProvider * @param base the descriptor to use as a template for this new descriptor */ public ArtifactDescriptor(IArtifactDescriptor base) { - super(); key = base.getArtifactKey(); setProcessingSteps(base.getProcessingSteps()); properties.putAll(base.getProperties()); @@ -63,7 +61,6 @@ public ArtifactDescriptor(IArtifactDescriptor base) { * @param key The artifact key corresponding to this descriptor */ public ArtifactDescriptor(IArtifactKey key) { - super(); this.key = key; } @@ -78,10 +75,11 @@ public String getProperty(String propertyKey) { } public void setProperty(String key, String value) { - if (value == null) + if (value == null) { properties.remove(key); - else + } else { properties.put(key, value); + } } public void addProperties(Map additionalProperties) { @@ -108,43 +106,22 @@ public void setProcessingSteps(IProcessingStepDescriptor[] value) { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) - return false; - + } // Other implementations of IArtifactDescriptor must not be considered equal - if (!(obj.getClass().equals(getClass()))) + if (obj == null || !(obj.getClass().equals(getClass()))) { return false; - + } ArtifactDescriptor other = (ArtifactDescriptor) obj; - if (key == null) { - if (other.getArtifactKey() != null) - return false; - } else if (!key.equals(other.getArtifactKey())) - return false; - - if (!Arrays.equals(processingSteps, other.getProcessingSteps())) - return false; - - String format = getProperty(FORMAT); - String otherFormat = other.getProperty(FORMAT); - if (format != null ? !format.equals(otherFormat) : otherFormat != null) - return false; - - return true; + return Objects.equals(key, other.getArtifactKey()) // + && Arrays.equals(processingSteps, other.getProcessingSteps()) + && Objects.equals(getProperty(FORMAT), other.getProperty(FORMAT)); } @Override public int hashCode() { - String format = getProperty(FORMAT); - - final int prime = 31; - int result = 1; - result = prime * result + ((key == null) ? 0 : key.hashCode()); - result = prime * result + Arrays.asList(processingSteps).hashCode(); - result = prime * result + (format != null ? format.hashCode() : 0); - return result; + return Objects.hash(key, Arrays.asList(processingSteps), getProperty(FORMAT)); } @Override @@ -159,26 +136,21 @@ public void setRepository(IArtifactRepository value) { @Override public String toString() { String format = getProperty(IArtifactDescriptor.FORMAT); - if (format == null) + if (format == null) { return "canonical: " + key.toString(); //$NON-NLS-1$ + } return format + ": " + key.toString(); //$NON-NLS-1$ } @Override public Object getMember(String memberName) { - if (memberName == MEMBER_ARTIFACT_KEY) - return key; - - if (memberName == MEMBER_PROPERTIES) - return properties; - - if (memberName == MEMBER_PROCESSING_STEPS) - return processingSteps; - - if (memberName == MEMBER_REPOSITORY) - return repository; - - throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ + return switch (memberName) { + case MEMBER_ARTIFACT_KEY -> key; + case MEMBER_PROPERTIES -> properties; + case MEMBER_PROCESSING_STEPS -> processingSteps; + case MEMBER_REPOSITORY -> repository; + default -> throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ + }; } }