/*******************************************************************************
 * Copyright (c) 2001, 2004 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.ui.internal.contentassist;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.sse.core.internal.encoding.ContentTypeEncodingPreferences;
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.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.core.internal.util.Debug;
import org.eclipse.wst.sse.ui.internal.IReleasable;
import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMEntityDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAction;
import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
import org.eclipse.wst.xml.core.internal.document.AttrImpl;
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
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.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.eclipse.wst.xml.ui.internal.Logger;
import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
import org.eclipse.wst.xml.ui.internal.editor.CMImageUtil;
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
import org.eclipse.wst.xml.ui.internal.taginfo.MarkupTagInfoProvider;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

abstract public class AbstractContentAssistProcessor implements IContentAssistProcessor, IReleasable {
	/**
	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
	 * way for expedency. Should be evolved in future to depend on
	 * "nestedContext".
	 */
	private class DOMJSPRegionContextsPrivateCopy {
		private static final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$
		private static final String JSP_COMMENT_CLOSE = "JSP_COMMENT_CLOSE"; //$NON-NLS-1$

		private static final String JSP_COMMENT_OPEN = "JSP_COMMENT_OPEN"; //$NON-NLS-1$
		private static final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$
		private static final String JSP_DIRECTIVE_CLOSE = "JSP_DIRECTIVE_CLOSE"; //$NON-NLS-1$
		private static final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$

		private static final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$
		private static final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$

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

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

	}

	protected static final String INTERNALERROR = XMLUIMessages.SEVERE_internal_error_occu_UI_;
	protected static final String UNKNOWN_ATTR = XMLUIMessages.No_known_attribute__UI_;
	protected static final String UNKNOWN_CONTEXT = XMLUIMessages.Content_Assist_not_availab_UI_;
	protected char completionProposalAutoActivationCharacters[] = null;
	protected char contextInformationAutoActivationCharacters[] = null;
	private AttributeContextInformationProvider fAttributeInfoProvider = null;
	private AttributeContextInformationPresenter fContextInformationPresenter = null;

	protected String fErrorMessage = null;
	protected XMLContentModelGenerator fGenerator;
	// protected IResource resource = null;
	protected MarkupTagInfoProvider fInfoProvider = null;
	protected ITextViewer fTextViewer = null;

	private final boolean showValues = true;

	public AbstractContentAssistProcessor() {
		init();
	}

	protected void addAttributeNameProposals(ContentAssistRequest contentAssistRequest) {
		IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
		IStructuredDocumentRegion sdRegion = contentAssistRequest.getDocumentRegion();
		// retrieve the list of attributes
		CMElementDeclaration elementDecl = getCMElementDeclaration(node);
		if (elementDecl != null) {
			CMNamedNodeMap attributes = elementDecl.getAttributes();
			String matchString = contentAssistRequest.getMatchString();

			// check whether an attribute really exists for the replacement
			// offsets AND if it possesses a value
			boolean attrAtLocationHasValue = false;
			NamedNodeMap attrs = node.getAttributes();
			for (int i = 0; i < attrs.getLength(); i++) {
				AttrImpl existingAttr = (AttrImpl) attrs.item(i);
				ITextRegion name = existingAttr.getNameRegion();

				if (sdRegion.getStartOffset(name) <= contentAssistRequest.getReplacementBeginPosition() && sdRegion.getStartOffset(name) + name.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength() && existingAttr.getValueRegion() != null) {
					attrAtLocationHasValue = true;
					break;
				}
			}

			// only add proposals for the attributes whose names begin with
			// the matchstring
			if (attributes != null) {
				for (int i = 0; i < attributes.getLength(); i++) {
					CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attributes.item(i);
					// CMVC 246618
					int isRequired = 0;
					if (attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED) {
						isRequired = XMLRelevanceConstants.R_REQUIRED;
					}

					boolean showAttribute = true;
					showAttribute = showAttribute && beginsWith(getRequiredName(node, attrDecl), matchString.trim());
					AttrImpl attr = (AttrImpl) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl));
					ITextRegion nameRegion = attr != null ? attr.getNameRegion() : null;
					// nameRegion.getEndOffset() + 1 is required to allow for
					// matches against the full name of an existing Attr
					showAttribute = showAttribute && ((attr == null) || (nameRegion != null && sdRegion.getStartOffset(nameRegion) <= contentAssistRequest.getReplacementBeginPosition() && sdRegion.getStartOffset(nameRegion) + nameRegion.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength()));
					if (showAttribute) {
						Image attrImage = CMImageUtil.getImage(attrDecl);
						if (attrImage == null) {
							if (isRequired > 0) {
								attrImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATT_REQ_OBJ);
							}
							else {
								attrImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
							}
						}

						String proposedText = null;
						String proposedInfo = getAdditionalInfo(elementDecl, attrDecl);
						CustomCompletionProposal proposal = null;
						// attribute is at this location and already exists
						if (attrAtLocationHasValue) {
							// only propose the name
							proposedText = getRequiredName(node, attrDecl);
							proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), attrImage, proposedText, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired, true); // CMVC
							// 269884
						}
						// no attribute exists or is elsewhere, generate
						// minimally
						else {
							Attr existingAttrNode = (Attr) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl));
							String value = null;
							if (existingAttrNode != null)
								value = existingAttrNode.getNodeValue();
							if (value != null && value.length() > 0)
								proposedText = getRequiredName(node, attrDecl);
							else {
								proposedText = getRequiredText(node, attrDecl);
							}
							proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), attrDecl.getNodeName().length() + 2, attrImage,
							// if the value isn't empty (no empty set of
										// quotes), show it
										(showValues && proposedText.indexOf("\"\"") < 0) ? proposedText : getRequiredName(node, attrDecl), //$NON-NLS-1$
										null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired);
						}
						contentAssistRequest.addProposal(proposal);
					}
				}
			}
		}
		else {
			setErrorMessage(NLS.bind(XMLUIMessages.Element__is_unknown, (new Object[]{node.getNodeName()})));
		}
	}

	protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest) {
		IDOMNode node = (IDOMNode) contentAssistRequest.getNode();

		// Find the attribute region and name for which this position should
		// have a value proposed
		IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion();
		ITextRegionList openRegions = open.getRegions();
		int i = openRegions.indexOf(contentAssistRequest.getRegion());
		if (i < 0)
			return;
		ITextRegion nameRegion = null;
		while (i >= 0) {
			nameRegion = openRegions.get(i--);
			if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)
				break;
		}

		// the name region is REQUIRED to do anything useful
		if (nameRegion != null) {
			// Retrieve the declaration
			CMElementDeclaration elementDecl = getCMElementDeclaration(node);

			// String attributeName = nameRegion.getText();
			String attributeName = open.getText(nameRegion);

			CMAttributeDeclaration attrDecl = null;

			// No CMElementDeclaration means no attribute metadata, but
			// retrieve the
			// declaration for the attribute otherwise
			if (elementDecl != null) {
				CMNamedNodeMap attributes = elementDecl.getAttributes();
				String noprefixName = DOMNamespaceHelper.getUnprefixedName(attributeName);
				if (attributes != null) {
					attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(noprefixName);
					if (attrDecl == null) {
						attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(attributeName);
					}
				}
				if (attrDecl == null) {
					setErrorMessage(UNKNOWN_ATTR, attributeName);
				}
			}

			String currentValue = node.getAttributes().getNamedItem(attributeName).getNodeValue();
			String proposedInfo = null;
			Image image = CMImageUtil.getImage(attrDecl);
			if (image == null) {
				if (attrDecl != null && attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED) {
					image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATT_REQ_OBJ);
				}
				else {
					image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
				}
			}

			if (attrDecl != null && attrDecl.getAttrType() != null) {
				// attribute is known, prompt with values from the declaration
				proposedInfo = getAdditionalInfo(elementDecl, attrDecl);
				List possibleValues = getPossibleDataTypeValues(node, attrDecl);
				if (possibleValues.size() > 0) {
					// ENUMERATED VALUES
					String matchString = contentAssistRequest.getMatchString();
					if (matchString == null)
						matchString = ""; //$NON-NLS-1$
					if (matchString.length() > 0 && (matchString.startsWith("\"") || matchString.startsWith("'"))) //$NON-NLS-2$//$NON-NLS-1$
						matchString = matchString.substring(1);
					boolean currentValid = false;

					// d210858, if the region's a container, don't suggest the
					// enumerated values as they probably won't help
					boolean existingComplicatedValue = contentAssistRequest.getRegion() != null && contentAssistRequest.getRegion() instanceof ITextRegionContainer;
					if (!existingComplicatedValue) {
						for (Iterator j = possibleValues.iterator(); j.hasNext();) {
							String possibleValue = (String) j.next();
							currentValid = currentValid || possibleValue.equals(currentValue);
							if (matchString.length() == 0 || possibleValue.startsWith(matchString)) {
								CustomCompletionProposal proposal = new CustomCompletionProposal("\"" + possibleValue + "\"", //$NON-NLS-2$//$NON-NLS-1$
											contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), possibleValue.length() + 1, image, possibleValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
								contentAssistRequest.addProposal(proposal);
							}
						}
					}
				}
				else if ((attrDecl.getUsage() == CMAttributeDeclaration.FIXED || attrDecl.getAttrType().getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) && attrDecl.getAttrType().getImpliedValue() != null) {
					// FIXED values
					String value = attrDecl.getAttrType().getImpliedValue();
					if (value != null && value.length() > 0) {
						CustomCompletionProposal proposal = new CustomCompletionProposal("\"" + value + "\"", //$NON-NLS-2$//$NON-NLS-1$
									contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), value.length() + 1, image, value, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
						contentAssistRequest.addProposal(proposal);
						if (currentValue.length() > 0 && !value.equals(currentValue)) {
							proposal = new CustomCompletionProposal("\"" + currentValue + "\"", //$NON-NLS-2$//$NON-NLS-1$
										contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), currentValue.length() + 1, image, currentValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
							contentAssistRequest.addProposal(proposal);
						}
					}
				}
			}
			else {
				// unknown attribute, so supply nice empty values
				proposedInfo = getAdditionalInfo(null, elementDecl);
				CustomCompletionProposal proposal = null;
				if (currentValue != null && currentValue.length() > 0) {
					proposal = new CustomCompletionProposal("\"" + currentValue + "\"", //$NON-NLS-2$//$NON-NLS-1$
								contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, image, "\"" + currentValue + "\"", //$NON-NLS-2$//$NON-NLS-1$
								null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
					contentAssistRequest.addProposal(proposal);
				}
			}
		}
		else
			setErrorMessage(UNKNOWN_CONTEXT);
	}

	protected void addCommentProposal(ContentAssistRequest contentAssistRequest) {
		contentAssistRequest.addProposal(new CustomCompletionProposal("<!--  -->", //$NON-NLS-1$
					contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 5, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_COMMENT), NLS.bind(XMLUIMessages.Comment__, (new Object[]{" <!--  -->"})), //$NON-NLS-1$
					null, null, XMLRelevanceConstants.R_COMMENT));
	}

	/**
	 * Add all of the element declarations int the CMContent object into one
	 * big list.
	 */
	protected void addContent(List contentList, CMContent content) {
		if (content == null)
			return;
		if (content instanceof CMGroup) {
			CMNodeList children = ((CMGroup) content).getChildNodes();
			if (children == null)
				return;
			for (int i = 0; i < children.getLength(); i++) {
				CMNode child = children.item(i);
				if (child.getNodeType() == CMNode.ELEMENT_DECLARATION) {
					contentList.add(child);
				}
				else {
					if (child.getNodeType() == CMNode.GROUP) {
						addContent(contentList, (CMContent) child);
					}
					else {
						throw new IllegalArgumentException("Unknown content child: " + child); //$NON-NLS-1$
					}
				}
			}
		}
		else {
			contentList.add(content);
		}
	}

	protected void addDocTypeProposal(ContentAssistRequest contentAssistRequest) {
		// if a DocumentElement exists, use that for the root Element name
		String rootname = "unspecified"; //$NON-NLS-1$
		if (contentAssistRequest.getNode().getOwnerDocument().getDocumentElement() != null)
			rootname = contentAssistRequest.getNode().getOwnerDocument().getDocumentElement().getNodeName();

		String proposedText = "<!DOCTYPE " + rootname + " PUBLIC \"//UNKNOWN/\" \"unknown.dtd\">"; //$NON-NLS-1$ //$NON-NLS-2$
		ICompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 10, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DOCTYPE), "<!DOCTYPE ... >", //$NON-NLS-1$
					null, null, XMLRelevanceConstants.R_DOCTYPE);
		// TODO provide special documentation on doc type
		contentAssistRequest.addProposal(proposal);
	}

	/**
	 * Add the proposals for a completely empty document
	 */
	protected void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest) {
		addXMLProposal(contentAssistRequest);
	}

	/**
	 * Add the proposals for the name in an end tag
	 */
	protected void addEndTagNameProposals(ContentAssistRequest contentAssistRequest) {

		if (contentAssistRequest.getStartOffset() + contentAssistRequest.getRegion().getTextLength() < contentAssistRequest.getReplacementBeginPosition()) {
			CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
						contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$
						null, null, XMLRelevanceConstants.R_END_TAG_NAME);
			contentAssistRequest.addProposal(proposal);
		}
		else {
			IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
			Node aNode = contentAssistRequest.getNode();
			String matchString = contentAssistRequest.getMatchString();
			if (matchString.startsWith("</")) //$NON-NLS-1$
				matchString = matchString.substring(2);
			while (aNode != null) {
				if (aNode.getNodeType() == Node.ELEMENT_NODE) {
					if (aNode.getNodeName().startsWith(matchString)) {
						IDOMNode aXMLNode = (IDOMNode) aNode;
						CMElementDeclaration ed = modelQuery.getCMElementDeclaration((Element) aNode);
						if ((aXMLNode.getEndStructuredDocumentRegion() == null) && (ed == null || (ed.getContentType() != CMElementDeclaration.EMPTY))) {
							String proposedText = aNode.getNodeName();
							String proposedInfo = (ed != null) ? getAdditionalInfo(null, ed) : null;
							if (node.getNodeType() == Node.TEXT_NODE && !contentAssistRequest.getDocumentRegion().isEnded())
								proposedText += ">"; //$NON-NLS-1$
							CustomCompletionProposal proposal = null;
							// double check to see if the region acted upon is
							// a tag name; replace it if so
							Image image = CMImageUtil.getImage(ed);
							if (image == null) {
								image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
							}
							if (contentAssistRequest.getRegion().getType() == DOMRegionContext.XML_TAG_NAME) {
								proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getStartOffset(), contentAssistRequest.getRegion().getTextLength(), proposedText.length(), image, proposedText, null, proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME);
							}
							else {
								proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{"'" + proposedText + "'"})), //$NON-NLS-1$ //$NON-NLS-2$
											null, proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME);
							}
							contentAssistRequest.addProposal(proposal);
						}
					}
				}
				aNode = aNode.getParentNode();
			}
		}
	}

	/**
	 * Prompt for end tags to a non-empty Node that hasn't ended Handles these
	 * cases: <br>
	 * <tagOpen>| <br>
	 * <tagOpen>< |<br>
	 * <tagOpen></ |
	 * 
	 * @param contentAssistRequest
	 */
	protected void addEndTagProposals(ContentAssistRequest contentAssistRequest) {
		IDOMNode node = (IDOMNode) contentAssistRequest.getParent();

		if (isCommentNode(node)) {
			// loop and find non comment node parent
			while (node != null && isCommentNode(node)) {
				node = (IDOMNode) node.getParentNode();
			}
		}
		
		// node is already closed
		if(node.isClosed()) {
			// loop and find non comment unclose node parent
			while (node != null && node.isClosed()) {
				node = (IDOMNode) node.getParentNode();
			}
		}
		// there were no unclosed tags
		if(node == null)
			return;
		
		// data to create a CustomCompletionProposal
		String replaceText = node.getNodeName() + ">"; //$NON-NLS-1$
		int replaceBegin = contentAssistRequest.getReplacementBeginPosition();
		int replaceLength = contentAssistRequest.getReplacementLength();
		int cursorOffset = node.getNodeName().length() + 1;
		String displayString = ""; //$NON-NLS-1$
		String proposedInfo = ""; //$NON-NLS-1$
		Image image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);

		setErrorMessage(null);
		boolean addProposal = false;

		if (node.getNodeType() == Node.ELEMENT_NODE) {
			// fix for CMVC 261790
			// ////////////////////////////////////////////////////////////////////////////////////
			IStructuredDocument sDoc = (IStructuredDocument) fTextViewer.getDocument();
			IStructuredDocumentRegion xmlEndTagOpen = sDoc.getRegionAtCharacterOffset(contentAssistRequest.getReplacementBeginPosition());
			// skip backward to "<", "</", or the (unclosed) start tag, null
			// if not found
			String type = ""; //$NON-NLS-1$
			while (xmlEndTagOpen != null && (type = xmlEndTagOpen.getType()) != DOMRegionContext.XML_END_TAG_OPEN && type != DOMRegionContext.XML_TAG_CLOSE && !needsEndTag(xmlEndTagOpen) && type != DOMRegionContext.XML_TAG_OPEN) {
				xmlEndTagOpen = xmlEndTagOpen.getPrevious();
			}

			if (xmlEndTagOpen == null)
				return;

			node = (IDOMNode) node.getModel().getIndexedRegion(xmlEndTagOpen.getStartOffset());
			node = (IDOMNode) node.getParentNode();
			
			if (isStartTag(xmlEndTagOpen)) {
				// this is the case for a start tag w/out end tag
				// eg:
				// <p>
				// <% String test = "test"; %>
				// |
				if (needsEndTag(xmlEndTagOpen)) {
					String tagName = getTagName(xmlEndTagOpen);
					xmlEndTagOpen.getTextEndOffset();
					replaceLength = 0;
					replaceText = "</" + tagName + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$
					// replaceText = "</" + node.getNodeName() + ">";
					// //$NON-NLS-1$ $NON-NLS-2$
					cursorOffset = tagName.length() + 3;
					displayString = NLS.bind(XMLUIMessages.End_with__, (new Object[]{tagName}));
					addProposal = true;
				}
			}
			else if (type == DOMRegionContext.XML_END_TAG_OPEN) {
				// this is the case for: <tag> </ |
				// possibly <tag> </ |<anotherTag>
				// should only be replacing white space...
				replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0;
				replaceText = node.getNodeName() + ">"; //$NON-NLS-1$
				cursorOffset = replaceText.length();
				replaceBegin = xmlEndTagOpen.getTextEndOffset();
				displayString = NLS.bind(XMLUIMessages.End_with_, (new Object[]{node.getNodeName()}));
				addProposal = true;
			}
			else if (type == DOMRegionContext.XML_TAG_OPEN) {
				// this is the case for: <tag> < |
				replaceText = "/" + node.getNodeName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$
				cursorOffset = replaceText.length();
				// replaceText = "/" + node.getNodeName() + ">"; //$NON-NLS-1$
				// $NON-NLS-2$
				// should only be replacing white space...
				replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0;
				replaceBegin = xmlEndTagOpen.getTextEndOffset();
				displayString = NLS.bind(XMLUIMessages.End_with_,  (new Object[]{"/" + node.getNodeName()})); //$NON-NLS-1$
				addProposal = true;
			}
		}
		// fix for CMVC 261790
		// ////////////////////////////////////////////////////////////////////////////////////
		// fix for CMVC 263163, sometimes the node is not null, but
		// getNodeValue() is null, put in a null check
		else if (node.getNodeValue() != null && node.getNodeValue().indexOf("</") != -1) { //$NON-NLS-1$
			// the case where "</" is started, but the nodes comes in as a
			// text node (instead of element)
			// like this: <tag> </|
			Node parent = node.getParentNode();
			if (parent != null && parent.getNodeType() != Node.DOCUMENT_NODE) {
				replaceText = parent.getNodeName() + ">"; //$NON-NLS-1$
				cursorOffset = replaceText.length();
				displayString = NLS.bind(XMLUIMessages.End_with__, (new Object[]{parent.getNodeName()}));
				setErrorMessage(null);
				addProposal = true;
			}
		}
		// end fix for CMVC 261790
		// ////////////////////////////////////////////////////////////////////////////////////
		else if (node.getNodeType() == Node.DOCUMENT_NODE) {
			setErrorMessage(UNKNOWN_CONTEXT);
		}
		if (addProposal == true) {
			CustomCompletionProposal proposal = new CustomCompletionProposal(replaceText, replaceBegin, replaceLength, cursorOffset, image, displayString, null, proposedInfo, XMLRelevanceConstants.R_END_TAG);
			contentAssistRequest.addProposal(proposal);
		}
	}

	protected void addEntityProposals(ContentAssistRequest contentAssistRequest, int documentPosition, ITextRegion completionRegion, IDOMNode treeNode) {
		ICompletionProposal[] eps = computeEntityReferenceProposals(documentPosition, completionRegion, treeNode);
		for (int i = 0; eps != null && i < eps.length; i++)
			contentAssistRequest.addProposal(eps[i]);
	}

	protected void addEntityProposals(Vector proposals, Properties map, String key, int nodeOffset, IStructuredDocumentRegion sdRegion, ITextRegion completionRegion) {
		if (map == null)
			return;
		String entityName = ""; //$NON-NLS-1$
		String entityValue = ""; //$NON-NLS-1$
		Image entityIcon = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENTITY_REFERENCE);
		String replacementText = ""; //$NON-NLS-1$
		String displayString = ""; //$NON-NLS-1$
		Enumeration keys = map.keys();

		while (keys != null && keys.hasMoreElements()) {
			entityName = (String) keys.nextElement();
			entityValue = map.getProperty(entityName);
			// filter based on partial entity string...
			if (entityName.toLowerCase().startsWith(key.toLowerCase()) || key.trim().equals("")) //$NON-NLS-1$
			{
				// figure out selection...if text is selected, add it to
				// selection length
				int selectionLength = nodeOffset;
				if (fTextViewer != null) {
					selectionLength += fTextViewer.getSelectedRange().y;
				}
				// create a new proposal for entity string...
				replacementText = "&" + entityName + ";"; //$NON-NLS-1$ //$NON-NLS-2$ 
				displayString = "&" + entityName + "; (" + entityValue + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				ICompletionProposal cp = new CustomCompletionProposal(replacementText, sdRegion.getStartOffset(completionRegion), selectionLength, replacementText.length(), entityIcon, displayString, null, null, XMLRelevanceConstants.R_ENTITY);
				if (cp != null) {
					proposals.add(cp);
				}
			}
		}
	}

	protected void addPCDATAProposal(String nodeName, ContentAssistRequest contentAssistRequest) {
		CustomCompletionProposal proposal = new CustomCompletionProposal("<![CDATA[]]>", //$NON-NLS-1$
					contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 9, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_CDATASECTION), "CDATA Section", //$NON-NLS-1$
					null, null, XMLRelevanceConstants.R_CDATA);
		contentAssistRequest.addProposal(proposal);

		proposal = new CustomCompletionProposal(nodeName, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), nodeName.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TXTEXT), "#PCDATA", //$NON-NLS-1$
					null, null, XMLRelevanceConstants.R_CDATA);
		contentAssistRequest.addProposal(proposal);
	}

	protected void addStartDocumentProposals(ContentAssistRequest contentAssistRequest) {
		Node aNode = contentAssistRequest.getNode();
		boolean xmlpiFound = false;
		Document owningDocument = aNode.getOwnerDocument();
		// ==> // int xmlpiNodePosition = -1;

		// make sure xmlpi is root element
		// don't want doctype proposal if XMLPI isn't first element...
		// CMVC 242943
		// CMVC 245532
		Node first = owningDocument.getFirstChild();
		boolean xmlpiIsFirstElement = (first != null && first.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE);
		boolean insertDoctype = xmlpiIsFirstElement;

		for (Node child = owningDocument.getFirstChild(); child != null; child = child.getNextSibling()) {
			boolean xmlpi = (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && child.getNodeName().equals("xml")); //$NON-NLS-1$
			xmlpiFound = xmlpiFound || xmlpi;
			if (xmlpiFound) {
				if (child instanceof IDOMNode) {
					// ==> // int xmlpiNodePosition =
					// ((XMLNode)child).getEndOffset();
				}
				// skip white space and text
				while ((child = child.getNextSibling()) != null && (child.getNodeType() == Node.TEXT_NODE)) {
				}
				// check if theres a node inbetween XMLPI and cursor position
				if (child != null && child instanceof IDOMNode) {
					// CMVC 257486
					if (contentAssistRequest.getReplacementBeginPosition() >= ((IDOMNode) child).getEndOffset() || !xmlpiIsFirstElement) {
						insertDoctype = false;
					}
				}
				break;
			}
		}

		if (!xmlpiFound) {
			addXMLProposal(contentAssistRequest);
		}
		else if (owningDocument.getDoctype() == null && isCursorAfterXMLPI(contentAssistRequest) && insertDoctype) {
			addDocTypeProposal(contentAssistRequest);
		}
	}

	/**
	 * Close an unclosed start tag
	 */
	protected void addTagCloseProposals(ContentAssistRequest contentAssistRequest) {
		IDOMNode node = (IDOMNode) contentAssistRequest.getParent();
		if (node.getNodeType() == Node.ELEMENT_NODE) {

			CMElementDeclaration elementDecl = getCMElementDeclaration(node);
			String proposedInfo = (elementDecl != null) ? getAdditionalInfo(null, elementDecl) : null;
			int contentType = (elementDecl != null) ? elementDecl.getContentType() : CMElementDeclaration.ANY;
			// if it's XML and content doesn't HAVE to be element, add "/>"
			// proposal.
			boolean endWithSlashBracket = (getXML(node) && contentType != CMElementDeclaration.ELEMENT);

			Image image = CMImageUtil.getImage(elementDecl);
			if (image == null) {
				image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
			}

			// is the start tag ended properly?
			if (contentAssistRequest.getDocumentRegion() == node.getFirstStructuredDocumentRegion() && !(node.getFirstStructuredDocumentRegion()).isEnded()) {
				setErrorMessage(null);
				// Is this supposed to be an empty tag? Note that if we can't
				// tell, we assume it's not.
				if (elementDecl != null && elementDecl.getContentType() == CMElementDeclaration.EMPTY) {
					// prompt with a self-closing end character if needed
					CustomCompletionProposal proposal = new CustomCompletionProposal(getContentGenerator().getStartTagClose(node, elementDecl), contentAssistRequest.getReplacementBeginPosition(),
					// this is one of the few times to ignore the length --
								// always insert
								// contentAssistRequest.getReplacementLength(),
								0, getContentGenerator().getStartTagClose(node, elementDecl).length(), image, NLS.bind(XMLUIMessages.Close_with___, (new Object[]{getContentGenerator().getStartTagClose(node, elementDecl)})),
								null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
					contentAssistRequest.addProposal(proposal);
				}
				else {
					// prompt with a close for the start tag
					CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
								contentAssistRequest.getReplacementBeginPosition(),
								// this is one of the few times to ignore the
								// length -- always insert
								// contentAssistRequest.getReplacementLength(),
								0, 1, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$
								null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
					contentAssistRequest.addProposal(proposal);

					// prompt with the closer for the start tag and an end tag
					// if one is not present
					if (node.getEndStructuredDocumentRegion() == null) {
						// FIX FOR CMVC 247482
						// make sure tag name is actually what it thinks it
						// is...(eg. <%@ vs. <jsp:directive)
						IStructuredDocumentRegion sdr = contentAssistRequest.getDocumentRegion();
						String openingTagText = (sdr != null) ? sdr.getFullText() : ""; //$NON-NLS-1$
						if (openingTagText != null && openingTagText.indexOf(node.getNodeName()) != -1) {
							proposal = new CustomCompletionProposal("></" + node.getNodeName() + ">", //$NON-NLS-2$//$NON-NLS-1$
										contentAssistRequest.getReplacementBeginPosition(),
										// this is one of the few times to
										// ignore the length -- always insert
										// contentAssistRequest.getReplacementLength(),
										0, 1, image, NLS.bind(XMLUIMessages.Close_with____, (new Object[]{node.getNodeName()})),
										null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
							contentAssistRequest.addProposal(proposal);
						}
					}
					// prompt with slash bracket "/>" incase if it's a self
					// ending tag
					if (endWithSlashBracket) {
						proposal = new CustomCompletionProposal("/>", //$NON-NLS-1$
									contentAssistRequest.getReplacementBeginPosition(),
									// this is one of the few times to ignore
									// the length -- always insert
									// contentAssistRequest.getReplacementLength(),
									0, 2, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" \"/>\""})), //$NON-NLS-1$
									null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG + 1); // +1
						// to
						// bring
						// to
						// top
						// of
						// list
						contentAssistRequest.addProposal(proposal);
					}
				}
			}
			else if (contentAssistRequest.getDocumentRegion() == node.getLastStructuredDocumentRegion() && !node.getLastStructuredDocumentRegion().isEnded()) {
				setErrorMessage(null);
				// prompt with a closing end character for the end tag
				CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
							contentAssistRequest.getReplacementBeginPosition(),
							// this is one of the few times to ignore the
							// length -- always insert
							// contentAssistRequest.getReplacementLength(),
							0, 1, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$
							null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
				contentAssistRequest.addProposal(proposal);
			}
		}
		else if (node.getNodeType() == Node.DOCUMENT_NODE) {
			setErrorMessage(UNKNOWN_CONTEXT);
		}
	}

	protected void addTagInsertionProposals(ContentAssistRequest contentAssistRequest, int childPosition) {
		List cmnodes = null;
		Node parent = contentAssistRequest.getParent();
		List validActions = null;
		String error = null;

		// CMVC #242943 shouldn't have proposals before XMLPI
		// (nsd) This is only valid at the document element level
		// only valid if it's XML (check added 2/17/2004)
		if (parent != null && parent.getNodeType() == Node.DOCUMENT_NODE && ((IDOMDocument) parent).isXMLType() && !isCursorAfterXMLPI(contentAssistRequest)) {
			return;
		}
		// only want proposals if cursor is after doctype...
		if (!isCursorAfterDoctype(contentAssistRequest))
			return;

		// CMVC 248081
		// fix for meta-info comment nodes.. they currently "hide" other
		// proposals because the don't
		// have a content model (so can't propose any children..)
		if (parent != null && parent instanceof IDOMNode && isCommentNode((IDOMNode) parent)) {
			// loop and find non comment node?
			while (parent != null && isCommentNode((IDOMNode) parent)) {
				parent = (IDOMNode) parent.getParentNode();
			}
		}

		if (parent.getNodeType() == Node.ELEMENT_NODE) {
			CMElementDeclaration parentDecl = getCMElementDeclaration(parent);
			if (parentDecl != null) {
				// XSD-specific ability - no filtering
				CMDataType childType = parentDecl.getDataType();
				if (childType != null) {
					String[] childStrings = childType.getEnumeratedValues();
					if (childStrings != null) {
						// the content string is the sole valid child...so
						// replace the rest
						int begin = contentAssistRequest.getReplacementBeginPosition();
						int length = contentAssistRequest.getReplacementLength();
						if (parent instanceof IDOMNode) {
							if (((IDOMNode) parent).getLastStructuredDocumentRegion() != ((IDOMNode) parent).getFirstStructuredDocumentRegion()) {
								begin = ((IDOMNode) parent).getFirstStructuredDocumentRegion().getEndOffset();
								length = ((IDOMNode) parent).getLastStructuredDocumentRegion().getStartOffset() - begin;
							}
						}
						String proposedInfo = getAdditionalInfo(parentDecl, childType);
						for (int i = 0; i < childStrings.length; i++) {
							CustomCompletionProposal textProposal = new CustomCompletionProposal(childStrings[i], begin, length, childStrings[i].length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENUM), childStrings[i], null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
							contentAssistRequest.addProposal(textProposal);
						}
					}
				}
			}
			if (parentDecl != null && parentDecl.getContentType() == CMElementDeclaration.PCDATA) {
				addPCDATAProposal(parentDecl.getNodeName(), contentAssistRequest);
			}
			else {
				// retrieve the list of children
				validActions = getAvailableChildrenAtIndex((Element) parent, childPosition);
				cmnodes = getValidCMNodes(childPosition, ModelQueryAction.INSERT, validActions);
				Iterator nodeIterator = cmnodes.iterator();
				if (!nodeIterator.hasNext()) {
					if (getCMElementDeclaration(parent) != null)
						error = NLS.bind(XMLUIMessages._Has_no_available_child, (new Object[]{parent.getNodeName()}));
					else
						error = NLS.bind(XMLUIMessages.Element__is_unknown, (new Object[]{parent.getNodeName()}));
				}
				String matchString = contentAssistRequest.getMatchString();
				// chop off any leading <'s and whitespace from the
				// matchstring
				while ((matchString.length() > 0) && (Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) //$NON-NLS-1$
					//$NON-NLS-1$
					matchString = matchString.substring(1);
				while (nodeIterator.hasNext()) {
					Object o = nodeIterator.next();
					if (o instanceof CMElementDeclaration) {
						CMElementDeclaration elementDecl = (CMElementDeclaration) o;
						// only add proposals for the child element's that
						// begin with the matchstring
						String tagname = getRequiredName(parent, elementDecl);
						Image image = CMImageUtil.getImage(elementDecl);
						if (image == null) {
							image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
						}
						// Account for the &lt; and &gt;. If attributes were
						// added, the cursor will be placed
						// at the offset before of the first character of the
						// first attribute name.
						int markupAdjustment = getContentGenerator().getMinimalStartTagLength(parent, elementDecl);
						if (beginsWith(tagname, matchString)) {
							String proposedText = getRequiredText(parent, elementDecl);
							String proposedInfo = getAdditionalInfo(parentDecl, elementDecl);
							CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), markupAdjustment, image, tagname, null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
							contentAssistRequest.addProposal(proposal);
						}
					}
				}
				if (contentAssistRequest.getProposals().size() == 0) {
					if (error != null)
						setErrorMessage(error);
					else if (contentAssistRequest.getMatchString() != null && contentAssistRequest.getMatchString().length() > 0)
						setErrorMessage(NLS.bind(XMLUIMessages.No_known_child_tag, (new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()})));
					//$NON-NLS-1$ = "No known child tag names of <{0}> begin with \"{1}\"."
					else
						setErrorMessage(NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()})));
				}
			}
		}
		else if (parent.getNodeType() == Node.DOCUMENT_NODE) {
			// Can only prompt with elements if the cursor position is past
			// the XML processing
			// instruction and DOCTYPE declaration
			boolean xmlpiFound = false;
			boolean doctypeFound = false;
			int minimumOffset = -1;

			for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {

				boolean xmlpi = (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && child.getNodeName().equals("xml")); //$NON-NLS-1$
				boolean doctype = child.getNodeType() == Node.DOCUMENT_TYPE_NODE;
				if (xmlpi || doctype && minimumOffset < 0)
					minimumOffset = ((IDOMNode) child).getFirstStructuredDocumentRegion().getStartOffset() + ((IDOMNode) child).getFirstStructuredDocumentRegion().getTextLength();
				xmlpiFound = xmlpiFound || xmlpi;
				doctypeFound = doctypeFound || doctype;
			}
			if (!xmlpiFound && contentAssistRequest.getReplacementBeginPosition() < minimumOffset) {
				addXMLProposal(contentAssistRequest);
			}

			if (contentAssistRequest.getReplacementBeginPosition() >= minimumOffset) {
				List childDecls = getAvailableRootChildren((Document) parent, childPosition);
				for (int i = 0; i < childDecls.size(); i++) {
					CMElementDeclaration ed = (CMElementDeclaration) childDecls.get(i);
					if (ed != null) {
						Image image = CMImageUtil.getImage(ed);
						if (image == null) {
							image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
						}
						String proposedText = getRequiredText(parent, ed);
						String tagname = getRequiredName(parent, ed);
						// account for the &lt; and &gt;
						int markupAdjustment = getContentGenerator().getMinimalStartTagLength(parent, ed);
						String proposedInfo = getAdditionalInfo(null, ed);
						CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), markupAdjustment, image, tagname, null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
						contentAssistRequest.addProposal(proposal);
					}
				}
			}
		}
	}

	protected void addTagNameProposals(ContentAssistRequest contentAssistRequest, int childPosition) {
		List cmnodes = null;
		Node parent = contentAssistRequest.getParent();
		IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
		List validActions = null;
		String error = null;
		String matchString = contentAssistRequest.getMatchString();
		if (parent.getNodeType() == Node.ELEMENT_NODE) {
			// retrieve the list of children
			validActions = getAvailableChildrenAtIndex((Element) parent, childPosition);
			cmnodes = getValidCMNodes(childPosition, ModelQueryAction.INSERT, validActions);
			Iterator nodeIterator = cmnodes.iterator();
			// chop off any leading <'s and whitespace from the matchstring
			while ((matchString.length() > 0) && (Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) //$NON-NLS-1$
				//$NON-NLS-1$
				matchString = matchString.substring(1);
			if (!nodeIterator.hasNext())
				error = NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()}));
			while (nodeIterator.hasNext()) {
				CMNode elementDecl = (CMNode) nodeIterator.next();
				if (elementDecl != null) {
					// only add proposals for the child element's that begin
					// with the matchstring
					String proposedText = null;
					int cursorAdjustment = 0;

					// do a check to see if partial attributes of partial tag
					// names are in list
					if ((node != null && node.getAttributes() != null && node.getAttributes().getLength() > 0 && attributeInList(node, parent, elementDecl)) || ((node.getNodeType() != Node.TEXT_NODE) && node.getFirstStructuredDocumentRegion().isEnded())) {

						proposedText = getRequiredName(parent, elementDecl);
						cursorAdjustment = proposedText.length();
					}
					else {
						proposedText = getRequiredName(parent, elementDecl);
						cursorAdjustment = proposedText.length();
						if (elementDecl instanceof CMElementDeclaration) {
							CMElementDeclaration ed = (CMElementDeclaration) elementDecl;
							if (ed.getContentType() == CMElementDeclaration.EMPTY) {
								proposedText += getContentGenerator().getStartTagClose(parent, ed);
								cursorAdjustment = proposedText.length();
							}
							else {
								cursorAdjustment = proposedText.length() + 1;
								proposedText += "></" + getRequiredName(parent, elementDecl) + ">"; //$NON-NLS-2$//$NON-NLS-1$
							}
						}
					}
					if (beginsWith(proposedText, matchString)) {
						Image image = CMImageUtil.getImage(elementDecl);
						if (image == null) {
							image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
						}
						String proposedInfo = getAdditionalInfo(getCMElementDeclaration(parent), elementDecl);
						CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), cursorAdjustment, image, getRequiredName(parent, elementDecl), null, proposedInfo, XMLRelevanceConstants.R_TAG_NAME);
						contentAssistRequest.addProposal(proposal);
					}
				}
			}
			if (contentAssistRequest.getProposals().size() == 0) {
				if (error != null)
					setErrorMessage(error);
				else if (contentAssistRequest.getMatchString() != null && contentAssistRequest.getMatchString().length() > 0)
					setErrorMessage(NLS.bind(XMLUIMessages.No_known_child_tag_names, (new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()})));
				//$NON-NLS-1$ = "No known child tag names of <{0}> begin with \"{1}\""
				else
					setErrorMessage(NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()})));
			}
		}
		else if (parent.getNodeType() == Node.DOCUMENT_NODE) {
			List childElements = getAvailableRootChildren((Document) parent, childPosition);
			for (int i = 0; i < childElements.size(); i++) {
				CMNode ed = (CMNode) childElements.get(i);
				if (ed == null)
					continue;
				String proposedText = null;
				int cursorAdjustment = 0;
				proposedText = getRequiredName(parent, ed);
				if (!beginsWith(proposedText, matchString))
					continue;
				if ((node != null && node.getAttributes() != null && node.getAttributes().getLength() > 0) || ((node.getNodeType() != Node.TEXT_NODE) && node.getFirstStructuredDocumentRegion().isEnded())) {
					cursorAdjustment = proposedText.length();
				}
				else {
					cursorAdjustment = proposedText.length();
					if (ed instanceof CMElementDeclaration) {
						CMElementDeclaration elementDecl = (CMElementDeclaration) ed;
						if (elementDecl.getContentType() == CMElementDeclaration.EMPTY) {
							proposedText += getContentGenerator().getStartTagClose(parent, elementDecl);
							cursorAdjustment = proposedText.length();
						}
						else {
							cursorAdjustment = proposedText.length() + 1;
							proposedText += "></" + getRequiredName(parent, elementDecl) + ">"; //$NON-NLS-2$//$NON-NLS-1$
						}
					}
				}
				String proposedInfo = getAdditionalInfo(null, ed);
				Image image = CMImageUtil.getImage(ed);
				if (image == null) {
					image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
				}
				CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), cursorAdjustment, image, getRequiredName(parent, ed), null, proposedInfo, XMLRelevanceConstants.R_TAG_NAME);
				contentAssistRequest.addProposal(proposal);
			}
		}
	}

	protected void addXMLProposal(ContentAssistRequest contentAssistRequest) {
		String proposedText = "<?xml version=\"1.0\" encoding=\"" + ContentTypeEncodingPreferences.getUserPreferredCharsetName(ContentTypeIdForXML.ContentTypeID_XML) + "\"?>"; //$NON-NLS-2$//$NON-NLS-1$
		ICompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION), proposedText, null, null, XMLRelevanceConstants.R_XML_DECLARATION);
		// TODO add special XML proposal info
		contentAssistRequest.addProposal(proposal);
	}

	/**
	 * This method determines if any of the attributes in the proposed XMLNode
	 * node, are possible values of attributes from possible Elements at this
	 * point in the document according to the Content Model.
	 * 
	 * @param node
	 *            the element with attributes that you would like to test if
	 *            are possible for possible Elements at this point
	 * @param cmnode
	 *            possible element at this point in the document (depending on
	 *            what 'node' is) true if any attributes of 'node' match any
	 *            possible attributes from 'cmnodes' list.
	 */
	protected boolean attributeInList(IDOMNode node, Node parent, CMNode cmnode) {
		if (node == null || parent == null || cmnode == null)
			return false;
		String elementMatchString = node.getNodeName();
		String cmnodeName = getRequiredName(parent, cmnode);// cmnode.getNodeName();
		if (node instanceof Element) {
			NamedNodeMap map = ((Element) node).getAttributes();
			String attrMatchString = ""; //$NON-NLS-1$
			CMNamedNodeMap cmattrMap = null;
			// iterate attribute possibilities for partially started node
			for (int i = 0; map != null && i < map.getLength(); i++) {
				attrMatchString = map.item(i).getNodeName();
				// filter on whatever user typed for element name already
				if (beginsWith(cmnodeName, elementMatchString)) {
					if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION) {
						cmattrMap = ((CMElementDeclaration) cmnode).getAttributes();
						// iterate possible attributes from a cmnode in
						// proposal list
						for (int k = 0; cmattrMap != null && k < cmattrMap.getLength(); k++) {
							// check if name matches
							if (cmattrMap.item(k).getNodeName().equals(attrMatchString)) {
								return true;
							}
						}
					}
				}
			}
		}
		return false;
	}

	protected boolean beginsWith(String aString, String prefix) {
		if (aString == null || prefix == null)
			return true;
		// (pa) 221190 matching independent of case to be consistant with Java
		// editor CA
		return aString.toLowerCase().startsWith(prefix.toLowerCase());
	}

	protected ContentAssistRequest computeAttributeProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
		ContentAssistRequest contentAssistRequest = null;
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
		if (documentPosition < sdRegion.getStartOffset(completionRegion)) {
			// setup to insert new attributes
			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
		}
		else {
			// Setup to replace an existing attribute name
			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
		}
		addAttributeNameProposals(contentAssistRequest);
		contentAssistRequest.setReplacementBeginPosition(documentPosition);
		contentAssistRequest.setReplacementLength(0);
		if (node.getFirstStructuredDocumentRegion() != null && (!node.getFirstStructuredDocumentRegion().isEnded())) {
			addTagCloseProposals(contentAssistRequest);
		}
		return contentAssistRequest;
	}

	protected ContentAssistRequest computeAttributeValueProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
		ContentAssistRequest contentAssistRequest = null;
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
		if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength() && sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength() != sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
			// setup to add a new attribute at the documentPosition
			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
			contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
			addAttributeNameProposals(contentAssistRequest);
			if (actualNode.getFirstStructuredDocumentRegion() != null && !actualNode.getFirstStructuredDocumentRegion().isEnded()) {
				addTagCloseProposals(contentAssistRequest);
			}
		}
		else {
			// setup to replace the existing value
			if (!nodeAtOffset.getFirstStructuredDocumentRegion().isEnded() && documentPosition < sdRegion.getStartOffset(completionRegion)) {
				// if the IStructuredDocumentRegion isn't closed and the
				// cursor is in front of the value, add
				contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
				addAttributeNameProposals(contentAssistRequest);
			}
			else {
				contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
				addAttributeValueProposals(contentAssistRequest);
			}
		}
		return contentAssistRequest;
	}

	protected ContentAssistRequest computeCompletionProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode treeNode, IDOMNode xmlnode) {
		ContentAssistRequest contentAssistRequest = null;
		String regionType = completionRegion.getType();
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);

		// Handle the most common and best supported cases
		if (xmlnode.getNodeType() == Node.ELEMENT_NODE || xmlnode.getNodeType() == Node.DOCUMENT_NODE) {
			if (regionType == DOMRegionContext.XML_TAG_OPEN) {
				contentAssistRequest = computeTagOpenProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
			}
			else if (regionType == DOMRegionContext.XML_TAG_NAME) {
				contentAssistRequest = computeTagNameProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				contentAssistRequest = computeAttributeProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
				contentAssistRequest = computeEqualsProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && documentPosition == sdRegion.getTextEndOffset() && (sdRegion.getText(completionRegion).endsWith("\"") || sdRegion.getText(completionRegion).endsWith("\'"))) //$NON-NLS-1$ //$NON-NLS-2$
			{
				// this is for when the cursor is at the end of the closing
				// quote for an attribute..
				IDOMNode actualNode = (IDOMNode) xmlnode.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
				contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
				addTagCloseProposals(contentAssistRequest);
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
				contentAssistRequest = computeAttributeValueProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
			}
			else if ((regionType == DOMRegionContext.XML_TAG_CLOSE) || (regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE) || (regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_CLOSE))) {
				contentAssistRequest = computeTagCloseProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
			}
			else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) {
				contentAssistRequest = computeEndTagOpenProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
			}
			else if (regionType == DOMRegionContext.XML_CONTENT || regionType == DOMRegionContext.XML_CHAR_REFERENCE || regionType == DOMRegionContext.XML_ENTITY_REFERENCE || regionType == DOMRegionContext.XML_PE_REFERENCE) {
				contentAssistRequest = computeContentProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
			}

			// These ITextRegion types begin DOM Elements as well and although
			// internally harder to assist,
			// text insertions directly before them can be made
			else if (documentPosition == sdRegion.getStartOffset(completionRegion) && (regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DECLARATION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_EXPRESSION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_SCRIPTLET_OPEN) || regionType == DOMRegionContext.XML_DECLARATION_OPEN || regionType == DOMRegionContext.XML_PI_OPEN || regionType == DOMRegionContext.XML_COMMENT_OPEN || regionType == DOMRegionContext.XML_CDATA_OPEN)) {
				contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
				addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode));
				addStartDocumentProposals(contentAssistRequest);
			}
		}
		// Not a Document or Element? (odd cases go here for now)
		else if (isCloseRegion(completionRegion)) {
			contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion) + completionRegion.getLength(), 0, matchString);
			addStartDocumentProposals(contentAssistRequest);
			if (documentPosition >= sdRegion.getTextEndOffset(completionRegion))
				addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode) + 1);
		}
		else if (documentPosition == sdRegion.getStartOffset(completionRegion) && (regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DECLARATION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_EXPRESSION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_SCRIPTLET_OPEN) || regionType == DOMRegionContext.XML_DECLARATION_OPEN || regionType == DOMRegionContext.XML_PI_OPEN || regionType == DOMRegionContext.XML_COMMENT_OPEN || regionType == DOMRegionContext.XML_CDATA_OPEN)) {
			contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
			addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode));
			addStartDocumentProposals(contentAssistRequest);
		}
		return contentAssistRequest;
	}

	/**
	 * CONTENT ASSIST STARTS HERE
	 * 
	 * Return a list of proposed code completions based on the specified
	 * location within the document that corresponds to the current cursor
	 * position within the text-editor control.
	 * 
	 * @param textViewer
	 * @param documentPosition -
	 *            the cursor location within the document
	 * 
	 * an array of ICompletionProposals
	 */
	public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int documentPosition) {

		setErrorMessage(null);

		fTextViewer = textViewer;

		IndexedRegion treeNode = ContentAssistUtils.getNodeAt((StructuredTextViewer) textViewer, documentPosition);

		Node node = (Node) treeNode;
		while (node != null && node.getNodeType() == Node.TEXT_NODE && node.getParentNode() != null)
			node = node.getParentNode();
		IDOMNode xmlnode = (IDOMNode) node;

		ContentAssistRequest contentAssistRequest = null;

		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
		ITextRegion completionRegion = getCompletionRegion(documentPosition, node);

		String matchString = getMatchString(sdRegion, completionRegion, documentPosition);

		// Handle empty Documents
		if (completionRegion == null) {
			if (((treeNode == null) || ((Node) treeNode).getNodeType() == Node.DOCUMENT_NODE) && completionRegion == null && (xmlnode == null || xmlnode.getChildNodes() == null || xmlnode.getChildNodes().getLength() == 0)) {
				IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(textViewer.getDocument());
				try {
					if (sModel != null) {
						IDOMDocument docNode = ((IDOMModel) sModel).getDocument();
						contentAssistRequest = newContentAssistRequest(docNode, docNode, sdRegion, completionRegion, documentPosition, 0, null);
						addEmptyDocumentProposals(contentAssistRequest);
					}
				}
				finally {
					if (sModel != null)
						sModel.releaseFromRead();
				}
				if (contentAssistRequest == null) {
					Logger.logException(new IllegalStateException("problem getting model")); //$NON-NLS-1$
					return new ICompletionProposal[0];
				}
				return contentAssistRequest.getCompletionProposals();
			}
			// MASSIVE ERROR CONDITION
			Logger.logException(new IllegalStateException("completion region was null")); //$NON-NLS-1$
			setErrorMessage(INTERNALERROR);
			contentAssistRequest = newContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
			return contentAssistRequest.getCompletionProposals();
		}


		// catch documents where no region can be determined
		if (xmlnode.getNodeType() == Node.DOCUMENT_NODE && (completionRegion == null || xmlnode.getChildNodes() == null || xmlnode.getChildNodes().getLength() == 0)) {
			contentAssistRequest = computeStartDocumentProposals(documentPosition, matchString, completionRegion, (IDOMNode) treeNode, xmlnode);
			return contentAssistRequest.getCompletionProposals();
		}

		// compute normal proposals
		contentAssistRequest = computeCompletionProposals(documentPosition, matchString, completionRegion, (IDOMNode) treeNode, xmlnode);
		if (contentAssistRequest == null) {
			contentAssistRequest = newContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
			if (Debug.displayWarnings)
				System.out.println(UNKNOWN_CONTEXT + " " + completionRegion.getType() + "@" + documentPosition); //$NON-NLS-2$//$NON-NLS-1$
			setErrorMessage(UNKNOWN_CONTEXT);
		}

		if (contentAssistRequest.getProposals().size() == 0)
			setErrorMessage(UNKNOWN_CONTEXT);

		return contentAssistRequest.getCompletionProposals();
	}

	protected ContentAssistRequest computeContentProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
		ContentAssistRequest contentAssistRequest = null;

		// setup to add children at the content node's position
		contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition, 0, matchString);
		if (node != null && node.getNodeType() == Node.DOCUMENT_NODE && ((Document) node).getDoctype() == null)
			addStartDocumentProposals(contentAssistRequest);
		addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
		if (node.getNodeType() != Node.DOCUMENT_NODE) {
			addEndTagProposals(contentAssistRequest);
		}
		// entities?
		addEntityProposals(contentAssistRequest, documentPosition, completionRegion, node);
		// addEntityProposals(contentAssistRequest);
		return contentAssistRequest;
	}

	/**
	 * Returns information about possible contexts based on the specified
	 * location within the document that corresponds to the current cursor
	 * position within the text viewer.
	 * 
	 * @param viewer
	 *            the viewer whose document is used to compute the possible
	 *            contexts an array of context information objects or
	 *            <code>null</code> if no context could be found
	 */
	public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
		if (fAttributeInfoProvider == null)
			fAttributeInfoProvider = new AttributeContextInformationProvider((IStructuredDocument) viewer.getDocument(), (AttributeContextInformationPresenter) getContextInformationValidator());
		return fAttributeInfoProvider.getAttributeInformation(documentOffset);
	}

	protected ContentAssistRequest computeEndTagOpenProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
		ContentAssistRequest contentAssistRequest = null;
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
		int completionRegionStart = sdRegion.getStartOffset(completionRegion);
		int completionRegionLength = completionRegion.getLength();
		IStructuredDocumentRegion sdRegionAtCompletionOffset = node.getStructuredDocument().getRegionAtCharacterOffset(completionRegionStart + completionRegionLength);
		ITextRegion regionAtEndOfCompletion = sdRegionAtCompletionOffset.getRegionAtCharacterOffset(completionRegionStart + completionRegionLength);

		if (documentPosition != completionRegionStart && regionAtEndOfCompletion != null && regionAtEndOfCompletion.getType() == DOMRegionContext.XML_TAG_NAME) {
			ITextRegion nameRegion = regionAtEndOfCompletion;
			contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(nameRegion), nameRegion.getTextLength(), matchString);
		}
		else {
			if (nodeAtOffset.getFirstStructuredDocumentRegion() == sdRegion) {
				// abnormal case, this unmatched end tag will be a sibling
				contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
			}
			else {
				// normal case, this end tag is the parent
				contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset, sdRegion, completionRegion, documentPosition, 0, matchString);
			}
		}
		// if (documentPosition >= sdRegion.getStartOffset(completionRegion) +
		// completionRegion.getTextLength())
		addEndTagProposals(contentAssistRequest);
		// else
		if (completionRegionStart == documentPosition) {
			// positioned at start of end tag
			addTagInsertionProposals(contentAssistRequest, node.getChildNodes().getLength());
		}
		return contentAssistRequest;
	}

	/**
	 * return all possible EntityReferenceProposals (according to current
	 * position in doc)
	 */
	protected ICompletionProposal[] computeEntityReferenceProposals(int documentPosition, ITextRegion completionRegion, IDOMNode treeNode) {
		// only handle XML content for now
		Vector proposals = new Vector(); // ICompletionProposals
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
		if (completionRegion != null && completionRegion.getType() == DOMRegionContext.XML_CONTENT) {
			int nodeOffset = documentPosition - sdRegion.getStartOffset(completionRegion);
			String regionText = sdRegion.getFullText(completionRegion);

			// if directly to the right of a &, region will be null, need to
			// move to
			// the previous region...there might be a better way to do this
			if (regionText != null && regionText.trim().equals("") && documentPosition > 0) { //$NON-NLS-1$
				IStructuredDocumentRegion prev = treeNode.getStructuredDocument().getRegionAtCharacterOffset(documentPosition - 1);
				if (prev != null && prev.getFullText().trim().equals("&")) { //$NON-NLS-1$		
					completionRegion = prev;
					regionText = prev.getFullText();
					nodeOffset = 1;
				}
			}

			// string must start w/ &
			if (regionText != null && regionText.startsWith("&")) { //$NON-NLS-1$						 		
				String key = (nodeOffset > 0) ? regionText.substring(1, nodeOffset) : ""; //$NON-NLS-1$

				// get entity proposals, passing in the appropriate start
				// string
				ModelQuery mq = ModelQueryUtil.getModelQuery(((Node) treeNode).getOwnerDocument());
				if (mq != null) {
					CMDocument xmlDoc = mq.getCorrespondingCMDocument(treeNode);
					CMNamedNodeMap cmmap = null;
					Properties entities = null;
					if (xmlDoc != null) {
						cmmap = xmlDoc.getEntities();
					}
					if (cmmap != null) {
						entities = mapToProperties(cmmap);
					}
					else // 224787 in absence of content model, just use
					// minimal 5 entities
					{
						entities = new Properties();
						entities.put("quot", "\""); //$NON-NLS-1$ //$NON-NLS-2$
						entities.put("apos", "'"); //$NON-NLS-1$ //$NON-NLS-2$
						entities.put("amp", "&"); //$NON-NLS-1$ //$NON-NLS-2$
						entities.put("lt", "<"); //$NON-NLS-1$ //$NON-NLS-2$
						entities.put("gt", ">"); //$NON-NLS-1$ //$NON-NLS-2$	
						entities.put("nbsp", " "); //$NON-NLS-1$ //$NON-NLS-2$									
					}
					addEntityProposals(proposals, entities, key, nodeOffset, sdRegion, completionRegion); //$NON-NLS-1$
				}
			}
		}
		return (ICompletionProposal[]) ((proposals.size() > 0) ? proposals.toArray(new ICompletionProposal[proposals.size()]) : null);
	}

	protected ContentAssistRequest computeEqualsProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
		ContentAssistRequest contentAssistRequest = null;
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
		ITextRegion valueRegion = node.getStartStructuredDocumentRegion().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) + completionRegion.getLength());
		if (valueRegion != null && valueRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && sdRegion.getStartOffset(valueRegion) <= documentPosition) {
			// replace the adjacent attribute value
			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, valueRegion, sdRegion.getStartOffset(valueRegion), valueRegion.getTextLength(), matchString);
		}
		else {
			// append an attribute value after the '='
			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
		}
		addAttributeValueProposals(contentAssistRequest);
		return contentAssistRequest;
	}

	protected ContentAssistRequest computeStartDocumentProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
		// setup for a non-empty document, but one that hasn't been formally
		// started
		ContentAssistRequest contentAssistRequest = null;
		contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition, 0, matchString);
		addStartDocumentProposals(contentAssistRequest);
		return contentAssistRequest;
	}

	protected ContentAssistRequest computeTagCloseProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
		ContentAssistRequest contentAssistRequest = null;
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);

		if ((node.getNodeType() == Node.DOCUMENT_NODE) || (documentPosition >= sdRegion.getEndOffset())) {
			// this is a content request as the documentPosition is AFTER the
			// end of the closing region
			if (node == nodeAtOffset && node.getParentNode() != null)
				node = (IDOMNode) node.getParentNode();
			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
			addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
			if (node.getNodeType() != Node.DOCUMENT_NODE && node.getEndStructuredDocumentRegion() == null) {
				addEndTagProposals(contentAssistRequest);
			}
		}
		else {
			// at the start of the tag's close or within it
			ITextRegion closeRegion = sdRegion.getLastRegion();
			boolean insideTag = !sdRegion.isEnded() || documentPosition <= sdRegion.getStartOffset(closeRegion);
			if (insideTag) {
				// this is a request for completions within a tag
				contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
				if (node.getNodeType() != Node.DOCUMENT_NODE && node.getEndStructuredDocumentRegion() != null) {
					addTagCloseProposals(contentAssistRequest);
				}
				if (sdRegion == nodeAtOffset.getFirstStructuredDocumentRegion()) {
					contentAssistRequest.setReplacementBeginPosition(documentPosition);
					contentAssistRequest.setReplacementLength(0);
					addAttributeNameProposals(contentAssistRequest);
				}
			}
		}
		return contentAssistRequest;
	}

	protected ContentAssistRequest computeTagNameProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
		ContentAssistRequest contentAssistRequest = null;
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);

		if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion()) {
			// completing the *first* tag in "<tagname1 |<tagname2"
			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
			if (actualNode != null) {
				if (actualNode.getFirstStructuredDocumentRegion() == sdRegion) {
					// start tag
					if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
						// it's attributes
						contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
						if (node.getStructuredDocument().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getType() == DOMRegionContext.XML_TAG_OPEN)
							addAttributeNameProposals(contentAssistRequest);
						addTagCloseProposals(contentAssistRequest);
					}
					else {
						// it's name
						contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
						addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(actualNode));
					}
				}
				else {
					if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
						// insert name
						contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
					}
					else {
						// replace name
						contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
					}
					addEndTagNameProposals(contentAssistRequest);
				}
			}
		}
		else {
			if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
				// unclosed tag with only a name; should prompt for attributes
				// and a close instead
				contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
				addAttributeNameProposals(contentAssistRequest);
				addTagCloseProposals(contentAssistRequest);
			}
			else {
				if (sdRegion.getRegions().get(0).getType() != DOMRegionContext.XML_END_TAG_OPEN) {
					contentAssistRequest = newContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
					addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
				}
				else {
					IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(documentPosition);
					if (actualNode != null) {
						if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
							contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
						}
						else {
							contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
						}
						addEndTagNameProposals(contentAssistRequest);
					}
				}
			}
		}
		return contentAssistRequest;
	}

	protected ContentAssistRequest computeTagOpenProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
		ContentAssistRequest contentAssistRequest = null;
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
		if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion()) {
			// completing the *first* XML_TAG_OPEN in "<<tagname"
			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
			if (actualNode != null) {
				contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
				addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(actualNode));
				addEndTagProposals(contentAssistRequest); // (pa) 220850
			}
		}
		else {
			if (documentPosition == sdRegion.getStartOffset(completionRegion)) {
				if (node.getNodeType() == Node.ELEMENT_NODE) {
					// at the start of an existing tag, right before the '<'
					contentAssistRequest = newContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
					addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
					addEndTagProposals(contentAssistRequest);
				}
				else if (node.getNodeType() == Node.DOCUMENT_NODE) {
					// at the opening of the VERY first tag with a '<'
					contentAssistRequest = newContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
					addStartDocumentProposals(contentAssistRequest);
				}
			}
			else {
				// within the white space
				ITextRegion name = getNameRegion(node.getStartStructuredDocumentRegion());
				// (pa) ITextRegion refactor
				// if (name != null && name.containsOffset(documentPosition))
				// {
				if (name != null && (sdRegion.getStartOffset(name) <= documentPosition && sdRegion.getEndOffset(name) >= documentPosition)) {
					// replace the existing name
					contentAssistRequest = newContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(name), name.getTextLength(), matchString);
				}
				else {
					// insert a valid new name, or possibly an end tag
					contentAssistRequest = newContentAssistRequest(nodeAtOffset, ((Node) nodeAtOffset).getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
					addEndTagProposals(contentAssistRequest);
					contentAssistRequest.setReplacementBeginPosition(documentPosition);
					contentAssistRequest.setReplacementLength(0);
				}
				addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
			}
		}
		return contentAssistRequest;
	}

	/**
	 * Retreives cmnode's documentation to display in the completion
	 * proposal's additional info. If no documentation exists for cmnode, try
	 * displaying parentOrOwner's documentation
	 * 
	 * String any documentation information to display for cmnode.
	 * <code>null</code> if there is nothing to display.
	 */
	protected String getAdditionalInfo(CMNode parentOrOwner, CMNode cmnode) {
		String addlInfo = null;

		if (cmnode == null) {
			if (Debug.displayWarnings) {
				new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
			}
			return null;
		}

		addlInfo = getInfoProvider().getInfo(cmnode);
		if (addlInfo == null && parentOrOwner != null)
			addlInfo = getInfoProvider().getInfo(parentOrOwner);
		return addlInfo;
	}

	// returns a list of ModelQueryActions
	protected List getAvailableChildrenAtIndex(Element parent, int index) {
		List list = new ArrayList();
		CMElementDeclaration parentDecl = getCMElementDeclaration(parent);
		if (parentDecl != null) {
			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(parent.getOwnerDocument());
			// taken from ActionManagers
			// int editMode = modelQuery.getEditMode();
			int editMode = ModelQuery.EDIT_MODE_UNCONSTRAINED;
			int ic = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.INCLUDE_CHILD_NODES | ModelQuery.INCLUDE_SEQUENCE_GROUPS : ModelQuery.INCLUDE_CHILD_NODES;
			int vc = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.VALIDITY_STRICT : ModelQuery.VALIDITY_NONE;
			modelQuery.getInsertActions(parent, parentDecl, index, ic, vc, list);
		}
		return list;
	}

	// returns a list of CMElementDeclarations
	protected List getAvailableRootChildren(Document document, int childIndex) {
		List list = null;

		// extract the valid 'root' node name from the DocumentType Node
		DocumentType docType = document.getDoctype();
		String rootName = null;
		if (docType != null) {
			rootName = docType.getNodeName();
		}
		if (rootName == null)
			return new ArrayList(0);

		for (Node child = document.getFirstChild(); child != null; child = child.getNextSibling()) {
			// make sure the "root" Element isn't already present
			// is it required to be an Element?
			if (child.getNodeType() == Node.ELEMENT_NODE && stringsEqual(child.getNodeName(), rootName)) {
				// if the node is missing either the start or end tag, don't
				// count it as present
				if (child instanceof IDOMNode && (((IDOMNode) child).getStartStructuredDocumentRegion() == null || ((IDOMNode) child).getEndStructuredDocumentRegion() == null))
					continue;
				if (Debug.displayInfo)
					System.out.println(rootName + " already present!"); //$NON-NLS-1$
				setErrorMessage(NLS.bind(XMLUIMessages.The_document_element__, (new Object[]{rootName})));
				return new ArrayList(0);
			}
		}

		list = new ArrayList(1);
		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
		if (modelQuery != null) {
			CMDocument cmdoc = modelQuery.getCorrespondingCMDocument(document);
			if (cmdoc != null) {
				if (rootName != null) {
					CMElementDeclaration rootDecl = (CMElementDeclaration) cmdoc.getElements().getNamedItem(rootName);
					if (rootDecl != null) {
						list.add(rootDecl);
					}
					else {
						// supply the given document name anyway, even if it
						// is an error
						list.add(new SimpleCMElementDeclaration(rootName));
						if (Debug.displayInfo || Debug.displayWarnings)
							System.out.println("No definition found for " + rootName + " in " + docType.getPublicId() + "/" + docType.getSystemId()); //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
						String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
						//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
						//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
						if (location.length() > 0)
							setErrorMessage(NLS.bind(XMLUIMessages.No_definition_for_in, (new Object[]{rootName, location})));
						else
							setErrorMessage(NLS.bind(XMLUIMessages.No_definition_for, (new Object[]{rootName})));
					}
				}
			}
			else {
				if (Debug.displayInfo || Debug.displayWarnings)
					System.out.println("No content model found."); //$NON-NLS-1$
				//$NON-NLS-1$
				//$NON-NLS-1$
				String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
				//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
				//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
				if (location.length() > 0)
					setErrorMessage(NLS.bind(XMLUIMessages.No_content_model_for, (new Object[]{location})));
				else
					setErrorMessage(XMLUIMessages.No_content_model_found_UI_);
			}
		}

		return list;
	}

	protected CMElementDeclaration getCMElementDeclaration(Node node) {
		CMElementDeclaration result = null;
		if (node.getNodeType() == Node.ELEMENT_NODE) {
			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
			if (modelQuery != null)
				result = modelQuery.getCMElementDeclaration((Element) node);
		}
		return result;
	}

	/**
	 * Returns the characters which when entered by the user should
	 * automatically trigger the presentation of possible completions.
	 * 
	 * the auto activation characters for completion proposal or
	 * <code>null</code> if no auto activation is desired
	 */
	public char[] getCompletionProposalAutoActivationCharacters() {
		return completionProposalAutoActivationCharacters;
	}

	protected ITextRegion getCompletionRegion(int offset, IStructuredDocumentRegion sdRegion) {
		ITextRegion region = sdRegion.getRegionAtCharacterOffset(offset);
		if (region == null)
			return null;

		if (sdRegion.getStartOffset(region) == offset) {
			// The offset is at the beginning of the region
			if ((sdRegion.getStartOffset(region) == sdRegion.getStartOffset()) && (sdRegion.getPrevious() != null) && (!sdRegion.getPrevious().isEnded())) {
				// Is the region also the start of the node? If so, the
				// previous IStructuredDocumentRegion is
				// where to look for a useful region.
				region = sdRegion.getPrevious().getRegionAtCharacterOffset(offset - 1);
			}
			else {
				// Is there no separating whitespace from the previous region?
				// If not,
				// then that region is the important one
				ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(offset - 1);
				if ((previousRegion != null) && (previousRegion != region) && (previousRegion.getTextLength() == previousRegion.getLength())) {
					region = previousRegion;
				}
			}
		}
		else {
			// The offset is NOT at the beginning of the region
			if (offset > sdRegion.getStartOffset(region) + region.getTextLength()) {
				// Is the offset within the whitespace after the text in this
				// region?
				// If so, use the next region
				ITextRegion nextRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) + region.getLength());
				if (nextRegion != null)
					region = nextRegion;
			}
			else {
				// Is the offset within the important text for this region?
				// If so, then we've already got the right one.
			}
		}

		// valid WHITE_SPACE region handler (#179924)
		if (region != null && region.getType() == DOMRegionContext.WHITE_SPACE) {
			ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) - 1);
			if (previousRegion != null)
				region = previousRegion;
		}

		return region;
	}

	/**
	 * Return the region whose content's require completion. This is something
	 * of a misnomer as sometimes the user wants to be prompted for contents
	 * of a non-existant ITextRegion, such as for enumerated attribute values
	 * following an '=' sign.
	 */
	protected ITextRegion getCompletionRegion(int documentPosition, Node domnode) {
		if (domnode == null)
			return null;

		ITextRegion region = null;
		int offset = documentPosition;
		IStructuredDocumentRegion flatNode = null;
		IDOMNode node = (IDOMNode) domnode;

		if (node.getNodeType() == Node.DOCUMENT_NODE) {
			if (node.getStructuredDocument().getLength() == 0)
				return null;
			ITextRegion result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
			while (result == null) {
				offset--;
				result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
			}
			return result;
		}

		IStructuredDocumentRegion startTag = node.getStartStructuredDocumentRegion();
		IStructuredDocumentRegion endTag = node.getEndStructuredDocumentRegion();

		// Determine if the offset is within the start
		// IStructuredDocumentRegion, end IStructuredDocumentRegion, or
		// somewhere within the Node's XML content.
		if ((startTag != null) && (startTag.getStartOffset() <= offset) && (offset < startTag.getStartOffset() + startTag.getLength()))
			flatNode = startTag;
		else if ((endTag != null) && (endTag.getStartOffset() <= offset) && (offset < endTag.getStartOffset() + endTag.getLength()))
			flatNode = endTag;

		if (flatNode != null) {
			// the offset is definitely within the start or end tag, continue
			// on and find the region
			region = getCompletionRegion(offset, flatNode);
		}
		else {
			// the docPosition is neither within the start nor the end, so it
			// must be content
			flatNode = node.getStructuredDocument().getRegionAtCharacterOffset(offset);
			// (pa) ITextRegion refactor
			// if (flatNode.contains(documentPosition)) {
			if (flatNode.getStartOffset() <= documentPosition && flatNode.getEndOffset() >= documentPosition) {
				// we're interesting in completing/extending the previous
				// IStructuredDocumentRegion if the current
				// IStructuredDocumentRegion isn't plain content or if it's
				// preceded by an orphan '<'
				if ((offset == flatNode.getStartOffset()) && (flatNode.getPrevious() != null) && (flatNode.getRegionAtCharacterOffset(documentPosition) != null && flatNode.getRegionAtCharacterOffset(documentPosition).getType() != DOMRegionContext.XML_CONTENT || flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_TAG_OPEN || flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN)) {
					// Is the region also the start of the node? If so, the
					// previous IStructuredDocumentRegion is
					// where to look for a useful region.
					region = flatNode.getPrevious().getLastRegion();
				}
				else if (flatNode.getEndOffset() == documentPosition) {
					region = flatNode.getLastRegion();
				}
				else
					region = flatNode.getFirstRegion();
			}
			else {
				// catch end of document positions where the docPosition isn't
				// in a IStructuredDocumentRegion
				region = flatNode.getLastRegion();
			}
		}

		return region;
	}

	/**
	 * Provided by default. Subclasses may override with their own
	 * implementations.
	 * 
	 * @see AbstractContentAssistProcessor#getContentGenerator()
	 */
	public XMLContentModelGenerator getContentGenerator() {
		if (fGenerator == null)
			fGenerator = new XMLContentModelGenerator();
		return fGenerator;
	}

	/**
	 * Returns the characters which when entered by the user should
	 * automatically trigger the presentation of context information.
	 * 
	 * the auto activation characters for presenting context information or
	 * <code>null</code> if no auto activation is desired
	 */
	public char[] getContextInformationAutoActivationCharacters() {
		return contextInformationAutoActivationCharacters;
	}

	/**
	 * Returns a validator used to determine when displayed context
	 * information should be dismissed. May only return <code>null</code> if
	 * the processor is incapable of computing context information.
	 * 
	 * a context information validator, or <code>null</code> if the
	 * processor is incapable of computing context information
	 */
	public IContextInformationValidator getContextInformationValidator() {
		if (fContextInformationPresenter == null)
			fContextInformationPresenter = new AttributeContextInformationPresenter();
		return fContextInformationPresenter;
	}

	protected int getElementPosition(Node child) {
		Node parent = child.getParentNode();
		if (parent == null)
			return 0;

		NodeList children = parent.getChildNodes();
		if (children == null)
			return 0;
		int count = 0;

		for (int i = 0; i < children.getLength(); i++) {
			if (children.item(i) == child)
				return count;
			else
				// if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
				count++;
		}
		return 0;
	}

	private int getElementPositionForModelQuery(Node child) {
		return getElementPosition(child);
		// return -1;
	}

	/**
	 * Return the reason why computeProposals was not able to find any
	 * completions.
	 * 
	 * an error message or null if no error occurred
	 */
	public String getErrorMessage() {
		return fErrorMessage;
	}

	/**
	 * @param iResource
	 */
	// public void initialize(IResource iResource) {
	// this.resource = iResource;
	// }
	/**
	 * Gets the infoProvider.
	 * 
	 * fInfoProvider and if fInfoProvider was <code>null</code> create a new
	 * instance
	 */
	public MarkupTagInfoProvider getInfoProvider() {
		if (fInfoProvider == null) {
			fInfoProvider = new MarkupTagInfoProvider();
		}
		return fInfoProvider;
	}

	protected String getMatchString(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) {
		if (aRegion == null || isCloseRegion(aRegion))
			return ""; //$NON-NLS-1$
		String matchString = null;
		String regionType = aRegion.getType();
		if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS || regionType == DOMRegionContext.XML_TAG_OPEN || (offset > parent.getStartOffset(aRegion) + aRegion.getTextLength())) {
			matchString = ""; //$NON-NLS-1$
		}
		else if (regionType == DOMRegionContext.XML_CONTENT) {
			matchString = ""; //$NON-NLS-1$
		}
		else {
			if (parent.getText(aRegion).length() > 0 && parent.getStartOffset(aRegion) < offset)
				matchString = parent.getText(aRegion).substring(0, offset - parent.getStartOffset(aRegion));
			else
				matchString = ""; //$NON-NLS-1$
		}
		return matchString;
	}

	protected ITextRegion getNameRegion(IStructuredDocumentRegion flatNode) {
		if (flatNode == null)
			return null;
		Iterator regionList = flatNode.getRegions().iterator();
		while (regionList.hasNext()) {
			ITextRegion region = (ITextRegion) regionList.next();
			if (isNameRegion(region))
				return region;
		}
		return null;
	}

	/**
	 * Retrieves all of the possible valid values for this attribute
	 * declaration
	 */
	protected List getPossibleDataTypeValues(Node node, CMAttributeDeclaration ad) {
		List list = null;
		if (node.getNodeType() == Node.ELEMENT_NODE) {
			Element element = (Element) node;
			String[] dataTypeValues = null;
			// The ModelQuery may not be available if the corresponding
			// adapter
			// is absent
			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
			if (modelQuery != null) {
				dataTypeValues = modelQuery.getPossibleDataTypeValues(element, ad);
			}
			else {
				if (ad.getAttrType() != null)
					dataTypeValues = ad.getAttrType().getEnumeratedValues();
			}
			if (dataTypeValues != null) {
				list = new ArrayList(dataTypeValues.length);
				for (int i = 0; i < dataTypeValues.length; i++) {
					list.add(dataTypeValues[i]);
				}
			}
		}
		if (list == null) {
			list = new ArrayList(0);
		}
		return list;
	}

	protected String getRequiredName(Node parentOrOwner, CMNode cmnode) {
		if (cmnode == null || parentOrOwner == null) {
			if (Debug.displayWarnings) {
				new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
			}
			return ""; //$NON-NLS-1$
		}
		return getContentGenerator().getRequiredName(parentOrOwner, cmnode);
	}

	protected String getRequiredText(Node parentOrOwner, CMAttributeDeclaration attrDecl) {
		if (attrDecl == null) {
			if (Debug.displayWarnings) {
				new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$
			}
			return ""; //$NON-NLS-1$
		}
		StringBuffer buff = new StringBuffer();
		getContentGenerator().generateRequiredAttribute(parentOrOwner, attrDecl, buff);
		return buff.toString();
	}

	protected String getRequiredText(Node parentOrOwner, CMElementDeclaration elementDecl) {
		if (elementDecl == null) {
			if (Debug.displayWarnings) {
				new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$
			}
			return ""; //$NON-NLS-1$
		}
		StringBuffer buff = new StringBuffer();
		getContentGenerator().generateTag(parentOrOwner, elementDecl, buff);
		return buff.toString();
	}

	/**
	 * StructuredTextViewer must be set before using this.
	 */
	public IStructuredDocumentRegion getStructuredDocumentRegion(int pos) {
		// (pa) ITextRegion refactor defect 245190
		// return
		// (IStructuredDocumentRegion)ContentAssistUtils.getNodeAt((StructuredTextViewer)fTextViewer,
		// pos);
		return ContentAssistUtils.getStructuredDocumentRegion((StructuredTextViewer) fTextViewer, pos);
	}

	private String getTagName(IStructuredDocumentRegion sdRegion) {
		ITextRegionList regions = sdRegion.getRegions();
		ITextRegion region = null;
		String name = ""; //$NON-NLS-1$
		for (int i = 0; i < regions.size(); i++) {
			region = regions.get(i);
			if (region.getType() == DOMRegionContext.XML_TAG_NAME) {
				name = sdRegion.getText(region);
				break;
			}
		}
		return name;
	}

	protected List getValidCMNodes(int childPosition, int kindOfAction, List modelQueryActions) {
		Iterator iterator = modelQueryActions.iterator();
		List cmnodes = new Vector();
		while (iterator.hasNext()) {
			ModelQueryAction action = (ModelQueryAction) iterator.next();
			if (childPosition < 0 || (action.getStartIndex() <= childPosition && childPosition <= action.getEndIndex()) && action.getKind() == kindOfAction) {
				CMNode actionCMNode = action.getCMNode();
				if (actionCMNode != null && !cmnodes.contains(actionCMNode))
					cmnodes.add(actionCMNode);
			}
		}
		return cmnodes;
	}

	/**
	 * Similar to the call in HTMLContentAssistProcessor. Pass in a node, it
	 * tells you if the document is XML type.
	 * 
	 * @param node
	 * 
	 */
	protected boolean getXML(Node node) {
		if (node == null)
			return false;

		Document doc = null;
		doc = (node.getNodeType() != Node.DOCUMENT_NODE) ? node.getOwnerDocument() : ((Document) node);

		return (doc instanceof IDOMDocument) && ((IDOMDocument) doc).isXMLType();
	}

	// Initialize local settings
	protected void init() {
		// implement in subclasses
	}

	protected boolean isCloseRegion(ITextRegion region) {
		String type = region.getType();
		return ((type == DOMRegionContext.XML_PI_CLOSE) || (type == DOMRegionContext.XML_TAG_CLOSE) || (type == DOMRegionContext.XML_EMPTY_TAG_CLOSE) || (type == DOMRegionContext.XML_CDATA_CLOSE) || (type == DOMRegionContext.XML_COMMENT_CLOSE) || (type == DOMRegionContext.XML_ATTLIST_DECL_CLOSE) || (type == DOMRegionContext.XML_ELEMENT_DECL_CLOSE) || (type == DOMRegionContext.XML_DOCTYPE_DECLARATION_CLOSE) || (type == DOMJSPRegionContextsPrivateCopy.JSP_CLOSE) || (type == DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_CLOSE) || (type.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_CLOSE)) || (type == DOMRegionContext.XML_DECLARATION_CLOSE));
	}

	/*
	 * This is to determine if a tag is a special meta-info comment tag that
	 * shows up as an ELEMENT
	 */
	private boolean isCommentNode(IDOMNode node) {
		return (node != null && node instanceof IDOMElement && ((IDOMElement) node).isCommentTag());
	}

	/**
	 * Checks if cursor position is after doctype tag...
	 * 
	 * @param car
	 * 
	 */
	protected boolean isCursorAfterDoctype(ContentAssistRequest car) {
		Node aNode = car.getNode();
		Document parent = aNode.getOwnerDocument();
		int xmldoctypeNodePosition = -1;
		boolean isAfterDoctype = true;

		if (parent == null)
			return true; // blank document case

		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
			if (child instanceof IDOMNode) {
				if (child.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
					xmldoctypeNodePosition = ((IDOMNode) child).getEndOffset();
					isAfterDoctype = (car.getReplacementBeginPosition() >= xmldoctypeNodePosition);
					break;
				}
			}
		}
		return isAfterDoctype;
	}

	/**
	 * This method can check if the cursor is after the XMLPI
	 * 
	 * @param car
	 * 
	 */
	protected boolean isCursorAfterXMLPI(ContentAssistRequest car) {
		Node aNode = car.getNode();
		boolean xmlpiFound = false;
		Document parent = aNode.getOwnerDocument();
		int xmlpiNodePosition = -1;
		boolean isAfterXMLPI = false;

		if (parent == null)
			return true; // blank document case

		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
			boolean xmlpi = (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && child.getNodeName().equals("xml")); //$NON-NLS-1$
			xmlpiFound = xmlpiFound || xmlpi;
			if (xmlpiFound) {
				if (child instanceof IDOMNode) {
					xmlpiNodePosition = ((IDOMNode) child).getEndOffset();
					isAfterXMLPI = (car.getReplacementBeginPosition() >= xmlpiNodePosition);
				}
				break;
			}
		}
		return isAfterXMLPI;
	}

	protected boolean isNameRegion(ITextRegion region) {
		String type = region.getType();
		return ((type == DOMRegionContext.XML_TAG_NAME) || (type == DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_NAME) || (type == DOMRegionContext.XML_ELEMENT_DECL_NAME) || (type == DOMRegionContext.XML_DOCTYPE_NAME) || (type == DOMRegionContext.XML_ATTLIST_DECL_NAME) || (type == DOMJSPRegionContextsPrivateCopy.JSP_ROOT_TAG_NAME) || type.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_NAME));
	}

	protected boolean isQuote(String string) {
		String trimmed = string.trim();
		if (trimmed.length() > 0) {
			return trimmed.charAt(0) == '\'' || trimmed.charAt(0) == '"';
		}
		return false;
	}

	private boolean isSelfClosed(IStructuredDocumentRegion startTag) {
		ITextRegionList regions = startTag.getRegions();
		return regions.get(regions.size() - 1).getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE;
	}

	private boolean isStartTag(IStructuredDocumentRegion sdRegion) {
		boolean result = false;
		if (sdRegion.getRegions().size() > 0) {
			ITextRegion r = sdRegion.getRegions().get(0);
			result = r.getType() == DOMRegionContext.XML_TAG_OPEN && sdRegion.isEnded();
		}
		return result;
	}

	protected Properties mapToProperties(CMNamedNodeMap map) {
		Properties p = new Properties();
		for (int i = 0; i < map.getLength(); i++) {
			CMEntityDeclaration decl = (CMEntityDeclaration) map.item(i);
			p.put(decl.getName(), decl.getValue());
		}
		return p;
	}

	/**
	 * Gets the corresponding XMLNode, and checks if it's closed.
	 * 
	 * @param startTag
	 * 
	 */
	private boolean needsEndTag(IStructuredDocumentRegion startTag) {
		boolean result = false;
		IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fTextViewer.getDocument());
		try {
			if (sModel != null) {
				IDOMNode xmlNode = (IDOMNode) sModel.getIndexedRegion(startTag.getStart());
				if (!isStartTag(startTag))
					result = false;
				else if (isSelfClosed(startTag))
					result = false;
				else if (!xmlNode.isContainer())
					result = false;
				else
					result = xmlNode.getEndStructuredDocumentRegion() == null;
			}
		}
		finally {
			if (sModel != null)
				sModel.releaseFromRead();
		}
		return result;
	}

	protected ContentAssistRequest newContentAssistRequest(Node node, Node possibleParent, IStructuredDocumentRegion documentRegion, ITextRegion completionRegion, int begin, int length, String filter) {
		return new ContentAssistRequest(node, possibleParent, documentRegion, completionRegion, begin, length, filter);
	}

	public void release() {
		fGenerator = null;
	}

	/**
	 * Set the reason why computeProposals was not able to find any
	 * completions.
	 */
	public void setErrorMessage(String errorMessage) {
		fErrorMessage = errorMessage;
	}

	/**
	 * Set the reason why computeProposals was not able to find any
	 * completions.
	 */
	protected void setErrorMessage(String errorMessage, String append) {
		setErrorMessage(errorMessage + append);
	}

	/**
	 * Set the reason why computeProposals was not able to find any
	 * completions.
	 */
	protected void setErrorMessage(String errorMessage, String prepend, String append) {
		setErrorMessage(prepend + errorMessage + append);
	}

	protected boolean stringsEqual(String a, String b) {
		// (pa) 221190 matching independent of case to be consistant with Java
		// editor CA
		return a.equalsIgnoreCase(b);
	}
}
