/*******************************************************************************
 * Copyright (c) 2000, 2008 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
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata.generator.features;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import javax.xml.parsers.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.core.helpers.Tracing;
import org.eclipse.equinox.internal.p2.metadata.repository.Activator;
import org.eclipse.equinox.internal.provisional.p2.metadata.generator.URLEntry;
import org.eclipse.osgi.util.NLS;
import org.w3c.dom.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Parses a site.xml file.
 * This class was initially copied from org.eclipse.update.core.model.DefaultSiteParser.
 */
public class DefaultSiteParser extends DefaultHandler {

	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 ASSOCIATE_SITES_URL = "associateSitesURL"; //$NON-NLS-1$
	private static final String ASSOCIATE_SITE = "associateSite"; //$NON-NLS-1$
	private static final String DEFAULT_INFO_URL = "index.html"; //$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 FEATURES = "features/"; //$NON-NLS-1$
	private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance();
	private static final String PLUGIN_ID = Activator.ID;
	private static final String SITE = "site"; //$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_IGNORED_ELEMENT = -1;
	private static final int STATE_INITIAL = 0;
	private static final int STATE_SITE = 1;

	private int currentState;

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

	private SAXParser parser;

	// Current State Information
	Stack stateStack = new Stack();

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

	private MultiStatus status;

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

