/*******************************************************************************
 * Copyright (c) 2009, 2020 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
 ******************************************************************************/
package org.eclipse.equinox.p2.publisher;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitFragmentDescription;
import org.eclipse.equinox.p2.metadata.expression.*;
import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;

public class AdviceFileParser {

	private static final String ADVICE_VERSION = "advice.version"; //$NON-NLS-1$

	private static final String QUALIFIER_SUBSTITUTION = "$qualifier$"; //$NON-NLS-1$
	private static final String VERSION_SUBSTITUTION = "$version$"; //$NON-NLS-1$

	private static final String UPDATE_DESCRIPTION = "update.description"; //$NON-NLS-1$
	private static final String UPDATE_SEVERITY = "update.severity"; //$NON-NLS-1$
	private static final String UPDATE_RANGE = "update.range"; //$NON-NLS-1$
	private static final String UPDATE_ID = "update.id"; //$NON-NLS-1$
	private static final String UPDATE_MATCH_EXP = "update.matchExp"; //$NON-NLS-1$
	private static final String CLASSIFIER = "classifier"; //$NON-NLS-1$
	private static final String TOUCHPOINT_VERSION = "touchpoint.version"; //$NON-NLS-1$
	private static final String TOUCHPOINT_ID = "touchpoint.id"; //$NON-NLS-1$
	private static final String COPYRIGHT_LOCATION = "copyright.location"; //$NON-NLS-1$
	private static final String COPYRIGHT = "copyright"; //$NON-NLS-1$
	private static final String ID = "id"; //$NON-NLS-1$
	private static final String SINGLETON = "singleton"; //$NON-NLS-1$
	private static final String IMPORT = "import"; //$NON-NLS-1$
	private static final String RANGE = "range"; //$NON-NLS-1$
	private static final String MIN = "min"; //$NON-NLS-1$
	private static final String MAX = "max"; //$NON-NLS-1$
	private static final String FILTER = "filter"; //$NON-NLS-1$
	private static final String MULTIPLE = "multiple"; //$NON-NLS-1$
	private static final String OPTIONAL = "optional"; //$NON-NLS-1$
	private static final String GREEDY = "greedy"; //$NON-NLS-1$
	private static final String VERSION = "version"; //$NON-NLS-1$
	private static final String NAMESPACE = "namespace"; //$NON-NLS-1$
	private static final String NAME = "name"; //$NON-NLS-1$
	private static final String MATCH_EXP = "matchExp"; //$NON-NLS-1$
	private static final String LOCATION = "location"; //$NON-NLS-1$
	private static final String VALUE = "value"; //$NON-NLS-1$

	private static final String UNITS_PREFIX = "units."; //$NON-NLS-1$
	private static final String INSTRUCTIONS_PREFIX = "instructions."; //$NON-NLS-1$
	private static final String REQUIRES_PREFIX = "requires."; //$NON-NLS-1$
	private static final String META_REQUIREMENTS_PREFIX = "metaRequirements."; //$NON-NLS-1$
	private static final String PROVIDES_PREFIX = "provides."; //$NON-NLS-1$
	private static final String PROPERTIES_PREFIX = "properties."; //$NON-NLS-1$
	private static final String LICENSES_PREFIX = "licenses."; //$NON-NLS-1$
	private static final String ARTIFACTS_PREFIX = "artifacts."; //$NON-NLS-1$
	private static final String HOST_REQUIREMENTS_PREFIX = "hostRequirements."; //$NON-NLS-1$
	private static final String UPDATE_DESCRIPTOR_PREFIX = "update."; //$NON-NLS-1$

	public static final Version COMPATIBLE_VERSION = Version.createOSGi(1, 0, 0);
	public static final VersionRange VERSION_TOLERANCE = new VersionRange(COMPATIBLE_VERSION, true,
			Version.createOSGi(2, 0, 0), false);

	private Map<String, String> adviceProperties = new HashMap<>();
	private List<IProvidedCapability> adviceProvides = new ArrayList<>();
	private List<IRequirement> adviceRequires = new ArrayList<>();
	private List<IRequirement> adviceMetaRequires = new ArrayList<>();
	private IUpdateDescriptor adviceUpdateDescriptor = null;
	private Map<String, ITouchpointInstruction> adviceInstructions = new HashMap<>();
	private List<InstallableUnitDescription> adviceOtherIUs = new ArrayList<>();

