/*******************************************************************************
 * Copyright (c) 2007, 2017 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 - added license support
 *		EclipseSource - ongoing development
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata.repository.io;

import static java.util.stream.Collectors.toList;

import java.net.URI;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties;
import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
import org.eclipse.equinox.internal.p2.persistence.XMLParser;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.MetadataFactory.*;
import org.eclipse.equinox.p2.metadata.expression.*;
import org.eclipse.equinox.p2.repository.IRepositoryReference;
import org.eclipse.equinox.p2.repository.spi.RepositoryReference;
import org.osgi.framework.BundleContext;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;

public abstract class MetadataParser extends XMLParser implements XMLConstants {
	static final ILicense[] NO_LICENSES = new ILicense[0];

	public MetadataParser(BundleContext context, String bundleId) {
		super(context, bundleId);
	}

	protected abstract class AbstractMetadataHandler extends AbstractHandler {

		public AbstractMetadataHandler(ContentHandler parentHandler, String elementHandled) {
			super(parentHandler, elementHandled);
		}

		int getOptionalSize(Attributes attributes, int dflt) {
			String sizeStr = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
			return sizeStr != null ? Integer.parseInt(sizeStr) : dflt;
		}
	}

	protected class RepositoryReferencesHandler extends AbstractMetadataHandler {
		private HashSet<IRepositoryReference> references;

		public RepositoryReferencesHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, REPOSITORY_REFERENCES_ELEMENT);
			references = new HashSet<>(getOptionalSize(attributes, 4));
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(REPOSITORY_REFERENCE_ELEMENT)) {
				new RepositoryReferenceHandler(this, attributes, references);
			} else {
				invalidElement(name, attributes);
			}
		}

		public IRepositoryReference[] getReferences() {
			return references.toArray(new IRepositoryReference[references.size()]);
		}
	}

	protected class RepositoryReferenceHandler extends AbstractHandler {

		private final String[] required = new String[] {TYPE_ATTRIBUTE, OPTIONS_ATTRIBUTE};

		public RepositoryReferenceHandler(AbstractHandler parentHandler, Attributes attributes, Set<IRepositoryReference> references) {
			super(parentHandler, REPOSITORY_REFERENCE_ELEMENT);
			String[] values = parseRequiredAttributes(attributes, required);
			String name = parseOptionalAttribute(attributes, NAME_ATTRIBUTE);
			int type = checkInteger(elementHandled, TYPE_ATTRIBUTE, values[0]);
			int options = checkInteger(elementHandled, OPTIONS_ATTRIBUTE, values[1]);
			URI location = parseURIAttribute(attributes, true);
			if (location != null)
				references.add(new RepositoryReference(location, name, type, options));
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			invalidElement(name, attributes);
		}
	}

	protected class InstallableUnitsHandler extends AbstractMetadataHandler {
		private ArrayList<InstallableUnitDescription> units;

		public InstallableUnitsHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, INSTALLABLE_UNITS_ELEMENT);
			units = new ArrayList<>(getOptionalSize(attributes, 4));
		}

		public IInstallableUnit[] getUnits() {
			int size = units.size();
			IInstallableUnit[] result = new IInstallableUnit[size];
			int i = 0;
			for (InstallableUnitDescription desc : units)
				result[i++] = MetadataFactory.createInstallableUnit(desc);
			return result;
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(INSTALLABLE_UNIT_ELEMENT)) {
				new InstallableUnitHandler(this, attributes, units);
			} else {
				invalidElement(name, attributes);
			}
		}
	}

	protected class InstallableUnitHandler extends AbstractHandler {

		InstallableUnitDescription currentUnit = null;

		private PropertiesHandler propertiesHandler = null;
		private ProvidedCapabilitiesHandler providedCapabilitiesHandler = null;
		private RequirementsHandler requiredCapabilitiesHandler = null;
		private HostRequiredCapabilitiesHandler hostRequiredCapabilitiesHandler = null;
		private MetaRequiredCapabilitiesHandler metaRequiredCapabilitiesHandler = null;
		private TextHandler filterHandler = null;
		private ArtifactsHandler artifactsHandler = null;
		private TouchpointTypeHandler touchpointTypeHandler = null;
		private TouchpointDataHandler touchpointDataHandler = null;
		private UpdateDescriptorHandler updateDescriptorHandler = null;
		private LicensesHandler licensesHandler = null;
		private CopyrightHandler copyrightHandler = null;
		private RequirementsChangeHandler requirementChangesHandler = null;
		private ApplicabilityScopesHandler applicabilityScopeHandler = null;
		private LifeCycleHandler lifeCycleHandler;

		private String id;
		private Version version;
		private boolean singleton;

		private List<InstallableUnitDescription> units;

		public InstallableUnitHandler(AbstractHandler parentHandler, Attributes attributes, List<InstallableUnitDescription> units) {
			super(parentHandler, INSTALLABLE_UNIT_ELEMENT);
			String[] values = parseAttributes(attributes, REQUIRED_IU_ATTRIBUTES, OPTIONAL_IU_ATTRIBUTES);
			this.units = units;
			//skip entire IU if the id is missing
			if (values[0] == null)
				return;

			id = values[0];
			version = checkVersion(INSTALLABLE_UNIT_ELEMENT, VERSION_ATTRIBUTE, values[1]);
			singleton = checkBoolean(INSTALLABLE_UNIT_ELEMENT, SINGLETON_ATTRIBUTE, values[2], true).booleanValue();
		}

		public IInstallableUnit getInstallableUnit() {
			return MetadataFactory.createInstallableUnit(currentUnit);
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			checkCancel();
			if (PROPERTIES_ELEMENT.equals(name)) {
				if (propertiesHandler == null) {
					propertiesHandler = new PropertiesHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (PROVIDED_CAPABILITIES_ELEMENT.equals(name)) {
				if (providedCapabilitiesHandler == null) {
					providedCapabilitiesHandler = new ProvidedCapabilitiesHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (REQUIREMENTS_ELEMENT.equals(name)) {
				if (requiredCapabilitiesHandler == null) {
					requiredCapabilitiesHandler = new RequirementsHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (HOST_REQUIREMENTS_ELEMENT.equals(name)) {
				if (hostRequiredCapabilitiesHandler == null) {
					hostRequiredCapabilitiesHandler = new HostRequiredCapabilitiesHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (META_REQUIREMENTS_ELEMENT.equals(name)) {
				if (metaRequiredCapabilitiesHandler == null) {
					metaRequiredCapabilitiesHandler = new MetaRequiredCapabilitiesHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (IU_FILTER_ELEMENT.equals(name)) {
				if (filterHandler == null) {
					filterHandler = new TextHandler(this, IU_FILTER_ELEMENT, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (ARTIFACT_KEYS_ELEMENT.equals(name)) {
				if (artifactsHandler == null) {
					artifactsHandler = new ArtifactsHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (TOUCHPOINT_TYPE_ELEMENT.equals(name)) {
				if (touchpointTypeHandler == null) {
					touchpointTypeHandler = new TouchpointTypeHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (TOUCHPOINT_DATA_ELEMENT.equals(name)) {
				if (touchpointDataHandler == null) {
					touchpointDataHandler = new TouchpointDataHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (UPDATE_DESCRIPTOR_ELEMENT.equals(name)) {
				if (updateDescriptorHandler == null)
					updateDescriptorHandler = new UpdateDescriptorHandler(this, attributes);
				else {
					duplicateElement(this, name, attributes);
				}
			} else if (LICENSES_ELEMENT.equals(name)) {
				if (licensesHandler == null) {
					licensesHandler = new LicensesHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (REQUIREMENT_CHANGES.equals(name)) {
				if (requirementChangesHandler == null) {
					requirementChangesHandler = new RequirementsChangeHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (APPLICABILITY_SCOPE.equals(name)) {
				if (applicabilityScopeHandler == null) {
					applicabilityScopeHandler = new ApplicabilityScopesHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (LIFECYCLE.equals(name)) {
				if (lifeCycleHandler == null) {
					lifeCycleHandler = new LifeCycleHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else if (COPYRIGHT_ELEMENT.equals(name)) {
				if (copyrightHandler == null) {
					copyrightHandler = new CopyrightHandler(this, attributes);
				} else {
					duplicateElement(this, name, attributes);
				}
			} else {
				invalidElement(name, attributes);
			}
		}

		@Override
		protected void finished() {
			if (isValidXML()) {
				if (requirementChangesHandler != null) {
					currentUnit = new MetadataFactory.InstallableUnitPatchDescription();
					((InstallableUnitPatchDescription) currentUnit).setRequirementChanges(requirementChangesHandler.getRequirementChanges().toArray(new IRequirementChange[requirementChangesHandler.getRequirementChanges().size()]));
					if (applicabilityScopeHandler != null)
						((InstallableUnitPatchDescription) currentUnit).setApplicabilityScope(applicabilityScopeHandler.getScope());
					if (lifeCycleHandler != null)
						((InstallableUnitPatchDescription) currentUnit).setLifeCycle(lifeCycleHandler.getLifeCycleRequirement());
				} else if (hostRequiredCapabilitiesHandler == null || hostRequiredCapabilitiesHandler.getHostRequiredCapabilities().length == 0) {
					currentUnit = new InstallableUnitDescription();
				} else {
					currentUnit = new MetadataFactory.InstallableUnitFragmentDescription();
					((InstallableUnitFragmentDescription) currentUnit).setHost(hostRequiredCapabilitiesHandler.getHostRequiredCapabilities());
				}
				currentUnit.setId(id);
				currentUnit.setVersion(version);
				currentUnit.setSingleton(singleton);
				OrderedProperties properties = (propertiesHandler == null ? new OrderedProperties(0) : propertiesHandler.getProperties());
				String updateFrom = null;
				VersionRange updateRange = null;
				for (Entry<String, String> e : properties.entrySet()) {
					String key = e.getKey();
					String value = e.getValue();
					//Backward compatibility
					if (key.equals("equinox.p2.update.from")) { //$NON-NLS-1$
						updateFrom = value;
						continue;
					}
					if (key.equals("equinox.p2.update.range")) { //$NON-NLS-1$
						updateRange = VersionRange.create(value);
						continue;
					}
					//End of backward compatibility
					currentUnit.setProperty(key, value);
				}
				//Backward compatibility
				if (updateFrom != null && updateRange != null)
					currentUnit.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(updateFrom, updateRange, IUpdateDescriptor.NORMAL, null));
				//End of backward compatibility

				if (licensesHandler != null) {
					currentUnit.setLicenses(licensesHandler.getLicenses());
				}

				if (copyrightHandler != null) {
					ICopyright copyright = copyrightHandler.getCopyright();
					currentUnit.setCopyright(copyright);
				}

				IProvidedCapability[] providedCapabilities = (providedCapabilitiesHandler == null ? new IProvidedCapability[0] : providedCapabilitiesHandler.getProvidedCapabilities());
				currentUnit.setCapabilities(providedCapabilities);
				IRequirement[] requiredCapabilities = (requiredCapabilitiesHandler == null ? new IRequirement[0] : requiredCapabilitiesHandler.getRequirements());
				currentUnit.setRequirements(requiredCapabilities);
				IRequirement[] metaRequiredCapabilities = (metaRequiredCapabilitiesHandler == null ? new IRequirement[0] : metaRequiredCapabilitiesHandler.getMetaRequiredCapabilities());
				currentUnit.setMetaRequirements(metaRequiredCapabilities);
				if (filterHandler != null) {
					currentUnit.setFilter(filterHandler.getText());
				}
				IArtifactKey[] artifacts = (artifactsHandler == null ? new IArtifactKey[0] : artifactsHandler.getArtifactKeys());
				currentUnit.setArtifacts(artifacts);
				if (touchpointTypeHandler != null) {
					currentUnit.setTouchpointType(touchpointTypeHandler.getTouchpointType());
				} else {
					// TODO: create an error
				}
				ITouchpointData[] touchpointData = (touchpointDataHandler == null ? new ITouchpointData[0] : touchpointDataHandler.getTouchpointData());
				for (ITouchpointData touchpointData1 : touchpointData) {
					currentUnit.addTouchpointData(touchpointData1);
				}
				if (updateDescriptorHandler != null)
					currentUnit.setUpdateDescriptor(updateDescriptorHandler.getUpdateDescriptor());
				units.add(currentUnit);
			}
		}
	}

	protected class ApplicabilityScopesHandler extends AbstractMetadataHandler {
		private List<IRequirement[]> scopes;

		public ApplicabilityScopesHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, APPLICABILITY_SCOPE);
			scopes = new ArrayList<>(getOptionalSize(attributes, 4));
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (APPLY_ON.equals(name)) {
				new ApplicabilityScopeHandler(this, attributes, scopes);
			} else {
				duplicateElement(this, name, attributes);
			}
		}

		public IRequirement[][] getScope() {
			return scopes.toArray(new IRequirement[scopes.size()][]);
		}
	}

	protected class ApplicabilityScopeHandler extends AbstractHandler {
		private RequirementsHandler children;
		private List<IRequirement[]> scopes;

		public ApplicabilityScopeHandler(AbstractHandler parentHandler, Attributes attributes, List<IRequirement[]> scopes) {
			super(parentHandler, APPLY_ON);
			this.scopes = scopes;
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (REQUIREMENTS_ELEMENT.equals(name)) {
				children = new RequirementsHandler(this, attributes);
			} else {
				duplicateElement(this, name, attributes);
			}
		}

		@Override
		protected void finished() {
			if (children != null) {
				scopes.add(children.getRequirements());
			}
		}
	}

	protected class RequirementsChangeHandler extends AbstractMetadataHandler {
		private List<IRequirementChange> requirementChanges;

		public RequirementsChangeHandler(InstallableUnitHandler parentHandler, Attributes attributes) {
			super(parentHandler, REQUIREMENT_CHANGES);
			requirementChanges = new ArrayList<>(getOptionalSize(attributes, 4));
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(REQUIREMENT_CHANGE)) {
				new RequirementChangeHandler(this, attributes, requirementChanges);
			} else {
				invalidElement(name, attributes);
			}
		}

		public List<IRequirementChange> getRequirementChanges() {
			return requirementChanges;
		}
	}

	protected class RequirementChangeHandler extends AbstractHandler {
		private List<IRequirement> from;
		private List<IRequirement> to;
		private List<IRequirementChange> requirementChanges;

		public RequirementChangeHandler(AbstractHandler parentHandler, Attributes attributes, List<IRequirementChange> requirementChanges) {
			super(parentHandler, REQUIREMENT_CHANGE);
			from = new ArrayList<>(1);
			to = new ArrayList<>(1);
			this.requirementChanges = requirementChanges;
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(REQUIREMENT_FROM)) {
				new RequirementChangeEltHandler(this, REQUIREMENT_FROM, attributes, from);
				return;
			}

			if (name.equals(REQUIREMENT_TO)) {
				new RequirementChangeEltHandler(this, REQUIREMENT_TO, attributes, to);
				return;
			}
			invalidElement(name, attributes);
		}

		@Override
		protected void finished() {
			requirementChanges.add(MetadataFactory.createRequirementChange(from.size() == 0 ? null : (IRequirement) from.get(0), to.size() == 0 ? null : (IRequirement) to.get(0)));
		}
	}

	protected class RequirementChangeEltHandler extends AbstractHandler {
		private List<IRequirement> requirement;

		public RequirementChangeEltHandler(AbstractHandler parentHandler, String parentId, Attributes attributes, List<IRequirement> from) {
			super(parentHandler, parentId);
			requirement = from;
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (REQUIREMENT_ELEMENT.equals(name))
				new RequirementHandler(this, attributes, requirement);
			else {
				invalidElement(name, attributes);
			}
		}

	}

	protected class LifeCycleHandler extends AbstractHandler {
		private List<IRequirement> lifeCycleRequirement;

		public LifeCycleHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, LIFECYCLE);
			lifeCycleRequirement = new ArrayList<>(1);
		}

		public IRequirement getLifeCycleRequirement() {
			if (lifeCycleRequirement.size() == 0)
				return null;
			return lifeCycleRequirement.get(0);
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (REQUIREMENT_ELEMENT.equals(name)) {
				new RequirementHandler(this, attributes, lifeCycleRequirement);
			} else {
				invalidElement(name, attributes);
			}
		}
	}

	protected class ProvidedCapabilitiesHandler extends AbstractMetadataHandler {
		private List<IProvidedCapability> providedCapabilities;

		public ProvidedCapabilitiesHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, PROVIDED_CAPABILITIES_ELEMENT);
			providedCapabilities = new ArrayList<>(getOptionalSize(attributes, 4));
		}

		public IProvidedCapability[] getProvidedCapabilities() {
			return providedCapabilities.toArray(new IProvidedCapability[providedCapabilities.size()]);
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(PROVIDED_CAPABILITY_ELEMENT)) {
				new ProvidedCapabilityHandler(this, attributes, providedCapabilities);
			} else {
				invalidElement(name, attributes);
			}
		}
	}

	protected class ProvidedCapabilityHandler extends AbstractHandler {
		private String namespace;
		private String name;
		private Version version;
		private ProvidedCapabilityPropertiesHandler propertiesHandler;

		private List<IProvidedCapability> capabilities;

		public ProvidedCapabilityHandler(AbstractHandler parentHandler, Attributes attributes, List<IProvidedCapability> capabilities) {
			super(parentHandler, PROVIDED_CAPABILITY_ELEMENT);

			this.capabilities = capabilities;

			String[] values = parseRequiredAttributes(attributes, REQUIRED_PROVIDED_CAPABILITY_ATTRIBUTES);
			this.namespace = values[0];
			this.name = values[1];
			this.version = checkVersion(PROVIDED_CAPABILITY_ELEMENT, VERSION_ATTRIBUTE, values[2]);
		}

		@Override
		public void startElement(String elem, Attributes attributes) {
			switch (elem) {
				case PROPERTIES_ELEMENT :
					this.propertiesHandler = new ProvidedCapabilityPropertiesHandler(this, attributes);
					break;
				default :
					invalidElement(elem, attributes);
					break;
			}
		}

		@Override
		protected void finished() {
			Map<String, Object> properties = (propertiesHandler != null)
					? propertiesHandler.getProperties()
					: new HashMap<>();

			properties.put(namespace, name);
			properties.put(IProvidedCapability.PROPERTY_VERSION, version);
			IProvidedCapability cap = MetadataFactory.createProvidedCapability(namespace, properties);
			capabilities.add(cap);
		}
	}

	protected class ProvidedCapabilityPropertiesHandler extends AbstractMetadataHandler {
		private Map<String, Object> properties;

		public ProvidedCapabilityPropertiesHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, PROPERTIES_ELEMENT);
			this.properties = new HashMap<>(getOptionalSize(attributes, 2));
		}

		public Map<String, Object> getProperties() {
			return properties;
		}

		@Override
		public void startElement(String elem, Attributes attributes) {
			switch (elem) {
				case PROPERTY_ELEMENT :
					new ProvidedCapabilityPropertyHandler(this, attributes, properties);
					break;
				default :
					invalidElement(elem, attributes);
					break;
			}
		}
	}

	protected class ProvidedCapabilityPropertyHandler extends AbstractMetadataHandler {
		public ProvidedCapabilityPropertyHandler(AbstractHandler parentHandler, Attributes attributes, Map<String, Object> properties) {
			super(parentHandler, PROPERTY_ELEMENT);

			String[] values = parseAttributes(attributes, PROPERTY_ATTRIBUTES, PROPERTY_OPTIONAL_ATTRIBUTES);

			String name = values[0];
			String value = values[1];
			String type = values[2] == null ? PROPERTY_TYPE_STRING : values[2];

			if (type.startsWith(PROPERTY_TYPE_LIST)) {
				properties.put(name, parseList(type, value));
			} else {
				properties.put(name, parseScalar(type, value));
			}
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			invalidElement(name, attributes);
		}

		private List<Object> parseList(String type, String value) {
			final String elType;
			if (type.length() > PROPERTY_TYPE_LIST.length()) {
				// Strip the leading "List<" and trailing ">"
				elType = type.substring(PROPERTY_TYPE_LIST.length() + 1, type.length() - 1);
			} else {
				elType = PROPERTY_TYPE_STRING;
			}

			return Arrays.stream(value.split("\\s*,\\s*")) //$NON-NLS-1$
					.map(val -> parseScalar(elType, val))
					.collect(toList());
		}

		private Object parseScalar(String type, String value) {
			if (PROPERTY_TYPE_STRING.equals(type)) {
				return value;
			}
			if (PROPERTY_TYPE_INTEGER.equals(type)) {
				return Integer.parseInt(value);
			}
			if (PROPERTY_TYPE_LONG.equals(type)) {
				return Long.parseLong(value);
			}
			if (PROPERTY_TYPE_FLOAT.equals(type)) {
				return Float.parseFloat(value);
			}
			if (PROPERTY_TYPE_DOUBLE.equals(type)) {
				return Double.parseDouble(value);
			}
			if (PROPERTY_TYPE_BYTE.equals(type)) {
				return Byte.parseByte(value);
			}
			if (PROPERTY_TYPE_SHORT.equals(type)) {
				return Short.parseShort(value);
			}
			if (PROPERTY_TYPE_CHARACTER.equals(type)) {
				return value.charAt(0);
			}
			if (PROPERTY_TYPE_BOOLEAN.equals(type)) {
				return Boolean.parseBoolean(value);
			}
			if (PROPERTY_TYPE_VERSION.equals(type)) {
				return Version.create(value);
			}

			// String is the default
			return value;
		}
	}

	protected class HostRequiredCapabilitiesHandler extends AbstractMetadataHandler {
		private List<IRequirement> requiredCapabilities;

		public HostRequiredCapabilitiesHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, HOST_REQUIREMENTS_ELEMENT);
			requiredCapabilities = new ArrayList<>(getOptionalSize(attributes, 4));
		}

		public IRequirement[] getHostRequiredCapabilities() {
			return requiredCapabilities.toArray(new IRequirement[requiredCapabilities.size()]);
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(REQUIREMENT_ELEMENT)) {
				new RequirementHandler(this, attributes, requiredCapabilities);
			} else {
				invalidElement(name, attributes);
			}
		}
	}

	protected class MetaRequiredCapabilitiesHandler extends AbstractMetadataHandler {
		private List<IRequirement> requiredCapabilities;

		public MetaRequiredCapabilitiesHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, META_REQUIREMENTS_ELEMENT);
			requiredCapabilities = new ArrayList<>(getOptionalSize(attributes, 4));
		}

		public IRequirement[] getMetaRequiredCapabilities() {
			return requiredCapabilities.toArray(new IRequirement[requiredCapabilities.size()]);
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(REQUIREMENT_ELEMENT)) {
				new RequirementHandler(this, attributes, requiredCapabilities);
			} else {
				invalidElement(name, attributes);
			}
		}
	}

	protected class RequirementsHandler extends AbstractMetadataHandler {
		private List<IRequirement> requirements;

		public RequirementsHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, REQUIREMENTS_ELEMENT);
			requirements = new ArrayList<>(getOptionalSize(attributes, 4));
		}

		public IRequirement[] getRequirements() {
			return requirements.toArray(new IRequirement[requirements.size()]);
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			switch (name) {
				case REQUIREMENT_ELEMENT :
					new RequirementHandler(this, attributes, requirements);
					break;
				case REQUIREMENT_PROPERTIES_ELEMENT :
					new RequirementPropertiesHandler(this, attributes, requirements);
					break;
				default :
					invalidElement(name, attributes);
					break;
			}
		}
	}

	protected class RequirementHandler extends AbstractHandler {
		private List<IRequirement> capabilities;

		// Expression based requirement
		private String match;
		private String matchParams;

		// Simple requirement
		private String namespace;
		private String name;
		private VersionRange range;

		private int min;
		private int max;
		private boolean greedy;

		private TextHandler filterHandler = null;
		private TextHandler descriptionHandler = null;

		public RequirementHandler(AbstractHandler parentHandler, Attributes attributes, List<IRequirement> capabilities) {
			super(parentHandler, REQUIREMENT_ELEMENT);
			this.capabilities = capabilities;

			// Version range requirement
			if (attributes.getIndex(NAMESPACE_ATTRIBUTE) >= 0) {
				String[] values = parseAttributes(attributes, REQIURED_CAPABILITY_ATTRIBUTES, REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTES);
				namespace = values[0];
				name = values[1];
				range = checkVersionRange(REQUIREMENT_ELEMENT, VERSION_RANGE_ATTRIBUTE, values[2]);
				boolean isOptional = checkBoolean(REQUIREMENT_ELEMENT, REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTE, values[3], false).booleanValue();
				min = isOptional ? 0 : 1;
				boolean isMultiple = checkBoolean(REQUIREMENT_ELEMENT, REQUIRED_CAPABILITY_MULTIPLE_ATTRIBUTE, values[4], false).booleanValue();
				max = isMultiple ? Integer.MAX_VALUE : 1;
				greedy = checkBoolean(REQUIREMENT_ELEMENT, REQUIREMENT_GREED_ATTRIBUTE, values[5], true).booleanValue();
			}
			// IU match expression requirement
			else {
				String[] values = parseAttributes(attributes, REQUIRED_IU_MATCH_ATTRIBUTES, REQUIRED_IU_MATCH_OPTIONAL_ATTRIBUTES);
				match = values[0];
				matchParams = values[1];
				min = values[2] == null ? 1 : checkInteger(REQUIREMENT_ELEMENT, MIN_ATTRIBUTE, values[2]);
				max = values[3] == null ? 1 : checkInteger(REQUIREMENT_ELEMENT, MAX_ATTRIBUTE, values[3]);
				greedy = checkBoolean(REQUIREMENT_ELEMENT, REQUIREMENT_GREED_ATTRIBUTE, values[4], true).booleanValue();
			}
		}

		@Override
		public void startElement(String elem, Attributes attributes) {
			switch (elem) {
				case REQUIREMENT_FILTER_ELEMENT:
					filterHandler = new TextHandler(this, REQUIREMENT_FILTER_ELEMENT, attributes);
					break;
				case REQUIREMENT_DESCRIPTION_ELEMENT:
					descriptionHandler = new TextHandler(this, REQUIREMENT_DESCRIPTION_ELEMENT, attributes);
					break;
				default:
					invalidElement(elem, attributes);
					break;
			}
		}

		@Override
		protected void finished() {
			if (!isValidXML())
				return;
			IMatchExpression<IInstallableUnit> filter = null;
			if (filterHandler != null) {
				try {
					filter = InstallableUnit.parseFilter(filterHandler.getText());
				} catch (ExpressionParseException e) {
					if (removeWhiteSpace(filterHandler.getText()).equals("(&(|)(|)(|))")) {//$NON-NLS-1$
						// We could log this I guess
					} else {
						throw e;
					}
				}
			}
			String description = descriptionHandler == null ? null : descriptionHandler.getText();
			IRequirement requirement;
			if (match != null) {
				IMatchExpression<IInstallableUnit> matchExpr = createMatchExpression(match, matchParams);
				requirement = MetadataFactory.createRequirement(matchExpr, filter, min, max, greedy, description);
			} else {
				requirement = MetadataFactory.createRequirement(namespace, name, range, filter, min, max, greedy, description);
			}
			capabilities.add(requirement);
		}

		private String removeWhiteSpace(String s) {
			if (s == null)
				return ""; //$NON-NLS-1$
			StringBuffer builder = new StringBuffer();
			for (int i = 0; i < s.length(); i++) {
				if (s.charAt(i) != ' ')
					builder.append(s.charAt(i));
			}
			return builder.toString();
		}
	}

	protected class RequirementPropertiesHandler extends AbstractHandler {
		private List<IRequirement> requirements;

		private String namespace;
		private String match;
		private int min;
		private int max;
		private boolean greedy;

		private TextHandler filterHandler;
		private TextHandler descriptionHandler;

		public RequirementPropertiesHandler(AbstractHandler parentHandler, Attributes attributes, List<IRequirement> requirements) {
			super(parentHandler, REQUIREMENT_PROPERTIES_ELEMENT);
			this.requirements = requirements;

			String[] values = parseAttributes(attributes, REQIURED_PROPERTIES_MATCH_ATTRIBUTES, REQIURED_PROPERTIES_MATCH_OPTIONAL_ATTRIBUTES);
			namespace = values[0];
			match = values[1];
			min = (values[2] == null) ? 1 : checkInteger(REQUIREMENT_PROPERTIES_ELEMENT, MIN_ATTRIBUTE, values[2]);
			max = (values[3] == null) ? 1 : checkInteger(REQUIREMENT_PROPERTIES_ELEMENT, MAX_ATTRIBUTE, values[3]);
			greedy = checkBoolean(REQUIREMENT_PROPERTIES_ELEMENT, REQUIREMENT_GREED_ATTRIBUTE, values[4], true).booleanValue();
		}

		@Override
		public void startElement(String elem, Attributes attributes) {
			switch (elem) {
				case REQUIREMENT_FILTER_ELEMENT :
					filterHandler = new TextHandler(this, REQUIREMENT_FILTER_ELEMENT, attributes);
					break;
				case REQUIREMENT_DESCRIPTION_ELEMENT :
					descriptionHandler = new TextHandler(this, REQUIREMENT_DESCRIPTION_ELEMENT, attributes);
					break;
				default :
					invalidElement(elem, attributes);
					break;
			}
		}

		@Override
		protected void finished() {
			if (!isValidXML()) {
				return;
			}

			IMatchExpression<IInstallableUnit> filter = null;
			if (filterHandler != null) {
				try {
					filter = InstallableUnit.parseFilter(filterHandler.getText());
				} catch (ExpressionParseException e) {
					if (removeWhiteSpace(filterHandler.getText()).equals("(&(|)(|)(|))")) {//$NON-NLS-1$
						// We could log this I guess
					} else {
						throw e;
					}
				}
			}

			String description = (descriptionHandler != null) ? descriptionHandler.getText() : null;

			IFilterExpression attrMatch = ExpressionUtil.parseLDAP(match);
			IRequirement requirement = MetadataFactory.createRequirement(namespace, attrMatch, filter, min, max, greedy, description);
			requirements.add(requirement);
		}

		private String removeWhiteSpace(String s) {
			if (s == null)
				return ""; //$NON-NLS-1$
			StringBuffer builder = new StringBuffer();
			for (int i = 0; i < s.length(); i++) {
				if (s.charAt(i) != ' ')
					builder.append(s.charAt(i));
			}
			return builder.toString();
		}
	}

	protected class ArtifactsHandler extends AbstractHandler {

		private List<IArtifactKey> artifacts;

		public ArtifactsHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, ARTIFACT_KEYS_ELEMENT);
			String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
			artifacts = (size != null ? new ArrayList<>(Integer.parseInt(size)) : new ArrayList<>(4));
		}

		public IArtifactKey[] getArtifactKeys() {
			return artifacts.toArray(new IArtifactKey[artifacts.size()]);
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(ARTIFACT_KEY_ELEMENT)) {
				new ArtifactHandler(this, attributes, artifacts);
			} else {
				invalidElement(name, attributes);
			}
		}
	}

	protected class ArtifactHandler extends AbstractHandler {

		private final String[] required = new String[] {CLASSIFIER_ATTRIBUTE, ID_ATTRIBUTE, VERSION_ATTRIBUTE};

		public ArtifactHandler(AbstractHandler parentHandler, Attributes attributes, List<IArtifactKey> artifacts) {
			super(parentHandler, ARTIFACT_KEY_ELEMENT);
			String[] values = parseRequiredAttributes(attributes, required);
			Version version = checkVersion(ARTIFACT_KEY_ELEMENT, VERSION_ATTRIBUTE, values[2]);
			artifacts.add(new ArtifactKey(values[0], values[1], version));
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			invalidElement(name, attributes);
		}
	}

	protected class TouchpointTypeHandler extends AbstractHandler {

		private final String[] required = new String[] {ID_ATTRIBUTE, VERSION_ATTRIBUTE};

		ITouchpointType touchpointType = null;

		public TouchpointTypeHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, TOUCHPOINT_TYPE_ELEMENT);
			String[] values = parseRequiredAttributes(attributes, required);
			Version version = checkVersion(TOUCHPOINT_TYPE_ELEMENT, VERSION_ATTRIBUTE, values[1]);
			touchpointType = MetadataFactory.createTouchpointType(values[0], version);
		}

		public ITouchpointType getTouchpointType() {
			return touchpointType;
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			invalidElement(name, attributes);
		}
	}

	protected class TouchpointDataHandler extends AbstractHandler {

		ITouchpointData touchpointData = null;

		List<TouchpointInstructionsHandler> data = null;

		public TouchpointDataHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, TOUCHPOINT_DATA_ELEMENT);
			String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
			data = (size != null ? new ArrayList<>(Integer.parseInt(size)) : new ArrayList<>(4));
		}

		public ITouchpointData[] getTouchpointData() {
			ITouchpointData[] result = new ITouchpointData[data.size()];
			for (int i = 0; i < result.length; i++)
				result[i] = data.get(i).getTouchpointData();
			return result;
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(TOUCHPOINT_DATA_INSTRUCTIONS_ELEMENT)) {
				data.add(new TouchpointInstructionsHandler(this, attributes, data));
			} else {
				invalidElement(name, attributes);
			}
		}
	}

	protected class TouchpointInstructionsHandler extends AbstractHandler {

		Map<String, ITouchpointInstruction> instructions = null;

		public TouchpointInstructionsHandler(AbstractHandler parentHandler, Attributes attributes, List<TouchpointInstructionsHandler> data) {
			super(parentHandler, TOUCHPOINT_DATA_INSTRUCTIONS_ELEMENT);
			String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
			instructions = (size != null ? new LinkedHashMap<>(Integer.parseInt(size)) : new LinkedHashMap<>(4));
		}

		public ITouchpointData getTouchpointData() {
			return MetadataFactory.createTouchpointData(instructions);
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(TOUCHPOINT_DATA_INSTRUCTION_ELEMENT)) {
				new TouchpointInstructionHandler(this, attributes, instructions);
			} else {
				invalidElement(name, attributes);
			}
		}
	}

	protected class TouchpointInstructionHandler extends TextHandler {

		private final String[] required = new String[] {TOUCHPOINT_DATA_INSTRUCTION_KEY_ATTRIBUTE};
		private final String[] optional = new String[] {TOUCHPOINT_DATA_INSTRUCTION_IMPORT_ATTRIBUTE};

		Map<String, ITouchpointInstruction> instructions = null;
		String key = null;
		String qualifier = null;

		public TouchpointInstructionHandler(AbstractHandler parentHandler, Attributes attributes, Map<String, ITouchpointInstruction> instructions) {
			super(parentHandler, TOUCHPOINT_DATA_INSTRUCTION_ELEMENT);
			String[] values = parseAttributes(attributes, required, optional);
			key = values[0];
			qualifier = values[1];
			this.instructions = instructions;
		}

		@Override
		protected void finished() {
			if (isValidXML()) {
				if (key != null) {
					instructions.put(key, MetadataFactory.createTouchpointInstruction(getText(), qualifier));
				}
			}
		}
	}

	protected class UpdateDescriptorHandler extends TextHandler {
		private final String[] requiredSimple = new String[] {ID_ATTRIBUTE, VERSION_RANGE_ATTRIBUTE};
		private final String[] optionalSimple = new String[] {UPDATE_DESCRIPTOR_SEVERITY, DESCRIPTION_ATTRIBUTE};

		private final String[] requiredComplex = new String[] {MATCH_ATTRIBUTE};
		private final String[] optionalComplex = new String[] {UPDATE_DESCRIPTOR_SEVERITY, DESCRIPTION_ATTRIBUTE, MATCH_PARAMETERS_ATTRIBUTE};

		private IUpdateDescriptor descriptor;

		public UpdateDescriptorHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, INSTALLABLE_UNIT_ELEMENT);
			boolean simple = attributes.getIndex(ID_ATTRIBUTE) >= 0;
			String[] values;
			int severityIdx;
			String description;
			if (simple) {
				values = parseAttributes(attributes, requiredSimple, optionalSimple);
				severityIdx = 2;
				description = values[3];
			} else {
				values = parseAttributes(attributes, requiredComplex, optionalComplex);
				severityIdx = 1;
				description = values[2];
			}

			int severity;
			try {
				severity = Integer.parseInt(values[severityIdx]);
			} catch (NumberFormatException e) {
				invalidAttributeValue(UPDATE_DESCRIPTOR_ELEMENT, UPDATE_DESCRIPTOR_SEVERITY, values[severityIdx]);
				severity = IUpdateDescriptor.NORMAL;
			}
			URI location = parseURIAttribute(attributes, false);

			if (simple) {
				VersionRange range = checkVersionRange(REQUIREMENT_ELEMENT, VERSION_RANGE_ATTRIBUTE, values[1]);
				descriptor = MetadataFactory.createUpdateDescriptor(values[0], range, severity, description, location);
			} else {
				IMatchExpression<IInstallableUnit> r = createMatchExpression(values[0], values[3]);
				descriptor = MetadataFactory.createUpdateDescriptor(Collections.singleton(r), severity, description, location);
			}
		}

		public IUpdateDescriptor getUpdateDescriptor() {
			return descriptor;
		}
	}

	/**
	 * 	Handler for a list of licenses.
	 */
	protected class LicensesHandler extends AbstractHandler {

		// Note this handler is set up to handle multiple license elements, but for now
		// the API for IInstallableUnit only reflects one.
		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=216911
		private List<ILicense> licenses;

		public LicensesHandler(ContentHandler parentHandler, Attributes attributes) {
			super(parentHandler, LICENSES_ELEMENT);
			String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE);
			licenses = (size != null ? new ArrayList<>(Integer.parseInt(size)) : new ArrayList<>(2));
		}

		public ILicense[] getLicenses() {
			if (licenses.size() == 0)
				return NO_LICENSES;
			return licenses.toArray(new ILicense[licenses.size()]);
		}

		@Override
		public void startElement(String name, Attributes attributes) {
			if (name.equals(LICENSE_ELEMENT)) {
				new LicenseHandler(this, attributes, licenses);
			} else {
				invalidElement(name, attributes);
			}
		}

	}

	/**
	 * 	Handler for a license in an list of licenses.
	 */
	protected class LicenseHandler extends TextHandler {

		URI location = null;

		private final List<ILicense> licenses;

		public LicenseHandler(AbstractHandler parentHandler, Attributes attributes, List<ILicense> licenses) {
			super(parentHandler, LICENSE_ELEMENT);
			location = parseURIAttribute(attributes, false);
			this.licenses = licenses;
		}

		@Override
		protected void finished() {
			if (isValidXML()) {
				licenses.add(MetadataFactory.createLicense(location, getText()));
			}
		}
	}

	/**
	 * 	Handler for a copyright.
	 */
	protected class CopyrightHandler extends TextHandler {

		URI location = null;
		private ICopyright copyright;

		public CopyrightHandler(AbstractHandler parentHandler, Attributes attributes) {
			super(parentHandler, COPYRIGHT_ELEMENT);
			location = parseURIAttribute(attributes, false);
		}

		@Override
		protected void finished() {
			if (isValidXML()) {
				copyright = MetadataFactory.createCopyright(location, getText());
			}
		}

		public ICopyright getCopyright() {
			return copyright;
		}
	}

	static IMatchExpression<IInstallableUnit> createMatchExpression(String match, String matchParams) {
		IExpressionFactory factory = ExpressionUtil.getFactory();
		IExpression expr = ExpressionUtil.parse(match);
		Object[] params;
		if (matchParams == null)
			params = new Object[0];
		else {
			IExpression[] arrayExpr = ExpressionUtil.getOperands(ExpressionUtil.parse(matchParams));
			params = new Object[arrayExpr.length];
			for (int idx = 0; idx < arrayExpr.length; ++idx)
				params[idx] = arrayExpr[idx].evaluate(null);
		}
		return factory.matchExpression(expr, params);
	}
}
