| /******************************************************************************* |
| * Copyright (c) 2007, 2012 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * 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.*; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.equinox.internal.p2.metadata.*; |
| import org.eclipse.equinox.p2.metadata.expression.*; |
| |
| /** |
| * 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<IProvidedCapability>(additional.size() + current.size()); |
| all.addAll(current); |
| all.addAll(additional); |
| unit().setCapabilities(all.toArray(new IProvidedCapability[all.size()])); |
| } |
| |
| /** @deprecated Use addRequirements(additional) instead */ |
| 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<IRequirement>(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 */ |
| 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 */ |
| 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 */ |
| 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 */ |
| 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)); |
| } |
| |
| 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); |
| } |
| |
| 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.<String, ITouchpointInstruction> 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 attributes The description of the capability |
| * @since 2.4 |
| */ |
| public static IProvidedCapability createProvidedCapability(String namespace, Map<String, Object> attributes) { |
| return new ProvidedCapability(namespace, attributes); |
| } |
| |
| /** |
| * 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 requirement the match expression |
| * @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(IMatchExpression<IInstallableUnit> requirement, IMatchExpression<IInstallableUnit> filter, int minCard, int maxCard, boolean greedy) { |
| return new RequiredCapability(requirement, 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 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, filter, optional, multiple, greedy); |
| } |
| |
| /** |
| * 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); |
| } |
| |
| /** |
| * Create and return a new requirement ({@link IRequirement}) with the specified values. |
| * |
| * @param requirement the match expression |
| * @param filter 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> filter, int minCard, int maxCard, boolean greedy, String description) { |
| return new RequiredCapability(requirement, filter, 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<String, ITouchpointInstruction>(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<String, ITouchpointInstruction>(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; |
| } |
| } |
| |
| 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<IMatchExpression<IInstallableUnit>>(1); |
| descriptors.add(createMatchExpressionFromRange(IInstallableUnit.NAMESPACE_IU_ID, id, range)); |
| return createUpdateDescriptor(descriptors, severity, description, location); |
| } |
| |
| private static final IExpression allVersionsExpression; |
| private static final IExpression range_II_Expression; |
| private static final IExpression range_IN_Expression; |
| private static final IExpression range_NI_Expression; |
| private static final IExpression range_NN_Expression; |
| private static final IExpression strictVersionExpression; |
| private static final IExpression openEndedExpression; |
| private static final IExpression openEndedNonInclusiveExpression; |
| |
| static { |
| IExpressionFactory factory = ExpressionUtil.getFactory(); |
| IExpression xVar = factory.variable("x"); //$NON-NLS-1$ |
| IExpression nameEqual = factory.equals(factory.member(xVar, ProvidedCapability.MEMBER_NAME), factory.indexedParameter(0)); |
| IExpression namespaceEqual = factory.equals(factory.member(xVar, ProvidedCapability.MEMBER_NAMESPACE), factory.indexedParameter(1)); |
| |
| IExpression versionMember = factory.member(xVar, ProvidedCapability.MEMBER_VERSION); |
| |
| IExpression versionCmpLow = factory.indexedParameter(2); |
| IExpression versionEqual = factory.equals(versionMember, versionCmpLow); |
| IExpression versionGt = factory.greater(versionMember, versionCmpLow); |
| IExpression versionGtEqual = factory.greaterEqual(versionMember, versionCmpLow); |
| |
| IExpression versionCmpHigh = factory.indexedParameter(3); |
| IExpression versionLt = factory.less(versionMember, versionCmpHigh); |
| IExpression versionLtEqual = factory.lessEqual(versionMember, versionCmpHigh); |
| |
| IExpression pvMember = factory.member(factory.thisVariable(), InstallableUnit.MEMBER_PROVIDED_CAPABILITIES); |
| allVersionsExpression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual))); |
| strictVersionExpression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionEqual))); |
| openEndedExpression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGtEqual))); |
| openEndedNonInclusiveExpression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGt))); |
| range_II_Expression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGtEqual, versionLtEqual))); |
| range_IN_Expression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGtEqual, versionLt))); |
| range_NI_Expression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGt, versionLtEqual))); |
| range_NN_Expression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGt, versionLt))); |
| } |
| |
| private static IMatchExpression<IInstallableUnit> createMatchExpressionFromRange(String namespace, String name, VersionRange range) { |
| IMatchExpression<IInstallableUnit> resultExpression = null; |
| IExpressionFactory factory = ExpressionUtil.getFactory(); |
| if (range == null || range.equals(VersionRange.emptyRange)) { |
| resultExpression = factory.matchExpression(allVersionsExpression, name, namespace); |
| } else { |
| if (range.getMinimum().equals(range.getMaximum())) { |
| // Explicit version appointed |
| resultExpression = factory.matchExpression(strictVersionExpression, name, namespace, range.getMinimum()); |
| } else { |
| if (range.getMaximum().equals(Version.MAX_VERSION)) { |
| // Open ended |
| resultExpression = factory.matchExpression(range.getIncludeMinimum() ? openEndedExpression : openEndedNonInclusiveExpression, name, namespace, range.getMinimum()); |
| } else { |
| resultExpression = factory.matchExpression(// |
| range.getIncludeMinimum() ? (range.getIncludeMaximum() ? range_II_Expression : range_IN_Expression) // |
| : (range.getIncludeMaximum() ? range_NI_Expression : range_NN_Expression), // |
| name, namespace, range.getMinimum(), range.getMaximum()); |
| } |
| } |
| } |
| return resultExpression; |
| } |
| |
| private static ITouchpointType getCachedTouchpointType(String id, Version version) { |
| for (int i = 0; i < typeCache.length; i++) { |
| if (typeCache[i] != null && typeCache[i].getId().equals(id) && typeCache[i].getVersion().equals(version)) |
| return typeCache[i]; |
| } |
| return null; |
| } |
| |
| private static void putCachedTouchpointType(ITouchpointType result) { |
| //simple rotating buffer |
| typeCache[typeCacheOffset] = result; |
| typeCacheOffset = (typeCacheOffset + 1) % typeCache.length; |
| } |
| } |