/*******************************************************************************
 *  Copyright (c) 2000, 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
 *     Red Hat Inc. - 383795 (bundle element), 406902 (nested categories),
 *                    505808 (platform filters in category.xml)
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.updatesite;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import javax.xml.parsers.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.*;
import org.eclipse.equinox.p2.publisher.eclipse.URLEntry;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.spi.RepositoryReference;
import org.eclipse.osgi.util.NLS;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Parses a category.xml file.
 * This class was initially copied from org.eclipse.update.core.model.DefaultSiteParser.
 */
public class CategoryParser extends DefaultHandler {
	private static final String PLUGIN_ID = Activator.ID;

	private static final String ARCHIVE = "archive"; //$NON-NLS-1$
	private static final String CATEGORY = "category"; //$NON-NLS-1$
	private static final String CATEGORY_DEF = "category-def"; //$NON-NLS-1$
	private static final String DESCRIPTION = "description"; //$NON-NLS-1$
	private static final String FEATURE = "feature"; //$NON-NLS-1$
	private static final String BUNDLE = "bundle"; //$NON-NLS-1$
	private static final String SITE = "site"; //$NON-NLS-1$
	private static final String IU = "iu"; //$NON-NLS-1$
	private static final String QUERY = "query"; //$NON-NLS-1$
	private static final String EXPRESSION = "expression"; //$NON-NLS-1$
	private static final String PARAM = "param"; //$NON-NLS-1$
	private static final String REPOSITORY_REF = "repository-reference"; //$NON-NLS-1$
	private static final String STATS_URI = "stats"; //$NON-NLS-1$

	private static final int STATE_ARCHIVE = 3;
	private static final int STATE_CATEGORY = 4;
	private static final int STATE_CATEGORY_DEF = 5;
	private static final int STATE_DESCRIPTION_CATEGORY_DEF = 7;
	private static final int STATE_DESCRIPTION_SITE = 6;
	private static final int STATE_FEATURE = 2;
	private static final int STATE_BUNDLE = 12;
	private static final int STATE_IGNORED_ELEMENT = -1;
	private static final int STATE_INITIAL = 0;
	private static final int STATE_IU = 8;
	private static final int STATE_EXPRESSION = 9;
	private static final int STATE_PARAM = 10;
	private static final int STATE_QUERY = 11;
	private static final int STATE_SITE = 1;
	private static final int STATE_REPOSITORY_REF = 13;
	private static final int STATE_STATS = 14;

	private boolean DESCRIPTION_SITE_ALREADY_SEEN = false;
	// Current object stack (used to hold the current object we are
	// populating in this plugin descriptor
	Stack<Object> objectStack = new Stack<>();

	private SAXParser parser;

	// Current State Information
	Stack<Integer> stateStack = new Stack<>();

	// List of string keys for translated strings
	private final List<String> messageKeys = new ArrayList<>(4);

	private MultiStatus status;

	/*
	 *
	 */
	private static void debug(String s) {
		Tracing.debug("CategoryParser: " + s); //$NON-NLS-1$
	}

	static void log(Exception e) {
		LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Internal Error", e)); //$NON-NLS-1$
	}

	static void log(String message) {
		LogHelper.log(new Status(IStatus.WARNING, Activator.ID, message, null));
	}

	static void log(String message, Exception e) {
		LogHelper.log(new Status(IStatus.WARNING, Activator.ID, message, e));
	}

	/**
	 * Constructs a site parser.
	 */
	public CategoryParser(URI siteLocation) {
		super();
		stateStack = new Stack<>();
		objectStack = new Stack<>();
		status = null;
		DESCRIPTION_SITE_ALREADY_SEEN = false;
		try {
			SAXParserFactory parserfactory = SecureXMLUtil.newSecureSAXParserFactory();
			parserfactory.setNamespaceAware(true);
			this.parser = parserfactory.newSAXParser();
		} catch (ParserConfigurationException e) {
			log(e);
		} catch (SAXException e) {
			log(e);
		}

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("Created"); //$NON-NLS-1$
	}

	public int currentState() {
		Integer state = stateStack.peek();
		if (state != null)
			return state.intValue();
		return STATE_IGNORED_ELEMENT;
	}

