| /******************************************************************************* |
| * Copyright (c) 2007, 2018 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Genuitec, LLC |
| * EclipseSource - ongoing development |
| *******************************************************************************/ |
| package org.eclipse.equinox.p2.metadata; |
| |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.equinox.internal.p2.metadata.Copyright; |
| import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability; |
| import org.eclipse.equinox.internal.p2.metadata.InstallableUnit; |
| import org.eclipse.equinox.internal.p2.metadata.InstallableUnitFragment; |
| import org.eclipse.equinox.internal.p2.metadata.InstallableUnitPatch; |
| import org.eclipse.equinox.internal.p2.metadata.License; |
| import org.eclipse.equinox.internal.p2.metadata.ProvidedCapability; |
| import org.eclipse.equinox.internal.p2.metadata.RequiredCapability; |
| import org.eclipse.equinox.internal.p2.metadata.RequiredPropertiesMatch; |
| import org.eclipse.equinox.internal.p2.metadata.Requirement; |
| import org.eclipse.equinox.internal.p2.metadata.RequirementChange; |
| import org.eclipse.equinox.internal.p2.metadata.ResolvedInstallableUnit; |
| import org.eclipse.equinox.internal.p2.metadata.TouchpointData; |
| import org.eclipse.equinox.internal.p2.metadata.TouchpointInstruction; |
| import org.eclipse.equinox.internal.p2.metadata.TouchpointType; |
| import org.eclipse.equinox.internal.p2.metadata.UpdateDescriptor; |
| import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil; |
| import org.eclipse.equinox.p2.metadata.expression.IFilterExpression; |
| import org.eclipse.equinox.p2.metadata.expression.IMatchExpression; |
| |
| /** |
| * A factory class for instantiating various p2 metadata objects. |
| * |
| * @since 2.0 |
| */ |
| public final class MetadataFactory { |
| /** |
| * A description containing information about an installable unit. Once created, |
| * installable units are immutable. This description class allows a client to |
| * build up the state for an installable unit incrementally, and then finally |
| * produce the resulting immutable unit. |
| */ |
| public static class InstallableUnitDescription { |
| InstallableUnit unit; |
| |
| /** |
| * A property key (value <code>"org.eclipse.equinox.p2.type.patch"</code>) for a |
| * boolean property indicating that an installable unit is a group. |
| * |
| */ |
| public static final String PROP_TYPE_GROUP = "org.eclipse.equinox.p2.type.group"; //$NON-NLS-1$ |
| |
| /** |
| * A property key (value <code>"org.eclipse.equinox.p2.type.patch"</code>) for a |
| * boolean property indicating that an installable unit is a patch. |
| * |
| */ |
| public static final String PROP_TYPE_PATCH = "org.eclipse.equinox.p2.type.patch"; //$NON-NLS-1$ |
| |
| /** |
| * A property key (value <code>"org.eclipse.equinox.p2.type.fragment"</code>) |
| * for a boolean property indicating that an installable unit is a fragment. |
| * |
| */ |
| public static final String PROP_TYPE_FRAGMENT = "org.eclipse.equinox.p2.type.fragment"; //$NON-NLS-1$ |
| |
| /** |
| * A property key (value <code>"org.eclipse.equinox.p2.type.category"</code>) |
| * for a boolean property indicating that an installable unit is a category. |
| * |
| */ |
| public static final String PROP_TYPE_CATEGORY = "org.eclipse.equinox.p2.type.category"; //$NON-NLS-1$ |
| |
| /** |
| * A property key (value <code>"org.eclipse.equinox.p2.type.product"</code>) for |
| * a boolean property indicating that an installable unit is the root IU of a |
| * product. |
| * |
| * @since 2.2 |
| */ |
| public static final String PROP_TYPE_PRODUCT = "org.eclipse.equinox.p2.type.product"; //$NON-NLS-1$ |
| |
| public InstallableUnitDescription() { |
| super(); |
| } |
| |
| /** |
| * Add the specified capabilities to the installable unit. |
| * |
| * @param additional the capabilities to add. |
| */ |
| public void addProvidedCapabilities(Collection<IProvidedCapability> additional) { |
| if (additional == null || additional.size() == 0) |
| return; |
| Collection<IProvidedCapability> current = unit().getProvidedCapabilities(); |
| ArrayList<IProvidedCapability> all = new ArrayList<>(additional.size() + current.size()); |
| all.addAll(current); |
| all.addAll(additional); |
| unit().setCapabilities(all.toArray(new IProvidedCapability[all.size()])); |
| } |
| |
| /** @deprecated Use addRequirements(additional) instead */ |
| @Deprecated |
| public void addRequiredCapabilities(Collection<IRequirement> additional) { |
| addRequirements(additional); |
| } |
| |
| /** |
| * Add the specified requirements to the installable unit. |
| * |
| * @param additional the requirements to add |
| */ |
| public void addRequirements(Collection<IRequirement> additional) { |
| if (additional == null || additional.size() == 0) |
| return; |
| List<IRequirement> current = unit().getRequirements(); |
| ArrayList<IRequirement> all = new ArrayList<>(additional.size() + current.size()); |
| all.addAll(current); |
| all.addAll(additional); |
| unit().setRequiredCapabilities(all.toArray(new IRequirement[all.size()])); |
| } |
| |
| public void addTouchpointData(ITouchpointData data) { |
| Assert.isNotNull(data); |
| unit().addTouchpointData(data); |
| } |
| |
| /** |
| * Returns the id of the installable unit. |
| */ |
| public String getId() { |
| return unit().getId(); |
| } |
| |
| /** |
| * Return a collection of all the capabilities specified on this installable |
| * unit. |
| */ |
| public Collection<IProvidedCapability> getProvidedCapabilities() { |
| return unit().getProvidedCapabilities(); |
| } |
| |
| /** @deprecated Use getRequirements() instead */ |
| @Deprecated |
| public List<IRequirement> getRequiredCapabilities() { |
| return getRequirements(); |
| } |
| |
| /** |
| * Return a collection of the requirements specified on this installable unit. |
| */ |
| public List<IRequirement> getRequirements() { |
| return unit().getRequirements(); |
| } |
| |
| /** @deprecated Use getMetaRequirements() instead */ |
| @Deprecated |
| public Collection<IRequirement> getMetaRequiredCapabilities() { |
| return getMetaRequirements(); |
| } |
| |
| /** |
| * Return a collection of the meta requirements specified on this installable |
| * unit. |
| */ |
| public Collection<IRequirement> getMetaRequirements() { |
| return unit().getMetaRequirements(); |
| } |
| |
| /** |
| * Returns the current touchpoint data on this installable unit description. The |
| * touchpoint data may change if further data is added to the description. |
| * |
| * @return The current touchpoint data on this description |
| */ |
| public Collection<ITouchpointData> getTouchpointData() { |
| return unit().getTouchpointData(); |
| |
| } |
| |
| /** |
| * Return the versiono on this installable unit description. |
| */ |
| public Version getVersion() { |
| return unit().getVersion(); |
| } |
| |
| /** |
| * Returns the UpdateDescriptor for this IU |
| * |
| * @since 2.1 |
| */ |
| public IUpdateDescriptor getUpdateDescriptor() { |
| return unit().getUpdateDescriptor(); |
| } |
| |
| /** |
| * Set the artifact keys for the installable unit. Previous values will be |
| * overwritten. |
| * |
| * @param value the artifacts to the used. |
| */ |
| public void setArtifacts(IArtifactKey[] value) { |
| unit().setArtifacts(value); |
| } |
| |
| /** |
| * Set the capabilities for the installable unit. Previous values will be |
| * overwritten. |
| * |
| * @param exportedCapabilities the capabilities to be used. |
| */ |
| public void setCapabilities(IProvidedCapability[] exportedCapabilities) { |
| unit().setCapabilities(exportedCapabilities); |
| } |
| |
| /** |
| * Set the copyright for the installable unit. Previous values will be |
| * overwritten. |
| * |
| * @param copyright the copyright to be used. |
| */ |
| public void setCopyright(ICopyright copyright) { |
| unit().setCopyright(copyright); |
| } |
| |
| public void setFilter(IMatchExpression<IInstallableUnit> filter) { |
| unit().setFilter(filter); |
| } |
| |
| public void setFilter(String filter) { |
| unit().setFilter(filter); |
| } |
| |
| /** |
| * Set the id of the installable unit. |
| */ |
| public void setId(String id) { |
| unit().setId(id); |
| } |
| |
| /** |
| * Set the licenses for the installable unit. Previous values will be |
| * overwritten. |
| */ |
| public void setLicenses(ILicense[] licenses) { |
| unit().setLicenses(licenses); |
| } |
| |
| /** |
| * Set a property with a specified value for this installable unit. |
| * |
| * @param key key with which the specified value is to be associated |
| * @param value value to be associated with the specified key |
| */ |
| public void setProperty(String key, String value) { |
| unit().setProperty(key, value); |
| } |
| |
| /** @deprecated Use setRequirements(requirements) instead */ |
| @Deprecated |
| public void setRequiredCapabilities(IRequirement[] requirements) { |
| setRequirements(requirements); |
| } |
| |
| /** |
| * Set the requirements for the installable unit. Previous values will be |
| * overwritten. |
| * |
| * @param requirements the requirements to be used. |
| */ |
| public void setRequirements(IRequirement[] requirements) { |
| unit().setRequiredCapabilities(requirements); |
| } |
| |
| /** @deprecated Use setMetaRequirements(requirements) instead */ |
| @Deprecated |
| public void setMetaRequiredCapabilities(IRequirement[] metaRequirements) { |
| setMetaRequirements(metaRequirements); |
| } |
| |
| /** |
| * Set the meta requirements for the installable unit. Previous values will be |
| * overwritten. |
| * |
| * @param metaRequirements the meta requirements to be used. |
| */ |
| public void setMetaRequirements(IRequirement[] metaRequirements) { |
| unit().setMetaRequiredCapabilities(metaRequirements); |
| } |
| |
| /** |
| * Change the singleton status of the installable unit. |
| */ |
| public void setSingleton(boolean singleton) { |
| unit().setSingleton(singleton); |
| } |
| |
| /** |
| * Set the touchpoint type for the installable unit. |
| */ |
| public void setTouchpointType(ITouchpointType type) { |
| unit().setTouchpointType(type); |
| } |
| |
| /** |
| * Set the update descriptor for the installable unit. |
| */ |
| public void setUpdateDescriptor(IUpdateDescriptor updateInfo) { |
| unit().setUpdateDescriptor(updateInfo); |
| } |
| |
| /** |
| * Set the version of this installable unit. |
| * |
| * @param newVersion version to be set on the installable unit. |
| */ |
| public void setVersion(Version newVersion) { |
| unit().setVersion(newVersion); |
| } |
| |
| InstallableUnit unit() { |
| if (unit == null) { |
| unit = new InstallableUnit(); |
| unit.setArtifacts(new IArtifactKey[0]); |
| } |
| return unit; |
| } |
| |
| IInstallableUnit unitCreate() { |
| IInstallableUnit result = unit(); |
| this.unit = null; |
| return result; |
| } |
| } |
| |
| /** |
| * A description containing information about an installable unit fragment. Once |
| * created, installable units are immutable. This description class allows a |
| * client to build up the state for an installable unit fragment incrementally, |
| * and then finally produce the resulting immutable unit. |
| */ |
| public static class InstallableUnitFragmentDescription extends InstallableUnitDescription { |
| public InstallableUnitFragmentDescription() { |
| super(); |
| setProperty(InstallableUnitDescription.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString()); |
| } |
| |
| /** |
| * Specify the requirements identifying the host to which the installable unit |
| * fragment should be attached to. |
| */ |
| public void setHost(IRequirement... hostRequirement) { |
| ((InstallableUnitFragment) unit()).setHost(Arrays.asList(hostRequirement)); |
| } |
| |
| @Override |
| InstallableUnit unit() { |
| if (unit == null) |
| unit = new InstallableUnitFragment(); |
| return unit; |
| } |
| } |
| |
| /** |
| * A description containing information about an installable unit patch. Once |
| * created, installable units are immutable. This description class allows a |
| * client to build up the state for an installable unit patch incrementally, and |
| * then finally produce the resulting immutable unit. |
| */ |
| public static class InstallableUnitPatchDescription extends InstallableUnitDescription { |
| |
| public InstallableUnitPatchDescription() { |
| super(); |
| setProperty(InstallableUnitDescription.PROP_TYPE_PATCH, Boolean.TRUE.toString()); |
| } |
| |
| /** |
| * Set the applicability scope for the installable unit patch. |
| */ |
| public void setApplicabilityScope(IRequirement[][] applyTo) { |
| if (applyTo == null) |
| throw new IllegalArgumentException("A patch scope can not be null"); //$NON-NLS-1$ |
| ((InstallableUnitPatch) unit()).setApplicabilityScope(applyTo); |
| } |
| |
| /** |
| * Set the lifecycle change for the installable unit patch. |
| */ |
| public void setLifeCycle(IRequirement lifeCycle) { |
| ((InstallableUnitPatch) unit()).setLifeCycle(lifeCycle); |
| } |
| |
| /** |
| * Set the requirement change for the installable unit patch. |
| */ |
| public void setRequirementChanges(IRequirementChange[] changes) { |
| ((InstallableUnitPatch) unit()).setRequirementsChange(changes); |
| } |
| |
| @Override |
| InstallableUnit unit() { |
| if (unit == null) { |
| unit = new InstallableUnitPatch(); |
| ((InstallableUnitPatch) unit()).setApplicabilityScope(new IRequirement[0][0]); |
| } |
| return unit; |
| } |
| } |
| |
| /** |
| * Singleton touchpoint data for a touchpoint with no instructions. |
| */ |
| private static final ITouchpointData EMPTY_TOUCHPOINT_DATA = new TouchpointData(Collections.emptyMap()); |
| |
| private static ITouchpointType[] typeCache = new ITouchpointType[5]; |
| |
| private static int typeCacheOffset; |
| |
| /** |
| * Returns an {@link IInstallableUnit} based on the given description. Once the |
| * installable unit has been created, the information is discarded from the |
| * description object. |
| * |
| * @param description The description of the unit to create |
| * @return The created installable unit |
| */ |
| public static IInstallableUnit createInstallableUnit(InstallableUnitDescription description) { |
| Assert.isNotNull(description); |
| return description.unitCreate(); |
| } |
| |
| /** |
| * Returns an {@link IInstallableUnitFragment} based on the given description. |
| * Once the fragment has been created, the information is discarded from the |
| * description object. |
| * |
| * @param description The description of the unit to create |
| * @return The created installable unit fragment |
| */ |
| public static IInstallableUnitFragment createInstallableUnitFragment( |
| InstallableUnitFragmentDescription description) { |
| Assert.isNotNull(description); |
| return (IInstallableUnitFragment) description.unitCreate(); |
| } |
| |
| /** |
| * Returns an {@link IInstallableUnitPatch} based on the given description. Once |
| * the patch installable unit has been created, the information is discarded |
| * from the description object. |
| * |
| * @param description The description of the unit to create |
| * @return The created installable unit patch |
| */ |
| public static IInstallableUnitPatch createInstallableUnitPatch(InstallableUnitPatchDescription description) { |
| Assert.isNotNull(description); |
| return (IInstallableUnitPatch) description.unitCreate(); |
| } |
| |
| /** |
| * Returns a {@link IProvidedCapability} with the given values. |
| * |
| * @param namespace The capability namespace |
| * @param name The capability name |
| * @param version The capability version |
| */ |
| public static IProvidedCapability createProvidedCapability(String namespace, String name, Version version) { |
| return new ProvidedCapability(namespace, name, version); |
| } |
| |
| /** |
| * Returns a {@link IProvidedCapability} with the given values. |
| * |
| * @param namespace The capability namespace |
| * @param properties The description of the capability |
| * @since 2.4 |
| */ |
| public static IProvidedCapability createProvidedCapability(String namespace, Map<String, Object> properties) { |
| return new ProvidedCapability(namespace, properties); |
| } |
| |
| /** |
| * Create and return a new requirement ({@link IRequirement}) with the specified |
| * values. |
| * |
| * @param namespace the namespace for the requirement. Must not be |
| * <code>null</code>. |
| * @param name the name for the requirement. Must not be <code>null</code>. |
| * @param range the version range. A value of <code>null</code> is |
| * equivalent to {@link VersionRange#emptyRange} and matches |
| * all versions. |
| * @param filter The filter used to evaluate whether this capability is |
| * applicable in the current environment, or <code>null</code> |
| * to indicate this capability is always applicable |
| * @param optional <code>true</code> if this requirement is optional, and |
| * <code>false</code> otherwise. |
| * @param multiple <code>true</code> if this requirement can be satisfied by |
| * multiple provided capabilities, or <code>false</code> if it |
| * requires exactly one match |
| * @param greedy <code>true</code> if the requirement should be considered |
| * greedy and <code>false</code> otherwise |
| * @return the requirement |
| */ |
| public static IRequirement createRequirement(String namespace, String name, VersionRange range, String filter, |
| boolean optional, boolean multiple, boolean greedy) { |
| return new RequiredCapability(namespace, name, range, InstallableUnit.parseFilter(filter), optional ? 0 : 1, |
| multiple ? Integer.MAX_VALUE : 1, greedy, null); |
| } |
| |
| /** |
| * Returns a {@link IRequirement} with the given values. |
| * |
| * @param namespace The capability namespace |
| * @param name The required capability name |
| * @param range The range of versions that are required, or |
| * <code>null</code> to indicate that any version will do. |
| * @param filter The filter used to evaluate whether this capability is |
| * applicable in the current environment, or <code>null</code> |
| * to indicate this capability is always applicable |
| * @param optional <code>true</code> if this required capability is optional, |
| * and <code>false</code> otherwise. |
| * @param multiple <code>true</code> if this capability can be satisfied by |
| * multiple provided capabilities, or <code>false</code> if it |
| * requires exactly one match |
| * @return the requirement |
| */ |
| public static IRequirement createRequirement(String namespace, String name, VersionRange range, |
| IMatchExpression<IInstallableUnit> filter, boolean optional, boolean multiple) { |
| return new RequiredCapability(namespace, name, range, filter, optional ? 0 : 1, |
| multiple ? Integer.MAX_VALUE : 1, true, null); |
| } |
| |
| /** |
| * Create and return a new requirement ({@link IRequirement}) with the specified |
| * values. |
| * |
| * @param namespace the namespace for the requirement. Must not be |
| * <code>null</code>. |
| * @param name the name for the requirement. Must not be <code>null</code>. |
| * @param range the version range. A value of <code>null</code> is |
| * equivalent to {@link VersionRange#emptyRange} and matches |
| * all versions. |
| * @param filter The filter used to evaluate whether this capability is |
| * applicable in the current environment, or <code>null</code> |
| * to indicate this capability is always applicable |
| * @param minCard minimum cardinality |
| * @param maxCard maximum cardinality |
| * @param greedy <code>true</code> if the requirement should be considered |
| * greedy and <code>false</code> otherwise |
| * @return the requirement |
| */ |
| public static IRequirement createRequirement(String namespace, String name, VersionRange range, |
| IMatchExpression<IInstallableUnit> filter, int minCard, int maxCard, boolean greedy) { |
| return new RequiredCapability(namespace, name, range, filter, minCard, maxCard, greedy, null); |
| } |
| |
| /** |
| * Create and return a new requirement ({@link IRequirement}) with the specified |
| * values. |
| * |
| * @param namespace the namespace for the requirement. Must not be |
| * <code>null</code>. |
| * @param name the name for the requirement. Must not be |
| * <code>null</code>. |
| * @param range the version range. A value of <code>null</code> is |
| * equivalent to {@link VersionRange#emptyRange} and matches |
| * all versions. |
| * @param filter The filter used to evaluate whether this capability is |
| * applicable in the current environment, or |
| * <code>null</code> to indicate this capability is always |
| * applicable |
| * @param minCard minimum cardinality |
| * @param maxCard maximum cardinality |
| * @param greedy <code>true</code> if the requirement should be considered |
| * greedy and <code>false</code> otherwise |
| * @param description a <code>String</code> description of the requirement, or |
| * <code>null</code> |
| * @return the requirement |
| */ |
| public static IRequirement createRequirement(String namespace, String name, VersionRange range, |
| IMatchExpression<IInstallableUnit> filter, int minCard, int maxCard, boolean greedy, String description) { |
| return new RequiredCapability(namespace, name, range, filter, minCard, maxCard, greedy, description); |
| } |
| |
| /** |
| * |
| * @param namespace the namespace for the requirement. Must not be |
| * <code>null</code>. |
| * @param propsFilter filter applied on |
| * {@link IProvidedCapability#getProperties()} of every |
| * {@link IInstallableUnit#getProvidedCapabilities()} |
| * @param envFilter matcher over {@link IInstallableUnit#getProperties()} |
| * @param minCard minimum cardinality |
| * @param maxCard maximum cardinality |
| * @param greedy <code>true</code> if the requirement should be considered |
| * greedy and <code>false</code> otherwise |
| * @return the requirement |
| * @since 2.4 |
| */ |
| public static IRequirement createRequirement(String namespace, String propsFilter, |
| IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy) { |
| IFilterExpression attrFilterExpr = ExpressionUtil.parseLDAP(propsFilter); |
| return new RequiredPropertiesMatch(namespace, attrFilterExpr, envFilter, minCard, maxCard, greedy, null); |
| } |
| |
| /** |
| * |
| * @param namespace the namespace for the requirement. Must not be |
| * <code>null</code>. |
| * @param propsFilter filter applied on |
| * {@link IProvidedCapability#getProperties()} of every |
| * {@link IInstallableUnit#getProvidedCapabilities()} |
| * @param envFilter matcher over {@link IInstallableUnit#getProperties()} |
| * @param minCard minimum cardinality |
| * @param maxCard maximum cardinality |
| * @param greedy <code>true</code> if the requirement should be considered |
| * greedy and <code>false</code> otherwise |
| * @return the requirement |
| * @since 2.5 |
| */ |
| public static IRequirement createRequirement(String namespace, String propsFilter, |
| IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy, |
| String description) { |
| IFilterExpression attrFilterExpr = ExpressionUtil.parseLDAP(propsFilter); |
| return new RequiredPropertiesMatch(namespace, attrFilterExpr, envFilter, minCard, maxCard, greedy, description); |
| } |
| |
| /** |
| * |
| * @param namespace the namespace for the requirement. Must not be |
| * <code>null</code>. |
| * @param propsFilter filter applied on |
| * {@link IProvidedCapability#getProperties()} of every |
| * {@link IInstallableUnit#getProvidedCapabilities()} |
| * @param envFilter matcher over {@link IInstallableUnit#getProperties()} |
| * @param minCard minimum cardinality |
| * @param maxCard maximum cardinality |
| * @param greedy <code>true</code> if the requirement should be considered |
| * greedy and <code>false</code> otherwise |
| * @param description a <code>String</code> description of the requirement, or |
| * <code>null</code> |
| * @return the requirement |
| * @since 2.4 |
| */ |
| public static IRequirement createRequirement(String namespace, IFilterExpression propsFilter, |
| IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy, |
| String description) { |
| return new RequiredPropertiesMatch(namespace, propsFilter, envFilter, minCard, maxCard, greedy, description); |
| } |
| |
| /** |
| * Create and return a new requirement ({@link IRequirement}) with the specified |
| * values. |
| * |
| * @param requirement the match expression |
| * @param envFilter The filter used to evaluate whether this capability is |
| * applicable in the current environment, or |
| * <code>null</code> to indicate this capability is always |
| * applicable |
| * @param minCard minimum cardinality |
| * @param maxCard maximum cardinality |
| * @param greedy <code>true</code> if the requirement should be considered |
| * greedy and <code>false</code> otherwise |
| * @return the requirement |
| */ |
| public static IRequirement createRequirement(IMatchExpression<IInstallableUnit> requirement, |
| IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy) { |
| return createRequirementInternal(requirement, envFilter, minCard, maxCard, greedy, null); |
| } |
| |
| /** |
| * Create and return a new requirement ({@link IRequirement}) with the specified |
| * values. |
| * |
| * @param requirement the match expression |
| * @param envFilter the filter, or <code>null</code> |
| * @param minCard minimum cardinality |
| * @param maxCard maximum cardinality |
| * @param greedy <code>true</code> if the requirement should be considered |
| * greedy and <code>false</code> otherwise |
| * @param description a <code>String</code> description of the requirement, or |
| * <code>null</code> |
| * @return the requirement |
| */ |
| public static IRequirement createRequirement(IMatchExpression<IInstallableUnit> requirement, |
| IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy, |
| String description) { |
| return createRequirementInternal(requirement, envFilter, minCard, maxCard, greedy, description); |
| } |
| |
| /** |
| * Returns a new requirement change. |
| * |
| * @param applyOn The source of the requirement change - the kind of |
| * requirement to apply the change to |
| * @param newValue The result of the requirement change - the requirement to |
| * replace the source requirement with |
| * @return a requirement change |
| */ |
| public static IRequirementChange createRequirementChange(IRequirement applyOn, IRequirement newValue) { |
| if ((applyOn == null || applyOn instanceof IRequiredCapability) |
| && (newValue == null || newValue instanceof IRequiredCapability)) |
| return new RequirementChange((IRequiredCapability) applyOn, (IRequiredCapability) newValue); |
| throw new IllegalArgumentException(); |
| } |
| |
| /** |
| * Returns a new {@link ICopyright}. |
| * |
| * @param location the location of a document containing the copyright notice, |
| * or <code>null</code> |
| * @param body the copyright body, cannot be <code>null</code> |
| * @throws IllegalArgumentException when the <code>body</code> is |
| * <code>null</code> |
| */ |
| public static ICopyright createCopyright(URI location, String body) { |
| return new Copyright(location, body); |
| } |
| |
| /** |
| * Return a new {@link ILicense} The body should contain either the full text of |
| * the license or an summary for a license fully specified in the given |
| * location. |
| * |
| * @param location the location of a document containing the full license, or |
| * <code>null</code> |
| * @param body the license body, cannot be <code>null</code> |
| * @throws IllegalArgumentException when the <code>body</code> is |
| * <code>null</code> |
| */ |
| public static ILicense createLicense(URI location, String body) { |
| return new License(location, body, null); |
| } |
| |
| /** |
| * Returns an {@link IInstallableUnit} that represents the given unit bound to |
| * the given fragments. |
| * |
| * @see IInstallableUnit#isResolved() |
| * @param unit The unit to be bound |
| * @param fragments The fragments to be bound |
| * @return A resolved installable unit |
| */ |
| public static IInstallableUnit createResolvedInstallableUnit(IInstallableUnit unit, |
| IInstallableUnitFragment[] fragments) { |
| if (unit.isResolved()) |
| return unit; |
| Assert.isNotNull(unit); |
| Assert.isNotNull(fragments); |
| return new ResolvedInstallableUnit(unit, fragments); |
| |
| } |
| |
| /** |
| * Returns an instance of {@link ITouchpointData} with the given instructions. |
| * |
| * @param instructions The instructions for the touchpoint data. |
| * @return The created touchpoint data |
| */ |
| public static ITouchpointData createTouchpointData(Map<String, ? extends Object> instructions) { |
| Assert.isNotNull(instructions); |
| // copy the map to protect against subsequent change by caller |
| if (instructions.isEmpty()) |
| return EMPTY_TOUCHPOINT_DATA; |
| |
| Map<String, ITouchpointInstruction> result = new LinkedHashMap<>(instructions.size()); |
| |
| for (Map.Entry<String, ? extends Object> entry : instructions.entrySet()) { |
| Object value = entry.getValue(); |
| ITouchpointInstruction instruction; |
| if (value == null || value instanceof String) |
| instruction = createTouchpointInstruction((String) value, null); |
| else |
| instruction = (ITouchpointInstruction) value; |
| result.put(entry.getKey(), instruction); |
| } |
| return new TouchpointData(result); |
| } |
| |
| /** |
| * Merge the given touchpoint instructions with a pre-existing touchpoint data |
| * |
| * @param initial - the initial ITouchpointData |
| * @param incomingInstructions - Map of ITouchpointInstructions to merge into |
| * the initial touchpoint data |
| * @return the merged ITouchpointData |
| */ |
| public static ITouchpointData mergeTouchpointData(ITouchpointData initial, |
| Map<String, ITouchpointInstruction> incomingInstructions) { |
| if (incomingInstructions == null || incomingInstructions.size() == 0) |
| return initial; |
| |
| Map<String, ITouchpointInstruction> resultInstructions = new HashMap<>(initial.getInstructions()); |
| for (String key : incomingInstructions.keySet()) { |
| ITouchpointInstruction instruction = incomingInstructions.get(key); |
| ITouchpointInstruction existingInstruction = resultInstructions.get(key); |
| |
| if (existingInstruction != null) { |
| String body = existingInstruction.getBody(); |
| if (body == null || body.length() == 0) |
| body = instruction.getBody(); |
| else if (instruction.getBody() != null) { |
| if (!body.endsWith(";")) //$NON-NLS-1$ |
| body += ';'; |
| body += instruction.getBody(); |
| } |
| |
| String importAttribute = existingInstruction.getImportAttribute(); |
| if (importAttribute == null || importAttribute.length() == 0) |
| importAttribute = instruction.getImportAttribute(); |
| else if (instruction.getImportAttribute() != null) { |
| if (!importAttribute.endsWith(",")) //$NON-NLS-1$ |
| importAttribute += ','; |
| importAttribute += instruction.getBody(); |
| } |
| instruction = createTouchpointInstruction(body, importAttribute); |
| } |
| resultInstructions.put(key, instruction); |
| } |
| return createTouchpointData(resultInstructions); |
| } |
| |
| public static ITouchpointInstruction createTouchpointInstruction(String body, String importAttribute) { |
| return new TouchpointInstruction(body, importAttribute); |
| } |
| |
| /** |
| * Returns a {@link TouchpointType} with the given id and version. |
| * |
| * @param id The touchpoint id |
| * @param version The touchpoint version |
| * @return A touchpoint type instance with the given id and version |
| */ |
| public static ITouchpointType createTouchpointType(String id, Version version) { |
| Assert.isNotNull(id); |
| Assert.isNotNull(version); |
| |
| if (id.equals(ITouchpointType.NONE.getId()) && version.equals(ITouchpointType.NONE.getVersion())) |
| return ITouchpointType.NONE; |
| |
| synchronized (typeCache) { |
| ITouchpointType result = getCachedTouchpointType(id, version); |
| if (result != null) |
| return result; |
| result = new TouchpointType(id, version); |
| putCachedTouchpointType(result); |
| return result; |
| } |
| } |
| |
| /** |
| * |
| * @param descriptors The IUs that the descriptor provides updates for. |
| * @param severity The update severity (either |
| * {@link IUpdateDescriptor#NORMAL} or |
| * {@link IUpdateDescriptor#HIGH}) |
| * @param description A description of the update |
| * @param location a {@link URI} specifying the location or <code>null</code> |
| * @return A new update descriptor |
| */ |
| public static IUpdateDescriptor createUpdateDescriptor(Collection<IMatchExpression<IInstallableUnit>> descriptors, |
| int severity, String description, URI location) { |
| return new UpdateDescriptor(descriptors, severity, description, location); |
| } |
| |
| /** |
| * Creates a new update descriptor object. |
| * |
| * @param id The id of the installable unit that the descriptor |
| * provides updates for |
| * @param range The version range that the descriptor provides updates for |
| * @param severity The update severity (either |
| * {@link IUpdateDescriptor#NORMAL} or |
| * {@link IUpdateDescriptor#HIGH}) |
| * @param description A description of the update |
| * @return A new update descriptor |
| */ |
| public static IUpdateDescriptor createUpdateDescriptor(String id, VersionRange range, int severity, |
| String description) { |
| return createUpdateDescriptor(id, range, severity, description, null); |
| } |
| |
| /** |
| * Create and return a new update descriptor {@link IUpdateDescriptor} with the |
| * specified values. |
| * |
| * @param id the identifiter for the update. Must not be |
| * <code>null</code>. |
| * @param range the version range. A <code>null</code> range is equivalent |
| * to {@link VersionRange#emptyRange} and matches all |
| * versions. |
| * @param severity the severity |
| * @param description a <code>String</code> description or <code>null</code> |
| * @param location a {@link URI} specifying the location or <code>null</code> |
| * @return the update descriptor |
| */ |
| public static IUpdateDescriptor createUpdateDescriptor(String id, VersionRange range, int severity, |
| String description, URI location) { |
| Collection<IMatchExpression<IInstallableUnit>> descriptors = new ArrayList<>(1); |
| descriptors.add(RequiredCapability.createMatchExpressionFromRange(IInstallableUnit.NAMESPACE_IU_ID, id, range)); |
| return createUpdateDescriptor(descriptors, severity, description, location); |
| } |
| |
| private static IRequirement createRequirementInternal(IMatchExpression<IInstallableUnit> requirement, |
| IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy, |
| String description) { |
| // IRequiredCapability is simply a requirement with a match expression derived |
| // from a (namespace, name, version) tripet. |
| // However the xml format also requires that maxCard > 1 or it is serialized in |
| // the generic format. |
| // When parsing back from xml try to convert to an IRequiredCapability to retain |
| // the representation prior to serialization |
| if (RequiredCapability.isVersionRangeRequirement(requirement)) { |
| String namespace = RequiredCapability.extractNamespace(requirement); |
| String name = RequiredCapability.extractName(requirement); |
| VersionRange range = RequiredCapability.extractRange(requirement); |
| return new RequiredCapability(namespace, name, range, envFilter, minCard, maxCard, greedy, description); |
| } |
| |
| if (RequiredPropertiesMatch.isPropertiesMatchRequirement(requirement)) { |
| String namespace = RequiredPropertiesMatch.extractNamespace(requirement); |
| IFilterExpression attrMatch = RequiredPropertiesMatch.extractPropertiesMatch(requirement); |
| return new RequiredPropertiesMatch(namespace, attrMatch, envFilter, minCard, maxCard, greedy, description); |
| } |
| |
| return new Requirement(requirement, envFilter, minCard, maxCard, greedy, description); |
| } |
| |
| private static ITouchpointType getCachedTouchpointType(String id, Version version) { |
| for (ITouchpointType typeCache1 : typeCache) { |
| if (typeCache1 != null && typeCache1.getId().equals(id) && typeCache1.getVersion().equals(version)) { |
| return typeCache1; |
| } |
| } |
| return null; |
| } |
| |
| private static void putCachedTouchpointType(ITouchpointType result) { |
| // simple rotating buffer |
| typeCache[typeCacheOffset] = result; |
| typeCacheOffset = (typeCacheOffset + 1) % typeCache.length; |
| } |
| } |