/*******************************************************************************
 * Copyright (c) 2005, 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
 *******************************************************************************/
package org.eclipse.equinox.metatype.impl;

import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.util.*;
import javax.xml.parsers.SAXParser;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.osgi.service.metatype.AttributeDefinition;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Meta XML Data Parser
 */
public class DataParser {
	private static final String METADATA = "MetaData"; //$NON-NLS-1$
	private static final String LOCALIZATION = "localization"; //$NON-NLS-1$
	private static final String OCD = "OCD"; //$NON-NLS-1$
	private static final String ICON = "Icon"; //$NON-NLS-1$
	private static final String AD = "AD"; //$NON-NLS-1$
	private static final String CARDINALITY = "cardinality"; //$NON-NLS-1$
	private static final String OPTION = "Option"; //$NON-NLS-1$
	private static final String LABEL = "label"; //$NON-NLS-1$
	private static final String VALUE = "value"; //$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 TYPE = "type"; //$NON-NLS-1$
	private static final String SIZE = "size"; //$NON-NLS-1$
	private static final String ID = "id"; //$NON-NLS-1$
	private static final String NAME = "name"; //$NON-NLS-1$
	private static final String DESCRIPTION = "description"; //$NON-NLS-1$
	private static final String RESOURCE = "resource"; //$NON-NLS-1$
	private static final String PID = "pid"; //$NON-NLS-1$
	private static final String DEFAULT = "default"; //$NON-NLS-1$
	private static final String ADREF = "adref"; //$NON-NLS-1$
	private static final String CONTENT = "content"; //$NON-NLS-1$
	private static final String FACTORY = "factoryPid"; //$NON-NLS-1$
	private static final String BUNDLE = "bundle"; //$NON-NLS-1$
	private static final String OPTIONAL = "optional"; //$NON-NLS-1$
	private static final String OBJECT = "Object"; //$NON-NLS-1$
	private static final String OCDREF = "ocdref"; //$NON-NLS-1$
	private static final String ATTRIBUTE = "Attribute"; //$NON-NLS-1$
	private static final String DESIGNATE = "Designate"; //$NON-NLS-1$
	private static final String MERGE = "merge"; //$NON-NLS-1$
	private static final String REQUIRED = "required"; //$NON-NLS-1$

	private static final String INTEGER = "Integer"; //$NON-NLS-1$
	private static final String STRING = "String"; //$NON-NLS-1$
	private static final String FLOAT = "Float"; //$NON-NLS-1$
	private static final String DOUBLE = "Double"; //$NON-NLS-1$
	private static final String BYTE = "Byte"; //$NON-NLS-1$
	private static final String LONG = "Long"; //$NON-NLS-1$
	private static final String CHAR = "Char"; //$NON-NLS-1$
	private static final String CHARACTER = "Character"; //$NON-NLS-1$
	private static final String BOOLEAN = "Boolean"; //$NON-NLS-1$
	private static final String SHORT = "Short"; //$NON-NLS-1$
	private static final String PASSWORD = "Password"; //$NON-NLS-1$
	private static final String BIGINTEGER = "BigInteger"; //$NON-NLS-1$
	private static final String BIGDECIMAL = "BigDecimal"; //$NON-NLS-1$

	protected Bundle _dp_bundle;
	protected URL _dp_url;
	protected SAXParser _dp_parser;
	protected XMLReader _dp_xmlReader;

	// DesignateHanders in DataParser class
	List<DesignateHandler> _dp_designateHandlers = new ArrayList<>(7);
	// ObjectClassDefinitions in DataParser class w/ corresponding reference keys
	Map<String, ObjectClassDefinitionImpl> _dp_OCDs = new HashMap<>(7);
	// Localization in DataParser class
	String _dp_localization;

	// Default visibility to avoid a plethora of synthetic accessor method warnings.
	final LogTracker logger;
	final Collection<Designate> designates = new ArrayList<>(7);

	/*
	 * Constructor of class DataParser.
	 */
	public DataParser(Bundle bundle, URL url, SAXParser parser, LogTracker logger) {

		this._dp_bundle = bundle;
		this._dp_url = url;
		this._dp_parser = parser;
		this.logger = logger;
	}