	/**
	 * Handle character text
	 * @see DefaultHandler#characters(char[], int, int)
	 * @since 2.0
	 */
	@Override
	public void characters(char[] ch, int start, int length) {
		String text = new String(ch, start, length);
		//only push if description
		int state = currentState();
		switch (state) {
			case STATE_DESCRIPTION_SITE :
			case STATE_DESCRIPTION_CATEGORY_DEF :
				objectStack.push(text);
				break;

			case STATE_EXPRESSION :
			case STATE_PARAM :
				text = text.trim();
				String existing = null;
				if (objectStack.peek() instanceof String)
					existing = (String) objectStack.pop();
				if (existing != null)
					text = existing + text;
				objectStack.push(text);
				break;
			default :
				break; // nothing
		}
	}

	/**
	 * Handle end of element tags
	 * @see DefaultHandler#endElement(String, String, String)
	 * @since 2.0
	 */
	@Override
	public void endElement(String uri, String localName, String qName) {

		String text = null;
		URLEntry info = null;

		int state = currentState();
		switch (state) {
			case STATE_IGNORED_ELEMENT :
			case STATE_ARCHIVE :
			case STATE_CATEGORY :
			case STATE_QUERY :
				stateStack.pop();
				break;

			case STATE_INITIAL :
				internalError(Messages.DefaultSiteParser_ParsingStackBackToInitialState);
				break;

			case STATE_SITE :
				stateStack.pop();
				if (objectStack.peek() instanceof String) {
					text = (String) objectStack.pop();
					SiteModel site = (SiteModel) objectStack.peek();
					site.getDescription().setAnnotation(text);
				}
				//do not pop the object
				break;

			case STATE_FEATURE :
				stateStack.pop();
				objectStack.pop();
				break;

			case STATE_BUNDLE :
				stateStack.pop();
				objectStack.pop();
				break;

			case STATE_IU :
				stateStack.pop();
				SiteIU completeIU = (SiteIU) objectStack.pop();
				String id = completeIU.getID();
				String expression = completeIU.getQueryExpression();
				if (id == null && expression == null)
					internalError("The IU must specify an id or an expression to match against."); //$NON-NLS-1$
				break;

			case STATE_EXPRESSION :
				stateStack.pop();
				if (objectStack.peek() instanceof String) {
					text = (String) objectStack.pop();
					SiteIU iu = (SiteIU) objectStack.peek();
					iu.setQueryExpression(text);
					if (Tracing.DEBUG_GENERATOR_PARSING)
						debug("Found Expression: " + text); //$NON-NLS-1$
				}
				break;
			case STATE_PARAM :
				stateStack.pop();
				if (objectStack.peek() instanceof String) {
					text = (String) objectStack.pop();
					SiteIU iu = (SiteIU) objectStack.peek();
					iu.addQueryParams(text);
					if (Tracing.DEBUG_GENERATOR_PARSING)
						debug("Found Param: " + text); //$NON-NLS-1$
				}
				break;

			case STATE_CATEGORY_DEF :
				stateStack.pop();
				if (objectStack.peek() instanceof String) {
					text = (String) objectStack.pop();
					SiteCategory category = (SiteCategory) objectStack.peek();
					category.setDescription(text);
				}
				objectStack.pop();
				break;

			case STATE_REPOSITORY_REF :
				stateStack.pop();
				// do not pop object as we did not push the reference
				break;

			case STATE_STATS :
				stateStack.pop();
				// do not pop object stack because we didn't push anything
				break;

			case STATE_DESCRIPTION_SITE :
				stateStack.pop();
				text = ""; //$NON-NLS-1$
				while (objectStack.peek() instanceof String) {
					// add text, preserving at most one space between text fragments
					String newText = (String) objectStack.pop();
					if (trailingSpace(newText) && !leadingSpace(text)) {
						text = " " + text; //$NON-NLS-1$
					}
					text = newText.trim() + text;
					if (leadingSpace(newText) && !leadingSpace(text)) {
						text = " " + text; //$NON-NLS-1$
					}
				}
				text = text.trim();

				info = (URLEntry) objectStack.pop();
				if (text != null)
					info.setAnnotation(text);

				SiteModel siteModel = (SiteModel) objectStack.peek();
				// override description.
				// do not raise error as previous description may be default one
				// when parsing site tag
				if (DESCRIPTION_SITE_ALREADY_SEEN)
					debug(NLS.bind(Messages.DefaultSiteParser_ElementAlreadySet, (new String[] {getState(state)})));
				siteModel.setDescription(info);
				DESCRIPTION_SITE_ALREADY_SEEN = true;
				break;

			case STATE_DESCRIPTION_CATEGORY_DEF :
				stateStack.pop();
				text = ""; //$NON-NLS-1$
				while (objectStack.peek() instanceof String) {
					// add text, preserving at most one space between text fragments
					String newText = (String) objectStack.pop();
					if (trailingSpace(newText) && !leadingSpace(text)) {
						text = " " + text; //$NON-NLS-1$
					}
					text = newText.trim() + text;
					if (leadingSpace(newText) && !leadingSpace(text)) {
						text = " " + text; //$NON-NLS-1$
					}
				}
				text = text.trim();

				info = (URLEntry) objectStack.pop();
				if (text != null)
					info.setAnnotation(text);

				SiteCategory category = (SiteCategory) objectStack.peek();
				if (category.getDescription() != null)
					internalError(NLS.bind(Messages.DefaultSiteParser_ElementAlreadySet, (new String[] {getState(state), category.getLabel()})));
				else {
					checkTranslated(info.getAnnotation());
					category.setDescription(info.getAnnotation());
				}
				break;

			default :
				internalError(NLS.bind(Messages.DefaultSiteParser_UnknownEndState, (new String[] {getState(state)})));
				break;
		}

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End Element:" + uri + ":" + localName + ":" + qName);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	/*
	 * Handles an error state specified by the status.  The collection of all logged status
	 * objects can be accessed using <code>getStatus()</code>.
	 *
	 * @param error a status detailing the error condition
	 */
	private void error(IStatus error) {

		if (status == null) {
			status = new MultiStatus(PLUGIN_ID, 0, Messages.DefaultSiteParser_ErrorParsingSite, null);
		}

		status.add(error);
		if (Tracing.DEBUG_GENERATOR_PARSING)
			LogHelper.log(error);
	}

	/**
	 * Handle errors
	 * @see DefaultHandler#error(SAXParseException)
	 * @since 2.0
	 */
	@Override
	public void error(SAXParseException ex) {
		logStatus(ex);
	}

	/**
	 * Handle fatal errors
	 * @see DefaultHandler#fatalError(SAXParseException)
	 * @exception SAXException
	 * @since 2.0
	 */
	@Override
	public void fatalError(SAXParseException ex) throws SAXException {
		logStatus(ex);
		throw ex;
	}

	/*
	 * return the state as String
	 */
	private String getState(int state) {

		switch (state) {
			case STATE_IGNORED_ELEMENT :
				return "Ignored"; //$NON-NLS-1$

			case STATE_INITIAL :
				return "Initial"; //$NON-NLS-1$

			case STATE_SITE :
				return "Site"; //$NON-NLS-1$

			case STATE_FEATURE :
				return "Feature"; //$NON-NLS-1$

			case STATE_BUNDLE :
				return "Bundle"; //$NON-NLS-1$

			case STATE_IU :
				return "IU"; //$NON-NLS-1$

			case STATE_ARCHIVE :
				return "Archive"; //$NON-NLS-1$

			case STATE_CATEGORY :
				return "Category"; //$NON-NLS-1$

			case STATE_CATEGORY_DEF :
				return "Category Def"; //$NON-NLS-1$

			case STATE_DESCRIPTION_CATEGORY_DEF :
				return "Description / Category Def"; //$NON-NLS-1$

			case STATE_DESCRIPTION_SITE :
				return "Description / Site"; //$NON-NLS-1$

			case STATE_REPOSITORY_REF :
				return "Repository Reference"; //$NON-NLS-1$

			case STATE_STATS :
				return "Stats Repository"; //$NON-NLS-1$

			default :
				return Messages.DefaultSiteParser_UnknownState;
		}
	}

	/**
	 * Returns all status objects accumulated by the parser.
	 *
	 * @return multi-status containing accumulated status, or <code>null</code>.
	 * @since 2.0
	 */
	public MultiStatus getStatus() {
		return status;
	}

	private void handleCategoryDefState(String elementName, Attributes attributes) {
		switch (elementName) {
			case DESCRIPTION:
				stateStack.push(Integer.valueOf(STATE_DESCRIPTION_CATEGORY_DEF));
				processInfo(attributes);
				break;
			case CATEGORY:
				stateStack.push(Integer.valueOf(STATE_CATEGORY));
				processCategory(attributes);
				break;
			default:
				internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
				break;
		}
	}

	private void handleCategoryState(String elementName, Attributes attributes) {
		internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
	}

	private void handleFeatureState(String elementName, Attributes attributes) {
		if (elementName.equals(CATEGORY)) {
			stateStack.push(Integer.valueOf(STATE_CATEGORY));
			processCategory(attributes);
		} else
			internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
	}

	private void handleBundleState(String elementName, Attributes attributes) {
		if (elementName.equals(CATEGORY)) {
			stateStack.push(Integer.valueOf(STATE_CATEGORY));
			processCategory(attributes);
		} else
			internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
	}

	private void handleInitialState(String elementName, Attributes attributes) throws SAXException {
		if (elementName.equals(SITE)) {
			stateStack.push(Integer.valueOf(STATE_SITE));
			processSite(attributes);
		} else {
			internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
			// what we received was not a site.xml, no need to continue
			throw new SAXException(Messages.DefaultSiteParser_InvalidXMLStream);
		}

	}

	private void handleSiteState(String elementName, Attributes attributes) {
		switch (elementName) {
			case DESCRIPTION:
				stateStack.push(Integer.valueOf(STATE_DESCRIPTION_SITE));
				processInfo(attributes);
				break;
			case FEATURE:
				stateStack.push(Integer.valueOf(STATE_FEATURE));
				processFeature(attributes);
				break;
			case BUNDLE:
				stateStack.push(Integer.valueOf(STATE_BUNDLE));
				processBundle(attributes);
				break;
			case IU:
				stateStack.push(Integer.valueOf(STATE_IU));
				processIU(attributes);
				break;
			case ARCHIVE:
				stateStack.push(Integer.valueOf(STATE_ARCHIVE));
				processArchive(attributes);
				break;
			case CATEGORY_DEF:
				stateStack.push(Integer.valueOf(STATE_CATEGORY_DEF));
				processCategoryDef(attributes);
				break;
			case REPOSITORY_REF:
				stateStack.push(Integer.valueOf(STATE_REPOSITORY_REF));
				processRepositoryReference(attributes);
				break;
			case STATS_URI:
				stateStack.push(Integer.valueOf(STATE_STATS));
				processStatsInfo(attributes);
				break;
			default:
				internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
				break;
		}
	}

	private void handleStatsState(String elementName, Attributes attributes) {
		switch (elementName) {
			case FEATURE:
				stateStack.push(STATE_FEATURE);
				processStatsFeature(attributes);
				break;
			case BUNDLE:
				stateStack.push(STATE_BUNDLE);
				processStatsBundle(attributes);
				break;
			default:
				internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
				break;
		}
	}

	private void handleIUState(String elementName, Attributes attributes) {
		switch (elementName) {
			case QUERY:
				stateStack.push(Integer.valueOf(STATE_QUERY));
				processQuery(attributes);
				break;
			case CATEGORY:
				stateStack.push(Integer.valueOf(STATE_CATEGORY));
				processCategory(attributes);
				break;
			default:
				internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
				break;
		}
	}

	private void handleQueryState(String elementName, Attributes attributes) {
		switch (elementName) {
			case EXPRESSION:
				stateStack.push(Integer.valueOf(STATE_EXPRESSION));
				processExpression(attributes);
				break;
			case PARAM:
				stateStack.push(Integer.valueOf(STATE_PARAM));
				processParam(attributes);
				break;
			default:
				internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
				break;
		}
	}

	private void handleExpression(String elementName, Attributes attributes) {
		internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
	}

	private void handleParamState(String elementName, Attributes attributes) {
		internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
	}

	/*
	 *
	 */
	private void internalError(String message) {
		error(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message, null));
	}

