/*******************************************************************************
 *  Copyright (c) 2000, 2016 IBM Corporation and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  Contributors:
 *     IBM Corporation - initial API and implementation
 *     Red Hat Inc. - 383795 (bundle element), 406902 (nested categories)
 *******************************************************************************/
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 final static SAXParserFactory parserFactory = SecureXMLUtil.newSecureSAXParserFactory();
	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<Object>();

	private SAXParser parser;

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

	// List of string keys for translated strings
	private final List<String> messageKeys = new ArrayList<String>(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<Integer>();
		objectStack = new Stack<Object>();
		status = null;
		DESCRIPTION_SITE_ALREADY_SEEN = false;
		try {
			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
	 */
	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
	 */
	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
	 */
	public void error(SAXParseException ex) {
		logStatus(ex);
	}

	/**
	 * Handle fatal errors
	 * @see DefaultHandler#fatalError(SAXParseException)
	 * @exception SAXException
	 * @since 2.0
	 */
	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) {
		if (elementName.equals(DESCRIPTION)) {
			stateStack.push(Integer.valueOf(STATE_DESCRIPTION_CATEGORY_DEF));
			processInfo(attributes);
		} else 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 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) {
		if (elementName.equals(DESCRIPTION)) {
			stateStack.push(Integer.valueOf(STATE_DESCRIPTION_SITE));
			processInfo(attributes);
		} else if (elementName.equals(FEATURE)) {
			stateStack.push(Integer.valueOf(STATE_FEATURE));
			processFeature(attributes);
		} else if (elementName.equals(BUNDLE)) {
			stateStack.push(Integer.valueOf(STATE_BUNDLE));
			processBundle(attributes);
		} else if (elementName.equals(IU)) {
			stateStack.push(Integer.valueOf(STATE_IU));
			processIU(attributes);
		} else if (elementName.equals(ARCHIVE)) {
			stateStack.push(Integer.valueOf(STATE_ARCHIVE));
			processArchive(attributes);
		} else if (elementName.equals(CATEGORY_DEF)) {
			stateStack.push(Integer.valueOf(STATE_CATEGORY_DEF));
			processCategoryDef(attributes);
		} else if (elementName.equals(REPOSITORY_REF)) {
			stateStack.push(Integer.valueOf(STATE_REPOSITORY_REF));
			processRepositoryReference(attributes);
		} else if (elementName.equals(STATS_URI)) {
			stateStack.push(Integer.valueOf(STATE_STATS));
			processStatsInfo(attributes);
		} else
			internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
	}

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

	private void handleIUState(String elementName, Attributes attributes) {
		if (elementName.equals(QUERY)) {
			stateStack.push(Integer.valueOf(STATE_QUERY));
			processQuery(attributes);
		} else 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 handleQueryState(String elementName, Attributes attributes) {
		if (elementName.equals(EXPRESSION)) {
			stateStack.push(Integer.valueOf(STATE_EXPRESSION));
			processExpression(attributes);
		} else if (elementName.equals(PARAM)) {
			stateStack.push(Integer.valueOf(STATE_PARAM));
			processParam(attributes);
		} else
			internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())})));
	}

	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$

		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.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$

		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.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
	 */
	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));
	}
}