	private final Map<String, String> advice;
	private Iterator<String> keysIterator;
	private String current;
	private String hostId;
	private Version hostVersion;

	public AdviceFileParser(String id, Version version, Map<String, String> advice) {
		this.hostId = id;
		this.hostVersion = version;
		this.advice = advice;
	}

	public void parse() {
		String adviceVersion = advice.get(ADVICE_VERSION);
		if (adviceVersion != null)
			checkAdviceVersion(adviceVersion);

		List<String> keys = new ArrayList<>(advice.keySet());
		keys.sort(null);

		keysIterator = keys.iterator();
		next();

		while (current != null) {
			if (current.startsWith(PROPERTIES_PREFIX))
				parseProperties(PROPERTIES_PREFIX, adviceProperties);
			else if (current.startsWith(UPDATE_DESCRIPTOR_PREFIX))
				this.adviceUpdateDescriptor = parseUpdateDescriptor(UPDATE_DESCRIPTOR_PREFIX, hostId);
			else if (current.startsWith(PROVIDES_PREFIX))
				parseProvides(PROVIDES_PREFIX, adviceProvides);
			else if (current.startsWith(REQUIRES_PREFIX))
				parseRequires(REQUIRES_PREFIX, adviceRequires);
			else if (current.startsWith(META_REQUIREMENTS_PREFIX))
				parseRequires(META_REQUIREMENTS_PREFIX, adviceMetaRequires);
			else if (current.startsWith(INSTRUCTIONS_PREFIX))
				parseInstructions(INSTRUCTIONS_PREFIX, adviceInstructions);
			else if (current.startsWith(UNITS_PREFIX))
				parseUnits(UNITS_PREFIX, adviceOtherIUs);
			else if (current.equals(ADVICE_VERSION)) {
				next();
			} else {
				// we ignore elements we do not understand
				next();
			}
		}
	}

	private void checkAdviceVersion(String adviceVersion) {
		Version version = Version.parseVersion(adviceVersion);
		if (!VERSION_TOLERANCE.isIncluded(version))
			throw new IllegalStateException("bad version: " + version + ". Expected range was " + VERSION_TOLERANCE); //$NON-NLS-1$ //$NON-NLS-2$
	}

	private void next() {
		current = keysIterator.hasNext() ? keysIterator.next() : null;
	}

	private String currentValue() {
		return advice.get(current).trim();
	}

	private void parseProperties(String prefix, Map<String, String> properties) {
		while (current != null && current.startsWith(prefix)) {
			int dotIndex = current.indexOf('.', prefix.length());
			if (dotIndex == -1)
				throw new IllegalStateException("bad token: " + current); //$NON-NLS-1$

			parseProperty(current.substring(0, dotIndex + 1), properties);
		}
	}

	private void parseProperty(String prefix, Map<String, String> properties) {
		String propertyName = null;
		String propertyValue = null;
		while (current != null && current.startsWith(prefix)) {
			String token = current.substring(prefix.length());
			switch (token) {
			case NAME:
				propertyName = currentValue();
				break;
			case VALUE:
				propertyValue = currentValue();
				break;
			// we ignore elements we do not understand
			default:
				break;
			}
			next();
		}

		properties.put(propertyName, propertyValue);
	}

	private IUpdateDescriptor parseUpdateDescriptor(String prefix, String id) {
		String name = id;
		String description = null;
		String range = "[0.0.0,$version$)"; //$NON-NLS-1$
		String severity = "0"; //$NON-NLS-1$
		String match = null;

		while (current != null && current.startsWith(prefix)) {
			String token = current;
			switch (token) {
			case UPDATE_MATCH_EXP:
				match = currentValue();
				break;
			case UPDATE_ID:
				name = currentValue();
				break;
			case UPDATE_DESCRIPTION:
				description = currentValue();
				break;
			case UPDATE_RANGE:
				range = currentValue();
				break;
			case UPDATE_SEVERITY:
				severity = currentValue();
				break;
			// ignore
			default:
				break;
			}
			next();
		}

		if (match != null) {
			// When update.match is specified, versionRange and id are ignored
			IExpression expr = ExpressionUtil.parse(substituteVersionAndQualifier(match));
			IMatchExpression<IInstallableUnit> matchExpression = ExpressionUtil.getFactory().matchExpression(expr);
			Collection<IMatchExpression<IInstallableUnit>> descriptors = new ArrayList<>(1);
			descriptors.add(matchExpression);
			return MetadataFactory.createUpdateDescriptor(descriptors, Integer.valueOf(severity), description,
					(URI) null);
		}
		range = substituteVersionAndQualifier(range);
		VersionRange versionRange = VersionRange.create(range);
		return MetadataFactory.createUpdateDescriptor(name, versionRange, Integer.valueOf(severity), description);
	}