	/*
	 *
	 */
	private void internalErrorUnknownTag(String msg) {
		stateStack.push(Integer.valueOf(STATE_IGNORED_ELEMENT));
		internalError(msg);
	}

	private boolean leadingSpace(String str) {
		if (str.length() <= 0) {
			return false;
		}
		return Character.isWhitespace(str.charAt(0));
	}

	/*
	 *
	 */
	private void logStatus(SAXParseException ex) {
		String name = ex.getSystemId();
		if (name == null)
			name = ""; //$NON-NLS-1$
		else
			name = name.substring(1 + name.lastIndexOf("/")); //$NON-NLS-1$

		String msg;
		if (name.equals("")) //$NON-NLS-1$
			msg = NLS.bind(Messages.DefaultSiteParser_ErrorParsing, (new String[] {ex.getMessage()}));
		else {
			String[] values = new String[] {name, Integer.toString(ex.getLineNumber()), Integer.toString(ex.getColumnNumber()), ex.getMessage()};
			msg = NLS.bind(Messages.DefaultSiteParser_ErrorlineColumnMessage, values);
		}
		error(new Status(IStatus.ERROR, PLUGIN_ID, msg, ex));
	}

	/**
	 * Parses the specified input steam and constructs a site model.
	 * The input stream is not closed as part of this operation.
	 *
	 * @param in input stream
	 * @return site model
	 * @exception SAXException
	 * @exception IOException
	 * @since 2.0
	 */
	public SiteModel parse(InputStream in) throws SAXException, IOException {
		stateStack.push(Integer.valueOf(STATE_INITIAL));
		parser.parse(new InputSource(in), this);
		if (objectStack.isEmpty())
			throw new SAXException(Messages.DefaultSiteParser_NoSiteTag);
		if (objectStack.peek() instanceof SiteModel) {
			SiteModel site = (SiteModel) objectStack.pop();
			site.setMessageKeys(messageKeys);
			return site;
		}
		String stack = ""; //$NON-NLS-1$
		Iterator<Object> iter = objectStack.iterator();
		while (iter.hasNext()) {
			stack = stack + iter.next().toString() + "\r\n"; //$NON-NLS-1$
		}
		throw new SAXException(NLS.bind(Messages.DefaultSiteParser_WrongParsingStack, (new String[] {stack})));
	}

