/*******************************************************************************
 * Copyright (c) 2001, 2006 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.StructuredModelManager;
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.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.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.XMLUIPlugin;
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.preferences.XMLUIPreferenceNames;
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);

					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);
						}
						// 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("'"))) {
						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)) {

								String rString = "\"" + possibleValue + "\""; //$NON-NLS-2$//$NON-NLS-1$
								int rOffset = contentAssistRequest.getReplacementBeginPosition();
								int rLength = contentAssistRequest.getReplacementLength();
								int cursorAfter = possibleValue.length() + 1;
								String displayString = "\"" + possibleValue + "\""; //$NON-NLS-2$//$NON-NLS-1$

								CustomCompletionProposal proposal = new CustomCompletionProposal(rString, rOffset, rLength, cursorAfter, image, displayString, 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)) {
						String rValue = "\"" + value + "\"";//$NON-NLS-2$//$NON-NLS-1$
						CustomCompletionProposal proposal = new CustomCompletionProposal(rValue, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), rValue.length() + 1, image, rValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
						contentAssistRequest.addProposal(proposal);
						if ((currentValue.length() > 0) && !value.equals(currentValue)) {
							rValue = "\"" + currentValue + "\""; //$NON-NLS-2$//$NON-NLS-1$
							proposal = new CustomCompletionProposal(rValue, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), rValue.length() + 1, image, rValue, 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)) {
					String rValue = "\"" + currentValue + "\""; //$NON-NLS-2$//$NON-NLS-1$
					proposal = new CustomCompletionProposal(rValue, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, image, rValue, 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) {
		// nothing
	}

	/**
	 * 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("</")) {
				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) {
			// ////////////////////////////////////////////////////////////////////////////////////
			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;
			}
		}
		// ////////////////////////////////////////////////////////////////////////////////////
		// 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;
			}
		}
		// ////////////////////////////////////////////////////////////////////////////////////
		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...
		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)) {
					// just skipping
				}
				// check if theres a node inbetween XMLPI and cursor position
				if ((child != null) && (child instanceof IDOMNode)) {
					if ((contentAssistRequest.getReplacementBeginPosition() >= ((IDOMNode) child).getEndOffset()) || !xmlpiIsFirstElement) {
						insertDoctype = false;
					}
				}
				break;
			}
		}

		if (xmlpiFound && (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) {
						// 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();
		String error = null;

		// (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;
		}

		// 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 = 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 all possible children within this
				// parent context
				cmnodes = getAvailableChildElementDeclarations((Element) parent, childPosition, ModelQueryAction.INSERT);

				// retrieve the list of the possible children within this
				// parent context and at this index
				List strictCMNodeSuggestions = null;
				if (XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_STRICT.equals(XMLUIPlugin.getInstance().getPreferenceStore().getString(XMLUIPreferenceNames.SUGGESTION_STRATEGY))) {
					strictCMNodeSuggestions = getValidChildElementDeclarations((Element) parent, childPosition, ModelQueryAction.INSERT);
				}
				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$
					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);
						boolean isStrictCMNodeSuggestion = strictCMNodeSuggestions != null ? strictCMNodeSuggestions.contains(elementDecl) : false;

						Image image = CMImageUtil.getImage(elementDecl);

						if (image == null) {
							if (strictCMNodeSuggestions != null) {
								image = isStrictCMNodeSuggestion ? XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC_EMPHASIZED) : XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC_DEEMPHASIZED);
							}
							else {
								image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
							}

						}

						// int markupAdjustment =
						// getContentGenerator().getMinimalStartTagLength(parent,
						// elementDecl);
						if (beginsWith(tagname, matchString)) {
							String proposedText = getRequiredText(parent, elementDecl);

							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=89811
							// place cursor in first empty quotes
							int markupAdjustment = getCursorPositionForProposedText(proposedText);

							String proposedInfo = getAdditionalInfo(parentDecl, elementDecl);
							int relevance = isStrictCMNodeSuggestion ? XMLRelevanceConstants.R_STRICTLY_VALID_TAG_INSERTION : XMLRelevanceConstants.R_TAG_INSERTION;
							CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), markupAdjustment, image, tagname, null, proposedInfo, relevance);
							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 (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();
		String error = null;
		String matchString = contentAssistRequest.getMatchString();
		if (parent.getNodeType() == Node.ELEMENT_NODE) {
			// retrieve the list of children
			// validActions = getAvailableChildrenAtIndex((Element) parent,
			// childPosition);
			cmnodes = getAvailableChildElementDeclarations((Element) parent, childPosition, ModelQueryAction.INSERT);
			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$
				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 {
								// https://bugs.eclipse.org/bugs/show_bug.cgi?id=89811
								StringBuffer sb = new StringBuffer();
								getContentGenerator().generateTag(parent, ed, sb);
								// since it's a name proposal, assume '<' is
								// already there
								// only return the rest of the tag
								proposedText = sb.toString().substring(1);
								cursorAdjustment = getCursorPositionForProposedText(proposedText);

								// 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;
				if (ed instanceof CMElementDeclaration) {
					// proposedText = getRequiredName(parent, ed);
					StringBuffer sb = new StringBuffer();
					getContentGenerator().generateTag(parent, (CMElementDeclaration) ed, sb);
					// tag starts w/ '<', but we want to compare to name
					proposedText = sb.toString().substring(1);

					if (!beginsWith(proposedText, matchString)) {
						continue;
					}

					cursorAdjustment = getCursorPositionForProposedText(proposedText);

					if (ed instanceof CMElementDeclaration) {
						CMElementDeclaration elementDecl = (CMElementDeclaration) ed;
						if (elementDecl.getContentType() == CMElementDeclaration.EMPTY) {
							proposedText += getContentGenerator().getStartTagClose(parent, elementDecl);
							cursorAdjustment = proposedText.length();
						}
					}

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

	/**
	 * this is the position the cursor should be in after the proposal is
	 * applied
	 * 
	 * @param proposedText
	 * @return the position the cursor should be in after the proposal is
	 *         applied
	 */
	private int getCursorPositionForProposedText(String proposedText) {
		int cursorAdjustment;
		cursorAdjustment = proposedText.indexOf("\"\"") + 1; //$NON-NLS-1$
		// otherwise, after the first tag
		if (cursorAdjustment == 0) {
			cursorAdjustment = proposedText.indexOf('>') + 1;
		}
		if (cursorAdjustment == 0) {
			cursorAdjustment = proposedText.length() + 1;
		}

		return cursorAdjustment;
	}

	/**
	 * @deprecated XML proposal is added via xml declaration template instead
	 */
	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) 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(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);
				}
			}
		}
		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) {
					int replaceLength = documentPosition - sdRegion.getStartOffset(completionRegion);
					contentAssistRequest = newContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), replaceLength, 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, int validityChecking) {
		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;
			modelQuery.getInsertActions(parent, parentDecl, index, ic, validityChecking, 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(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;
	}

	// returns a list of CMNodes that are available within this parent context
	// Given the grammar shown below and a snippet of XML code (where the '|'
	// indicated the cursor position)
	// the list would return all of the element declarations that are
	// potential child elements of Foo.
	//
	// grammar : Foo -> (A, B, C)
	// snippet : <Foo><A>|
	// result : {A, B, C}
	// 
	// TODO cs... do we need to pass in the 'kindOfAction'? Seems to me we
	// could assume it's always an insert.
	protected List getAvailableChildElementDeclarations(Element parent, int childPosition, int kindOfAction) {
		List modelQueryActions = getAvailableChildrenAtIndex(parent, childPosition, ModelQuery.VALIDITY_NONE);
		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;
	}

	// returns a list of CMNodes that can be validly inserted at this
	// childPosition
	// Given the grammar shown below and a snippet of XML code (where the '|'
	// indicated the cursor position)
	// the list would return only the element declarations can be inserted
	// while maintaing validity of the content.
	//
	// grammar : Foo -> (A, B, C)
	// snippet : <Foo><A>|
	// result : {B}
	//    
	protected List getValidChildElementDeclarations(Element parent, int childPosition, int kindOfAction) {
		List modelQueryActions = getAvailableChildrenAtIndex(parent, childPosition, ModelQuery.VALIDITY_STRICT);
		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);
	}
}
