/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. 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:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.pagedesigner.dom;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Vector;

import org.eclipse.gef.EditPart;
import org.eclipse.jface.text.Assert;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jst.pagedesigner.IHTMLConstants;
import org.eclipse.jst.pagedesigner.IJSFConstants;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.common.logging.Logger;
import org.eclipse.jst.pagedesigner.css2.ICSSStyle;
import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID;
import org.eclipse.jst.pagedesigner.parts.ElementEditPart;
import org.eclipse.jst.pagedesigner.parts.HTMLEditPartsFactory;
import org.eclipse.jst.pagedesigner.parts.NodeEditPart;
import org.eclipse.jst.pagedesigner.utils.HTMLUtil;
import org.eclipse.jst.pagedesigner.validation.caret.Target;
import org.eclipse.jst.pagedesigner.viewer.DesignPosition;
import org.eclipse.jst.pagedesigner.viewer.DesignRange;
import org.eclipse.swt.SWT;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

/**
 * @author mengbo
 */
public class EditModelQuery {
	private static Logger _log = PDPlugin.getLogger(EditModelQuery.class);

	private static EditModelQuery _instance;

	public static final int START_INDEX_BEFORE_TAG = 1;

	public static final int END_INDEX_WITHIN_TAG = 2;

	public static final HashSet SPECIAL_EMPTY_CHARS = new HashSet();

	public static final HashMap CHAR_NODE_MAP = new HashMap();

	// Cursor can't go outside of these container.
	public static final HashSet HTML_CONSTRAINED_CONTAINERS = new HashSet();

	public static final HashSet HTML_STYLE_NODES = new HashSet();

	public static final HashSet UNREMOVEBLE_TAGS = new HashSet();

	// Nodes that can hold other nodes.
	public static final String[] HTML_CONTAINER_NODES = {
	//
			IHTMLConstants.TAG_BODY, //
			IHTMLConstants.TAG_HTML, //
			IHTMLConstants.TAG_SPAN, //
			IHTMLConstants.TAG_FORM, //
			IHTMLConstants.TAG_P,//
			IHTMLConstants.TAG_SPAN,//
			IHTMLConstants.TAG_DIV,//
			IHTMLConstants.TAG_LI,//
			IHTMLConstants.TAG_OL,//
			IHTMLConstants.TAG_UL //
	};