	/*
	 * Main method to parse specific MetaData file.
	 */
	public Collection<Designate> doParse() throws IOException, SAXException {
		_dp_xmlReader = _dp_parser.getXMLReader();
		_dp_xmlReader.setContentHandler(new RootHandler());
		_dp_xmlReader.setErrorHandler(new MyErrorHandler(System.err));
		InputStream is = _dp_url.openStream();
		InputSource isource = new InputSource(is);
		logger.log(LogTracker.LOG_DEBUG, "Starting to parse " + _dp_url); //$NON-NLS-1$					
		_dp_xmlReader.parse(isource);
		return designates;
	}

	/*
	 * Convert String for expected data type.
	 */
	@SuppressWarnings("deprecation")
	static Object convert(String value, int type) {

		if (value == null) {
			return null;
		}

		switch (type) {
			// PASSWORD should be treated like STRING.
			case AttributeDefinition.PASSWORD :
			case AttributeDefinition.STRING :
				return value;
			case AttributeDefinition.LONG :
				return Long.valueOf(value);
			case AttributeDefinition.INTEGER :
				return Integer.valueOf(value);
			case AttributeDefinition.SHORT :
				return Short.valueOf(value);
			case AttributeDefinition.CHARACTER :
				return Character.valueOf(value.charAt(0));
			case AttributeDefinition.BYTE :
				return Byte.valueOf(value);
			case AttributeDefinition.DOUBLE :
				return Double.valueOf(value);
			case AttributeDefinition.FLOAT :
				return Float.valueOf(value);
			case AttributeDefinition.BIGINTEGER :
				return new BigInteger(value);
			case AttributeDefinition.BIGDECIMAL :
				return new BigDecimal(value);
			case AttributeDefinition.BOOLEAN :
				return Boolean.valueOf(value);
			default :
				// Unknown data type
				return null;
		}
	}

	/**
	 * Abstract of all Handlers.
	 */
	private class AbstractHandler extends DefaultHandler {
		protected ContentHandler _doc_handler;
		protected boolean _isParsedDataValid = true;
		protected Map<String, Map<String, String>> extensionAttributes = new HashMap<String, Map<String, String>>();
		protected String elementId;
		protected String elementName;

		public AbstractHandler(ContentHandler parentHandler) {
			this._doc_handler = parentHandler;
			_dp_xmlReader.setContentHandler(this);
		}

		protected void init(String name, Attributes attributes) {
			elementId = attributes.getValue(ID);
			elementName = name;
		}

		@Override
		public void endElement(String namespaceURI, String localName, String qName) {
			finished();
			// Let parent resume handling SAX events
			_dp_xmlReader.setContentHandler(_doc_handler);
		}

