/*******************************************************************************
 * Copyright (c) 2001, 2005 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.xml.core.internal.document;



import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.xml.core.internal.commentelement.impl.CommentElementConfiguration;
import org.eclipse.wst.xml.core.internal.commentelement.impl.CommentElementRegistry;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Text;


/**
 * XMLModelParser
 */
public class XMLModelParser {
	private XMLModelContext context = null;
	private DOMModelImpl model = null;

	/**
	 */
	protected XMLModelParser(DOMModelImpl model) {
		super();

		if (model != null) {
			this.model = model;
		}
	}

	/**
	 */
	protected boolean canBeImplicitTag(Element element) {
		ModelParserAdapter adapter = getParserAdapter();
		if (adapter != null) {
			return adapter.canBeImplicitTag(element);
		}
		return false;
	}

	/**
	 */
	protected boolean canBeImplicitTag(Element element, Node child) {
		ModelParserAdapter adapter = getParserAdapter();
		if (adapter != null) {
			return adapter.canBeImplicitTag(element, child);
		}
		return false;
	}

	/**
	 */
	protected boolean canContain(Element element, Node child) {
		if (element == null || child == null)
			return false;
		ElementImpl impl = (ElementImpl) element;
		if (impl.isEndTag())
			return false; // invalid (floating) end tag
		if (!impl.isContainer())
			return false;
		if (child.getNodeType() != Node.TEXT_NODE) {
			if (impl.isJSPContainer() || impl.isCDATAContainer()) {
				// accepts only Text child
				return false;
			}
		}
		ModelParserAdapter adapter = getParserAdapter();
		if (adapter != null) {
			return adapter.canContain(element, child);
		}
		return true;
	}

