/*******************************************************************************
 * Copyright (c) 2002, 2017 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.ui.internal.cheatsheets.data;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.help.internal.UAElement;
import org.eclipse.help.internal.UAElementFactory;
import org.eclipse.help.internal.dynamic.DocumentProcessor;
import org.eclipse.help.internal.dynamic.DocumentReader;
import org.eclipse.help.internal.dynamic.ExtensionHandler;
import org.eclipse.help.internal.dynamic.FilterHandler;
import org.eclipse.help.internal.dynamic.IncludeHandler;
import org.eclipse.help.internal.dynamic.ProcessorHandler;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.cheatsheets.AbstractItemExtensionElement;
import org.eclipse.ui.internal.cheatsheets.CheatSheetEvaluationContext;
import org.eclipse.ui.internal.cheatsheets.CheatSheetPlugin;
import org.eclipse.ui.internal.cheatsheets.ICheatSheetResource;
import org.eclipse.ui.internal.cheatsheets.Messages;
import org.eclipse.ui.internal.cheatsheets.composite.model.CompositeCheatSheetModel;
import org.eclipse.ui.internal.cheatsheets.composite.parser.CompositeCheatSheetParser;
import org.eclipse.ui.internal.cheatsheets.composite.parser.ICompositeCheatsheetTags;
import org.eclipse.ui.internal.cheatsheets.composite.parser.IStatusContainer;
import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetItemExtensionElement;
import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetRegistryReader;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * Parser for the cheatsheet content files.
 *
 * Construct an intance of the CheatSheetDomParser.
 * Call <code>parse()</code>.
 * Then get the content items by calling
 * <code>getIntroItem()</code> and <code>getItemsList()</code>.
 * The title of the cheatsheet can be retrieved by calling
 * <code>getTitle()</code>.
 *
 */
public class CheatSheetParser implements IStatusContainer {

	private static final String TRUE_STRING = "true"; //$NON-NLS-1$

	private DocumentBuilder documentBuilder;
	private DocumentProcessor processor;
	private ArrayList<CheatSheetItemExtensionElement> itemExtensionContainerList;

	// Cheatsheet kinds that can be parsed
	public static final int COMPOSITE_ONLY = 1;
	public static final int SIMPLE_ONLY = 2;
	public static final int ANY = 3;

	private IStatus status;

	private int commandCount;

	private int actionCount;


	/**
	 * Java constructor comment.
	 */
	public CheatSheetParser() {
		super();
		documentBuilder = CheatSheetPlugin.getPlugin().getDocumentBuilder();
	}

	/**
	 *  Gets the status of the last call to parse()
	 */
	public IStatus getStatus() {
		return status;
	}

	@Override
	public void addStatus(int severity, String message, Throwable exception) {
		status = ParserStatusUtility.addStatus(status, severity, message, exception);
	}

	/**
	 * Converts any characters required to escaped by an XML parser to
	 * their escaped counterpart.
	 *
	 * Characters			XML escaped counterpart
	 * <			->		&lt;
	 * >			->		&gt;
	 * &			->		&amp;
	 * '			->		&apos;
	 * "			->		&quot;
	 *
	 * Tags that will be ignored <b>, </b> and <br/>.
	 *
	 * @param text the string buffer to have its characters escaped
	 * @return string buffer with any of the characters requiring XML escaping escaped
	 */
	private StringBuilder escapeXMLCharacters(StringBuilder text) {
		// Set the maximum length of the tags to ignore
		final int MAXIMUM_TAG_LENGTH = 5;

		// Keep a local variable for the orignal string's length
		int length = text.length();

		// Create the buffer to store the resulting string
		StringBuilder result = new StringBuilder(length);

		// Loop for the characters of the original string
		for(int i=0; i<length; i++) {
			// Grab the next character and determine how to handle it
			char c = text.charAt(i);
			switch (c) {
				case '<': {
					// We have a less than, grab the maximum tag length of characters
					// or the remaining characters which follow and determine if it
					// is the start of a tag to ignore.
					String tmp = ICheatSheetResource.EMPTY_STRING;
					if(i+MAXIMUM_TAG_LENGTH < length)
						tmp = text.substring(i, i+MAXIMUM_TAG_LENGTH).toLowerCase();
					else {
						tmp = text.substring(i, length).toLowerCase();
					}
					if(tmp.startsWith(IParserTags.BOLD_START_TAG) || tmp.startsWith(IParserTags.BOLD_END_TAG) || tmp.startsWith(IParserTags.BREAK_TAG)) {
						// We have a tag to ignore so just emit the character
						result.append(c);
					} else {
						// We have detemined that it is just a less than
						// so emit the XML escaped counterpart
						result.append(IParserTags.LESS_THAN);
					}
					break; }
				case '>': {
					// We have a greater than, grab the maximum tag length of characters
					// or the starting characters which come before and determine if it
					// is the end of a tag to ignore.
					String tmp = ICheatSheetResource.EMPTY_STRING;
					if(i>=MAXIMUM_TAG_LENGTH) {
						tmp = text.substring(i-MAXIMUM_TAG_LENGTH, i+1).toLowerCase();
					} else {
						tmp = text.substring(0, i+1).toLowerCase();
					}
					if(tmp.endsWith(IParserTags.BOLD_START_TAG) || tmp.endsWith(IParserTags.BOLD_END_TAG) || tmp.endsWith(IParserTags.BREAK_TAG)) {
						// We have a tag to ignore so just emit the character
						result.append(c);
					} else {
						// We have detemined that it is just a greater than
						// so emit the XML escaped counterpart
						result.append(IParserTags.GREATER_THAN);
					}
					break; }
				case '&':
					// We have an ampersand so emit the XML escaped counterpart
					result.append(IParserTags.AMPERSAND);
					break;
				case '\'':
					// We have an apostrophe so emit the XML escaped counterpart
					result.append(IParserTags.APOSTROPHE);
					break;
				case '"':
					// We have a quote so emit the XML escaped counterpart
					result.append(IParserTags.QUOTE);
					break;
				case '\t':
					// We have a tab, replace with a space
					result.append(' ');
					break;
				default:
					// We have a character that does not require escaping
					result.append(c);
					break;
			}
		}
		return result;
	}