	/*
	 * process archive info
	 */
	private void processArchive(Attributes attributes) {
		// don't care about archives in category xml
		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End processing Archive"); //$NON-NLS-1$
	}

	/*
	 * process the Category  info
	 */
	private void processCategory(Attributes attributes) {
		String category = attributes.getValue("name"); //$NON-NLS-1$
		Object obj = objectStack.peek();
		// TODO could create common class/interface for adding categories
		if (obj instanceof SiteFeature) {
			((SiteFeature) obj).addCategoryName(category);
		} else if (obj instanceof SiteBundle) {
			((SiteBundle) obj).addCategoryName(category);
		} else if (obj instanceof SiteIU) {
			((SiteIU) obj).addCategoryName(category);
		} else if (obj instanceof SiteCategory) {
			((SiteCategory) obj).addCategoryName(category);
		}

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End processing Category: name:" + category); //$NON-NLS-1$
	}

	/*
	 * process category def info
	 */
	private void processCategoryDef(Attributes attributes) {
		SiteCategory category = new SiteCategory();
		String name = attributes.getValue("name"); //$NON-NLS-1$
		String label = attributes.getValue("label"); //$NON-NLS-1$
		checkTranslated(label);
		category.setName(name);
		category.setLabel(label);

		SiteModel site = (SiteModel) objectStack.peek();
		site.addCategory(category);
		objectStack.push(category);

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End processing CategoryDef: name:" + name + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/*
	 * process repository reference info
	 */
	private void processRepositoryReference(Attributes attributes) {
		String location = attributes.getValue("location"); //$NON-NLS-1$
		String nickname = attributes.getValue("name"); //$NON-NLS-1$
		URI uri;
		try {
			uri = URIUtil.fromString(location);
			boolean enabled = Boolean.parseBoolean(attributes.getValue("enabled")); //$NON-NLS-1$
			// First add a metadata repository
			RepositoryReference metadata = new RepositoryReference(uri, nickname, IRepository.TYPE_METADATA, enabled ? IRepository.ENABLED : IRepository.NONE);
			// Now a colocated artifact repository
			RepositoryReference artifact = new RepositoryReference(uri, nickname, IRepository.TYPE_ARTIFACT, enabled ? IRepository.ENABLED : IRepository.NONE);

			SiteModel site = (SiteModel) objectStack.peek();
			site.addRepositoryReference(metadata);
			site.addRepositoryReference(artifact);
			// we do not push the references onto the object stack as we do not go deeper, and
			// references are not SiteModel objects.
		} catch (URISyntaxException e) {
			// UI should have already caught this
		}
	}

	/*
	 * process stats top level element
	 */
	private void processStatsInfo(Attributes attributes) {
		String location = attributes.getValue("location"); //$NON-NLS-1$
		try {
			// One final validation but UI should have already done this.
			URIUtil.fromString(location);
			SiteModel site = (SiteModel) objectStack.peek();
			site.setStatsURIString(location);
		} catch (URISyntaxException e) {
			// Ignore if not valid.
		}

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End processing Repository Reference: location:" + location); //$NON-NLS-1$
	}

	/*
	 * process stats feature artifact
	 */
	private void processStatsFeature(Attributes attributes) {
		SiteFeature feature = new SiteFeature();

		// identifier and version
		String id = attributes.getValue("id"); //$NON-NLS-1$
		String ver = attributes.getValue("version"); //$NON-NLS-1$

		boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$

		// We need to have id and version, or the url, or both.
		if (noId)
			internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$

		feature.setFeatureIdentifier(id);
		feature.setFeatureVersion(ver);

		SiteModel site = (SiteModel) objectStack.peek();
		site.addStatsFeature(feature);
		objectStack.push(feature);
		feature.setSiteModel(site);

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End Processing Stats Feature Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$	}
	}