	/**
	 */
	private void changeAttrEqual(IStructuredDocumentRegion flatNode, ITextRegion region) {
		int offset = flatNode.getStart();
		if (offset < 0)
			return;
		NodeImpl root = (NodeImpl) this.context.getRootNode();
		if (root == null)
			return;
		Node node = root.getNodeAt(offset);
		if (node == null)
			return;
		if (node.getNodeType() != Node.ELEMENT_NODE) {
			if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
				// just notify the change instead of setting data
				ProcessingInstructionImpl pi = (ProcessingInstructionImpl) node;
				pi.notifyValueChanged();
			}
			return;
		}
		// actually, do nothing
	}

	/**
	 * changeAttrName method
	 * 
	 */
	private void changeAttrName(IStructuredDocumentRegion flatNode, ITextRegion region) {
		int offset = flatNode.getStart();
		if (offset < 0)
			return;
		NodeImpl root = (NodeImpl) this.context.getRootNode();
		if (root == null)
			return;
		Node node = root.getNodeAt(offset);
		if (node == null)
			return;
		if (node.getNodeType() != Node.ELEMENT_NODE) {
			if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
				// just notify the change instead of setting data
				ProcessingInstructionImpl pi = (ProcessingInstructionImpl) node;
				pi.notifyValueChanged();
			}
			return;
		}

		ElementImpl element = (ElementImpl) node;
		NamedNodeMap attributes = element.getAttributes();
		if (attributes == null)
			return;
		int length = attributes.getLength();
		for (int i = 0; i < length; i++) {
			AttrImpl attr = (AttrImpl) attributes.item(i);
			if (attr == null)
				continue;
			if (attr.getNameRegion() != region)
				continue;

			String name = flatNode.getText(region);
			attr.setName(name);
			break;
		}
	}

	/**
	 * changeAttrValue method
	 * 
	 */
	private void changeAttrValue(IStructuredDocumentRegion flatNode, ITextRegion region) {
		int offset = flatNode.getStart();
		if (offset < 0)
			return;
		NodeImpl root = (NodeImpl) this.context.getRootNode();
		if (root == null)
			return;
		Node node = root.getNodeAt(offset);
		if (node == null)
			return;
		if (node.getNodeType() != Node.ELEMENT_NODE) {
			if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
				// just notify the change instead of setting data
				ProcessingInstructionImpl pi = (ProcessingInstructionImpl) node;
				pi.notifyValueChanged();
			}
			return;
		}

		ElementImpl element = (ElementImpl) node;
		NamedNodeMap attributes = element.getAttributes();
		if (attributes == null)
			return;
		int length = attributes.getLength();
		for (int i = 0; i < length; i++) {
			AttrImpl attr = (AttrImpl) attributes.item(i);
			if (attr == null)
				continue;
			if (attr.getValueRegion() != region)
				continue;
			// just notify the change instead of setting value
			attr.notifyValueChanged();
			break;
		}
	}

	/**
	 * changeData method
	 * 
	 */
	private void changeData(IStructuredDocumentRegion flatNode, ITextRegion region) {
		int offset = flatNode.getStart();
		if (offset < 0)
			return;
		NodeImpl root = (NodeImpl) this.context.getRootNode();
		if (root == null)
			return;
		Node node = root.getNodeAt(offset);
		if (node == null)
			return;
		switch (node.getNodeType()) {
			case Node.TEXT_NODE : {
				TextImpl text = (TextImpl) node;
				if (text.isSharingStructuredDocumentRegion(flatNode)) {
					// has consecutive text sharing IStructuredDocumentRegion
					changeStructuredDocumentRegion(flatNode);
					return;
				}
				this.context.setNextNode(node);
				cleanupText();
				break;
			}
			case Node.CDATA_SECTION_NODE :
			case Node.PROCESSING_INSTRUCTION_NODE :
				break;
			case Node.COMMENT_NODE :
			case Node.ELEMENT_NODE :
				// comment tag
				changeStructuredDocumentRegion(flatNode);
				return;
			default :
				return;
		}

		// just notify the change instead of setting data
		NodeImpl impl = (NodeImpl) node;
		impl.notifyValueChanged();
	}

	/**
	 */
	private void changeEndTag(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
		int offset = flatNode.getStart();
		if (offset < 0)
			return; // error
		NodeImpl root = (NodeImpl) this.context.getRootNode();
		if (root == null)
			return; // error
		Node node = root.getNodeAt(offset);
		if (node == null)
			return; // error

		if (node.getNodeType() != Node.ELEMENT_NODE) {
			changeStructuredDocumentRegion(flatNode);
			return;
		}

		// check if change is only for close tag
		if (newRegions != null) {
			Iterator e = newRegions.iterator();
			while (e.hasNext()) {
				ITextRegion region = (ITextRegion) e.next();
				String regionType = region.getType();
				if (regionType == DOMRegionContext.XML_TAG_CLOSE)
					continue;

				// other region has changed
				changeStructuredDocumentRegion(flatNode);
				return;
			}
		}
		if (oldRegions != null) {
			Iterator e = oldRegions.iterator();
			while (e.hasNext()) {
				ITextRegion region = (ITextRegion) e.next();
				String regionType = region.getType();
				if (regionType == DOMRegionContext.XML_TAG_CLOSE)
					continue;

				// other region has changed
				changeStructuredDocumentRegion(flatNode);
				return;
			}
		}

		// change for close tag has no impact
		// do nothing
	}

	/**
	 * changeRegion method
	 * 
	 */
	void changeRegion(IStructuredDocumentRegion flatNode, ITextRegion region) {
		if (flatNode == null || region == null)
			return;
		if (this.model.getDocument() == null)
			return;
		this.context = new XMLModelContext(this.model.getDocument());

		// optimize typical cases
		String regionType = region.getType();
		if (regionType == DOMRegionContext.XML_CONTENT || regionType == DOMRegionContext.XML_COMMENT_TEXT || regionType == DOMRegionContext.XML_CDATA_TEXT || regionType == DOMRegionContext.BLOCK_TEXT || isNestedContent(regionType)) {
			changeData(flatNode, region);
		}
		else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
			changeAttrName(flatNode, region);
		}
		else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
			changeAttrValue(flatNode, region);
		}
		else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
			changeAttrEqual(flatNode, region);
		}
		else if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
			changeTagName(flatNode, region);
		}
		else {
			changeStructuredDocumentRegion(flatNode);
		}
	}



	/**
	 */
	private void changeStartTag(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
		int offset = flatNode.getStart();
		if (offset < 0)
			return; // error
		NodeImpl root = (NodeImpl) this.context.getRootNode();
		if (root == null)
			return; // error
		Node node = root.getNodeAt(offset);
		if (node == null)
			return; // error

		if (node.getNodeType() != Node.ELEMENT_NODE) {
			changeStructuredDocumentRegion(flatNode);
			return;
		}
		ElementImpl element = (ElementImpl) node;

		// check if changes are only for attributes and close tag
		boolean tagNameUnchanged = false;
		if (newRegions != null) {
			Iterator e = newRegions.iterator();
			while (e.hasNext()) {
				ITextRegion region = (ITextRegion) e.next();
				String regionType = region.getType();
				if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME || regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS || regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
					continue;
				if (regionType == DOMRegionContext.XML_TAG_CLOSE) {
					// change from empty tag may have impact on structure
					if (!element.isEmptyTag())
						continue;
				}
				else if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
					String oldTagName = element.getTagName();
					String newTagName = flatNode.getText(region);
					if (oldTagName != null && newTagName != null && oldTagName.equals(newTagName)) {
						// the tag name is unchanged
						tagNameUnchanged = true;
						continue;
					}
				}

				// other region has changed
				changeStructuredDocumentRegion(flatNode);
				return;
			}
		}
		if (oldRegions != null) {
			Iterator e = oldRegions.iterator();
			while (e.hasNext()) {
				ITextRegion region = (ITextRegion) e.next();
				String regionType = region.getType();
				if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME || regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS || regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
					continue;
				if (regionType == DOMRegionContext.XML_TAG_CLOSE) {
					// change from empty tag may have impact on structure
					if (!element.isEmptyTag())
						continue;
				}
				else if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
					// if new tag name is unchanged, it's OK
					if (tagNameUnchanged)
						continue;
				}

				// other region has changed
				changeStructuredDocumentRegion(flatNode);
				return;
			}
		}

		// update attributes
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return; // error
		NamedNodeMap attributes = element.getAttributes();
		if (attributes == null)
			return; // error

		// first remove attributes
		int regionIndex = 0;
		int attrIndex = 0;
		AttrImpl attr = null;
		while (attrIndex < attributes.getLength()) {
			attr = (AttrImpl) attributes.item(attrIndex);
			if (attr == null) { // error
				attrIndex++;
				continue;
			}
			ITextRegion nameRegion = attr.getNameRegion();
			if (nameRegion == null) { // error
				element.removeAttributeNode(attr);
				continue;
			}
			boolean found = false;
			for (int i = regionIndex; i < regions.size(); i++) {
				ITextRegion region = regions.get(i);
				if (region == nameRegion) {
					regionIndex = i + 1; // next region
					found = true;
					break;
				}
			}
			if (found) {
				attrIndex++;
			}
			else {
				element.removeAttributeNode(attr);
			}
		}

		// insert or update attributes
		attrIndex = 0; // reset to first
		AttrImpl newAttr = null;
		ITextRegion oldValueRegion = null;
		Iterator e = regions.iterator();
		while (e.hasNext()) {
			ITextRegion region = (ITextRegion) e.next();
			String regionType = region.getType();
			if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				if (newAttr != null) {
					// insert deferred new attribute
					element.insertAttributeNode(newAttr, attrIndex++);
					newAttr = null;
				}
				else if (attr != null && oldValueRegion != null) {
					// notify existing attribute value removal
					attr.notifyValueChanged();
				}

				oldValueRegion = null;
				attr = (AttrImpl) attributes.item(attrIndex);
				if (attr != null && attr.getNameRegion() == region) {
					// existing attribute
					attrIndex++;
					// clear other regions
					oldValueRegion = attr.getValueRegion();
					attr.setEqualRegion(null);
					attr.setValueRegion(null);
				}
				else {
					String name = flatNode.getText(region);
					attr = (AttrImpl) this.model.getDocument().createAttribute(name);
					if (attr != null)
						attr.setNameRegion(region);
					// defer insertion of new attribute
					newAttr = attr;
				}
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
				if (attr != null) {
					attr.setEqualRegion(region);
				}
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
				if (attr != null) {
					attr.setValueRegion(region);
					if (attr != newAttr && oldValueRegion != region) {
						// notify existing attribute value changed
						attr.notifyValueChanged();
					}
					oldValueRegion = null;
					attr = null;
				}
			}
		}

		if (newAttr != null) {
			// insert deferred new attribute
			element.appendAttributeNode(newAttr);
		}
		else if (attr != null && oldValueRegion != null) {
			// notify existing attribute value removal
			attr.notifyValueChanged();
		}
	}

	/**
	 * changeStructuredDocumentRegion method
	 * 
	 */
	private void changeStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
		if (flatNode == null)
			return;
		if (this.model.getDocument() == null)
			return;

		setupContext(flatNode);

		removeStructuredDocumentRegion(flatNode);
		// make sure the parent is set to deepest level
		// when end tag has been removed
		this.context.setLast();
		insertStructuredDocumentRegion(flatNode);

		cleanupText();
		cleanupEndTag();
	}

	/**
	 */
	private void changeTagName(IStructuredDocumentRegion flatNode, ITextRegion region) {
		int offset = flatNode.getStart();
		if (offset < 0)
			return; // error
		NodeImpl root = (NodeImpl) this.context.getRootNode();
		if (root == null)
			return; // error
		Node node = root.getNodeAt(offset);
		if (node == null)
			return; // error

		if (node.getNodeType() != Node.ELEMENT_NODE) {
			changeStructuredDocumentRegion(flatNode);
			return;
		}

		ElementImpl element = (ElementImpl) node;
		String newTagName = flatNode.getText(region);
		if (newTagName == null || !element.matchTagName(newTagName)) {
			// the tag name is changed
			changeStructuredDocumentRegion(flatNode);
			return;
		}

		// the tag name is unchanged
		// this happens when typing spaces after the tag name
		// do nothing, but...
		// if it's not a change in the end tag of an element with the start
		// tag,
		// and case has been changed, set to element and notify
		if (!element.hasStartTag() || StructuredDocumentRegionUtil.getFirstRegionType(flatNode) != DOMRegionContext.XML_END_TAG_OPEN) {
			String tagName = element.getTagName();
			if (tagName == null || !tagName.equals(newTagName)) {
				element.setTagName(newTagName);
				element.notifyValueChanged();
			}
		}
	}

	/**
	 * cleanupContext method
	 */
	private void cleanupEndTag() {
		Node parent = this.context.getParentNode();
		Node next = this.context.getNextNode();
		while (parent != null) {
			while (next != null) {
				if (next.getNodeType() == Node.ELEMENT_NODE) {
					ElementImpl element = (ElementImpl) next;
					if (element.isEndTag()) {
						// floating end tag
						String tagName = element.getTagName();
						String rootName = getFindRootName(tagName);
						ElementImpl start = (ElementImpl) this.context.findStartTag(tagName, rootName);
						if (start != null) {
							insertEndTag(start);
							// move the end tag from 'element' to 'start'
							start.addEndTag(element);
							removeNode(element);
							parent = this.context.getParentNode();
							next = this.context.getNextNode();
							continue;
						}
					}
				}

				Node first = next.getFirstChild();
				if (first != null) {
					parent = next;
					next = first;
					this.context.setNextNode(next);
				}
				else {
					next = next.getNextSibling();
					this.context.setNextNode(next);
				}
			}

			if (parent.getNodeType() == Node.ELEMENT_NODE) {
				ElementImpl element = (ElementImpl) parent;
				if (!element.hasEndTag() && element.hasStartTag() && element.getNextSibling() == null) {
					String tagName = element.getTagName();
					ElementImpl end = (ElementImpl) this.context.findEndTag(tagName);
					if (end != null) {
						// move the end tag from 'end' to 'element'
						element.addEndTag(end);
						removeEndTag(end);
						this.context.setParentNode(parent); // reset context
						continue;
					}
				}
			}

			next = parent.getNextSibling();
			parent = parent.getParentNode();
			if (next != null) {
				this.context.setNextNode(next);
			}
			else {
				this.context.setParentNode(parent);
			}
		}
	}

	/**
	 */
	private void cleanupText() {
		Node parent = this.context.getParentNode();
		if (parent == null)
			return; // error
		Node next = this.context.getNextNode();
		Node prev = (next == null ? parent.getLastChild() : next.getPreviousSibling());

		TextImpl nextText = null;
		TextImpl prevText = null;
		if (next != null && next.getNodeType() == Node.TEXT_NODE) {
			nextText = (TextImpl) next;
		}
		if (prev != null && prev.getNodeType() == Node.TEXT_NODE) {
			prevText = (TextImpl) prev;
		}
		if (nextText == null && prevText == null)
			return;
		if (nextText != null && prevText != null) {
			// consecutive Text nodes created by setupContext(),
			// concat them
			IStructuredDocumentRegion flatNode = nextText.getStructuredDocumentRegion();
			if (flatNode != null)
				prevText.appendStructuredDocumentRegion(flatNode);
			Node newNext = next.getNextSibling();
			parent.removeChild(next);
			next = null;
			this.context.setNextNode(newNext);
		}

		TextImpl childText = (prevText != null ? prevText : nextText);
		if (childText.getNextSibling() == null && childText.getPreviousSibling() == null) {
			if (parent.getNodeType() == Node.ELEMENT_NODE) {
				ElementImpl parentElement = (ElementImpl) parent;
				if (!parentElement.hasStartTag() && !parentElement.hasEndTag()) {
					if (childText.isWhitespace() || childText.isInvalid()) {
						// implicit parent is not required
						Node newParent = parent.getParentNode();
						if (newParent != null) {
							Node newNext = parent.getNextSibling();
							newParent.removeChild(parent);
							parent.removeChild(childText);
							newParent.insertBefore(childText, newNext);
							if (childText == next) {
								this.context.setNextNode(childText);
							}
							else if (newNext != null) {
								this.context.setNextNode(newNext);
							}
							else {
								this.context.setParentNode(newParent);
							}
							// try again
							cleanupText();
						}
					}
				}
			}
		}
	}

	/**
	 * This routine create an Element from comment data for comment style
	 * elements, such as SSI and METADATA
	 */
	protected Element createCommentElement(String data, boolean isJSPTag) {
		String trimmedData = data.trim();
		CommentElementConfiguration[] configs = CommentElementRegistry.getInstance().getConfigurations();
		for (int iConfig = 0; iConfig < configs.length; iConfig++) {
			CommentElementConfiguration config = configs[iConfig];
			if ((isJSPTag && !config.acceptJSPComment()) || (!isJSPTag && !config.acceptXMLComment())) {
				continue;
			}
			String[] prefixes = config.getPrefix();
			for (int iPrefix = 0; iPrefix < prefixes.length; iPrefix++) {
				if (trimmedData.startsWith(prefixes[iPrefix])) {
					return config.createElement(this.model.getDocument(), data, isJSPTag);
				}
			}
		}
		ModelParserAdapter adapter = getParserAdapter();
		if (adapter != null) {
			return adapter.createCommentElement(this.model.getDocument(), data, isJSPTag);
		}
		return null;
	}

	/**
	 * This routine create an implicit Element for given parent and child,
	 * such as HTML, BODY, HEAD, and TBODY for HTML document.
	 */
	protected Element createImplicitElement(Node parent, Node child) {
		ModelParserAdapter adapter = getParserAdapter();
		if (adapter != null) {
			return adapter.createImplicitElement(this.model.getDocument(), parent, child);
		}
		return null;
	}

	/**
	 */
	private void demoteNodes(Node root, Node newParent, Node oldParent, Node next) {
		if (newParent.getNodeType() != Node.ELEMENT_NODE)
			return;
		ElementImpl newElement = (ElementImpl) newParent;

		// find next
		while (next == null) {
			if (oldParent.getNodeType() != Node.ELEMENT_NODE)
				return;
			ElementImpl oldElement = (ElementImpl) oldParent;
			if (oldElement.hasEndTag())
				return;
			oldParent = oldElement.getParentNode();
			if (oldParent == null)
				return; // error
			next = oldElement.getNextSibling();
		}

		while (next != null) {
			boolean done = false;
			if (next.getNodeType() == Node.ELEMENT_NODE) {
				ElementImpl nextElement = (ElementImpl) next;
				if (!nextElement.hasStartTag()) {
					Node nextChild = nextElement.getFirstChild();
					if (nextChild != null) {
						// demote children
						next = nextChild;
						oldParent = nextElement;
						continue;
					}

					if (nextElement.hasEndTag()) {
						if (nextElement.matchEndTag(newElement)) {
							// stop at the matched invalid end tag
							next = nextElement.getNextSibling();
							oldParent.removeChild(nextElement);
							newElement.addEndTag(nextElement);

							if (newElement == root)
								return;
							Node p = newElement.getParentNode();
							// check if reached to top
							if (p == null || p == oldParent || p.getNodeType() != Node.ELEMENT_NODE)
								return;
							newElement = (ElementImpl) p;
							done = true;
						}
					}
					else {
						// remove implicit element
						next = nextElement.getNextSibling();
						oldParent.removeChild(nextElement);
						done = true;
					}
				}
			}

			if (!done) {
				if (!canContain(newElement, next)) {
					if (newElement == root)
						return;
					Node p = newElement.getParentNode();
					// check if reached to top
					if (p == null || p == oldParent || p.getNodeType() != Node.ELEMENT_NODE)
						return;
					newElement = (ElementImpl) p;
					continue;
				}

				Node child = next;
				next = next.getNextSibling();
				oldParent.removeChild(child);
				insertNode(newElement, child, null);
				Node childParent = child.getParentNode();
				if (childParent != newElement) {
					newElement = (ElementImpl) childParent;
				}
			}

			// find next parent and sibling
			while (next == null) {
				if (oldParent.getNodeType() != Node.ELEMENT_NODE)
					return;
				ElementImpl oldElement = (ElementImpl) oldParent;

				// dug parent must not have children at this point
				if (!oldElement.hasChildNodes() && !oldElement.hasStartTag()) {
					oldParent = oldElement.getParentNode();
					if (oldParent == null)
						return; // error
					next = oldElement;
					break;
				}

				if (oldElement.hasEndTag())
					return;
				oldParent = oldElement.getParentNode();
				if (oldParent == null)
					return; // error
				next = oldElement.getNextSibling();
			}
		}
	}

	private ModelParserAdapter getParserAdapter() {
		return (ModelParserAdapter) this.model.getDocument().getAdapterFor(ModelParserAdapter.class);
	}
	
	/**
	 */
	protected String getFindRootName(String tagName) {
		ModelParserAdapter adapter = getParserAdapter();
		if (adapter != null) {
			return adapter.getFindRootName(tagName);
		}
		return null;
	}

	/**
	 */
	protected final IDOMModel getModel() {
		return this.model;
	}

	/**
	 * insertCDATASection method
	 * 
	 */
	private void insertCDATASection(IStructuredDocumentRegion flatNode) {
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return;

		CDATASectionImpl cdata = null;
		try {
			cdata = (CDATASectionImpl) this.model.getDocument().createCDATASection(null);
		}
		catch (DOMException ex) {
		}
		if (cdata == null) { // CDATA section might not be supported
			insertInvalidDecl(flatNode); // regard as invalid decl
			return;
		}

		cdata.setStructuredDocumentRegion(flatNode);
		insertNode(cdata);
	}

	/**
	 * insertComment method
	 * 
	 */
	private void insertComment(IStructuredDocumentRegion flatNode) {
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return;

		String data = null;
		boolean isJSPTag = false;
		Iterator e = regions.iterator();
		while (e.hasNext()) {
			ITextRegion region = (ITextRegion) e.next();
			String regionType = region.getType();
			if (isNestedCommentOpen(regionType)) {
				isJSPTag = true;
			}
			else if (regionType == DOMRegionContext.XML_COMMENT_TEXT || isNestedCommentText(regionType)) {
				if (data == null) {
					data = flatNode.getText(region);
				}
			}
		}

		if (data != null) {
			ElementImpl element = (ElementImpl) createCommentElement(data, isJSPTag);
			if (element != null) {
				if (!isEndTag(element)) {
					element.setStartStructuredDocumentRegion(flatNode);
					insertStartTag(element);
					return;
				}

				// end tag
				element.setEndStructuredDocumentRegion(flatNode);

				String tagName = element.getTagName();
				String rootName = getFindRootName(tagName);
				ElementImpl start = (ElementImpl) this.context.findStartTag(tagName, rootName);
				if (start != null) { // start tag found
					insertEndTag(start);
					start.addEndTag(element);
					return;
				}

				// invalid end tag
				insertNode(element);
				return;
			}
		}

		CommentImpl comment = (CommentImpl) this.model.getDocument().createComment(null);
		if (comment == null)
			return;
		if (isJSPTag)
			comment.setJSPTag(true);
		comment.setStructuredDocumentRegion(flatNode);
		insertNode(comment);
	}

	/**
	 * insertDecl method
	 * 
	 */
	private void insertDecl(IStructuredDocumentRegion flatNode) {
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return;

		boolean isDocType = false;
		String name = null;
		String publicId = null;
		String systemId = null;
		Iterator e = regions.iterator();
		while (e.hasNext()) {
			ITextRegion region = (ITextRegion) e.next();
			String regionType = region.getType();
			if (regionType == DOMRegionContext.XML_DOCTYPE_DECLARATION) {
				isDocType = true;
			}
			else if (regionType == DOMRegionContext.XML_DOCTYPE_NAME) {
				if (name == null)
					name = flatNode.getText(region);
			}
			else if (regionType == DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBREF) {
				if (publicId == null)
					publicId = StructuredDocumentRegionUtil.getAttrValue(flatNode, region);
			}
			else if (regionType == DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSREF) {
				if (systemId == null)
					systemId = StructuredDocumentRegionUtil.getAttrValue(flatNode, region);
			}
		}

		// invalid declaration
		if (!isDocType) {
			insertInvalidDecl(flatNode);
			return;
		}

		DocumentTypeImpl docType = (DocumentTypeImpl) this.model.getDocument().createDoctype(name);
		if (docType == null)
			return;
		if (publicId != null)
			docType.setPublicId(publicId);
		if (systemId != null)
			docType.setSystemId(systemId);
		docType.setStructuredDocumentRegion(flatNode);
		insertNode(docType);
	}

	/**
	 * insertEndTag method can be used by subclasses, but not overrided.
	 * 
	 * @param element
	 *            org.w3c.dom.Element
	 */
	protected void insertEndTag(Element element) {
		if (element == null)
			return;

		Node newParent = element.getParentNode();
		if (newParent == null)
			return; // error

		if (!((ElementImpl) element).isContainer()) {
			// just update context
			Node elementNext = element.getNextSibling();
			if (elementNext != null)
				this.context.setNextNode(elementNext);
			else
				this.context.setParentNode(newParent);
			return;
		}

		// promote children
		Node newNext = element.getNextSibling();
		Node oldParent = this.context.getParentNode();
		if (oldParent == null)
			return; // error
		Node oldNext = this.context.getNextNode();
		promoteNodes(element, newParent, newNext, oldParent, oldNext);

		// update context
		// re-check the next sibling
		newNext = element.getNextSibling();
		if (newNext != null)
			this.context.setNextNode(newNext);
		else
			this.context.setParentNode(newParent);
	}

	/**
	 * insertEndTag method
	 * 
	 */
	private void insertEndTag(IStructuredDocumentRegion flatNode) {
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return;

		String tagName = null;
		Iterator e = regions.iterator();
		while (e.hasNext()) {
			ITextRegion region = (ITextRegion) e.next();
			String regionType = region.getType();
			if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
				if (tagName == null)
					tagName = flatNode.getText(region);
			}
		}

		if (tagName == null) { // invalid end tag
			insertText(flatNode); // regard as invalid text
			return;
		}

		String rootName = getFindRootName(tagName);
		ElementImpl start = (ElementImpl) this.context.findStartTag(tagName, rootName);
		if (start != null) { // start tag found
			insertEndTag(start);
			start.setEndStructuredDocumentRegion(flatNode);
			return;
		}

		// invalid end tag
		ElementImpl end = null;
		try {
			end = (ElementImpl) this.model.getDocument().createElement(tagName);
		}
		catch (DOMException ex) {
		}
		if (end == null) { // invalid end tag
			insertText(flatNode); // regard as invalid text
			return;
		}
		end.setEndStructuredDocumentRegion(flatNode);
		insertNode(end);
	}

	/**
	 * insertEntityRef method
	 * 
	 */
	private void insertEntityRef(IStructuredDocumentRegion flatNode) {
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return;

		String name = null;
		Iterator e = regions.iterator();
		while (e.hasNext()) {
			ITextRegion region = (ITextRegion) e.next();
			String regionType = region.getType();
			if (regionType == DOMRegionContext.XML_ENTITY_REFERENCE || regionType == DOMRegionContext.XML_CHAR_REFERENCE) {
				if (name == null)
					name = StructuredDocumentRegionUtil.getEntityRefName(flatNode, region);
			}
		}

		if (name == null) { // invalid entity
			insertText(flatNode);
			return;
		}

		// ISSUE: avoid this cast
		String value = ((DocumentImpl)this.model.getDocument()).getCharValue(name);
		if (value != null) { // character entity
			TextImpl text = (TextImpl) this.context.findPreviousText();
			if (text != null) { // existing text found
				// do not append data
				text.appendStructuredDocumentRegion(flatNode);
				// notify the change
				text.notifyValueChanged();
				return;
			}

			// new text
			text = (TextImpl) this.model.getDocument().createTextNode(null);
			if (text == null)
				return;
			text.setStructuredDocumentRegion(flatNode);
			insertNode(text);
			return;
		}

		// general entity reference
		EntityReferenceImpl ref = null;
		try {
			ref = (EntityReferenceImpl) this.model.getDocument().createEntityReference(name);
		}
		catch (DOMException ex) {
		}
		if (ref == null) { // entity reference might not be supported
			insertText(flatNode); // regard as invalid text
			return;
		}

		ref.setStructuredDocumentRegion(flatNode);
		insertNode(ref);
	}

	/**
	 * insertInvalidDecl method
	 * 
	 */
	private void insertInvalidDecl(IStructuredDocumentRegion flatNode) {
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return;

		ElementImpl element = null;
		try {
			element = (ElementImpl) this.model.getDocument().createElement("!");//$NON-NLS-1$
		}
		catch (DOMException ex) {
		}
		if (element == null) { // invalid tag
			insertText(flatNode); // regard as invalid text
			return;
		}
		element.setEmptyTag(true);
		element.setStartStructuredDocumentRegion(flatNode);
		insertNode(element);
	}

	/**
	 * insertJSPTag method
	 * 
	 */
	private void insertNestedTag(IStructuredDocumentRegion flatNode) {
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return;

		String tagName = null;
		AttrImpl attr = null;
		Vector attrNodes = null;
		boolean isCloseTag = false;
		Iterator e = regions.iterator();
		while (e.hasNext()) {
			ITextRegion region = (ITextRegion) e.next();
			String regionType = region.getType();
			if (isNestedTagOpen(regionType) || isNestedTagName(regionType)) {
				tagName = computeNestedTag(regionType, tagName, flatNode, region);
			}
			else if (isNestedTagClose(regionType)) {
				isCloseTag = true;
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				String name = flatNode.getText(region);
				attr = (AttrImpl) this.model.getDocument().createAttribute(name);
				if (attr != null) {
					attr.setNameRegion(region);
					if (attrNodes == null)
						attrNodes = new Vector();
					attrNodes.addElement(attr);
				}
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
				if (attr != null) {
					attr.setEqualRegion(region);
				}
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
				if (attr != null) {
					attr.setValueRegion(region);
					attr = null;
				}
			}
		}

		if (tagName == null) {
			if (isCloseTag) {
				// close JSP tag
				Node parent = this.context.getParentNode();
				if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
					ElementImpl start = (ElementImpl) parent;
					if (start.isJSPContainer()) {
						insertEndTag(start);
						start.setEndStructuredDocumentRegion(flatNode);
						return;
					}
				}
			}
			// invalid JSP tag
			insertText(flatNode); // regard as invalid text
			return;
		}

		ElementImpl element = null;
		try {
			element = (ElementImpl) this.model.getDocument().createElement(tagName);
		}
		catch (DOMException ex) {
		}
		if (element == null) { // invalid tag
			insertText(flatNode); // regard as invalid text
			return;
		}
		if (attrNodes != null) {
			Enumeration ae = attrNodes.elements();
			while (ae.hasMoreElements()) {
				Attr a = (Attr) ae.nextElement();
				if (a == null)
					continue;
				element.appendAttributeNode(a);
			}
		}
		element.setJSPTag(true);
		element.setStartStructuredDocumentRegion(flatNode);
		insertStartTag(element);
	}

	protected boolean isNestedTagClose(String regionType) {
		boolean result = false;
		return result;
	}

	protected boolean isNestedTagOpen(String regionType) {
		boolean result = false;
		return result;
	}

	protected String computeNestedTag(String regionType, String tagName, IStructuredDocumentRegion structuredDocumentRegion, ITextRegion region) {
		return tagName;
	}

	/**
	 * insertNode method
	 * 
	 * @param child
	 *            org.w3c.dom.Node
	 */
	private void insertNode(Node node) {
		if (node == null)
			return;
		if (this.context == null)
			return;

		Node parent = this.context.getParentNode();
		if (parent == null)
			return;
		Node next = this.context.getNextNode();
		while (parent.getNodeType() == Node.ELEMENT_NODE) {
			ElementImpl element = (ElementImpl) parent;
			if (canContain(element, node)) {
				if (!element.hasStartTag() && next == element.getFirstChild()) {
					// first child of implicit tag
					// deletege to the parent
					parent = element.getParentNode();
					if (parent == null)
						return;
					next = element;
					this.context.setNextNode(next);
					continue;
				}
				break;
			}
			parent = element.getParentNode();
			if (parent == null)
				return;

			// promote siblings
			Node newNext = element.getNextSibling();
			Node child = next;
			while (child != null) {
				Node nextChild = child.getNextSibling();
				element.removeChild(child);
				parent.insertBefore(child, newNext);
				child = nextChild;
			}

			// leave the old end tag where it is
			if (element.hasEndTag()) {
				Element end = element.removeEndTag();
				if (end != null) {
					parent.insertBefore(end, newNext);
					if (next == null)
						next = end;
				}
			}
			if (!element.hasStartTag()) {
				// implicit element
				if (!element.hasChildNodes()) {
					parent.removeChild(element);
				}
			}

			// update context
			if (next == null)
				next = newNext;
			if (next != null)
				this.context.setNextNode(next);
			else
				this.context.setParentNode(parent);
		}

		insertNode(parent, node, next);
		next = node.getNextSibling();
		if (next != null)
			this.context.setNextNode(next);
		else
			this.context.setParentNode(node.getParentNode());
	}

	/**
	 */
	private void insertNode(Node parent, Node node, Node next) {
		while (next != null && next.getNodeType() == Node.ELEMENT_NODE) {
			ElementImpl nextElement = (ElementImpl) next;
			if (nextElement.hasStartTag())
				break;
			if (!canBeImplicitTag(nextElement, node))
				break;
			parent = nextElement;
			next = nextElement.getFirstChild();
		}
		Element implicitElement = createImplicitElement(parent, node);
		if (implicitElement != null)
			node = implicitElement;
		parent.insertBefore(node, next);
	}

	/**
	 * insertPI method
	 * 
	 */
	private void insertPI(IStructuredDocumentRegion flatNode) {
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return;

		String target = null;
		Iterator e = regions.iterator();
		while (e.hasNext()) {
			ITextRegion region = (ITextRegion) e.next();
			String regionType = region.getType();
			if (regionType == DOMRegionContext.XML_PI_OPEN || regionType == DOMRegionContext.XML_PI_CLOSE)
				continue;
			if (target == null)
				target = flatNode.getText(region);
		}

		ProcessingInstructionImpl pi = (ProcessingInstructionImpl) this.model.getDocument().createProcessingInstruction(target, null);
		if (pi == null)
			return;
		pi.setStructuredDocumentRegion(flatNode);
		insertNode(pi);
	}

	/**
	 * insertStartTag method can be used by subclasses, but not overridden.
	 * 
	 * @param element
	 *            org.w3c.dom.Element
	 */
	protected void insertStartTag(Element element) {
		if (element == null)
			return;
		if (this.context == null)
			return;

		insertNode(element);

		ElementImpl newElement = (ElementImpl) element;
		if (newElement.isEmptyTag() || !newElement.isContainer())
			return;

		// demote siblings
		Node parent = this.context.getParentNode();
		if (parent == null)
			return; // error
		Node next = this.context.getNextNode();
		demoteNodes(element, element, parent, next);

		// update context
		Node firstChild = element.getFirstChild();
		if (firstChild != null)
			this.context.setNextNode(firstChild);
		else
			this.context.setParentNode(element);
	}

	/**
	 * insertStartTag method
	 * 
	 */
	private void insertStartTag(IStructuredDocumentRegion flatNode) {
		ITextRegionList regions = flatNode.getRegions();
		if (regions == null)
			return;

		String tagName = null;
		boolean isEmptyTag = false;
		AttrImpl attr = null;
		Vector attrNodes = null;
		Iterator e = regions.iterator();
		while (e.hasNext()) {
			ITextRegion region = (ITextRegion) e.next();
			String regionType = region.getType();
			if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
				if (tagName == null)
					tagName = flatNode.getText(region);
			}
			else if (regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
				isEmptyTag = true;
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				String name = flatNode.getText(region);
				attr = (AttrImpl) this.model.getDocument().createAttribute(name);
				if (attr != null) {
					attr.setNameRegion(region);
					if (attrNodes == null)
						attrNodes = new Vector();
					attrNodes.addElement(attr);
				}
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
				if (attr != null) {
					attr.setEqualRegion(region);
				}
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
				if (attr != null) {
					attr.setValueRegion(region);
					attr = null;
				}
			}
		}

		if (tagName == null) { // invalid start tag
			insertText(flatNode); // regard as invalid text
			return;
		}

		ElementImpl element = null;
		try {
			element = (ElementImpl) this.model.getDocument().createElement(tagName);
		}
		catch (DOMException ex) {
			// typically invalid name
		}
		if (element == null) { // invalid tag
			insertText(flatNode); // regard as invalid text
			return;
		}
		if (attrNodes != null) {
			Enumeration ae = attrNodes.elements();
			while (ae.hasMoreElements()) {
				Attr a = (Attr) ae.nextElement();
				if (a == null)
					continue;
				element.appendAttributeNode(a);
			}
		}
		if (isEmptyTag)
			element.setEmptyTag(true);
		element.setStartStructuredDocumentRegion(flatNode);
		insertStartTag(element);
	}

	/**
	 * insertStructuredDocumentRegion method
	 * 
	 */
	protected void insertStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
		String regionType = StructuredDocumentRegionUtil.getFirstRegionType(flatNode);
		if (regionType == DOMRegionContext.XML_TAG_OPEN) {
			insertStartTag(flatNode);
		}
		else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) {
			insertEndTag(flatNode);
		}
		else if (regionType == DOMRegionContext.XML_COMMENT_OPEN || isNestedCommentOpen(regionType)) {
			insertComment(flatNode);
		}
		else if (regionType == DOMRegionContext.XML_ENTITY_REFERENCE || regionType == DOMRegionContext.XML_CHAR_REFERENCE) {
			insertEntityRef(flatNode);
		}
		else if (regionType == DOMRegionContext.XML_DECLARATION_OPEN) {
			insertDecl(flatNode);
		}
		else if (regionType == DOMRegionContext.XML_PI_OPEN) {
			insertPI(flatNode);
		}
		else if (regionType == DOMRegionContext.XML_CDATA_OPEN) {
			insertCDATASection(flatNode);
		}
		else if (isNestedTag(regionType)) {
			insertNestedTag(flatNode);
		}
		else {
			insertText(flatNode);
		}
	}

	protected boolean isNestedTag(String regionType) {
		boolean result = false;
		return result;
	}

	protected boolean isNestedCommentText(String regionType) {
		boolean result = false;
		return result;
	}


	protected boolean isNestedCommentOpen(String regionType) {
		boolean result = false;
		return result;
	}

	protected boolean isNestedTagName(String regionType) {
		boolean result = false;
		return result;
	}

	protected boolean isNestedContent(String regionType) {
		boolean result = false;
		return result;
	}

	/**
	 * insertText method Can be called from subclasses, not to be overrided or
	 * re-implemented.
	 * 
	 */
	protected void insertText(IStructuredDocumentRegion flatNode) {
		TextImpl text = (TextImpl) this.context.findPreviousText();
		if (text != null) { // existing text found
			text.appendStructuredDocumentRegion(flatNode);
			// notify the change
			text.notifyValueChanged();
			return;
		}

		// new text
		text = (TextImpl) this.model.getDocument().createTextNode(null);
		if (text == null)
			return;
		text.setStructuredDocumentRegion(flatNode);
		insertNode(text);
	}

	/**
	 */
	protected boolean isEndTag(IDOMElement element) {
		ModelParserAdapter adapter = getParserAdapter();
		if (adapter != null) {
			return adapter.isEndTag(element);
		}
		return element.isEndTag();
	}

	/**
	 */
	private void promoteNodes(Node root, Node newParent, Node newNext, Node oldParent, Node next) {
		ElementImpl newElement = null;
		if (newParent.getNodeType() == Node.ELEMENT_NODE) {
			newElement = (ElementImpl) newParent;
		}

		Node rootParent = root.getParentNode();
		while (oldParent != rootParent) {
			while (next != null) {
				boolean done = false;
				boolean endTag = false;
				if (next.getNodeType() == Node.ELEMENT_NODE) {
					ElementImpl nextElement = (ElementImpl) next;
					if (!nextElement.hasStartTag()) {
						Node nextChild = nextElement.getFirstChild();
						if (nextChild != null) {
							// promote children
							next = nextChild;
							oldParent = nextElement;
							continue;
						}

						if (nextElement.hasEndTag()) {
							if (nextElement.matchEndTag(newElement)) {
								endTag = true;
							}
						}
						else {
							// remove implicit element
							next = nextElement.getNextSibling();
							oldParent.removeChild(nextElement);
							done = true;
						}
					}
				}

				if (!done) {
					if (!endTag && newElement != null && !canContain(newElement, next)) {
						newParent = newElement.getParentNode();
						if (newParent == null)
							return; // error
						Node elementNext = newElement.getNextSibling();
						// promote siblings
						promoteNodes(newElement, newParent, elementNext, newElement, newNext);
						newNext = newElement.getNextSibling();
						if (newParent.getNodeType() == Node.ELEMENT_NODE) {
							newElement = (ElementImpl) newParent;
						}
						else {
							newElement = null;
						}
						continue;
					}

					Node child = next;
					next = next.getNextSibling();
					oldParent.removeChild(child);
					insertNode(newParent, child, newNext);
					Node childParent = child.getParentNode();
					if (childParent != newParent) {
						newParent = childParent;
						newElement = (ElementImpl) newParent;
						newNext = child.getNextSibling();
					}
				}
			}

			if (oldParent.getNodeType() != Node.ELEMENT_NODE)
				return;
			ElementImpl oldElement = (ElementImpl) oldParent;
			oldParent = oldElement.getParentNode();
			if (oldParent == null)
				return; // error
			next = oldElement.getNextSibling();

			if (oldElement.hasEndTag()) {
				Element end = null;
				if (!oldElement.hasChildNodes() && !oldElement.hasStartTag()) {
					oldParent.removeChild(oldElement);
					end = oldElement;
				}
				else {
					end = oldElement.removeEndTag();
				}
				if (end != null) {
					insertNode(newParent, end, newNext);
					Node endParent = end.getParentNode();
					if (endParent != newParent) {
						newParent = endParent;
						newElement = (ElementImpl) newParent;
						newNext = end.getNextSibling();
					}
				}
			}
		}
	}

	/**
	 * removeEndTag method
	 * 
	 * @param element
	 *            org.w3c.dom.Element
	 */
	private void removeEndTag(Element element) {
		if (element == null)
			return;
		if (this.context == null)
			return;

		Node parent = element.getParentNode();
		if (parent == null)
			return; // error

		if (!((ElementImpl) element).isContainer()) {
			// just update context
			Node elementNext = element.getNextSibling();
			if (elementNext != null)
				this.context.setNextNode(elementNext);
			else
				this.context.setParentNode(parent);
			return;
		}

		// demote siblings
		Node next = element.getNextSibling();
		ElementImpl newElement = (ElementImpl) element;
		// find new parent
		for (Node last = newElement.getLastChild(); last != null; last = last.getLastChild()) {
			if (last.getNodeType() != Node.ELEMENT_NODE)
				break;
			ElementImpl lastElement = (ElementImpl) last;
			if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
				break;
			newElement = lastElement;
		}
		Node lastChild = newElement.getLastChild();
		demoteNodes(element, newElement, parent, next);

		// update context
		Node newNext = null;
		if (lastChild != null)
			newNext = lastChild.getNextSibling();
		else
			newNext = newElement.getFirstChild();
		if (newNext != null)
			this.context.setNextNode(newNext);
		else
			this.context.setParentNode(newElement);
	}

	/**
	 * Remove the specified node if it is no longer required implicit tag with
	 * remaining child nodes promoted.
	 */
	private Element removeImplicitElement(Node parent) {
		if (parent == null)
			return null;
		if (parent.getNodeType() != Node.ELEMENT_NODE)
			return null;
		ElementImpl element = (ElementImpl) parent;
		if (!element.isImplicitTag())
			return null;
		if (canBeImplicitTag(element))
			return null;

		Node elementParent = element.getParentNode();
		if (elementParent == null)
			return null; // error
		Node firstChild = element.getFirstChild();
		Node child = firstChild;
		Node elementNext = element.getNextSibling();
		while (child != null) {
			Node nextChild = child.getNextSibling();
			element.removeChild(child);
			elementParent.insertBefore(child, elementNext);
			child = nextChild;
		}

		// reset context
		if (this.context.getParentNode() == element) {
			Node oldNext = this.context.getNextNode();
			if (oldNext != null) {
				this.context.setNextNode(oldNext);
			}
			else {
				if (elementNext != null) {
					this.context.setNextNode(elementNext);
				}
				else {
					this.context.setParentNode(elementParent);
				}
			}
		}
		else if (this.context.getNextNode() == element) {
			if (firstChild != null) {
				this.context.setNextNode(firstChild);
			}
			else {
				if (elementNext != null) {
					this.context.setNextNode(elementNext);
				}
				else {
					this.context.setParentNode(elementParent);
				}
			}
		}

		removeNode(element);
		return element;
	}

	/**
	 * removeNode method
	 * 
	 * @param node
	 *            org.w3c.dom.Node
	 */
	private void removeNode(Node node) {
		if (node == null)
			return;
		if (this.context == null)
			return;

		Node parent = node.getParentNode();
		if (parent == null)
			return;
		Node next = node.getNextSibling();
		Node prev = node.getPreviousSibling();

		// update context
		Node oldParent = this.context.getParentNode();
		if (node == oldParent) {
			if (next != null)
				this.context.setNextNode(next);
			else
				this.context.setParentNode(parent);
		}
		else {
			Node oldNext = this.context.getNextNode();
			if (node == oldNext) {
				this.context.setNextNode(next);
			}
		}

		parent.removeChild(node);

		if (removeImplicitElement(parent) != null)
			return;

		// demote sibling
		if (prev != null && prev.getNodeType() == Node.ELEMENT_NODE) {
			ElementImpl newElement = (ElementImpl) prev;
			if (!newElement.hasEndTag() && !newElement.isEmptyTag() && newElement.isContainer()) {
				// find new parent
				for (Node last = newElement.getLastChild(); last != null; last = last.getLastChild()) {
					if (last.getNodeType() != Node.ELEMENT_NODE)
						break;
					ElementImpl lastElement = (ElementImpl) last;
					if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
						break;
					newElement = lastElement;
				}
				Node lastChild = newElement.getLastChild();
				demoteNodes(prev, newElement, parent, next);

				// update context
				Node newNext = null;
				if (lastChild != null)
					newNext = lastChild.getNextSibling();
				else
					newNext = newElement.getFirstChild();
				if (newNext != null)
					this.context.setNextNode(newNext);
				else
					this.context.setParentNode(newElement);
			}
		}
	}

	/**
	 * removeStartTag method
	 * 
	 * @param element
	 *            org.w3c.dom.Element
	 */
	private void removeStartTag(Element element) {
		if (element == null)
			return;
		if (this.context == null)
			return;

		// for implicit tag
		ElementImpl oldElement = (ElementImpl) element;
		if (canBeImplicitTag(oldElement)) {
			Node newParent = null;
			Node prev = oldElement.getPreviousSibling();
			if (prev != null && prev.getNodeType() == Node.ELEMENT_NODE) {
				ElementImpl prevElement = (ElementImpl) prev;
				if (!prevElement.hasEndTag()) {
					if (prevElement.hasStartTag() || prevElement.matchTagName(oldElement.getTagName())) {
						newParent = prevElement;
					}
				}
			}
			if (newParent == null) {
				// this element should stay as implicit tag
				// just remove all attributes
				oldElement.removeStartTag();

				// update context
				Node child = oldElement.getFirstChild();
				if (child != null) {
					this.context.setNextNode(child);
				}
				else if (oldElement.hasEndTag()) {
					this.context.setParentNode(oldElement);
				}
				return;
			}
		}
		// for comment tag
		if (oldElement.isCommentTag())
			oldElement.removeStartTag();

		// promote children
		Node elementParent = element.getParentNode();
		Node parent = elementParent;
		if (parent == null)
			return;
		Node first = element.getFirstChild();
		Node firstElement = null; // for the case first is removed as end
		// tag
		if (first != null) {
			// find new parent for children
			ElementImpl newElement = null;
			for (Node last = element.getPreviousSibling(); last != null; last = last.getLastChild()) {
				if (last.getNodeType() != Node.ELEMENT_NODE)
					break;
				ElementImpl lastElement = (ElementImpl) last;
				if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
					break;
				newElement = lastElement;
			}
			Node next = first;
			if (newElement != null) {
				while (next != null) {
					if (!newElement.hasEndTag() && newElement.hasStartTag() && next.getNodeType() == Node.ELEMENT_NODE) {
						ElementImpl nextElement = (ElementImpl) next;
						if (!nextElement.hasStartTag() && nextElement.hasEndTag() && nextElement.matchEndTag(newElement)) {
							// stop at the matched invalid end tag
							Node elementChild = nextElement.getFirstChild();
							while (elementChild != null) {
								Node nextChild = elementChild.getNextSibling();
								nextElement.removeChild(elementChild);
								newElement.appendChild(elementChild);
								elementChild = nextChild;
							}

							next = nextElement.getNextSibling();
							element.removeChild(nextElement);
							newElement.addEndTag(nextElement);
							if (nextElement == first)
								firstElement = newElement;

							Node newParent = newElement.getParentNode();
							if (newParent == parent)
								break;
							if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
								break; // error
							newElement = (ElementImpl) newParent;
							continue;
						}
					}
					if (!canContain(newElement, next)) {
						Node newParent = newElement.getParentNode();
						if (newParent == parent)
							break;
						if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
							break; // error
						newElement = (ElementImpl) newParent;
						continue;
					}
					Node child = next;
					next = next.getNextSibling();
					element.removeChild(child);
					newElement.appendChild(child);
				}
				newElement = null;
			}
			if (parent.getNodeType() == Node.ELEMENT_NODE) {
				newElement = (ElementImpl) parent;
			}
			while (next != null) {
				if (newElement == null || canContain(newElement, next)) {
					Node child = next;
					next = next.getNextSibling();
					element.removeChild(child);
					parent.insertBefore(child, element);
					continue;
				}

				parent = newElement.getParentNode();
				if (parent == null)
					return;

				// promote siblings
				Node newNext = newElement.getNextSibling();
				Node child = element;
				while (child != null) {
					Node nextChild = child.getNextSibling();
					newElement.removeChild(child);
					parent.insertBefore(child, newNext);
					child = nextChild;
				}

				// leave the old end tag where it is
				if (newElement.hasEndTag()) {
					Element end = newElement.removeEndTag();
					if (end != null) {
						parent.insertBefore(end, newNext);
					}
				}
				if (!newElement.hasStartTag()) {
					// implicit element
					if (!newElement.hasChildNodes()) {
						parent.removeChild(newElement);
					}
				}

				if (parent.getNodeType() == Node.ELEMENT_NODE) {
					newElement = (ElementImpl) parent;
				}
				else {
					newElement = null;
				}
			}
		}

		Node newNext = element;
		Node startElement = null; // for the case element is removed as end
		// tag
		if (oldElement.hasEndTag()) {
			// find new parent for invalid end tag and siblings
			ElementImpl newElement = null;
			for (Node last = element.getPreviousSibling(); last != null; last = last.getLastChild()) {
				if (last.getNodeType() != Node.ELEMENT_NODE)
					break;
				ElementImpl lastElement = (ElementImpl) last;
				if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
					break;
				newElement = lastElement;
			}
			if (newElement != null) {
				// demote invalid end tag and sibling
				Node next = element;
				while (next != null) {
					if (!newElement.hasEndTag() && newElement.hasStartTag() && next.getNodeType() == Node.ELEMENT_NODE) {
						ElementImpl nextElement = (ElementImpl) next;
						if (!nextElement.hasStartTag() && nextElement.hasEndTag() && nextElement.matchEndTag(newElement)) {
							// stop at the matched invalid end tag
							Node elementChild = nextElement.getFirstChild();
							while (elementChild != null) {
								Node nextChild = elementChild.getNextSibling();
								nextElement.removeChild(elementChild);
								newElement.appendChild(elementChild);
								elementChild = nextChild;
							}

							next = nextElement.getNextSibling();
							parent.removeChild(nextElement);
							newElement.addEndTag(nextElement);
							if (nextElement == newNext)
								startElement = newElement;

							Node newParent = newElement.getParentNode();
							if (newParent == parent)
								break;
							if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
								break; // error
							newElement = (ElementImpl) newParent;
							continue;
						}
					}
					if (!canContain(newElement, next)) {
						Node newParent = newElement.getParentNode();
						if (newParent == parent)
							break;
						if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
							break; // error
						newElement = (ElementImpl) newParent;
						continue;
					}
					Node child = next;
					next = next.getNextSibling();
					parent.removeChild(child);
					if (child == oldElement) {
						if (!oldElement.isCommentTag()) {
							// clone (re-create) end tag
							Element end = oldElement.removeEndTag();
							if (end != null) {
								child = end;
								newNext = end;
							}
						}
					}
					newElement.appendChild(child);
				}
			}
			else {
				if (!oldElement.isCommentTag()) {
					// clone (re-create) end tag
					Element end = oldElement.removeEndTag();
					if (end != null) {
						parent.insertBefore(end, oldElement);
						parent.removeChild(oldElement);
						newNext = end;
					}
				}
			}
		}
		else {
			newNext = oldElement.getNextSibling();
			parent.removeChild(oldElement);
		}

		// update context
		Node oldParent = this.context.getParentNode();
		Node oldNext = this.context.getNextNode();
		if (element == oldParent) {
			if (oldNext != null) {
				this.context.setNextNode(oldNext); // reset for new parent
			}
			else if (newNext != null) {
				this.context.setNextNode(newNext);
			}
			else {
				this.context.setParentNode(parent);
			}
		}
		else if (element == oldNext) {
			if (firstElement != null) {
				this.context.setParentNode(firstElement);
			}
			else if (first != null) {
				this.context.setNextNode(first);
			}
			else if (startElement != null) {
				this.context.setParentNode(startElement);
			}
			else {
				this.context.setNextNode(newNext);
			}
		}

		removeImplicitElement(elementParent);
	}

	/**
	 * removeStructuredDocumentRegion method
	 * 
	 */
	private void removeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
		NodeImpl next = (NodeImpl) this.context.getNextNode();
		if (next != null) {
			short nodeType = next.getNodeType();
			if (nodeType != Node.ELEMENT_NODE) {
				IStructuredDocumentRegion flatNode = next.getStructuredDocumentRegion();
				if (flatNode == oldStructuredDocumentRegion) {
					removeNode(next);
					return;
				}
				if (nodeType != Node.TEXT_NODE) {
					throw new StructuredDocumentRegionManagementException();
				}
				if (flatNode == null) {
					// this is the case for empty Text
					// remove and continue
					removeNode(next);
					removeStructuredDocumentRegion(oldStructuredDocumentRegion);
					return;
				}
				TextImpl text = (TextImpl) next;
				boolean isShared = text.isSharingStructuredDocumentRegion(oldStructuredDocumentRegion);
				if (isShared) {
					// make sure there is next Text node sharing this
					TextImpl nextText = (TextImpl) this.context.findNextText();
					if (nextText == null || !nextText.hasStructuredDocumentRegion(oldStructuredDocumentRegion)) {
						isShared = false;
					}
				}
				oldStructuredDocumentRegion = text.removeStructuredDocumentRegion(oldStructuredDocumentRegion);
				if (oldStructuredDocumentRegion == null) {
					throw new StructuredDocumentRegionManagementException();
				}
				if (text.getStructuredDocumentRegion() == null) {
					// this is the case partial IStructuredDocumentRegion is
					// removed
					removeNode(text);
				}
				else {
					// notify the change
					text.notifyValueChanged();
				}
				// if shared, continue to remove IStructuredDocumentRegion
				// from them
				if (isShared)
					removeStructuredDocumentRegion(oldStructuredDocumentRegion);
				return;
			}

			ElementImpl element = (ElementImpl) next;
			if (element.hasStartTag()) {
				IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
				if (flatNode != oldStructuredDocumentRegion) {
					throw new StructuredDocumentRegionManagementException();
				}
				if (element.hasEndTag() || element.hasChildNodes()) {
					element.setStartStructuredDocumentRegion(null);
					removeStartTag(element);
				}
				else {
					removeNode(element);
				}
			}
			else {
				Node child = element.getFirstChild();
				if (child != null) {
					this.context.setNextNode(child);
					removeStructuredDocumentRegion(oldStructuredDocumentRegion);
					return;
				}

				if (!element.hasEndTag()) {
					// implicit element
					removeNode(element);
					removeStructuredDocumentRegion(oldStructuredDocumentRegion);
					return;
				}

				IStructuredDocumentRegion flatNode = element.getEndStructuredDocumentRegion();
				if (flatNode != oldStructuredDocumentRegion) {
					throw new StructuredDocumentRegionManagementException();
				}
				removeNode(element);
			}
			return;
		}

		Node parent = this.context.getParentNode();
		if (parent == null || parent.getNodeType() != Node.ELEMENT_NODE) {
			throw new StructuredDocumentRegionManagementException();
		}

		ElementImpl end = (ElementImpl) parent;
		if (end.hasEndTag()) {
			IStructuredDocumentRegion flatNode = end.getEndStructuredDocumentRegion();
			if (flatNode != oldStructuredDocumentRegion) {
				throw new StructuredDocumentRegionManagementException();
			}
			if (!end.hasStartTag() && !end.hasChildNodes()) {
				this.context.setNextNode(end);
				removeNode(end);
			}
			else {
				end.setEndStructuredDocumentRegion(null);
				removeEndTag(end);
			}
			return;
		}

		next = (NodeImpl) end.getNextSibling();
		if (next != null) {
			this.context.setNextNode(next);
			removeStructuredDocumentRegion(oldStructuredDocumentRegion);
			return;
		}

		parent = end.getParentNode();
		if (parent != null) {
			this.context.setParentNode(parent);
			removeStructuredDocumentRegion(oldStructuredDocumentRegion);
			return;
		}
	}

	/**
	 * replaceRegions method
	 * 
	 * @param newRegions
	 *            java.util.Vector
	 * @param oldRegions
	 *            java.util.Vector
	 */
	void replaceRegions(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
		if (flatNode == null)
			return;
		if (this.model.getDocument() == null)
			return;
		this.context = new XMLModelContext(this.model.getDocument());

		// optimize typical cases
		String regionType = StructuredDocumentRegionUtil.getFirstRegionType(flatNode);
		if (regionType == DOMRegionContext.XML_TAG_OPEN) {
			changeStartTag(flatNode, newRegions, oldRegions);
		}
		else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) {
			changeEndTag(flatNode, newRegions, oldRegions);
		}
		else {
			changeStructuredDocumentRegion(flatNode);
		}
	}

	/**
	 * replaceStructuredDocumentRegions method
	 * 
	 */
	void replaceStructuredDocumentRegions(IStructuredDocumentRegionList newStructuredDocumentRegions, IStructuredDocumentRegionList oldStructuredDocumentRegions) {
		if (this.model.getDocument() == null)
			return;
		this.context = new XMLModelContext(this.model.getDocument());

		int newCount = (newStructuredDocumentRegions != null ? newStructuredDocumentRegions.getLength() : 0);
		int oldCount = (oldStructuredDocumentRegions != null ? oldStructuredDocumentRegions.getLength() : 0);

		if (oldCount > 0) {
			setupContext(oldStructuredDocumentRegions.item(0));
			// Node startParent = this.context.getParentNode();

			Enumeration e = oldStructuredDocumentRegions.elements();
			while (e.hasMoreElements()) {
				IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e.nextElement();
				if (flatNode == null)
					continue;
				removeStructuredDocumentRegion(flatNode);
			}
		}
		else {
			if (newCount == 0)
				return;
			setupContext(newStructuredDocumentRegions.item(0));
		}
		// make sure the parent is set to deepest level
		// when end tag has been removed
		this.context.setLast();

		if (newCount > 0) {
			Enumeration e = newStructuredDocumentRegions.elements();
			while (e.hasMoreElements()) {
				IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e.nextElement();
				if (flatNode == null)
					continue;
				insertStructuredDocumentRegion(flatNode);
			}
		}

		cleanupText();
		cleanupEndTag();
	}

	/**
	 * setupContext method
	 * 
	 */
	private void setupContext(IStructuredDocumentRegion startStructuredDocumentRegion) {
		int offset = startStructuredDocumentRegion.getStart();
		if (offset < 0)
			return;
		NodeImpl root = (NodeImpl) this.context.getRootNode();
		if (root == null)
			return;

		if (offset == 0) {
			// at the beggining of document
			Node child = root.getFirstChild();
			if (child != null)
				this.context.setNextNode(child);
			else
				this.context.setParentNode(root);
			return;
		}

		NodeImpl node = (NodeImpl) root.getNodeAt(offset);
		if (node == null) {
			// might be at the end of document
			this.context.setParentNode(root);
			this.context.setLast();
			return;
		}

		if (offset == node.getStartOffset()) {
			this.context.setNextNode(node);
			return;
		}

		if (node.getNodeType() == Node.TEXT_NODE) {
			TextImpl text = (TextImpl) node;
			Text nextText = text.splitText(startStructuredDocumentRegion);
			// notify the change
			text.notifyValueChanged();
			if (nextText == null)
				return; // error
			this.context.setNextNode(nextText);
			return;
		}

		for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
			if (offset >= ((NodeImpl) child).getEndOffset())
				continue;
			this.context.setNextNode(child);
			return;
		}
		this.context.setParentNode(node);
		this.context.setLast();
	}

	protected XMLModelContext getContext() {
		return context;
	}

}