	private void parseProvides(String prefix, List<IProvidedCapability> provides) {
		while (current != null && current.startsWith(prefix)) {
			int dotIndex = current.indexOf('.', prefix.length());
			if (dotIndex == -1)
				throw new IllegalStateException("bad token: " + current); //$NON-NLS-1$

			parseProvided(current.substring(0, dotIndex + 1), provides);
		}
	}

	private void parseProvided(String prefix, List<IProvidedCapability> provides) {
		String namespace = null;
		String name = null;
		Version capabilityVersion = null;
		while (current != null && current.startsWith(prefix)) {
			String token = current.substring(prefix.length());
			switch (token) {
			case NAME:
				name = currentValue();
				break;
			case NAMESPACE:
				namespace = currentValue();
				break;
			case VERSION:
				capabilityVersion = Version.parseVersion(substituteVersionAndQualifier(currentValue()));
				break;
			// we ignore elements we do not understand
			default:
				break;
			}
			next();
		}

		IProvidedCapability capability = MetadataFactory.createProvidedCapability(namespace, name, capabilityVersion);
		provides.add(capability);
	}

	private void parseRequires(String prefix, List<IRequirement> requires) {
		while (current != null && current.startsWith(prefix)) {
			int dotIndex = current.indexOf('.', prefix.length());
			if (dotIndex == -1)
				throw new IllegalStateException("bad token: " + current); //$NON-NLS-1$

			parseRequired(current.substring(0, dotIndex + 1), requires);
		}
	}

	private void parseRequired(String prefix, List<IRequirement> requires) {

		String namespace = null;
		String name = null;
		VersionRange range = null;
		String matchExp = null;
		String filter = null;
		boolean optional = false;
		boolean multiple = false;
		boolean greedy = true;

		int min = -1;
		int max = -1;

		while (current != null && current.startsWith(prefix)) {
			String token = current.substring(prefix.length());
			switch (token) {
			case GREEDY:
				greedy = Boolean.parseBoolean(currentValue());
				break;
			case OPTIONAL:
				optional = Boolean.parseBoolean(currentValue());
				break;
			case MULTIPLE:
				multiple = Boolean.parseBoolean(currentValue());
				break;
			case FILTER:
				filter = currentValue();
				break;
			case NAME:
				name = currentValue();
				break;
			case NAMESPACE:
				namespace = currentValue();
				break;
			case RANGE:
				range = VersionRange.create(substituteVersionAndQualifier(currentValue()));
				break;
			case MIN:
				min = Integer.valueOf(currentValue()).intValue();
				break;
			case MAX:
				max = Integer.valueOf(currentValue()).intValue();
				break;
			case MATCH_EXP:
				matchExp = currentValue();
				break;
			// we ignore elements we do not understand
			default:
				break;
			}
			next();
		}
		IRequirement capability = null;
		if (matchExp == null) {
			if (min >= 0 && max >= 0) {
				capability = createRequirement(namespace, name, range, filter, min, max, greedy);
			} else {
				capability = createRequirement(namespace, name, range, filter, optional, multiple, greedy);
			}
		} else {
			// When a match expression is specified, namespace, name and versionRange are
			// ignored
			if (optional && min == -1 && max == -1) {
				min = 0;
				max = 1;
			}
			capability = createRequirement(matchExp, filter, min, max, greedy, null);
		}
		if (capability != null) {
			requires.add(capability);
		}
	}

	protected IRequirement createRequirement(String requirement, String filter, int min, int max, boolean greedy,
			String description) {
		IExpression expr = ExpressionUtil.parse(substituteVersionAndQualifier(requirement));
		IMatchExpression<IInstallableUnit> requirementExp = ExpressionUtil.getFactory().matchExpression(expr);
		IMatchExpression<IInstallableUnit> filterExp = InstallableUnit.parseFilter(filter);
		return MetadataFactory.createRequirement(requirementExp, filterExp, min, max, greedy, description);
	}