	public static final String[] NON_HTML_CONTAINER_NODES = {
			IJSFConstants.TAG_VIEW, //
			IJSFConstants.TAG_PANELGRID, //
			IJSFConstants.TAG_PANELGROUP, //
			IJSFConstants.TAG_SUBVIEW };
	static {
		UNREMOVEBLE_TAGS.add(IHTMLConstants.TAG_HTML);
		UNREMOVEBLE_TAGS.add(IHTMLConstants.TAG_HEAD);
		UNREMOVEBLE_TAGS.add(IHTMLConstants.TAG_BODY);
		EditModelQuery.CHAR_NODE_MAP.put(new Character(SWT.CR),
				IHTMLConstants.TAG_BR);
		EditModelQuery.CHAR_NODE_MAP.put(new Character(SWT.LF),
				IHTMLConstants.TAG_BR);
		EditModelQuery.SPECIAL_EMPTY_CHARS.add(" ");
		EditModelQuery.SPECIAL_EMPTY_CHARS.add("\t");
		EditModelQuery.SPECIAL_EMPTY_CHARS.add("\r");
		EditModelQuery.SPECIAL_EMPTY_CHARS.add("\n");
		EditModelQuery.HTML_CONSTRAINED_CONTAINERS.add(IHTMLConstants.TAG_TD);
		EditModelQuery.HTML_CONSTRAINED_CONTAINERS.add(IHTMLConstants.TAG_TR);
		EditModelQuery.HTML_CONSTRAINED_CONTAINERS
				.add(IHTMLConstants.TAG_TABLE);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_B);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_EM);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_H1);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_H2);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_H3);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_H4);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_H5);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_H6);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_A);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_U);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_I);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_S);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_STRONG);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_TT);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_BIG);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_SMALL);
		EditModelQuery.HTML_STYLE_NODES.add(IHTMLConstants.TAG_FONT);
	}

	private EditModelQuery() {
        // no  external instantiation
	}

	public static EditModelQuery getInstance() {
		if (_instance == null) {
			_instance = new EditModelQuery();
		}
		return _instance;
	}

	/**
	 * Get previous sibling, or if sibling is null then get previous neighbor.
	 * 
	 * @param node
	 * @return
	 */
	public Node getPreviousNeighbor(Node node) {
		if (!EditValidateUtil.validNode(node)) {
			return null;
		}
		while (node != null && node.getNodeType() != Node.DOCUMENT_NODE
				&& node.getPreviousSibling() == null) {
			node = node.getParentNode();
		}
		return (node != null && node.getNodeType() != Node.DOCUMENT_NODE) ? node
				.getPreviousSibling()
				: null;
	}

	/**
	 * Get privous sibling, or if sibling is null then get previous neighor's
	 * rightmost child, which is adjacent to 'node'.
	 * 
	 * @param node
	 * @return
	 */
	public Node getPreviousLeafNeighbor(Node node) {
		return getLastLeafChild(getPreviousNeighbor(node));
	}

	/**
	 * Get next sibling, or if sibling is null get next neighbor.
	 * 
	 * @param node
	 * @return
	 */
	public Node getNextNeighbor(Node node) {
		if (!EditValidateUtil.validNode(node)) {
			return null;
		}

		while (node != null && node.getNodeType() != Node.DOCUMENT_NODE
				&& node.getNextSibling() == null) {
			node = node.getParentNode();
		}
		return (node != null && node.getNodeType() != Node.DOCUMENT_NODE) ? node
				.getNextSibling()
				: null;
	}

	/**
	 * Get next sibling, or if sibling is null get next neighbor's leftmost leaf
	 * child which will be adjacent to 'node'.
	 * 
	 * @param node
	 * @return
	 */
	public Node getNextLeafNeighbor(Node node) {
		return getFirstLeafChild(getNextNeighbor(node));
	}

	/**
	 * Get node's rightmost leaf child.
	 * 
	 * @param node
	 * @return
	 */
	private Node getLastLeafChild(Node node) {
		if (node == null) {
			return null;
		}
		if (node.getLastChild() != null) {
			return getLastLeafChild(node.getLastChild());
		}
        return node;
	}

	/**
	 * Get node's leftmost leaf child.
	 * 
	 * @param node
	 * @return
	 */
	protected Node getFirstLeafChild(Node node) {
		if (node == null) {
			return null;
		}

		if (node.getFirstChild() != null) {
			return getFirstLeafChild(node.getFirstChild());
		}
        return node;
	}

	/**
	 * To see if node is within a indexed region that is started from 'start',
	 * ended at 'end'
	 */
	public static boolean within(int start, int end, Node theNode) {
		return getNodeStartIndex(theNode) >= start
				&& getNodeEndIndex(theNode) <= end;
	}

	/**
	 * To see whether the 'position' is within indexed location (start, end)
	 * 
	 * @param start
	 * @param end
	 * @param position
	 * @return
	 */
	public boolean within(int start, int end, IDOMPosition position) {
		int pos = getIndexedRegionLocation(position);
		return start <= pos && pos <= end;
	}

	/**
	 * To see whether the 'theNode' is not within indexed region (start, end)
	 * 
	 * @param start
	 * @param end
	 * @param theNode
	 * @return
	 */
	public static boolean outOf(int start, int end, Node theNode) {
		if (getNodeLenth(theNode) > 0) {
			return getNodeStartIndex(theNode) >= end
					|| getNodeEndIndex(theNode) <= start;
		}
        return !((getNodeStartIndex(theNode) >= start && getNodeEndIndex(theNode) <= end));
	}

	/**
	 * Determine whether the position is at node's edge. When the offset is at
	 * edge, it is in the leftmost or rightmost offset of node's region.
	 * 
	 * @param node
	 * @param offset
	 * @param direction
	 * @return
	 */
	public boolean atEdge(IDOMPosition position, boolean forward) {
		Node node = position.getContainerNode();
		int offset = position.getOffset();
		if (forward) {
			if (EditModelQuery.isText(node)) {
				return offset == node.getNodeValue().length();
			}
            return offset == node.getChildNodes().getLength();
		}
        return offset == 0;
	}

	/**
	 * Get node's neighbor on the node tree, if forward, then get next,
	 * otherwise go backward.
	 * 
	 * @param node
	 * @param forward
	 * @return
	 */
	public Node getNeighbor(Node node, boolean forward) {
		if (forward) {
			return getNextNeighbor(node);
		}
        return getPreviousNeighbor(node);
	}

	/**
	 * Get neighbor which is descendent of root.
	 * 
	 * @param node
	 * @param root
	 * @return
	 */
	public Node getPreviousNeighbor(Node node, Node root) {
		if (!EditValidateUtil.validNode(node)) {
			return null;
		}
		while (node != null && node != root
				&& node.getNodeType() != Node.DOCUMENT_NODE
				&& node.getPreviousSibling() == null) {
			node = node.getParentNode();
		}
		return (node != null && node != root && node.getNodeType() != Node.DOCUMENT_NODE) ? node
				.getPreviousSibling()
				: null;
	}

	/**
	 * Get neighbor which is descendent of root.
	 * 
	 * @param node
	 * @param root
	 * @return
	 */
	public Node getNextNeighbor(Node node, Node root) {
		if (!EditValidateUtil.validNode(node)) {
			return null;
		}

		while (node != null && node != root
				&& node.getNodeType() != Node.DOCUMENT_NODE
				&& node.getNextSibling() == null) {
			node = node.getParentNode();
		}
		return (node != null && node != root && node.getNodeType() != Node.DOCUMENT_NODE) ? node
				.getNextSibling()
				: null;
	}

	/**
	 * Get neighbor which is descendent of root.
	 * 
	 * @param node
	 * @param forward
	 * @param root
	 * @return
	 */
	public Node getNeighbor(Node node, boolean forward, Node root) {
		Assert.isTrue(root != null);
		if (forward) {
			return getNextNeighbor(node, root);
		}
        return getPreviousNeighbor(node, root);
	}

	/**
	 * Get node's leaf child which is adjacent to 'node', according to
	 * 'forward', it will search backward or forward.
	 * 
	 * @param node
	 * @param forward
	 * @return
	 */
	public Node getLeafNeighbor(Node node, boolean forward) {
		if (node == null) {
			return null;
		}
		if (forward) {
			return getNextLeafNeighbor(node);
		}
        return getPreviousLeafNeighbor(node);
	}

	/**
	 * Get neighbor's leaf child, which is adjacent to 'node'
	 * 
	 * @param node
	 * @param childIndex
	 * @param forward
	 * @return
	 */
	public Node getLeafNeighbor(Node node, int childIndex, boolean forward) {
		if (node == null) {
			return null;
		}
		Node neighbor = getNeighbor(node, childIndex, forward);
		if (neighbor != null) {
			if (forward) {
				return getFirstLeafChild(neighbor);
			}
            return getLastLeafChild(neighbor);
		}
		return null;
	}

	/**
	 * First try sibling, if it retruns null, try search neighbor.
	 * 
	 * @param parent
	 * @param childIndex
	 * @param forward
	 * @return
	 */
	public Node getNeighbor(Node parent, int childIndex, boolean forward) {
		if (!EditValidateUtil.validNode(parent)) {
			return null;
		}

		NodeList nodeList = parent.getChildNodes();
		if (nodeList != null && nodeList.getLength() > 0) {
			if (nodeList.getLength() < childIndex) {
				return null;
			}
			Node childNode = null;
			if (!forward) {
				--childIndex;
			}
			childNode = nodeList.item(childIndex);
			if (childNode != null) {
				return childNode;
			}
            return getNeighbor(parent, forward);
		}
        if (parent.getNodeType() == Node.TEXT_NODE) {
        	return getNeighbor(parent, forward);
        }
        return null;
	}

	/**
	 * To see whether the textSelection start and end are on the same.
	 * 
	 * @param model
	 * @param textSelection
	 * @param lookForChildren
	 * @return
	 */
	public static boolean isSame(IStructuredModel model,
			TextSelection textSelection) {
		if (model != null && textSelection != null) {
			int t1 = textSelection.getOffset();
			int t2 = textSelection.getLength() + t1;
			return model.getIndexedRegion(t1) == model.getIndexedRegion(t2);
		}
		return false;
	}

	/**
	 * To see if the range and text selection covered the same range.
	 * 
	 * @param model
	 * @param range
	 * @param textSelection
	 * @return
	 */
	public static boolean isSame(IStructuredModel model, DesignRange range,
			TextSelection textSelection) {
		if (model != null && range != null && textSelection != null) {
			int t1 = textSelection.getOffset();
			int t2 = textSelection.getLength() + t1;
			int r1 = getIndexedRegionLocation(DOMRangeHelper.toDOMRange(range)
					.getStartPosition());
			int r2 = getIndexedRegionLocation(DOMRangeHelper.toDOMRange(range)
					.getEndPosition());
			return (model.getIndexedRegion(t1) == model.getIndexedRegion(r1) && //
					model.getIndexedRegion(t2) == model.getIndexedRegion(r2))
					|| (model.getIndexedRegion(t2) == model
							.getIndexedRegion(r1) && //
					model.getIndexedRegion(t1) == model.getIndexedRegion(r2));
		}
		return false;
	}

	/**
	 * To see whether the selection is single point.
	 * 
	 * @param model
	 * @param textSelection
	 * @return
	 */
	public static boolean isSamePoint(TextSelection textSelection) {
		return textSelection.getLength() == 0;
	}

	/**
	 * To see whether two IDOMPosition are pointed to a same location.
	 * 
	 * @param p1
	 * @param p2
	 * @return
	 */
	public static boolean isSame(IDOMPosition p1, IDOMPosition p2) {
		if (p1 == p2
				|| (p1.getContainerNode() == p2.getContainerNode() && p1
						.getOffset() == p2.getOffset())) {
			return true;
		}
		return false;
	}

	/**
	 * To see whether the range's start and end position are pointed to a same
	 * location.
	 * 
	 * @param range
	 * @return
	 */
	public static boolean isSame(DOMRange range) {
		EditValidateUtil.validRange(range);
		return isSame(range.getStartPosition(), range.getEndPosition());
	}

	public static boolean isSame(DesignRange range) {
		return isSame(range.getStartPosition(), range.getEndPosition());
	}

	public static boolean isSame(DesignPosition p1, DesignPosition p2) {
		if (p1 == p2) {
			return true;
		}
		if (p1.getContainerNode() == p2.getContainerNode()
				&& p1.getOffset() == p2.getOffset()) {
			return true;
		}
		return false;
	}

	public boolean isWithinSameText(IDOMPosition p1, IDOMPosition p2) {
		if (p1 == null || p2 == null) {
			return false;
		}
		return p1.isText() && p2.isText()
				&& p1.getContainerNode() == p2.getContainerNode();
	}

	/**
	 * Get the node absolute start location in its residing IStructuredModel.
	 * 
	 * @param p
	 * @return
	 */
	public static int getIndexedRegionLocation(IDOMPosition p) {
		if (!EditValidateUtil.validPosition(p)) {
			return -1;
		}
		Node parent = p.getContainerNode();
		if (p.isText()) {
			return ((IndexedRegion) parent).getStartOffset() + p.getOffset();
		}
        int index = p.getOffset();
        if (!parent.hasChildNodes()) {
        	// Element:
        	if (!isDocument(parent)) {
        		IStructuredDocumentRegion region = ((IDOMNode) parent)
        				.getStartStructuredDocumentRegion();
        		return region.getEnd();
        	}
            // Document node:
            int offset = ((IndexedRegion) parent).getStartOffset();
            return offset;
        }
        NodeList children = parent.getChildNodes();
        // After rightmost child
        if (children.getLength() == index) {
        	if (!isDocument(parent)) {
        		int pos = getNodeEndNameStartIndex(parent);
        		return pos;
        	}
            int offset = ((IndexedRegion) parent).getEndOffset();
            return offset;
        }
        Node node = children.item(index);
        return ((IndexedRegion) node).getStartOffset();
	}

	/**
	 * To determine whether the position is at the edge of a node. TODO: temp
	 * func for later combination
	 * 
	 * @param node
	 * @param position
	 * @return
	 */
	public boolean isLinked(IDOMPosition nodePos, IDOMPosition position,
			boolean left) {
		int index = getIndexedRegionLocation(position);
		if (left) {
			int pos = getIndexedRegionLocation(nodePos);
			return pos == index;
		}
        Node node = null;
        int end;
        if (nodePos.isText()) {
        	node = nodePos.getContainerNode();
        	end = ((IndexedRegion) node).getEndOffset();
        } else {
        	node = nodePos.getNextSiblingNode();
        	Assert.isTrue(node != null);
        	end = ((IndexedRegion) node).getEndOffset();
        }
        return end == index;
	}

	/**
	 * To see if the location is at the node's indexed pos, posType can be
	 * START_INDEX_BEFORE_TAG, END_INDEX_WITHIN_TAG When location is at these
	 * two position, webtools returns the container tag name, so we need to know
	 * these.
	 * 
	 * @param location
	 * @param node
	 * @return
	 */
	public boolean isAtNodeNameEdge(int location, Node node, int posType) {
		int start = getNodeEndNameStartIndex(node);
		return location == start;
	}

	public boolean isAtNodeNameEdge(int location, Node node) {
		return isAtNodeNameEdge(location, node, START_INDEX_BEFORE_TAG)
				|| isAtNodeNameEdge(location, node, END_INDEX_WITHIN_TAG);
	}

	/**
	 * If text only contains chars '\r' or '\n', it is considered to be
	 * transparent.
	 * 
	 * @param node
	 * @return
	 */
	public static boolean isTransparentText(Node node) {
		// should valid non null?
		Assert.isTrue(node != null);
		if (node == null || !isText(node)) {
			return false;
		}
		if (!EditValidateUtil.validText(node)) {
			return false;
		}

		Text text = (Text) node;
		if (text.getLength() == 0) {
			return true;
		}
		String value = text.getNodeValue();
		int i = 0;
		while (i < value.length() && HTMLUtil.isHTMLWhitespace(value.charAt(i))) {
			i++;
		}
		return i == value.length();
	}

	/**
	 * Get node index in its parent's children.
	 * 
	 * @param node
	 * @return
	 */
	public static int getNodeIndex(Node node) {
		EditValidateUtil.validNode(node);
		Node parent = node.getParentNode();
		int index = 0;
		for (Node child = parent.getFirstChild(); child != null; child = child
				.getNextSibling()) {
			if (child == node) {
				return index;
			}
			index++;
		}
		return -1; // error
	}

	/**
	 * If parent has more than one children of which each node's localName is
	 * the same as of 'node', return the index of 'node' in the same type
	 * children list.
	 * 
	 * @param node
	 * @return
	 */
	public int getSameTypeNodeIndex(Node node) {
		EditValidateUtil.validNode(node);
		int i = 0;
		while (node != null) {
			Node sibling = node.getPreviousSibling();
			if (sibling != null && sibling.getLocalName() != null
					&& sibling.getLocalName().equals(node.getLocalName())) {
				i++;
			}
			node = sibling;
		}
		return i; // error
	}

	/**
	 * Start from position, skip transparent chars, and returns the first
	 * non-transparent char's index. based on 'forward', go previously or next .
	 * 
	 * @param value
	 * @param position
	 * @param forward
	 * @return
	 */
	public int getNextConcretePosition(String value, int position,
			boolean forward) {
		if (value == null) {
			return -1;
		}
		if (value.length() == 0) {
			return 0;
		}
		// validate
		Assert.isTrue(position >= 0 && position <= value.length());
		int i = -1;
		if (forward) {
			i = position;
			while (i < value.length()
					&& (value.charAt(i) == SWT.CR || value.charAt(i) == SWT.LF)) {
				i++;
			}
			return i;
		}
        i = position - 1;
        while (i >= 0
        		&& (value.charAt(i) == SWT.CR || value.charAt(i) == SWT.LF)) {
        	i--;
        }
        return i + 1;
	}

	/**
	 * Get two nodes' lowest common ancestor.
	 * 
	 * @param node1
	 * @param node2
	 * @return
	 */
	public Node getCommonAncestor(Node node1, Node node2) {
		if (node1 == null || node2 == null) {
			return null;
		}

		for (Node na = node1; na != null; na = na.getParentNode()) {
			for (Node ta = node2; ta != null; ta = ta.getParentNode()) {
				if (ta == na)
					return ta;
			}
		}
		return null; // not found
	}

	/**
	 * Get lowest common ancestor of two IDOMPositions' container nodes..
	 * 
	 * @param p1
	 * @param p2
	 * @return
	 */
	public Node getCommonAncestor(IDOMPosition p1, IDOMPosition p2) {
		Node n1 = p1.getContainerNode();
		Node n2 = p2.getContainerNode();
		return getCommonAncestor(n1, n2);
	}

	/**
	 * Get lowest ancestor of a 'node' which is block type.
	 * 
	 * @param node
	 * @return
	 */
	public Node getBlockAncestor(Node node) {
		if (!EditValidateUtil.validNode(node)) {
			return null;
		}
		while (node != null && isChild(IHTMLConstants.TAG_BODY, node, true)) {
			if (isBlockNode(node)) {
				return node;
			}
			node = node.getParentNode();
		}
		return null;
	}

	/**
	 * To see whether a node is block type.
	 * 
	 * @param node
	 * @return
	 */
	public static boolean isBlockNode(Node node) {
		return !isInline(node);
	}

	public static boolean isTableCell(Node node) {
		if (node instanceof INodeNotifier) {
			Object adapter = ((INodeNotifier) node)
					.getAdapterFor(ICSSStyle.class);
			if (adapter != null) {
				ICSSStyle style = (ICSSStyle) adapter;
				String display = style.getDisplay();
				return display.equalsIgnoreCase(ICSSPropertyID.VAL_TABLE_CELL);
			}
		}
		return false;
	}

	/**
	 * To see if a node's display type is inline.
	 * 
	 * @param node
	 * @return
	 */
	public static boolean isInline(Node refNode) {
		Node node = refNode;
		EditPart part = Target.resolvePart(node);
		if (part instanceof ElementEditPart) {
			node = ((ElementEditPart) part).getTagConvert().getResultElement();
		}
		if (isText(node)) {
			return true;
		} else if (node instanceof INodeNotifier) {
			Object adapter = ((INodeNotifier) node)
					.getAdapterFor(ICSSStyle.class);
			if (adapter != null) {
				ICSSStyle style = (ICSSStyle) adapter;
				String display = style.getDisplay();
				return (display.equalsIgnoreCase(ICSSPropertyID.VAL_INLINE)
						|| //
						display
								.equalsIgnoreCase(ICSSPropertyID.VAL_INLINE_TABLE)
						|| //
						display.equalsIgnoreCase(ICSSPropertyID.VAL_COMPACT) || //
				display.equalsIgnoreCase(ICSSPropertyID.VAL_RUN_IN));
			}
		}
		return false;
	}

	public static boolean isListItem(Node node) {
		if (node instanceof INodeNotifier) {
			Object adapter = ((INodeNotifier) node)
					.getAdapterFor(ICSSStyle.class);
			if (adapter != null) {
				ICSSStyle style = (ICSSStyle) adapter;
				String display = style.getDisplay();
				return (display.equalsIgnoreCase(ICSSPropertyID.VAL_LIST_ITEM));
			}
		}
		return false;
	}

	/**
	 * Determine whether a node is a child of node that is named as 'name', if
	 * the node itself is named as 'name' return true also.
	 * 
	 * @param names
	 * @param node
	 * @return
	 */
	public static boolean isChild(String names[], Node node,
			boolean ignoreCase, boolean noSame) {
		if (node == null) {
			return false;
		}
		if (noSame) {
			node = node.getParentNode();
		}
		while (node != null && !isDocument(node)) {
			String nodeName = node.getLocalName();
			if (nodeName != null
					&& (ignoreCase
							&& Arrays.asList(names).contains(
									nodeName.toLowerCase()) || !ignoreCase
							&& Arrays.asList(names).contains(nodeName))) {
				return true;
			}
			node = node.getParentNode();
		}
		return false;
	}

	/**
	 * Determine whether a node is a child of node that is named as 'name', if
	 * the node itself is named as 'name' return true also.
	 * 
	 * @param name
	 * @param node
	 * @return
	 */
	public static boolean isChild(String name, Node node, boolean ignoreCase) {
		if (node == null) {
			return false;
		}

		while (node != null && node.getNodeType() != Node.DOCUMENT_NODE) {
			String nodeName = node.getLocalName();
			if (nodeName != null
					&& (ignoreCase && name.equalsIgnoreCase(nodeName) || !ignoreCase
							&& name.equalsIgnoreCase(nodeName))) {
				return true;
			}
			node = node.getParentNode();
		}
		return false;
	}

	/**
	 * To see whether 'node' is 'ancestor's child.
	 * 
	 * @param ancestor
	 * @param node
	 * @return
	 */
	public static boolean isChild(Node ancestor, Node node) {
		if (node == null || ancestor == null) {
			return false;
		}

		if (isDocument(ancestor)) {
			return true;
		}
		while (node != null && !isDocument(ancestor)) {
			if (node == null) {
				break;
			}
			if (node == ancestor) {
				return true;
			}
			node = node.getParentNode();
		}
		return false;
	}

	/**
	 * Get next sibling node to position's container node.
	 * 
	 * @param position
	 * @return
	 */
	public Node getNextSibling(IDOMPosition position) {
		if (position.isText()) {
			return position.getContainerNode().getNextSibling();
		}
        return position.getNextSiblingNode();
	}

	/**
	 * Get previous sibling node to position's container node.
	 * 
	 * @param position
	 * @return
	 */
	public Node getPreviousSibling(IDOMPosition position) {
		if (position.isText()) {
			return position.getContainerNode().getPreviousSibling();
		}
        return position.getPreviousSiblingNode();
	}

	/**
	 * Get position's container node's parent.
	 * 
	 * @param position
	 * @return
	 */
	public Node getParent(IDOMPosition position) {
		if (position.isText()) {
			return position.getContainerNode().getParentNode();
		}
        return position.getContainerNode();
	}

	/**
	 * Get node's sibling according to 'forward' direction
	 * 
	 * @param node
	 * @param forward
	 * @return
	 */
	public Node getSibling(Node node, boolean forward) {
		EditValidateUtil.validNode(node);
		if (forward) {
			return node.getNextSibling();
		}
        return node.getPreviousSibling();
	}

	/**
	 * Get position's container node's sibling.
	 * 
	 * @param position
	 * @param forward
	 * @return
	 */
	public Node getSibling(IDOMPosition position, boolean forward) {
		if (forward) {
			return getNextSibling(position);
		}
        return getPreviousSibling(position);
	}

	/**
	 * Get position's container node's editable items number. this is temp
	 * functions for future use.
	 * 
	 * @param position
	 * @return
	 */
	public int getSize(IDOMPosition position) {
		EditValidateUtil.validPosition(position);
		if (position.isText()) {
			return ((Text) position.getContainerNode()).getLength();
		}
        if (position.getContainerNode().hasChildNodes()) {
        	return position.getContainerNode().getChildNodes().getLength();
        }
        return 0;
	}

	/**
	 * Valid position and return text, if it contains text node.
	 * 
	 * @param position
	 * @return
	 */
	public Text getText(IDOMPosition position) {
		if (position.isText()) {
			if (position.getContainerNode() != null) {
				return (Text) position.getContainerNode();
			}
		}
		return null;
	}

	public static Document getDocumentNode(Node node) {
		if (node != null) {
			return isDocument(node) ? (Document) node : node.getOwnerDocument();
		}
		return null;
	}

	/**
	 * To see whether a node is empty, here we can insert rules to see whether
	 * it is empty, for delete operation, it could be deleted.
	 * 
	 * @param node
	 * @return
	 */
	public static boolean isEmptyNode(Node node) {
		if (node.getNodeType() == Node.TEXT_NODE) {
			return isTransparentText(node);
		}
		if (node.getChildNodes() == null
				|| node.getChildNodes().getLength() == 0) {
			return true;
		}
		return false;
	}

	/**
	 * To see whther a node is text node.
	 * 
	 * @param node
	 * @return
	 */
	public static boolean isText(Node node) {
		return node != null && node.getNodeType() == Node.TEXT_NODE;
	}

	/**
	 * To see whether a node is Document node.
	 * 
	 * @param node
	 * @return
	 */
	public static boolean isDocument(Node node) {
		return node != null && node.getNodeType() == Node.DOCUMENT_NODE;
	}

    // TODO: dead?