	private Node findNode(Node startNode, String nodeName) {
		if(startNode == null) {
			return null;
		}

		if(startNode.getNodeName().equals(nodeName)) {
			return startNode;
		}

		NodeList nodes = startNode.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			if(node.getNodeName().equals(nodeName)) {
				return node;
			}
		}

		return null;
	}

	private void handleExecutable(IExecutableItem item, Node executableNode, AbstractExecutable executable) throws CheatSheetParserException {
		Assert.isNotNull(item);
		Assert.isNotNull(executableNode);

		String[] params = null;

		if (executable instanceof CheatSheetCommand) {
			commandCount++;
		}
		if (executable instanceof Action) {
			actionCount++;
		}

		NamedNodeMap attributes = executableNode.getAttributes();
		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;
				if (attributeName.equals(IParserTags.CONFIRM)) {
					executable.setConfirm(attribute.getNodeValue().equals(TRUE_STRING));}
				else if (attributeName.equals(IParserTags.WHEN)) {
					executable.setWhen(attribute.getNodeValue());
				} else if (attributeName.equals(IParserTags.REQUIRED)) {
					executable.setRequired(attribute.getNodeValue().equals(TRUE_STRING));
				} else if (attributeName.equals(IParserTags.TRANSLATE)) {
					// Translation hint, no semantic effect
				} else if (executable.hasParams() && attributeName.startsWith(IParserTags.PARAM)) {
					try {
						if(params == null) {
							params = new String[9];
						}
						String paramNum = attributeName.substring(IParserTags.PARAM.length());
						int num = Integer.parseInt(paramNum)-1;

						if(num>-1 && num<9){
							params[num] = attribute.getNodeValue();
						} else {
							String message = NLS.bind(Messages.ERROR_PARSING_PARAM_INVALIDRANGE, (new Object[] {attributeName, paramNum}));
							addStatus(IStatus.ERROR, message, null);
						}
					} catch(NumberFormatException e) {
						String message = Messages.ERROR_PARSING_PARAM_INVALIDNUMBER;
						addStatus(IStatus.ERROR, message, e);
					}
				} else if (!executable.handleAttribute(attribute)) {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE, (new Object[] {attributeName, executableNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
			String errorMessage = executable.checkAttributes(executableNode);
			if (errorMessage != null) {
				throw new CheatSheetParserException(errorMessage);
			}
		}
        checkForNoChildren(executableNode);
		executable.setParams(params);
		item.setExecutable(executable);
	}

	private void checkForNoChildren(Node parentNode) {
		NodeList nodes = parentNode.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			if(node.getNodeType() != Node.TEXT_NODE && node.getNodeType() != Node.COMMENT_NODE ) {
				String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ELEMENT, (new Object[] {node.getNodeName(), parentNode.getNodeName()}));
				addStatus(IStatus.WARNING, message, null);
			}
		}
	}

	private void handleCheatSheetAttributes(CheatSheet cheatSheet, Node cheatSheetNode) throws CheatSheetParserException {
		Assert.isNotNull(cheatSheet);
		Assert.isNotNull(cheatSheetNode);
		Assert.isTrue(cheatSheetNode.getNodeName().equals(IParserTags.CHEATSHEET));

		boolean title = false;

		NamedNodeMap attributes = cheatSheetNode.getAttributes();
		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;

				if (attributeName.equals(IParserTags.TITLE)) {
					title = true;
					cheatSheet.setTitle(attribute.getNodeValue());
				} else {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE, (new Object[] {attributeName, cheatSheetNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}

		if(!title) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_TITLE, (new Object[] {cheatSheetNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}
	}

	private void handleConditionalSubItem(Item item, Node conditionalSubItemNode) throws CheatSheetParserException {
		Assert.isNotNull(item);
		Assert.isNotNull(conditionalSubItemNode);
		Assert.isTrue(conditionalSubItemNode.getNodeName().equals(IParserTags.CONDITIONALSUBITEM));

		ConditionalSubItem conditionalSubItem = new ConditionalSubItem();

		boolean condition = false;

		// Handle attributes
		NamedNodeMap attributes = conditionalSubItemNode.getAttributes();
		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;

				if (attributeName.equals(IParserTags.CONDITION)) {
					condition = true;
					conditionalSubItem.setCondition(attribute.getNodeValue());
				} else {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE, (new Object[] {attributeName, conditionalSubItemNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}

		if(!condition) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_CONDITION, (new Object[] {conditionalSubItemNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}

		boolean subitem = false;

		// Handle nodes
		NodeList nodes = conditionalSubItemNode.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);

			if(node.getNodeName().equals(IParserTags.SUBITEM)) {
				subitem = true;
				handleSubItem(conditionalSubItem, node);
			} else {
				if(node.getNodeType() != Node.TEXT_NODE && node.getNodeType() != Node.COMMENT_NODE ) {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ELEMENT, (new Object[] {node.getNodeName(), conditionalSubItemNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}

		if(!subitem) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_SUBITEM, (new Object[] {conditionalSubItemNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}

		item.addSubItem(conditionalSubItem);
	}

	private void handleDescription(Item item, Node startNode) throws CheatSheetParserException {
		Assert.isNotNull(item);
		Assert.isNotNull(startNode);

		Node descriptionNode = findNode(startNode, IParserTags.DESCRIPTION);

		if(descriptionNode != null) {
			String text = handleMarkedUpText(descriptionNode, startNode, IParserTags.DESCRIPTION);
			item.setDescription(text);
		} else {
			Node parentNode = startNode;
			if( startNode.getNodeName().equals(IParserTags.DESCRIPTION) ) {
				parentNode = startNode.getParentNode();
			}
			String message = NLS.bind(Messages.ERROR_PARSING_NO_DESCRIPTION, (new Object[] {parentNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}
	}

	private void handleSubItemDescription(SubItem subItem, Node startNode) throws CheatSheetParserException {
		Assert.isNotNull(subItem);
		Assert.isNotNull(startNode);

		Node descriptionNode = findNode(startNode, IParserTags.DESCRIPTION);

		if(descriptionNode != null) {
			String text = handleMarkedUpText(descriptionNode, startNode, IParserTags.DESCRIPTION);
			subItem.setLabel(text);
			subItem.setFormatted(true);
		}
	}

	private String handleMarkedUpText(Node nodeContainingText, Node startNode, String nodeName ) {
		NodeList nodes = nodeContainingText.getChildNodes();
		StringBuilder text = new StringBuilder();

		boolean containsMarkup = false;

		// The documentation for the content file specifies
		// that leading whitespace should be ignored at the
		// beginning of a description or after a <br/>. This
		// applies also to <onCompletion> elements.
		// See Bug 129208 and Bug 131185
		boolean isLeadingTrimRequired = true;

		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			if(node.getNodeType() == Node.TEXT_NODE) {
				String nodeValue = node.getNodeValue();
			    if (isLeadingTrimRequired) {
					nodeValue = trimLeadingWhitespace(nodeValue);
				}
				text.append(nodeValue);
				isLeadingTrimRequired = false;
			} else if(node.getNodeType() == Node.ELEMENT_NODE) {
				// handle <b></b> and <br/>
				if(node.getNodeName().equals(IParserTags.BOLD)) {
					containsMarkup = true;
					text.append(IParserTags.BOLD_START_TAG);
					text.append(node.getFirstChild().getNodeValue());
					text.append(IParserTags.BOLD_END_TAG);
					isLeadingTrimRequired = false;
				} else if(node.getNodeName().equals(IParserTags.BREAK)) {
					containsMarkup = true;
					text.append(IParserTags.BREAK_TAG);
					isLeadingTrimRequired = true;
				} else {
					warnUnknownMarkupElement(startNode, nodeName, node);
				}
			}
		}

		if(containsMarkup) {
			text = escapeXMLCharacters(text);
			text.insert(0, IParserTags.FORM_START_TAG);
			text.append(IParserTags.FORM_END_TAG);
		} else {
			deTab(text);
		}

		// Remove the new line, form feed and tab chars
		return text.toString().trim();
	}

	// Replace any tabs with spaces

	private void deTab(StringBuilder text) {
		for (int i = 0; i < text.length(); i++) {
			if (text.charAt(i) == '\t') {
				text.setCharAt(i, ' ');
			}
		}
	}

	private String trimLeadingWhitespace(String nodeValue) {
		int firstNonWhitespaceIndex = 0;
		while (firstNonWhitespaceIndex < nodeValue.length() &&
				Character.isWhitespace(nodeValue.charAt(firstNonWhitespaceIndex))) {
			firstNonWhitespaceIndex++;
		}
		if (firstNonWhitespaceIndex > 0) {
		    return nodeValue.substring(firstNonWhitespaceIndex, nodeValue.length());
		}
		return nodeValue;
	}

	/*
	 * Write a warning to the log
	 */
	private void warnUnknownMarkupElement(Node startNode, String nodeName, Node node) {
		Node parentNode = startNode;
		if( startNode.getNodeName().equals(nodeName) ) {
			parentNode = startNode.getParentNode();
		}
		String message;
		if (IParserTags.DESCRIPTION.equals(nodeName)) {
		    message = NLS.bind(Messages.WARNING_PARSING_DESCRIPTION_UNKNOWN_ELEMENT, (new Object[] {parentNode.getNodeName(), node.getNodeName()}));
		} else {
			message = NLS.bind(Messages.WARNING_PARSING_ON_COMPLETION_UNKNOWN_ELEMENT, (new Object[] {parentNode.getNodeName(), node.getNodeName()}));
		}
		addStatus(IStatus.WARNING, message, null);

	}

	private void handleOnCompletion(Item item, Node onCompletionNode) {
		String text = handleMarkedUpText(onCompletionNode, onCompletionNode, IParserTags.ON_COMPLETION);
		item.setCompletionMessage(text);
	}

	private void handleIntroNode(CheatSheet cheatSheet, Node introNode)
			throws CheatSheetParserException {
		Item introItem = new Item();
		introItem.setTitle(Messages.CHEAT_SHEET_INTRO_TITLE);

		handleIntroAttributes(introItem, introNode);

        boolean hasDescription = false;

		NodeList nodes = introNode.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);

			if(node.getNodeName().equals(IParserTags.DESCRIPTION)) {
				if (hasDescription) {
					String message = NLS.bind(Messages.ERROR_PARSING_MULTIPLE_DESCRIPTION, (new Object[] {introNode.getNodeName()}));
					addStatus(IStatus.ERROR, message, null);
				} else {
				    hasDescription = true;
				    handleDescription(introItem, node);
				}
			} else {
				if(node.getNodeType() != Node.TEXT_NODE && node.getNodeType() != Node.COMMENT_NODE ) {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ELEMENT, (new Object[] {node.getNodeName(), introNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}

		if(!hasDescription) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_DESCRIPTION, (new Object[] {introNode.getNodeName()}));
			addStatus(IStatus.ERROR, message, null);
		}

		cheatSheet.setIntroItem(introItem);
	}

	private void handleIntroAttributes(Item item, Node introNode) {
		Assert.isNotNull(item);
		Assert.isNotNull(introNode);

		NamedNodeMap attributes = introNode.getAttributes();
		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;

				if (attributeName.equals(IParserTags.CONTEXTID)) {
					item.setContextId(attribute.getNodeValue());
				} else if (attributeName.equals(IParserTags.HREF)) {
					item.setHref(attribute.getNodeValue());
				} else {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE, (new Object[] {attributeName, introNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}
	}

	private Item handleItem(Node itemNode) throws CheatSheetParserException {
		Assert.isNotNull(itemNode);
		Assert.isTrue(itemNode.getNodeName().equals(IParserTags.ITEM));

		Item item = new Item();

		handleItemAttributes(item, itemNode);

		boolean hasDescription = false;

		NodeList nodes = itemNode.getChildNodes();

		IncompatibleSiblingChecker checker = new IncompatibleSiblingChecker(this, itemNode);
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			checker.checkElement(node.getNodeName());
			if(node.getNodeName().equals(IParserTags.ACTION)) {
				handleExecutable(item, node, new Action());
			} else if(node.getNodeName().equals(IParserTags.COMMAND)) {
				handleExecutable(item, node, new CheatSheetCommand());
			} else if(node.getNodeName().equals(IParserTags.DESCRIPTION)) {
				if (hasDescription) {
					String message = NLS.bind(Messages.ERROR_PARSING_MULTIPLE_DESCRIPTION, (new Object[] {itemNode.getNodeName()}));
					addStatus(IStatus.ERROR, message, null);
				} else {
				    hasDescription = true;
				    handleDescription(item, node);
				}
			} else if(node.getNodeName().equals(IParserTags.ON_COMPLETION)) {
				handleOnCompletion(item, node);
			} else if(node.getNodeName().equals(IParserTags.SUBITEM)) {
				handleSubItem(item, node);
			} else if(node.getNodeName().equals(IParserTags.CONDITIONALSUBITEM)) {
				handleConditionalSubItem(item, node);
			} else if(node.getNodeName().equals(IParserTags.REPEATEDSUBITM)) {
				handleRepeatedSubItem(item, node);
			} else if(node.getNodeName().equals(IParserTags.PERFORMWHEN)) {
				handlePerformWhen(item, node);
			} else {
				if(node.getNodeType() != Node.TEXT_NODE && node.getNodeType() != Node.COMMENT_NODE ) {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ELEMENT, (new Object[] {node.getNodeName(), itemNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}

		if(!hasDescription) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_DESCRIPTION, (new Object[] {itemNode.getNodeName()}));
			addStatus(IStatus.ERROR, message, null);
		}

		return item;
	}

	private void handleItemAttributes(Item item, Node itemNode) throws CheatSheetParserException {
		Assert.isNotNull(item);
		Assert.isNotNull(itemNode);

		ArrayList<AbstractItemExtensionElement[]> itemExtensionElements = new ArrayList<>();

		boolean title = false;

		NamedNodeMap attributes = itemNode.getAttributes();
		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;

				if (attributeName.equals(IParserTags.TITLE)) {
					title = true;
					item.setTitle(attribute.getNodeValue());
				} else if (attributeName.equals(IParserTags.CONTEXTID)) {
					item.setContextId(attribute.getNodeValue());
				} else if (attributeName.equals(IParserTags.HREF)) {
					item.setHref(attribute.getNodeValue());
				} else if (attributeName.equals(IParserTags.SKIP)) {
					item.setSkip(attribute.getNodeValue().equals(TRUE_STRING));
				} else if (attributeName.equals(IParserTags.DIALOG)) {
					item.setDialog(attribute.getNodeValue().equals(TRUE_STRING));
				} else {
					AbstractItemExtensionElement[] ie = handleUnknownItemAttribute(attribute, itemNode);
					if (ie != null) {
						itemExtensionElements.add(ie);
					} else {
						String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE, (new Object[] {attributeName, itemNode.getNodeName()}));
						addStatus(IStatus.WARNING, message, null);
					}
				}
			}
		}

		if(!title) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_TITLE, (new Object[] {itemNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}

		if (itemExtensionElements != null)
			item.setItemExtensions(itemExtensionElements);
	}

	private void handlePerformWhen(IPerformWhenItem item, Node performWhenNode) throws CheatSheetParserException {
		Assert.isNotNull(item);
		Assert.isNotNull(performWhenNode);
		Assert.isTrue(performWhenNode.getNodeName().equals(IParserTags.PERFORMWHEN));

		PerformWhen performWhen = new PerformWhen();

		 boolean condition = false;

		// Handle attributes
		NamedNodeMap attributes = performWhenNode.getAttributes();
		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;

				if (attributeName.equals(IParserTags.CONDITION)) {
					condition = true;
					performWhen.setCondition(attribute.getNodeValue());
				} else {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE, (new Object[] {attributeName, performWhenNode.getNodeName()}));
					addStatus(IStatus.WARNING,message, null);
				}
			}
		}

		if(!condition) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_CONDITION, (new Object[] {performWhenNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}

		boolean exeutable = false;

		// Handle nodes
		NodeList nodes = performWhenNode.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			if(node.getNodeName().equals(IParserTags.ACTION)) {
				exeutable = true;
				handleExecutable(performWhen, node, new Action());
			} else if(node.getNodeName().equals(IParserTags.COMMAND)) {
				exeutable = true;
				handleExecutable(performWhen, node, new CheatSheetCommand());
			} else {
				if(node.getNodeType() != Node.TEXT_NODE && node.getNodeType() != Node.COMMENT_NODE ) {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ELEMENT, (new Object[] {node.getNodeName(), performWhenNode .getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}

		if(!exeutable) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_ACTION, (new Object[] {performWhenNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}

		item.setPerformWhen(performWhen);
	}

	private void handleRepeatedSubItem(Item item, Node repeatedSubItemNode) throws CheatSheetParserException {
		Assert.isNotNull(item);
		Assert.isNotNull(repeatedSubItemNode);
		Assert.isTrue(repeatedSubItemNode.getNodeName().equals(IParserTags.REPEATEDSUBITM));

		RepeatedSubItem repeatedSubItem = new RepeatedSubItem();

		boolean values = false;

		// Handle attributes
		NamedNodeMap attributes = repeatedSubItemNode.getAttributes();
		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;

				if (attributeName.equals(IParserTags.VALUES)) {
					values = true;
					repeatedSubItem.setValues(attribute.getNodeValue());
				} else {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE, (new Object[] {attributeName, repeatedSubItemNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}

		if(!values) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_VALUES, (new Object[] {repeatedSubItemNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}

		boolean subitem = false;

		// Handle nodes
		NodeList nodes = repeatedSubItemNode.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);

			if(node.getNodeName().equals(IParserTags.SUBITEM)) {
				subitem = true;
				handleSubItem(repeatedSubItem, node);
			} else {
				if(node.getNodeType() != Node.TEXT_NODE && node.getNodeType() != Node.COMMENT_NODE ) {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ELEMENT, (new Object[] {node.getNodeName(), repeatedSubItemNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}

		if(!subitem) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_SUBITEM, (new Object[] {repeatedSubItemNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}

		item.addSubItem(repeatedSubItem);
	}

	private void handleSubItem(ISubItemItem item, Node subItemNode) throws CheatSheetParserException {
		Assert.isNotNull(item);
		Assert.isNotNull(subItemNode);
		Assert.isTrue(subItemNode.getNodeName().equals(IParserTags.SUBITEM));

		SubItem subItem = new SubItem();

		IncompatibleSiblingChecker checker = new IncompatibleSiblingChecker(this, subItemNode);

		NodeList nodes = subItemNode.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			checker.checkElement(node.getNodeName());

			if(node.getNodeName().equals(IParserTags.ACTION)) {
				handleExecutable(subItem, node, new Action());
			} else if(node.getNodeName().equals(IParserTags.COMMAND)) {
				handleExecutable(subItem, node, new CheatSheetCommand());
			} else if(node.getNodeName().equals(IParserTags.PERFORMWHEN)) {
				handlePerformWhen(subItem, node);
			} else if (node.getNodeName().equals(IParserTags.DESCRIPTION)) {
				if (subItem.isFormatted()) {
					String message = NLS.bind(
							Messages.ERROR_PARSING_MULTIPLE_DESCRIPTION,
							(new Object[] { node.getNodeName() }));
					addStatus(IStatus.ERROR, message, null);
				} else {
					handleSubItemDescription(subItem, node);
				}
			} else {
				if(node.getNodeType() != Node.TEXT_NODE && node.getNodeType() != Node.COMMENT_NODE ) {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ELEMENT, (new Object[] {node.getNodeName(), subItemNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}
		handleSubItemAttributes(subItem, subItemNode);
		item.addSubItem(subItem);
	}

	private void handleSubItemAttributes(SubItem subItem, Node subItemNode) throws CheatSheetParserException {
		Assert.isNotNull(subItem);
		Assert.isNotNull(subItemNode);

		NamedNodeMap attributes = subItemNode.getAttributes();
		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;

				if (attributeName.equals(IParserTags.LABEL)) {
					subItem.setLabel(attribute.getNodeValue());
				} else if (attributeName.equals(IParserTags.SKIP)) {
					subItem.setSkip(attribute.getNodeValue().equals(TRUE_STRING));
				} else if (attributeName.equals(IParserTags.WHEN)) {
					subItem.setWhen(attribute.getNodeValue());
				} else {
					String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE, (new Object[] {attributeName, subItemNode.getNodeName()}));
					addStatus(IStatus.WARNING, message, null);
				}
			}
		}

		if(subItem.getLabel() == null) {
			String message = NLS.bind(Messages.ERROR_PARSING_NO_LABEL, (new Object[] {subItemNode.getNodeName()}));
			throw new CheatSheetParserException(message);
		}
	}

	private AbstractItemExtensionElement[] handleUnknownItemAttribute(Node item, Node node) {
		ArrayList<AbstractItemExtensionElement> al = new ArrayList<>();
		if (itemExtensionContainerList == null)
			return null;

		for (int i = 0; i < itemExtensionContainerList.size(); i++) {
			CheatSheetItemExtensionElement itemExtensionElement = itemExtensionContainerList.get(i);

			if (itemExtensionElement.getItemAttribute().equals(item.getNodeName())) {
				AbstractItemExtensionElement itemElement = itemExtensionElement.createInstance();
				if(itemElement != null) {
					itemElement.handleAttribute(item.getNodeValue());
					al.add(itemElement);
				}
			}
		}

		if(al.size() == 0) {
			String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ATTRIBUTE, (new Object[] {item.getNodeName(), node.getNodeName()}));
			addStatus(IStatus.WARNING, message, null);
		}
		return al.toArray(new AbstractItemExtensionElement[al.size()]);
	}

	public ICheatSheet parse(URL url, String pluginId, int cheatSheetKind) {
		return parse(new ParserInput(url, pluginId, null), cheatSheetKind);
	}

	public ICheatSheet parse(ParserInput input, int cheatSheetKind) {
		status = Status.OK_STATUS;
		commandCount = 0;
		actionCount = 0;
		if(input == null) {
			return null;
		}
		if (input.getErrorMessage() != null) {
			addStatus(IStatus.ERROR, input.getErrorMessage(), null);
		}

		InputStream is = null;
		InputSource inputSource = null;
        String filename = ""; //$NON-NLS-1$
		URL url = input.getUrl();

		if (input.getXml() != null) {
			StringReader reader = new StringReader(input.getXml());
			inputSource = new InputSource(reader);
		} else if (input.getUrl() != null){
			try {
				is = url.openStream();

				if (is != null) {
					inputSource = new InputSource(is);
				}
			} catch (Exception e) {
				String message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object[] {url.getFile()}));
				addStatus(IStatus.ERROR, message, e);
				return null;
			}
		} else {
			return null;
		}

		if (input.getUrl() != null){
			filename = url.getFile();
		}

		Document document;
		try {
			if(documentBuilder == null) {
				addStatus(IStatus.ERROR, Messages.ERROR_DOCUMENT_BUILDER_NOT_INIT, null);
				return null;
			}
			document = documentBuilder.parse(inputSource);
		} catch (IOException e) {
			String message = NLS.bind(Messages.ERROR_OPENING_FILE_IN_PARSER, (new Object[] {filename}));
			addStatus(IStatus.ERROR, message, e);
			return null;
		} catch (SAXParseException spe) {
			String message = NLS.bind(Messages.ERROR_SAX_PARSING_WITH_LOCATION, (new Object[] {filename, new Integer(spe.getLineNumber()), new Integer(spe.getColumnNumber())}));
			addStatus(IStatus.ERROR, message, spe);
			return null;
		} catch (SAXException se) {
			String message = NLS.bind(Messages.ERROR_SAX_PARSING, (new Object[] {filename}));
			addStatus(IStatus.ERROR, message, se);
			return null;
		} finally {
			try {
				is.close();
			} catch (Exception e) {
			}
		}

		// process dynamic content, normalize paths
		if (processor == null) {
			DocumentReader reader = new DocumentReader();
			processor = new DocumentProcessor(new ProcessorHandler[] {
				new FilterHandler(CheatSheetEvaluationContext.getContext()),
				new NormalizeHandler(),
				new IncludeHandler(reader, Platform.getNL()),
				new ExtensionHandler(reader, Platform.getNL())
			});
		}
		String documentPath = null;
		if (input.getPluginId() != null) {
			documentPath = '/' + input.getPluginId() + input.getUrl().getPath();
		}
		processor.process(UAElementFactory.newElement(document.getDocumentElement()), documentPath);

		if ( cheatSheetKind == COMPOSITE_ONLY  ||  (cheatSheetKind == ANY && isComposite(document))) {
			CompositeCheatSheetParser compositeParser = new CompositeCheatSheetParser();
			CompositeCheatSheetModel result = compositeParser.parseCompositeCheatSheet(document, input.getUrl());
			status = compositeParser.getStatus();
			return result;
		}
		try {
			return parseCheatSheet(document);
		} catch(CheatSheetParserException e) {
			addStatus(IStatus.ERROR, e.getMessage(), e);
		}
		return null;
	}

	private boolean isComposite(Document document) {
		if (document != null) {
			Node rootnode = document.getDocumentElement();
			// Is the root node compositeCheatsheet?
			return rootnode.getNodeName().equals(ICompositeCheatsheetTags.COMPOSITE_CHEATSHEET) ;
		}
		return false;
	}

	private CheatSheet parseCheatSheet(Document document) throws CheatSheetParserException {
		// If the document passed is null return a null tree and update the status
		if (document != null) {
			Node rootnode = document.getDocumentElement();

			// Is the root node really <cheatsheet>?
			if( !rootnode.getNodeName().equals(IParserTags.CHEATSHEET) ) {
				throw new CheatSheetParserException(Messages.ERROR_PARSING_CHEATSHEET_ELEMENT);
			}

			// Create the cheat sheet model object
			CheatSheet cheatSheet = new CheatSheet();

			handleCheatSheetAttributes(cheatSheet, rootnode);

			boolean hasItem = false;
			boolean hasIntro = false;

			CheatSheetRegistryReader reader = CheatSheetRegistryReader.getInstance();
			itemExtensionContainerList = reader.readItemExtensions();

			NodeList nodes = rootnode.getChildNodes();
			for (int i = 0; i < nodes.getLength(); i++) {
				Node node = nodes.item(i);

				if(node.getNodeName().equals(IParserTags.ITEM)) {
					hasItem = true;
					Item item = handleItem(node);
					cheatSheet.addItem(item);
				} else if(node.getNodeName().equals(IParserTags.INTRO)) {
					if (hasIntro) {
						addStatus(IStatus.ERROR, Messages.ERROR_PARSING_MORE_THAN_ONE_INTRO, null);
					} else {
					    hasIntro = true;
					    handleIntroNode(cheatSheet, node);
					}
				} else {
					if(node.getNodeType() != Node.TEXT_NODE && node.getNodeType() != Node.COMMENT_NODE ) {
						String message = NLS.bind(Messages.WARNING_PARSING_UNKNOWN_ELEMENT, (new Object[] {node.getNodeName(), rootnode.getNodeName()}));
						addStatus(IStatus.WARNING, message, null);
					}
				}
			}

			if(!hasIntro) {
				addStatus(IStatus.ERROR, Messages.ERROR_PARSING_NO_INTRO, null);
			}
			if(!hasItem) {
				addStatus(IStatus.ERROR, Messages.ERROR_PARSING_NO_ITEM, null);
			}

			//handleIntro(cheatSheet, document);

			//handleItems(cheatSheet, document);

			if (status.getSeverity() == IStatus.ERROR) {
				return null;
			}

			cheatSheet.setContainsCommandOrAction(actionCount != 0 || commandCount != 0);
			return cheatSheet;
		}
		throw new CheatSheetParserException(Messages.ERROR_PARSING_CHEATSHEET_CONTENTS);
	}

	/*
	 * Normalizes composite cheat sheet-relative paths to simple cheat sheets into fully
	 * qualified paths, e.g. for the path "tasks/mySimpleCheatSheet.xml" in composite cheat
	 * sheet "/my.plugin/cheatsheets/myCompositeCheatSheet.xml", this normalizes to
	 * "/my.plugin/cheatsheets/tasks/mySimpleCheatSheet.xml".
	 *
	 * This is necessary because with dynamic content we are pulling in tasks from other
	 * plug-ins and those tasks have relative paths. It also only applies for cheat sheets
	 * located in running plug-ins.
	 */
	private class NormalizeHandler extends ProcessorHandler {

		private static final String ELEMENT_PARAM = "param"; //$NON-NLS-1$
		private static final String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$
		private static final String ATTRIBUTE_VALUE = "value"; //$NON-NLS-1$
		private static final String NAME_PATH = "path"; //$NON-NLS-1$

		@Override
		public short handle(UAElement element, String id) {
			if (id != null && ELEMENT_PARAM.equals(element.getElementName())) {
				String name = element.getAttribute(ATTRIBUTE_NAME);
				if (NAME_PATH.equals(name)) {
					String value = element.getAttribute(ATTRIBUTE_VALUE);
					if (value != null) {
						int index = id.lastIndexOf('/');
						element.setAttribute(ATTRIBUTE_VALUE, id.substring(0, index + 1) + value);
					}
				}
				return HANDLED_CONTINUE;
			}
			return UNHANDLED;
		}
	}
}