	protected IRequirement createRequirement(String namespace, String name, VersionRange range, String filter, int min,
			int max, boolean greedy) {
		IMatchExpression<IInstallableUnit> filterExpression = InstallableUnit.parseFilter(filter);
		return MetadataFactory.createRequirement(namespace, name, range, filterExpression, min, max, greedy);
	}

	protected IRequirement createRequirement(String namespace, String name, VersionRange range, String filter,
			boolean optional, boolean multiple, boolean greedy) {
		return MetadataFactory.createRequirement(namespace, name, range, filter, optional, multiple, greedy);
	}

	private void parseInstructions(String prefix, Map<String, ITouchpointInstruction> instructions) {
		while (current != null && current.startsWith(prefix)) {
			int dotIndex = current.indexOf('.', prefix.length());
			if (dotIndex != -1)
				throw new IllegalStateException("bad token: " + current); //$NON-NLS-1$

			parseInstruction(current, instructions);
		}
	}

	private void parseInstruction(String prefix, Map<String, ITouchpointInstruction> instructions) {
		String phase = current.substring(current.lastIndexOf('.') + 1);
		String body = currentValue();
		next();

		prefix += '.';
		String importAttribute = null;
		if (current != null && current.startsWith(prefix)) {
			if (current.substring(prefix.length()).equals(IMPORT)) {
				importAttribute = currentValue();
			} else {
				// we ignore elements we do not understand
			}
			next();
		}
		ITouchpointInstruction instruction = MetadataFactory.createTouchpointInstruction(body, importAttribute);
		instructions.put(phase, instruction);
	}