//	private static boolean isHead(Node node) {
//		return node.getNodeName().equalsIgnoreCase(IHTMLConstants.TAG_HEAD);
//	}

	/**
	 * Get style from parent node. from first paret 'firstF', we will traverse
	 * the tree up untile reaching Document node, get all style node's, we may
	 * insert rules here to stop the search at a before paricular node. Style
	 * nodes could <b>, <u>...
	 * 
	 * @param children
	 * @param firstF
	 * @return
	 */
	public void assignFather(Vector children, Node firstF) {
		if (children.size() == 0) {
			return;
		}
		if (firstF != null && !isDocument(firstF)) {
			String name = firstF.getNodeName();
			// To see whether it is a style node that is our anticipated node.
			if (name != null && HTML_STYLE_NODES.contains(name.toLowerCase())) {
				Node newParent = firstF.cloneNode(false);
				while (children.size() > 0) {
					newParent.appendChild((Node) children.remove(0));
				}
				children.add(newParent);
			}
			assignFather(children, firstF.getParentNode());
		}
	}

	/**
	 * Get a node that is at Indexed position 'pos' in 'model'.
	 * 
	 * @param model
	 * @param pos
	 * @return
	 */
	public Object getPosNode(IStructuredModel model, int pos) {
		IndexedRegion inode = model.getIndexedRegion(pos);
		return inode;
	}

	/**
	 * If the pos is at right edge within container.
	 * 
	 * @param model
	 * @param pos
	 * @return
	 */
	public boolean isAtRightMostWithin(Node node, int pos) {
		return getNodeEndNameStartIndex(node) == pos;
	}

	/**
	 * Create the node, if 'refNode' is null, then position is at the edge of
	 * 'container'. otherwize calculate refNode's related index in its parent's
	 * children list and return DOMPosition.
	 * 
	 * @param container
	 * @param refNode
	 * @param forward
	 * @return
	 */
	public IDOMPosition createDomposition(Node container, Node refNode,
			boolean forward) {
		if (refNode == null) {
			if (forward && container.hasChildNodes()) {
				return new DOMPosition(container, container.getChildNodes()
						.getLength());
			}
            return new DOMPosition(container, 0);
		}
        Assert.isTrue(refNode.getParentNode() == container);
        int index = getNodeIndex(refNode);
        if (!forward) {
        	index++;
        }
        return new DOMPosition(container, index);
	}

	public static DesignRange convertToDesignRange(IStructuredModel fModel,
			TextSelection textSelection) {
		int start = textSelection.getOffset();
		int end = textSelection.getLength() + start;
		IDOMPosition startDomPos = EditModelQuery.getInstance()
				.createDomposition((IDOMModel) fModel, start, false);
		IDOMPosition endDomPos = EditModelQuery.getInstance()
				.createDomposition((IDOMModel) fModel, end, false);
		if (startDomPos == null) {
			startDomPos = endDomPos;
		} else if (endDomPos == null) {
			endDomPos = startDomPos;
		}
		if (startDomPos != null) {
			DesignPosition startPos = null, endPos = null;
			startPos = DOMPositionHelper.toDesignPosition(startDomPos);
			endPos = DOMPositionHelper.toDesignPosition(endDomPos);
			if (startPos != null) {
				return new DesignRange(startPos, endPos);
			}
		}
		return null;
	}

	/**
	 * Create IDOMPosition based on Indexed 'position' in model. If node at
	 * position is text, use position to calculate DOMPosition offset,
	 * otherwize, simply create position pointed to container's children list's
	 * edge.
	 * 
	 * @param container
	 * @param position
	 * @return
	 */
	public IDOMPosition createDomposition(IDOMModel model, int position,
			boolean adjust) {
		return createDomposition1(model, position, adjust);
	}

	/**
	 * Create IDOMPosition based on Indexed 'position' in model. If node at
	 * position is text, use position to calculate DOMPosition offset,
	 * otherwize, simply create position pointed to container's children list's
	 * edge.
	 * 
	 * @param container
	 * @param position
	 * @return
	 */
	public IDOMPosition createDomposition1(IDOMModel model, int position,
			boolean adjust) {
		try {
            // TODO: never read
//			IMovementMediator validator = new InlineEditingNavigationMediator(
//					new ActionData(ActionData.INLINE_EDIT, null));
			// get the container
			Object object = getPosNode(model, position);
			if (object == null && position > 0) {
				// The end of file?
				object = getPosNode(model, position - 1);
			}
			Node container = null;
			if (object == null) {
				// empty file?
				return new DOMPosition(model.getDocument(), 0);
			}
			container = (Node) object;
			Object oppNode = getPosNode(model, position - 1);
			if (oppNode != null
					&& !EditModelQuery.isChild((Node) oppNode, container)
					&& //
					!EditModelQuery.isInline(container)
					&& EditModelQuery.isInline((Node) oppNode)) {
				container = (Node) oppNode;
			}
			int location = EditHelper.getInstance().getLocation(container,
					position, false);
			IDOMPosition result = null;
			switch (location) {
			case 1:
			case 2:
				result = new DOMRefPosition(container, false);
				break;
			case 4:
			case 5:
				result = new DOMRefPosition(container, true);
				break;
			case 3:
				if (EditModelQuery.isText(container)) {
					result = new DOMPosition(container, position
							- EditModelQuery.getNodeStartIndex(container));
				} else {
					result = new DOMPosition(container, container
							.getChildNodes().getLength());
				}
			}
			return result;
		} catch (Exception e) {
			// "Error in position creation"
			_log.error("Error.EditModelQuery.0" + e); //$NON-NLS-1$
			return null;
		}
	}

	/**
	 * Calculate node's Indexed length in model.
	 * 
	 * @param node
	 * @return
	 */
	public static int getNodeLenth(Node node) {
		if (node != null
               && EditValidateUtil.validNode(node)) {
			return ((IndexedRegion) node).getEndOffset()
					- ((IndexedRegion) node).getStartOffset();
		}
        return 0;
	}

	/**
	 * Return 'node' indexed start position Example: |<a></a>, the position is
	 * indicated by '|'
	 * 
	 * @param node
	 * @return
	 */
	public static int getNodeStartIndex(Node node) {
		if (EditValidateUtil.validNode(node) && node instanceof IndexedRegion) {
			return ((IndexedRegion) node).getStartOffset();
		}
		return -1;
	}

	/**
	 * Return 'node' indexed end position Example: <a></a>|, the position is
	 * indicated by '|'
	 * 
	 * @param node
	 * @return
	 */
	public static int getNodeEndIndex(Node node) {
		if (EditValidateUtil.validNode(node) && node instanceof IndexedRegion) {
			return ((IndexedRegion) node).getEndOffset();
		}
		return -1;
	}

	/**
	 * Get node at indexed position.
	 * 
	 * @param position
	 * @return
	 */
	public static Node getNodeAt(IStructuredModel model, int position) {
		try {
			IndexedRegion region = model.getIndexedRegion(position);
			if (region instanceof Node) {
				return (Node) region;
			}
			return null;
		} catch (Exception e) {
			// "Error in region node creation"
			_log.error("Error.EditModelQuery.1", e); //$NON-NLS-1$
			return null;
		}
	}

	/**
	 * Return 'node' indexed start name's end position Example: <a>|aaa </a>,
	 * the position is indicated by '|'
	 * 
	 * @param node
	 * @return
	 */
	public static int getNodeStartNameEndIndex(Node node) {
		if (isText(node)) {
			return getNodeStartIndex(node);
		}
		if (EditValidateUtil.validNode(node) && node instanceof IDOMNode) {
			IStructuredDocumentRegion region = ((IDOMNode) node)
					.getStartStructuredDocumentRegion();
			if (region != null) {
				return region.getEndOffset();
			}
			// else
			// {
			// // if (node.hasChildNodes())
			// // {
			// // // Node should always have start name, so this part should
			// never reach,
			// // // the assert is for inner debug.
			// // Assert.isTrue(false);
			// // return getNodeStartIndex(node);
			// // }
			// }
		}
		// This should never happen.
		return getNodeStartIndex(node);
	}

	/**
	 * Return 'node' indexed end name' start position Example: <a>aaa| </a>, the
	 * position is indicated by '|' If node is <a /> style or there is no </a>
	 * to pair with <a>, the function return -1.
	 * 
	 * @param node
	 * @return
	 */
	public static int getNodeEndNameStartIndex(Node node) {
		if (isText(node)) {
			return getNodeEndIndex(node);
		}
		if (EditValidateUtil.validNode(node) && node instanceof IDOMNode) {
			IStructuredDocumentRegion region = ((IDOMNode) node)
					.getEndStructuredDocumentRegion();
			if (region != null) {
				return region.getStartOffset();
			}
			// else
			// {
			// if (node.hasChildNodes())
			// {
			// return getNodeEndIndex(node);
			// }
			// }
		}
		return getNodeEndIndex(node);
	}

	/**
	 * To see if a node is <a/>style.
	 * 
	 * @param node
	 * @return
	 */
	public boolean isSingleRegionNode(Node node) {
		if (getNodeEndNameStartIndex(node) == getNodeEndIndex(node)
				&& !node.hasChildNodes()) {
			return true;
		}
		return false;
	}

	/**
	 * To see if a node has child that is not transparent child only.
	 * 
	 * @param node
	 * @return
	 */
	public boolean hasNonTransparentChild(Node node) {
        NodeList children = node.getChildNodes();
        for (int i = 0, n = children.getLength(); i < n; i++) {
        	Object child = children.item(i);
        	if (isText((Node) child)) {
        		if (!isTransparentText((Node) child)) {
        			return true;
        		}
        	} else {
        		return true;
        	}
        }
		return false;
	}

	/**
	 * To see if a node has child that is not transparent child only.
	 * 
	 * @param node
	 * @return
	 */
	public boolean hasNonTransparentChild(Node node, String[] excludes) {
		if (!node.hasChildNodes()) {
			return false;
		}
        NodeList children = node.getChildNodes();
        for (int i = 0, n = children.getLength(); i < n; i++) {
        	Object child = children.item(i);
        	if (isText((Node) child)) {
        		if (!isTransparentText((Node) child)) {
        			return true;
        		}
        	} else if (!Arrays.asList(excludes).contains(
        			((Node) child).getLocalName())) {
        		return true;
        	}
        }
		return false;
	}

	/**
	 * To see whether tag has whitespace char.
	 * 
	 * @param node
	 * @return
	 */
	public boolean hasWhitespaceNeighbor(Node node) {
		node = getNeighbor(node, true);
		if (isWidget(node)) {
			return false;
		}
        node = getFirstLeafChild(node);
        return isTransparentText(node);

	}

	/**
	 * @param host
	 * @return
	 */
	public static boolean isWidget(Object host) {
		boolean result = false;
		EditPart part = null;
		if (host instanceof EditPart) {
			part = (EditPart) host;
		} else if (host instanceof Node) {
			part = Target.resolvePart((Node) host);
			if (part == null) {
				part = new HTMLEditPartsFactory(
						(IDOMDocument) getDocumentNode((Node) host))
						.createEditPart(null, host);
			}
		}
		if (part instanceof NodeEditPart) {
			result = ((NodeEditPart) part).isWidget();
		}
		return result;
	}

	/**
	 * To combind whitespace chars, only one whitespace string should be create.
	 * 
	 * @param node
	 * @return
	 */
	public boolean isRedundantWightspaces(Node node) {
		if (isTransparentText(node) && hasWhitespaceNeighbor(node)) {
			return true;
		}
        return false;
	}

	public static boolean hasAncestor(Node node, String names[],
			boolean ignoreCase) {
		Assert.isTrue(names != null);
		while (node != null && !EditModelQuery.isDocument(node)) {
			if (isElement(node))
				if (containItem(names, node, ignoreCase)) {
					return true;
				}
			node = node.getParentNode();
		}
		return false;
	}

	/**
	 * To see if 'node' has ancestor that has name as 'name'
	 * 
	 * @param node
	 * @param name
	 * @param ignoreCase
	 * @return
	 */
	public static boolean hasAncestor(Node node, String name, boolean ignoreCase) {
		Assert.isTrue(name != null);
		while (node != null && !EditModelQuery.isDocument(node)) {
			if (node.getNodeName() != null)
				if ((ignoreCase && name.equalsIgnoreCase(node.getNodeName())) || //
						(!ignoreCase && name.equals(node.getNodeName()))) {
					return true;
				}
			node = node.getParentNode();
		}
		return false;
	}

	/**
	 * To see if 'node' has direct ancestors that has names listed in 'name[]'
	 * 
	 * @param node
	 * @param name
	 * @param ignoreCase
	 * @return
	 */
	public static List getAncestors(Node node, String top, boolean ignoreCase) {
		List result = new ArrayList();
		Assert.isTrue(node != null);
		while (node != null && !EditModelQuery.isDocument(node)) {
			result.add(node);
			String name = node.getLocalName();
			if (ignoreCase && top.equalsIgnoreCase(name) || //
					(!ignoreCase && top.equals(name))) {
				break;
			}
			node = node.getParentNode();
		}
		return result;
	}

	/**
	 * Copy old node's children to newNode.If the newNode is the father of the
	 * old node,then the old node's children will be inserted before the old
	 * node,otherwise,the old node's children just append to the newNode.
	 * 
	 * @param old
	 * @param newNode
	 * @return
	 */
	public static void copyChildren(Node old, Node newNode) {
		Node child = old.getFirstChild();
		while (child != null) {
			Node next = child.getNextSibling();
			child = old.removeChild(child);
			if (old.getParentNode() == newNode) {
				newNode.insertBefore(child, old);
			} else {
				newNode.appendChild(child);
			}
			child = next;
		}
	}

	public static boolean isElement(Node node) {
		return node.getNodeType() == Node.ELEMENT_NODE;
	}

	/**
	 * Return a offspring of ancestor, the offsprint has a name listed in
	 * childrenNames.
	 * 
	 * @param ancestor
	 * @param childrenNames
	 * @param maxLevelToSearch:
	 *            the max level from ancestor to the offspring in family tree.
	 * @param ignoreCase
	 * @return
	 */
	public static Node getChild(Node ancestor, String childrenNames[],
			int maxLevelToSearch, boolean ignoreCase) {
		if (ancestor == null || maxLevelToSearch < 0) {
			return null;
		}
        if (ancestor.getLocalName() != null
        		&& ignoreCase
        		&& Arrays.asList(childrenNames).contains(
        				ancestor.getLocalName().toLowerCase())
        		|| !ignoreCase
        		&& Arrays.asList(childrenNames).contains(
        				ancestor.getLocalName())) {
        	return ancestor;
        }
		NodeList children = ancestor.getChildNodes();
		for (int i = 0, n = children.getLength(); i < n; i++) {
			Node result = getChild(children.item(i), childrenNames,
					maxLevelToSearch - 1, ignoreCase);
			if (result != null) {
				return result;
			}
		}
		return null;
	}

	/**
	 * Return a offspring of ancestor, the nodes on the tree are type of
	 * DeferredElementImpl, the offsprint has a name listed in childrenNames.
	 * 
	 * @param ancestor
	 * @param childrenNames
	 * @param maxLevelToSearch:
	 *            the max level from ancestor to the offspring in family tree.
	 * @param ignoreCase
	 * @return
	 */
	public static Node getChildDeferredNode(Node ancestor,
			String childrenNames[], int maxLevelToSearch, boolean ignoreCase) {
		if (ancestor == null || maxLevelToSearch < 0) {
			return null;
		}
        String nodeName = ancestor.getNodeName();
        if (nodeName != null && ignoreCase
        		&& Arrays.asList(childrenNames).contains(nodeName)
        		|| !ignoreCase
        		&& Arrays.asList(childrenNames).contains(nodeName)) {
        	return ancestor;
        }
		NodeList children = ancestor.getChildNodes();
		for (int i = 0, n = children.getLength(); i < n; i++) {
			Node result = getChildDeferredNode(children.item(i), childrenNames,
					maxLevelToSearch - 1, ignoreCase);
			if (result != null) {
				return result;
			}
		}
		return null;
	}

	public static boolean hasTransparentNodeOnly(Node node) {
		NodeList children = node.getChildNodes();
		for (int i = 0, n = children.getLength(); i < n; i++) {
			if (!EditModelQuery.isTransparentText(children.item(i))) {
				return false;
			}
		}
		return true;
	}

	public static Node getParent(String name, Node node, boolean ignoreCase) {
		if (node == null) {
			return null;
		}

		while (node != null && node.getNodeType() != Node.DOCUMENT_NODE) {
			String nodeName = node.getLocalName();
			if (nodeName != null
					&& (ignoreCase && name.equalsIgnoreCase(nodeName) || !ignoreCase
							&& name.equalsIgnoreCase(nodeName))) {
				return node;
			}
			node = node.getParentNode();
		}
		return null;
	}

	/**
	 * get Elements with the same localName as the input localName under the
	 * rootNode,it is a recursive computation.
	 * 
	 * @param rootNode
	 * @param localName
	 * @param caseSensitive
	 * @param list
	 *            The input list to hold the matched elements.
	 */
	public static void getElementByLocalName(Node rootNode, String localName,
			boolean caseSensitive, List list) {
		if (list == null) {
			return;
		}
		NodeList nodeList = rootNode.getChildNodes();
		if (nodeList != null && nodeList.getLength() > 0) {
			for (int i = 0, size = nodeList.getLength(); i < size; i++) {
				Node node = nodeList.item(i);
				if (node.getNodeType() == Node.ELEMENT_NODE) {
					String nodeLocalName = node.getLocalName();
					if (caseSensitive && localName.equals(nodeLocalName)) {
						list.add(node);
					} else if (!caseSensitive
							&& localName.equalsIgnoreCase(nodeLocalName)) {
						list.add(node);
					}
					getElementByLocalName(node, localName, true, list);
				}

			}
		}
	}

	public static boolean containItem(String[] tags, Node node,
			boolean ignoreCase) {
		if (ignoreCase) {
			for (int i = 0, size = tags.length; i < size; i++) {
				if (tags[i] == null) {
					continue;
				}
				if (tags[i].equalsIgnoreCase(node.getNodeName())) {
					return true;
				}
			}
		} else {
			for (int i = 0, size = tags.length; i < size; i++) {
				if (tags[i] == null) {
					continue;
				}
				if (tags[i].equals(node.getNodeName())) {
					return true;
				}
			}
		}
		return false;
	}
}