		@Override
		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
			throw new SAXException(NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, new Object[] {qName, attributes.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
		}

		@Override
		public void characters(char[] buf, int start, int end) throws SAXException {
			String s = new String(buf, start, end).trim();
			if (s.length() > 0) {
				throw new SAXException(NLS.bind(MetaTypeMsg.UNEXPECTED_TEXT, new Object[] {s, elementName, elementId, _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
			}
		}

		protected void collectExtensionAttributes(Attributes attributes) {
			for (int i = 0; i < attributes.getLength(); i++) {
				String key = attributes.getURI(i);
				if (key.length() == 0 || key.startsWith("http://www.osgi.org/xmlns/metatype/v")) //$NON-NLS-1$
					continue;
				Map<String, String> value = extensionAttributes.get(key);
				if (value == null) {
					value = new HashMap<String, String>();
					extensionAttributes.put(key, value);
				}
				value.put(getName(attributes.getLocalName(i), attributes.getQName(i)), attributes.getValue(i));
			}
		}

		/**
		 * Called when this element and all elements nested into it have been
		 * handled.
		 */
		protected void finished() {
			// do nothing by default
		}
	}

	/**
	 * Handler for the root element.
	 */
	private class RootHandler extends DefaultHandler {

		public RootHandler() {
			super();
		}

		@Override
		public void startElement(String uri, String localName, String qName, Attributes attributes) {

			logger.log(LogTracker.LOG_DEBUG, "Here is AbstractHandler:startElement():" //$NON-NLS-1$
					+ qName);
			String name = getName(localName, qName);
			if (name.equalsIgnoreCase(METADATA)) {
				new MetaDataHandler(this).init(name, attributes);
			} else {
				logger.log(LogTracker.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, new Object[] {name, attributes.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
			}
		}

		@Override
		public void setDocumentLocator(Locator locator) {
			// do nothing
		}
	}

	/**
	 * Handler for the MetaData element.
	 */
	private class MetaDataHandler extends AbstractHandler {

		public MetaDataHandler(ContentHandler handler) {
			super(handler);
		}

		@Override
		public void init(String name, Attributes attributes) {

			logger.log(LogTracker.LOG_DEBUG, "Here is MetaDataHandler():init()"); //$NON-NLS-1$
			super.init(name, attributes);
			_dp_localization = attributes.getValue(LOCALIZATION);
			if (_dp_localization == null) {
				// Not a problem, because LOCALIZATION is an optional attribute.
			}
			// The global variable "_dp_localization" will be used within
			// OcdHandler and AttributeDefinitionHandler later.
		}

		@Override
		public void startElement(String uri, String localName, String qName, Attributes atts) {

			logger.log(LogTracker.LOG_DEBUG, "Here is MetaDataHandler:startElement():" //$NON-NLS-1$
					+ qName);
			String name = getName(localName, qName);
			if (name.equalsIgnoreCase(DESIGNATE)) {
				DesignateHandler designateHandler = new DesignateHandler(this);
				designateHandler.init(name, atts);
				if (designateHandler._isParsedDataValid) {
					_dp_designateHandlers.add(designateHandler);
				}
			} else if (name.equalsIgnoreCase(OCD)) {
				OcdHandler ocdHandler = new OcdHandler(this);
				ocdHandler.init(name, atts, _dp_OCDs);
			} else {
				logger.log(LogTracker.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, new Object[] {name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
			}
		}

		@Override
		protected void finished() {

			logger.log(LogTracker.LOG_DEBUG, "Here is MetaDataHandler():finished()"); //$NON-NLS-1$
			if (_dp_designateHandlers.size() == 0) {
				// Schema defines at least one DESIGNATE is required.
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_WARNING, NLS.bind(MetaTypeMsg.MISSING_ELEMENT, new Object[] {DESIGNATE, METADATA, elementId, _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}

			for (DesignateHandler dh : _dp_designateHandlers) {
				ObjectClassDefinitionImpl ocd = _dp_OCDs.get(dh._ocdref);
				if (ocd != null) {
					designates.add(new Designate.Builder(ocd).bundle(dh._bundle_val).factoryPid(dh._factory_val).merge(dh._merge_val).pid(dh._pid_val).optional(dh._optional_val).build());
				} else {
					logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.OCD_REF_NOT_FOUND, new Object[] {dh._pid_val, dh._factory_val, dh._ocdref, _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				}
			}
		}
	}

	/**
	 * Handler for the ObjectClassDefinition element.
	 */
	private class OcdHandler extends AbstractHandler {

		Map<String, ObjectClassDefinitionImpl> _parent_OCDs;
		// This ID "_refID" is only used for reference by Designate element,
		// not the PID or FPID of this OCD.
		String _refID;
		ObjectClassDefinitionImpl _ocd;
		List<AttributeDefinitionImpl> _ads = new ArrayList<AttributeDefinitionImpl>(7);
		List<Icon> icons = new ArrayList<Icon>(5);

		public OcdHandler(ContentHandler handler) {
			super(handler);
		}

		public void init(String name, Attributes atts, Map<String, ObjectClassDefinitionImpl> ocds_hashtable) {

			logger.log(LogTracker.LOG_DEBUG, "Here is OcdHandler():init()"); //$NON-NLS-1$
			super.init(name, atts);
			_parent_OCDs = ocds_hashtable;
			collectExtensionAttributes(atts);
			String ocd_name_val = atts.getValue(NAME);
			if (ocd_name_val == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {NAME, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}

			String ocd_description_val = atts.getValue(DESCRIPTION);
			if (ocd_description_val == null) {
				// Not a problem, because DESCRIPTION is an optional attribute.
			}

			_refID = atts.getValue(ID);
			if (_refID == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {ID, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}

			_ocd = new ObjectClassDefinitionImpl(ocd_name_val, ocd_description_val, _refID, _dp_localization, extensionAttributes);
		}

		@Override
		public void startElement(String uri, String localName, String qName, Attributes atts) {

			logger.log(LogTracker.LOG_DEBUG, "Here is OcdHandler:startElement():" //$NON-NLS-1$
					+ qName);
			if (!_isParsedDataValid)
				return;

			String name = getName(localName, qName);
			if (name.equalsIgnoreCase(AD)) {
				AttributeDefinitionHandler attributeDefHandler = new AttributeDefinitionHandler(this);
				attributeDefHandler.init(name, atts, _ads);
			} else if (name.equalsIgnoreCase(ICON)) {
				IconHandler iconHandler = new IconHandler(this);
				iconHandler.init(name, atts);
				if (iconHandler._isParsedDataValid)
					icons.add(iconHandler._icon);
			} else {
				logger.log(LogTracker.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, new Object[] {name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
			}
		}

		@Override
		protected void finished() {
			logger.log(LogTracker.LOG_DEBUG, "Here is OcdHandler():finished()"); //$NON-NLS-1$
			if (!_isParsedDataValid)
				return;
			// OCD gets all parsed ADs.
			for (AttributeDefinitionImpl ad : _ads) {
				_ocd.addAttributeDefinition(ad, ad.isRequired());
			}
			_ocd.setIcons(icons);
			_parent_OCDs.put(_refID, _ocd);
		}
	}

	/**
	 * Handler for the Icon element.
	 */
	private class IconHandler extends AbstractHandler {

		Icon _icon;

		public IconHandler(ContentHandler handler) {
			super(handler);
		}

		@Override
		public void init(String name, Attributes atts) {

			logger.log(LogTracker.LOG_DEBUG, "Here is IconHandler:init()"); //$NON-NLS-1$
			super.init(name, atts);
			String icon_resource_val = atts.getValue(RESOURCE);
			if (icon_resource_val == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {RESOURCE, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}

			String icon_size_val = atts.getValue(SIZE);
			if (icon_size_val == null) {
				// Not a problem, because SIZE is an optional attribute.
				icon_size_val = "0"; //$NON-NLS-1$
			} else if (icon_size_val.equalsIgnoreCase("")) { //$NON-NLS-1$
				icon_size_val = "0"; //$NON-NLS-1$
			}

			_icon = new Icon(icon_resource_val, Integer.parseInt(icon_size_val), _dp_bundle);
		}
	}

	/**
	 * Handler for the Attribute element.
	 */
	private class AttributeDefinitionHandler extends AbstractHandler {

		AttributeDefinitionImpl _ad;
		int _dataType;

		List<AttributeDefinitionImpl> _parent_ADs;
		ArrayList<String> _optionLabels = new ArrayList<>(7);
		ArrayList<String> _optionValues = new ArrayList<>(7);

		private String ad_defaults_str;

		public AttributeDefinitionHandler(ContentHandler handler) {
			super(handler);
		}

		@SuppressWarnings("deprecation")
		public void init(String name, Attributes atts, List<AttributeDefinitionImpl> ads) {

			logger.log(LogTracker.LOG_DEBUG, "Here is AttributeDefinitionHandler():init()"); //$NON-NLS-1$
			super.init(name, atts);
			_parent_ADs = ads;
			collectExtensionAttributes(atts);
			String ad_name_val = atts.getValue(NAME);
			if (ad_name_val == null) {
				// Not a problem, because NAME is an optional attribute.
			}

			String ad_description_val = atts.getValue(DESCRIPTION);
			if (ad_description_val == null) {
				// Not a problem, because DESCRIPTION is an optional attribute.
			}

			String ad_id_val = atts.getValue(ID);
			if (ad_id_val == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {ID, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}

			String ad_type_val = atts.getValue(TYPE);
			if (ad_type_val == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {TYPE, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}
			if (ad_type_val.equalsIgnoreCase(STRING)) {
				_dataType = AttributeDefinition.STRING;
			} else if (ad_type_val.equalsIgnoreCase(LONG)) {
				_dataType = AttributeDefinition.LONG;
			} else if (ad_type_val.equalsIgnoreCase(DOUBLE)) {
				_dataType = AttributeDefinition.DOUBLE;
			} else if (ad_type_val.equalsIgnoreCase(FLOAT)) {
				_dataType = AttributeDefinition.FLOAT;
			} else if (ad_type_val.equalsIgnoreCase(INTEGER)) {
				_dataType = AttributeDefinition.INTEGER;
			} else if (ad_type_val.equalsIgnoreCase(BYTE)) {
				_dataType = AttributeDefinition.BYTE;
			} else if (ad_type_val.equalsIgnoreCase(CHAR) || ad_type_val.equalsIgnoreCase(CHARACTER)) {
				_dataType = AttributeDefinition.CHARACTER;
			} else if (ad_type_val.equalsIgnoreCase(BOOLEAN)) {
				_dataType = AttributeDefinition.BOOLEAN;
			} else if (ad_type_val.equalsIgnoreCase(SHORT)) {
				_dataType = AttributeDefinition.SHORT;
			} else if (ad_type_val.equalsIgnoreCase(PASSWORD)) {
				_dataType = AttributeDefinition.PASSWORD;
			} else if (ad_type_val.equalsIgnoreCase(BIGDECIMAL)) {
				_dataType = AttributeDefinition.BIGDECIMAL;
			} else if (ad_type_val.equalsIgnoreCase(BIGINTEGER)) {
				_dataType = AttributeDefinition.BIGINTEGER;
			} else {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.INVALID_TYPE, new Object[] {ad_type_val, ad_id_val, _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}

			String ad_cardinality_str = atts.getValue(CARDINALITY);
			int ad_cardinality_val = 0;
			if (ad_cardinality_str == null) {
				// Not a problem, because CARDINALITY is an optional attribute.
				// And the default value is 0.
			} else {
				ad_cardinality_val = Integer.parseInt(ad_cardinality_str);
			}

			String ad_min_val = atts.getValue(MIN);
			if (ad_min_val == null) {
				// Not a problem, because MIN is an optional attribute.
			}

			String ad_max_val = atts.getValue(MAX);
			if (ad_max_val == null) {
				// Not a problem, because MAX is an optional attribute.
			}

			ad_defaults_str = atts.getValue(DEFAULT);
			if (ad_defaults_str == null) {
				// Not a problem, because DEFAULT is an optional attribute.
			}

			String ad_required_val = atts.getValue(REQUIRED);
			if (ad_required_val == null) {
				// Not a problem, because REQUIRED is an optional attribute.
				// And the default value is 'true'.
				ad_required_val = Boolean.TRUE.toString();
			}

			_ad = new AttributeDefinitionImpl(ad_id_val, ad_name_val, ad_description_val, _dataType, ad_cardinality_val, convert(ad_min_val, _dataType), convert(ad_max_val, _dataType), Boolean.valueOf(ad_required_val).booleanValue(), _dp_localization, logger, extensionAttributes);
		}

		@Override
		public void startElement(String uri, String localName, String qName, Attributes atts) {

			logger.log(LogTracker.LOG_DEBUG, "Here is AttributeDefinitionHandler:startElement():" //$NON-NLS-1$
					+ qName);
			if (!_isParsedDataValid)
				return;

			String name = getName(localName, qName);
			if (name.equalsIgnoreCase(OPTION)) {
				OptionHandler optionHandler = new OptionHandler(this);
				optionHandler.init(name, atts);
				if (optionHandler._isParsedDataValid) {
					// Only add valid Option
					_optionLabels.add(optionHandler._label_val);
					_optionValues.add(optionHandler._value_val);
				}
			} else {
				logger.log(LogTracker.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, new Object[] {name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
			}
		}

		@Override
		protected void finished() {

			logger.log(LogTracker.LOG_DEBUG, "Here is AttributeDefinitionHandler():finished()"); //$NON-NLS-1$
			if (!_isParsedDataValid)
				return;
			int numOfValues = _optionValues.size();
			_ad.setOption(_optionLabels, _optionValues, true);
			String[] values = _ad.getOptionValues();
			if (values == null)
				values = new String[0];
			if (numOfValues != values.length)
				logger.log(LogTracker.LOG_WARNING, NLS.bind(MetaTypeMsg.INVALID_OPTIONS_XML, new Object[] {elementId, _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));

			if (ad_defaults_str != null) {
				_ad.setDefaultValue(ad_defaults_str, true);
				if (_ad.getDefaultValue() == null)
					logger.log(LogTracker.LOG_WARNING, NLS.bind(MetaTypeMsg.INVALID_DEFAULTS_XML, new Object[] {ad_defaults_str, elementId, _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
			}

			_parent_ADs.add(_ad);
		}
	}

	/**
	 * Handler for the Option element.
	 */
	private class OptionHandler extends AbstractHandler {

		String _label_val;
		String _value_val;

		public OptionHandler(ContentHandler handler) {
			super(handler);
		}

		@Override
		public void init(String name, Attributes atts) {

			logger.log(LogTracker.LOG_DEBUG, "Here is OptionHandler:init()"); //$NON-NLS-1$
			super.init(name, atts);
			_label_val = atts.getValue(LABEL);
			if (_label_val == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {LABEL, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}

			_value_val = atts.getValue(VALUE);
			if (_value_val == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {VALUE, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}
		}
	}

	/**
	 * Handler for the Designate element.
	 */
	class DesignateHandler extends AbstractHandler {

		String _pid_val = null;
		String _factory_val = null;
		String _bundle_val = null; // Only used by RFC94
		boolean _optional_val = false; // Only used by RFC94
		boolean _merge_val = false; // Only used by RFC94

		// Referenced OCD ID
		String _ocdref;

		public DesignateHandler(ContentHandler handler) {
			super(handler);
		}

		@Override
		public void init(String name, Attributes atts) {
			logger.log(LogTracker.LOG_DEBUG, "Here is DesignateHandler():init()"); //$NON-NLS-1$
			super.init(name, atts);
			_pid_val = atts.getValue(PID);
			_factory_val = atts.getValue(FACTORY);
			if (_pid_val == null && _factory_val == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_DESIGNATE_PID_AND_FACTORYPID, new Object[] {elementId, _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}

			_bundle_val = atts.getValue(BUNDLE);
			if (_bundle_val == null) {
				// Not a problem because BUNDLE is an optional attribute.
			}

			String optional_str = atts.getValue(OPTIONAL);
			if (optional_str == null) {
				// Not a problem, because OPTIONAL is an optional attribute.
				// The default value is "false".
				_optional_val = false;
			} else {
				_optional_val = Boolean.valueOf(optional_str).booleanValue();
			}

			String merge_str = atts.getValue(MERGE);
			if (merge_str == null) {
				// Not a problem, because MERGE is an optional attribute.
				// The default value is "false".
				_merge_val = false;
			} else {
				_merge_val = Boolean.valueOf(merge_str).booleanValue();
			}
		}

		@Override
		public void startElement(String uri, String localName, String qName, Attributes atts) {

			logger.log(LogTracker.LOG_DEBUG, "Here is DesignateHandler:startElement():" //$NON-NLS-1$
					+ qName);
			if (!_isParsedDataValid)
				return;

			String name = getName(localName, qName);
			if (name.equalsIgnoreCase(OBJECT)) {
				ObjectHandler objectHandler = new ObjectHandler(this);
				objectHandler.init(name, atts);
				if (objectHandler._isParsedDataValid) {
					_ocdref = objectHandler._ocdref;
				}
			} else {
				logger.log(LogTracker.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, new Object[] {name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
			}
		}

		@Override
		protected void finished() {

			logger.log(LogTracker.LOG_DEBUG, "Here is DesignateHandler():finished()"); //$NON-NLS-1$
			if (!_isParsedDataValid)
				return;

			if (_ocdref == null) {
				_isParsedDataValid = false;
				// Schema defines at least one OBJECT is required.
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ELEMENT, new Object[] {OBJECT, DESIGNATE, elementId, _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;

			}
		}
	}

	/**
	 * Handler for the Object element.
	 */
	private class ObjectHandler extends AbstractHandler {

		String _ocdref;

		public ObjectHandler(ContentHandler handler) {
			super(handler);
		}

		@Override
		public void init(String name, Attributes atts) {

			logger.log(LogTracker.LOG_DEBUG, "Here is ObjectHandler():init()"); //$NON-NLS-1$
			super.init(name, atts);
			_ocdref = atts.getValue(OCDREF);
			if (_ocdref == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {OCDREF, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}
		}

		@Override
		public void startElement(String uri, String localName, String qName, Attributes atts) {

			logger.log(LogTracker.LOG_DEBUG, "Here is ObjectHandler:startElement():" //$NON-NLS-1$
					+ qName);
			if (!_isParsedDataValid)
				return;

			String name = getName(localName, qName);
			if (name.equalsIgnoreCase(ATTRIBUTE)) {
				AttributeHandler attributeHandler = new AttributeHandler(this);
				attributeHandler.init(name, atts);
				// The ATTRIBUTE element is only used by RFC94, do nothing for it here.
			} else {
				logger.log(LogTracker.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, new Object[] {name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
			}
		}
	}

	/**
	 * Handler for the Attribute element.
	 * 
	 * This Handler is only used by RFC94.
	 */
	private class AttributeHandler extends AbstractHandler {

		String _adref_val;
		String _content_val;

		public AttributeHandler(ContentHandler handler) {
			super(handler);
		}

		@Override
		public void init(String name, Attributes atts) {

			logger.log(LogTracker.LOG_DEBUG, "Here is AttributeHandler():init()"); //$NON-NLS-1$
			super.init(name, atts);
			_adref_val = atts.getValue(ADREF);
			if (_adref_val == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {ADREF, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}

			_content_val = atts.getValue(CONTENT);
			if (_content_val == null) {
				_isParsedDataValid = false;
				logger.log(LogTracker.LOG_ERROR, NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, new Object[] {CONTENT, name, atts.getValue(ID), _dp_url, _dp_bundle.getBundleId(), _dp_bundle.getSymbolicName()}));
				return;
			}
		}
	}

	/**
	 * Error Handler to report errors and warnings
	 */
	private static class MyErrorHandler implements ErrorHandler {

		/** Error handler output goes here */
		private PrintStream _out;

		MyErrorHandler(PrintStream out) {
			this._out = out;
		}

		/**
		 * Returns a string describing parse exception details
		 */
		private String getParseExceptionInfo(SAXParseException spe) {
			String systemId = spe.getSystemId();
			if (systemId == null) {
				systemId = "null"; //$NON-NLS-1$
			}
			String info = "URI=" + systemId + //$NON-NLS-1$
					" Line=" + spe.getLineNumber() + //$NON-NLS-1$
					": " + spe.getMessage(); //$NON-NLS-1$

			return info;
		}

		// The following methods are standard SAX ErrorHandler methods.
		// See SAX documentation for more info.

		@Override
		public void warning(SAXParseException spe) {
			_out.println("Warning: " + getParseExceptionInfo(spe)); //$NON-NLS-1$
		}

		@Override
		public void error(SAXParseException spe) throws SAXException {
			String message = "Error: " + getParseExceptionInfo(spe); //$NON-NLS-1$
			throw new SAXException(message);
		}

		@Override
		public void fatalError(SAXParseException spe) throws SAXException {
			String message = "Fatal Error: " + getParseExceptionInfo(spe); //$NON-NLS-1$
			throw new SAXException(message);
		}
	}

	public static String getName(String localName, String qName) {
		if (localName != null && localName.length() > 0) {
			return localName;
		}

		int nameSpaceIndex = qName.indexOf(":"); //$NON-NLS-1$
		return nameSpaceIndex == -1 ? qName : qName.substring(nameSpaceIndex + 1);
	}
}