	private static URLEntry[] getAssociateSites(String associateSitesURL) {

		try {
			DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = domFactory.newDocumentBuilder();
			Document document = builder.parse(associateSitesURL);
			if (document == null)
				return null;
			NodeList mirrorNodes = document.getElementsByTagName(ASSOCIATE_SITE);
			URLEntry[] mirrors = new URLEntry[mirrorNodes.getLength()];
			for (int i = 0; i < mirrorNodes.getLength(); i++) {
				Element mirrorNode = (Element) mirrorNodes.item(i);
				mirrors[i] = new URLEntry();
				String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$
				String label = mirrorNode.getAttribute("label"); //$NON-NLS-1$
				mirrors[i].setURL(infoURL);
				mirrors[i].setAnnotation(label);

				if (Tracing.DEBUG_GENERATOR_PARSING)
					debug("Processed mirror: url:" + infoURL + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$
			}
			return mirrors;
		} catch (Exception e) {
			// log if absolute url
			if (associateSitesURL != null && (associateSitesURL.startsWith("http://") //$NON-NLS-1$
					|| associateSitesURL.startsWith("https://") //$NON-NLS-1$
					|| associateSitesURL.startsWith("file://") //$NON-NLS-1$
					|| associateSitesURL.startsWith("ftp://") //$NON-NLS-1$
			|| associateSitesURL.startsWith("jar://"))) //$NON-NLS-1$
				log(Messages.DefaultSiteParser_mirrors, e);
			return null;
		}
	}

	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 DefaultSiteParser() {
		super();
		stateStack = new Stack();
		objectStack = new Stack();
		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$
	}

	/**
	 * 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 = ((Integer) stateStack.peek()).intValue();
		if (state == STATE_DESCRIPTION_SITE || state == STATE_DESCRIPTION_CATEGORY_DEF)
			objectStack.push(text);

	}

	/**
	 * 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 = ((Integer) stateStack.peek()).intValue();
		switch (state) {
			case STATE_IGNORED_ELEMENT :
			case STATE_ARCHIVE :
			case STATE_CATEGORY :
				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_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_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
					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_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$

			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(FEATURE)) {
			stateStack.push(new Integer(STATE_FEATURE));
			processFeature(attributes);
		} else if (elementName.equals(ARCHIVE)) {
			stateStack.push(new Integer(STATE_ARCHIVE));
			processArchive(attributes);
		} else if (elementName.equals(CATEGORY_DEF)) {
			stateStack.push(new Integer(STATE_CATEGORY_DEF));
			processCategoryDef(attributes);
		} else if (elementName.equals(DESCRIPTION)) {
			stateStack.push(new Integer(STATE_DESCRIPTION_CATEGORY_DEF));
			processInfo(attributes);
		} else
			internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
	}

	private void handleCategoryState(String elementName, Attributes attributes) {
		if (elementName.equals(DESCRIPTION)) {
			stateStack.push(new Integer(STATE_DESCRIPTION_SITE));
			processInfo(attributes);
		} else if (elementName.equals(FEATURE)) {
			stateStack.push(new Integer(STATE_FEATURE));
			processFeature(attributes);
		} else if (elementName.equals(ARCHIVE)) {
			stateStack.push(new Integer(STATE_ARCHIVE));
			processArchive(attributes);
		} else if (elementName.equals(CATEGORY_DEF)) {
			stateStack.push(new Integer(STATE_CATEGORY_DEF));
			processCategoryDef(attributes);
		} else if (elementName.equals(CATEGORY)) {
			stateStack.push(new Integer(STATE_CATEGORY));
			processCategory(attributes);
		} else
			internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
	}

	private void handleFeatureState(String elementName, Attributes attributes) {
		if (elementName.equals(DESCRIPTION)) {
			stateStack.push(new Integer(STATE_DESCRIPTION_SITE));
			processInfo(attributes);
		} else if (elementName.equals(FEATURE)) {
			stateStack.push(new Integer(STATE_FEATURE));
			processFeature(attributes);
		} else if (elementName.equals(ARCHIVE)) {
			stateStack.push(new Integer(STATE_ARCHIVE));
			processArchive(attributes);
		} else if (elementName.equals(CATEGORY_DEF)) {
			stateStack.push(new Integer(STATE_CATEGORY_DEF));
			processCategoryDef(attributes);
		} else if (elementName.equals(CATEGORY)) {
			stateStack.push(new Integer(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(new Integer(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(new Integer(STATE_DESCRIPTION_SITE));
			processInfo(attributes);
		} else if (elementName.equals(FEATURE)) {
			stateStack.push(new Integer(STATE_FEATURE));
			processFeature(attributes);
		} else if (elementName.equals(ARCHIVE)) {
			stateStack.push(new Integer(STATE_ARCHIVE));
			processArchive(attributes);
		} else if (elementName.equals(CATEGORY_DEF)) {
			stateStack.push(new Integer(STATE_CATEGORY_DEF));
			processCategoryDef(attributes);
		} else
			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(new Integer(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(new Integer(STATE_INITIAL));
		currentState = ((Integer) stateStack.peek()).intValue();
		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 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) {
		URLEntry archive = new URLEntry();
		String id = attributes.getValue("path"); //$NON-NLS-1$
		if (id == null || id.trim().equals("")) { //$NON-NLS-1$
			internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"path", getState(currentState)}))); //$NON-NLS-1$
		}

		archive.setAnnotation(id);

		String url = attributes.getValue("url"); //$NON-NLS-1$
		if (url == null || url.trim().equals("")) { //$NON-NLS-1$
			internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"archive", getState(currentState)}))); //$NON-NLS-1$
		} else {
			archive.setURL(url);

			SiteModel site = (SiteModel) objectStack.peek();
			site.addArchive(archive);
		}
		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End processing Archive: path:" + id + " url:" + url);//$NON-NLS-1$ //$NON-NLS-2$

	}

	/* 
	 * process the Category  info
	 */
	private void processCategory(Attributes attributes) {
		String category = attributes.getValue("name"); //$NON-NLS-1$
		SiteFeature feature = (SiteFeature) objectStack.peek();
		feature.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 feature info
	 */
	private void processFeature(Attributes attributes) {
		SiteFeature feature = new SiteFeature();

		// feature location on the site
		String urlInfo = attributes.getValue("url"); //$NON-NLS-1$
		// identifier and version
		String id = attributes.getValue("id"); //$NON-NLS-1$
		String ver = attributes.getValue("version"); //$NON-NLS-1$

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

		// We need to have id and version, or the url, or both.
		if (noURL) {
			if (noId || noVersion)
				internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState)}))); //$NON-NLS-1$
			else
				// default url
				urlInfo = FEATURES + id + '_' + ver; // 
		}

		feature.setURLString(urlInfo);

		// if one is null, and not the other
		if (noId ^ noVersion) {
			String[] values = new String[] {id, ver, getState(currentState)};
			log(NLS.bind(Messages.DefaultFeatureParser_IdOrVersionInvalid, values));
		} else {
			feature.setFeatureIdentifier(id);
			feature.setFeatureVersion(ver);
		}

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

		objectStack.push(feature);

		if (Tracing.DEBUG_GENERATOR_PARSING)
			debug("End Processing DefaultFeature Tag: url:" + urlInfo); //$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();

		// provide default description URL
		// If <description> is specified, for the site,  it takes precedence		
		URLEntry description = new URLEntry();
		description.setURL(DEFAULT_INFO_URL);
		site.setDescription(description);

		// get mirrors, if any
		String mirrorsURL = attributes.getValue("mirrorsURL"); //$NON-NLS-1$
		if (mirrorsURL != null && mirrorsURL.trim().length() > 0) {
			site.setMirrorsURLString(mirrorsURL);
		}

		if (attributes.getValue(ASSOCIATE_SITES_URL) != null)
			site.setAssociateSites(getAssociateSites(attributes.getValue(ASSOCIATE_SITES_URL)));

		objectStack.push(site);
	}

	/**
	 * 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_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;

			default :
				internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownStartState, (new String[] {getState(currentState)})));
				break;
		}
		int newState = ((Integer) stateStack.peek()).intValue();
		if (newState != STATE_IGNORED_ELEMENT)
			currentState = newState;

	}

	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));
	}
}