	private void parseUnits(String prefix, List<InstallableUnitDescription> ius) {
		while (current != null && current.startsWith(prefix)) {
			int dotIndex = current.indexOf('.', prefix.length());
			if (dotIndex == -1)
				throw new IllegalStateException("bad token: " + current + " = " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$

			parseUnit(current.substring(0, dotIndex + 1), ius);
		}
	}

	private void parseUnit(String prefix, List<InstallableUnitDescription> units) {
		String unitId = null;
		Version unitVersion = null;
		boolean unitSingleton = false;
		String unitFilter = null;
		String unitCopyright = null;
		String unitCopyrightLocation = null;
		String unitTouchpointId = null;
		Version unitTouchpointVersion = null;

		String unitUpdateId = null;
		VersionRange unitUpdateRange = null;
		int unitUpdateSeverity = 0;
		String unitUpdateDescription = null;

		List<IArtifactKey> unitArtifacts = new ArrayList<>();
		Map<String, String> unitProperties = new HashMap<>();
		List<IRequirement> unitHostRequirements = new ArrayList<>();
		List<IProvidedCapability> unitProvides = new ArrayList<>();
		List<IRequirement> unitRequires = new ArrayList<>();
		List<IRequirement> unitMetaRequirements = new ArrayList<>();
		List<ILicense> unitLicenses = new ArrayList<>();
		Map<String, ITouchpointInstruction> unitInstructions = new HashMap<>();
		// updatedescriptor ??

		while (current != null && current.startsWith(prefix)) {
			String token = current.substring(prefix.length());
			if (token.equals(ID)) {
				unitId = currentValue();
				next();
			} else if (token.equals(VERSION)) {
				unitVersion = Version.parseVersion(substituteVersionAndQualifier(currentValue()));
				next();
			} else if (token.equals(SINGLETON)) {
				unitSingleton = Boolean.parseBoolean(currentValue());
				next();
			} else if (token.equals(FILTER)) {
				unitFilter = currentValue();
				next();
			} else if (token.equals(COPYRIGHT)) {
				unitCopyright = currentValue();
				next();
			} else if (token.equals(COPYRIGHT_LOCATION)) {
				unitCopyrightLocation = currentValue();
				next();
			} else if (token.equals(TOUCHPOINT_ID)) {
				unitTouchpointId = currentValue();
				next();
			} else if (token.equals(TOUCHPOINT_VERSION)) {
				unitTouchpointVersion = Version.parseVersion(substituteVersionAndQualifier(currentValue()));
				next();
			} else if (token.equals(UPDATE_ID)) {
				unitUpdateId = currentValue();
				next();
			} else if (token.equals(UPDATE_RANGE)) {
				unitUpdateRange = VersionRange.create(substituteVersionAndQualifier(currentValue()));
				next();
			} else if (token.equals(UPDATE_SEVERITY)) {
				unitUpdateSeverity = Integer.parseInt(currentValue());
				next();
			} else if (token.equals(UPDATE_DESCRIPTION)) {
				unitUpdateDescription = currentValue();
				next();
			} else if (token.startsWith(HOST_REQUIREMENTS_PREFIX))
				parseRequires(prefix + HOST_REQUIREMENTS_PREFIX, unitHostRequirements);
			else if (token.startsWith(ARTIFACTS_PREFIX))
				parseArtifacts(prefix + ARTIFACTS_PREFIX, unitArtifacts);
			else if (token.startsWith(LICENSES_PREFIX))
				parseLicenses(prefix + LICENSES_PREFIX, unitLicenses);
			else if (token.startsWith(PROPERTIES_PREFIX))
				parseProperties(prefix + PROPERTIES_PREFIX, unitProperties);
			else if (token.startsWith(PROVIDES_PREFIX))
				parseProvides(prefix + PROVIDES_PREFIX, unitProvides);
			else if (token.startsWith(REQUIRES_PREFIX))
				parseRequires(prefix + REQUIRES_PREFIX, unitRequires);
			else if (token.startsWith(META_REQUIREMENTS_PREFIX))
				parseRequires(prefix + META_REQUIREMENTS_PREFIX, unitMetaRequirements);
			else if (token.startsWith(INSTRUCTIONS_PREFIX))
				parseInstructions(prefix + INSTRUCTIONS_PREFIX, unitInstructions);
			else {
				// we ignore elements we do not understand
				next();
			}
		}

		InstallableUnitDescription description = unitHostRequirements.isEmpty() ? new InstallableUnitDescription()
				: new InstallableUnitFragmentDescription();
		description.setId(unitId);
		description.setVersion(unitVersion);
		description.setSingleton(unitSingleton);
		description.setFilter(unitFilter);
		if (unitCopyright != null || unitCopyrightLocation != null) {
			try {
				URI uri = unitCopyrightLocation != null ? new URI(unitCopyrightLocation) : null;
				description.setCopyright(MetadataFactory.createCopyright(uri, unitCopyright));
			} catch (URISyntaxException e) {
				throw new IllegalStateException("bad copyright URI at token: " + current + ", " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
		if (unitTouchpointId != null)
			description
					.setTouchpointType(MetadataFactory.createTouchpointType(unitTouchpointId, unitTouchpointVersion));

		if (unitUpdateId != null)
			description.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(unitUpdateId, unitUpdateRange,
					unitUpdateSeverity, unitUpdateDescription));

		if (!unitLicenses.isEmpty())
			description.setLicenses(unitLicenses.toArray(new ILicense[unitLicenses.size()]));

		if (!unitArtifacts.isEmpty())
			description.setArtifacts(unitArtifacts.toArray(new IArtifactKey[unitArtifacts.size()]));

		if (!unitHostRequirements.isEmpty())
			((InstallableUnitFragmentDescription) description)
					.setHost(unitHostRequirements.toArray(new IRequirement[unitHostRequirements.size()]));

		if (!unitProperties.isEmpty()) {
			for (Entry<String, String> entry : unitProperties.entrySet()) {
				description.setProperty(entry.getKey(), entry.getValue());
			}
		}

		if (!unitProvides.isEmpty())
			description.setCapabilities(unitProvides.toArray(new IProvidedCapability[unitProvides.size()]));

		if (!unitRequires.isEmpty())
			description.setRequirements(unitRequires.toArray(new IRequirement[unitRequires.size()]));

		if (!unitMetaRequirements.isEmpty())
			description
					.setMetaRequirements(unitMetaRequirements.toArray(new IRequirement[unitMetaRequirements.size()]));

		if (!unitInstructions.isEmpty())
			description.addTouchpointData(MetadataFactory.createTouchpointData(unitInstructions));

		adviceOtherIUs.add(description);
	}

	private void parseLicenses(String prefix, List<ILicense> licenses) {
		while (current != null && current.startsWith(prefix)) {
			int dotIndex = current.indexOf('.', prefix.length());
			if (dotIndex != -1)
				throw new IllegalStateException("bad token: " + current + " = " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$

			parseLicense(current, licenses);
		}
	}

	private void parseLicense(String prefix, List<ILicense> licenses) {
		String body = currentValue();
		next();

		prefix += '.';
		String location = null;
		if (current != null && current.startsWith(prefix)) {
			if (current.substring(prefix.length()).equals(LOCATION)) {
				location = currentValue();
			} else {
				// we ignore elements we do not understand
			}
			next();
		}

		try {
			URI uri = location != null ? new URI(location) : null;
			ILicense license = MetadataFactory.createLicense(uri, body);
			licenses.add(license);
		} catch (URISyntaxException e) {
			throw new IllegalStateException("bad license URI at token: " + current + ", " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	private void parseArtifacts(String prefix, List<IArtifactKey> artifacts) {
		while (current != null && current.startsWith(prefix)) {
			int dotIndex = current.indexOf('.', prefix.length());
			if (dotIndex == -1)
				throw new IllegalStateException("bad token: " + current + " = " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$

			parseArtifact(current.substring(0, dotIndex + 1), artifacts);
		}
	}

	private void parseArtifact(String prefix, List<IArtifactKey> artifacts) {
		String artifactClassifier = null;
		String artifactId = null;
		Version artifactVersion = null;
		while (current != null && current.startsWith(prefix)) {
			String token = current.substring(prefix.length());
			switch (token) {
			case CLASSIFIER:
				artifactClassifier = currentValue();
				break;
			case ID:
				artifactId = currentValue();
				break;
			case VERSION:
				artifactVersion = Version.parseVersion(substituteVersionAndQualifier(currentValue()));
				break;
			// we ignore elements we do not understand
			default:
				break;
			}

			next();
		}
		IArtifactKey artifactKey = new ArtifactKey(artifactClassifier, artifactId, artifactVersion);
		artifacts.add(artifactKey);
	}

	private String substituteVersionAndQualifier(String version) {
		if (version.contains(VERSION_SUBSTITUTION)) {
			version = replace(version, VERSION_SUBSTITUTION, hostVersion.toString());
		}

		if (version.contains(QUALIFIER_SUBSTITUTION)) {
			try {
				String qualifier = PublisherHelper.toOSGiVersion(hostVersion).getQualifier();
				if (qualifier == null)
					qualifier = ""; //$NON-NLS-1$
				if (qualifier.length() == 0) {
					// Note: this works only for OSGi versions and version ranges
					// where the qualifier if present must be at the end of a version string
					version = replace(version, "." + QUALIFIER_SUBSTITUTION, ""); //$NON-NLS-1$ //$NON-NLS-2$
				}
				version = replace(version, QUALIFIER_SUBSTITUTION, qualifier);
			} catch (UnsupportedOperationException e) {
				// Version cannot be converted to OSGi
			}
		}
		return version;
	}

	// originally from org.eclipse.core.internal.net.StringUtil
	public static String replace(String source, String from, String to) {
		if (from.length() == 0)
			return source;
		StringBuilder buffer = new StringBuilder();
		int current = 0;
		int pos = 0;
		while (pos != -1) {
			pos = source.indexOf(from, current);
			if (pos == -1) {
				buffer.append(source.substring(current));
			} else {
				buffer.append(source.substring(current, pos));
				buffer.append(to);
				current = pos + from.length();
			}
		}
		return buffer.toString();
	}

	public Map<String, String> getProperties() {
		if (adviceProperties.isEmpty())
			return null;
		return adviceProperties;
	}

	public IRequirement[] getRequiredCapabilities() {
		if (adviceRequires.isEmpty())
			return null;

		return adviceRequires.toArray(new IRequirement[adviceRequires.size()]);
	}

	public IProvidedCapability[] getProvidedCapabilities() {
		if (adviceProvides.isEmpty())
			return null;

		return adviceProvides.toArray(new IProvidedCapability[adviceProvides.size()]);
	}

	public IUpdateDescriptor getUpdateDescriptor() {
		return adviceUpdateDescriptor;
	}

	public Map<String, ITouchpointInstruction> getTouchpointInstructions() {
		if (adviceInstructions.isEmpty())
			return null;

		return adviceInstructions;
	}

	public InstallableUnitDescription[] getAdditionalInstallableUnitDescriptions() {
		if (adviceOtherIUs.isEmpty())
			return null;

		return adviceOtherIUs.toArray(new InstallableUnitDescription[adviceOtherIUs.size()]);
	}

	public IRequirement[] getMetaRequiredCapabilities() {
		if (adviceMetaRequires.isEmpty())
			return null;

		return adviceMetaRequires.toArray(new IRequirement[adviceMetaRequires.size()]);
	}
}