	/*
	 * process stats bundle artifact info
	 */
	private void processStatsBundle(Attributes attributes) {
		SiteBundle bundle = new SiteBundle();

		// identifier and version
		String id = attributes.getValue("id"); //$NON-NLS-1$
		String ver = attributes.getValue("version"); //$NON-NLS-1$

		boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$

		// We need to have id and version, or the url, or both.
		if (noId)
			internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$

		bundle.setBundleIdentifier(id);
		bundle.setBundleVersion(ver);

		SiteModel site = (SiteModel) objectStack.peek();
		site.addStatsBundle(bundle);
		objectStack.push(bundle);
		bundle.setSiteModel(site);

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End Processing Stats Bundle Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/*
	 * process feature info
	 */
	private void processFeature(Attributes attributes) {
		SiteFeature feature = new SiteFeature();

		// identifier and version
		String id = attributes.getValue("id"); //$NON-NLS-1$
		String ver = attributes.getValue("version"); //$NON-NLS-1$
		String os = attributes.getValue("os"); //$NON-NLS-1$
		String ws = attributes.getValue("ws"); //$NON-NLS-1$
		String arch = attributes.getValue("arch"); //$NON-NLS-1$

		boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$

		// We need to have id and version, or the url, or both.
		if (noId)
			internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$

		feature.setFeatureIdentifier(id);
		feature.setFeatureVersion(ver);
		feature.setOS(os);
		feature.setWS(ws);
		feature.setArch(arch);

		SiteModel site = (SiteModel) objectStack.peek();
		site.addFeature(feature);
		feature.setSiteModel(site);

		objectStack.push(feature);

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End Processing Feature Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/*
	 * process bundle info
	 */
	private void processBundle(Attributes attributes) {
		SiteBundle bundle = new SiteBundle();

		// identifier and version
		String id = attributes.getValue("id"); //$NON-NLS-1$
		String ver = attributes.getValue("version"); //$NON-NLS-1$
		String os = attributes.getValue("os"); //$NON-NLS-1$
		String ws = attributes.getValue("ws"); //$NON-NLS-1$
		String arch = attributes.getValue("arch"); //$NON-NLS-1$

		boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$

		// We need to have id and version, or the url, or both.
		if (noId)
			internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$

		bundle.setBundleIdentifier(id);
		bundle.setBundleVersion(ver);
		bundle.setOS(os);
		bundle.setWS(ws);
		bundle.setArch(arch);

		SiteModel site = (SiteModel) objectStack.peek();
		site.addBundle(bundle);
		bundle.setSiteModel(site);

		objectStack.push(bundle);

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End Processing Bundle Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/*
	 * process IU info
	 */
	private void processIU(Attributes attributes) {
		SiteIU iu = new SiteIU();
		SiteModel site = (SiteModel) objectStack.peek();

		// identifier and version
		String id = attributes.getValue("id"); //$NON-NLS-1$
		String range = attributes.getValue("range"); //$NON-NLS-1$
		id = id == null ? null : id.trim();
		range = range == null ? null : range.trim();

		iu.setID(id);
		iu.setRange(range);

		site.addIU(iu);
		objectStack.push(iu);

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End processing iu."); //$NON-NLS-1$
	}

	/*
	 * process expression info
	 */
	private void processExpression(Attributes attributes) {
		SiteIU iu = (SiteIU) objectStack.peek();
		iu.setQueryType(attributes.getValue("type")); //$NON-NLS-1$

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End processing Expression: " + iu.getQueryType()); //$NON-NLS-1$
	}

	/*
	 * process query info
	 */
	private void processQuery(Attributes attributes) {
		// TODO may have simple attriutes for id and range
		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End processing Query."); //$NON-NLS-1$
	}

	/*
	 * process param info
	 */
	private void processParam(Attributes attributes) {
		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End processing Param."); //$NON-NLS-1$
	}

	/*
	 * process URL info with element text
	 */
	private void processInfo(Attributes attributes) {
		URLEntry inf = new URLEntry();
		String infoURL = attributes.getValue("url"); //$NON-NLS-1$
		inf.setURL(infoURL);

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("Processed Info: url:" + infoURL); //$NON-NLS-1$

		objectStack.push(inf);
	}

	/*
	 * process site info
	 */
	private void processSite(Attributes attributes) {
		// create site map
		SiteModel site = new SiteModel();
		objectStack.push(site);

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End process Site tag."); //$NON-NLS-1$

	}

	/**
	 * Handle start of element tags
	 * @see DefaultHandler#startElement(String, String, String, Attributes)
	 * @since 2.0
	 */
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

		if (Tracing.DEBUG_GENERATOR_PARSING) {
			debug("State: " + currentState()); //$NON-NLS-1$
			debug("Start Element: uri:" + uri + " local Name:" + localName + " qName:" + qName);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

		switch (currentState()) {
			case STATE_IGNORED_ELEMENT :
				internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {localName, getState(currentState())})));
				break;
			case STATE_INITIAL :
				handleInitialState(localName, attributes);
				break;

			case STATE_SITE :
				handleSiteState(localName, attributes);
				break;

			case STATE_FEATURE :
				handleFeatureState(localName, attributes);
				break;

			case STATE_BUNDLE :
				handleBundleState(localName, attributes);
				break;

			case STATE_IU :
				handleIUState(localName, attributes);
				break;

			case STATE_EXPRESSION :
				handleExpression(localName, attributes);
				break;

			case STATE_QUERY :
				handleQueryState(localName, attributes);
				break;

			case STATE_PARAM :
				handleParamState(localName, attributes);
				break;

			case STATE_ARCHIVE :
				handleSiteState(localName, attributes);
				break;

			case STATE_CATEGORY :
				handleCategoryState(localName, attributes);
				break;

			case STATE_CATEGORY_DEF :
				handleCategoryDefState(localName, attributes);
				break;

			case STATE_DESCRIPTION_SITE :
				handleSiteState(localName, attributes);
				break;

			case STATE_DESCRIPTION_CATEGORY_DEF :
				handleSiteState(localName, attributes);
				break;

			case STATE_STATS :
				handleStatsState(localName, attributes);
				break;

			default :
				internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownStartState, (new String[] {getState(currentState())})));
				break;
		}

	}

	private boolean trailingSpace(String str) {
		if (str.length() <= 0) {
			return false;
		}
		return Character.isWhitespace(str.charAt(str.length() - 1));
	}

	// Add translatable strings from the site.xml
	// to the list of message keys.
	private void checkTranslated(String value) {
		if (value != null && value.length() > 1 && value.startsWith("%")) //$NON-NLS-1$
			messageKeys.add(value.substring(1));
	}
}
