/*******************************************************************************
 * Copyright (c) 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     
 *******************************************************************************/
package org.eclipse.jpt.jpa.ui.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.wst.sse.core.StructuredModelManager;
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.ui.contentassist.CompletionProposalInvocationContext;
import org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer;
import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.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.contentassist.ContentAssistRequest;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * <p>Implements the framework for making proposals in XML type documents.  Deals with
 * all the nastiness needed to figure out where in an XML type document the content
 * assist was invoked and then calls one of many abstract methods depending on the
 * area the content assist was invoked.  In this way implementers only have to worry about
 * implementing what to do in each situation while not having to deal with figuring out
 * which situation the content assist was invoked in.</p>
 * 
 * @base org.eclipse.wst.xml.ui.internal.contentassist.AbstractContentAssistProcessor
 * @see DefaultJpaXmlCompletionProposalComputer
 * 
 * The code of this class was copied from AbstractXMLCompletionProposalComputer and modified according to
 * the needs of the XML content assist of Dali. This class can be removed after bug 371939 is addressed.
 */

public abstract class AbstractJpaXmlCompletionProposalComputer implements ICompletionProposalComputer {

	private String fErrorMessage;
	private ITextViewer fTextViewer;

	public AbstractJpaXmlCompletionProposalComputer() {
		fErrorMessage = null;
		fTextViewer = null;
	}

	/**
	 * <p>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.</p>
	 * 
	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#computeCompletionProposals(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
	 */
	public List<ICompletionProposal> computeCompletionProposals(
			CompletionProposalInvocationContext context,
			IProgressMonitor monitor) {

		ITextViewer textViewer = context.getViewer();
		int documentPosition = context.getInvocationOffset();

		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 = null;
		try {
			matchString = getMatchString(sdRegion, completionRegion, documentPosition);
		} catch (BadLocationException e) {
			e.printStackTrace();
		}

		// 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 = null;
				try {
					if(textViewer.getDocument() instanceof IStructuredDocument) {
						sModel = StructuredModelManager.getModelManager().getModelForRead((IStructuredDocument)textViewer.getDocument());
					}
					if (sModel != null) {
						IDOMDocument docNode = ((IDOMModel) sModel).getDocument();
						contentAssistRequest = new ContentAssistRequest(docNode, docNode, sdRegion, completionRegion, documentPosition, 0, null);
						addEmptyDocumentProposals(contentAssistRequest, context);
					}
				}
				finally {
					if (sModel != null) {
						sModel.releaseFromRead();
					}
				}
				if (contentAssistRequest == null) {
					Logger.logException(new IllegalStateException("problem getting model")); //$NON-NLS-1$
					return new ArrayList<ICompletionProposal>(0);
				}

				ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
				return (props != null) ? Arrays.asList(props) : new ArrayList<ICompletionProposal>(0);
			}
			// MASSIVE ERROR CONDITION
			Logger.logException(new IllegalStateException("completion region was null")); //$NON-NLS-1$
			setErrorMessage(XMLUIMessages.SEVERE_internal_error_occu_UI_);
			contentAssistRequest = new ContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
			ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
			return (props != null) ? Arrays.asList(props) : new ArrayList<ICompletionProposal>(0);
		}


		// 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(matchString, completionRegion,
					(IDOMNode) treeNode,xmlnode, context);
			ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
			return (props != null) ? Arrays.asList(props) : new ArrayList<ICompletionProposal>(0);
		}

		// compute normal proposals
		contentAssistRequest = computeCompletionProposals(matchString, completionRegion, (IDOMNode) treeNode, xmlnode, context);
		if (contentAssistRequest == null) {
			contentAssistRequest = new ContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
			setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_);
		}

		/* 
		 * Only set this error message if nothing else was already set 
		 **/
		if (contentAssistRequest.getProposals().size() == 0 && getErrorMessage() == null) {
			setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_);
		}

		ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
		return (props != null) ? Arrays.asList(props) : new ArrayList<ICompletionProposal>(0);
	}

	/**
	 * <p>Returns information about possible contexts based on the specified
	 * location within the document that corresponds to the current cursor
	 * position within the text viewer.</p>
	 * 
	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
	 */
	public List<ICompletionProposal> computeContextInformation(
			CompletionProposalInvocationContext context,
			IProgressMonitor monitor) {

		//no default context info
		return Collections.emptyList();
	}

	/**
	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#getErrorMessage()
	 */
	public String getErrorMessage() {
		return fErrorMessage;
	}

	/**
	 * Add proposals for attribute names
	 * 
	 * @param contentAssistRequest
	 * @param context
	 */
	protected abstract void addAttributeNameProposals(ContentAssistRequest contentAssistRequest,
			CompletionProposalInvocationContext context);

	/**
	 * Add proposals for attribute values
	 * 
	 * @param contentAssistRequest
	 * @param context
	 */
	protected abstract void addAttributeValueProposals(ContentAssistRequest contentAssistRequest,
			CompletionProposalInvocationContext context);

	/**
	 * Add comment proposals
	 * 
	 * @param contentAssistRequest
	 * @param context
	 */
	protected abstract void addCommentProposal(ContentAssistRequest contentAssistRequest,
			CompletionProposalInvocationContext context);

	/**
	 * Add the proposals for a completely empty document
	 * 
	 * @param contentAssistRequest
	 * @param context
	 */
	protected abstract void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest,
			CompletionProposalInvocationContext context);

	/**
	 * Add the proposals for the name in an end tag
	 * 
	 * @param contentAssistRequest
	 * @param context
	 */
	protected abstract void addEndTagNameProposals(ContentAssistRequest contentAssistRequest,
			CompletionProposalInvocationContext context);

	/**
	 * Prompt for end tags to a non-empty Node that hasn't ended Handles these
	 * cases: <br>
	 * <tagOpen>| <br>
	 * <tagOpen>< |<br>
	 * <tagOpen></ |
	 * 
	 * @param contentAssistRequest
	 * @param context
	 */
	protected abstract void addEndTagProposals(ContentAssistRequest contentAssistRequest,
			CompletionProposalInvocationContext context);

	/**
	 * Add entity proposals
	 * 
	 * @param contentAssistRequest
	 * @param completionRegion
	 * @param treeNode
	 * @param context
	 */
	protected abstract void addEntityProposals(ContentAssistRequest contentAssistRequest,
			ITextRegion completionRegion, IDOMNode treeNode, CompletionProposalInvocationContext context);

	/**
	 * add entity proposals
	 * 
	 * @param proposals
	 * @param map
	 * @param key
	 * @param nodeOffset
	 * @param sdRegion
	 * @param completionRegion
	 * @param context
	 */
	protected abstract void addEntityProposals(Vector<ICompletionProposal> proposals, Properties map, String key,
			int nodeOffset, IStructuredDocumentRegion sdRegion, ITextRegion completionRegion,
			CompletionProposalInvocationContext context);

	/**
	 * Add PCData proposals
	 * 
	 * @param nodeName
	 * @param contentAssistRequest
	 * @param context
	 */
	protected abstract void addPCDATAProposal(String nodeName, ContentAssistRequest contentAssistRequest,
			CompletionProposalInvocationContext context);

	/**
	 * Add start document proposals
	 * 
	 * @param contentAssistRequest
	 * @param context
	 */
	protected abstract void addStartDocumentProposals(ContentAssistRequest contentAssistRequest,
			CompletionProposalInvocationContext context);

	/**
	 * Close an unclosed start tag
	 * 
	 * @param contentAssistRequest
	 * @param context
	 */
	protected abstract void addTagCloseProposals(ContentAssistRequest contentAssistRequest,
			CompletionProposalInvocationContext context);

	/**
	 * Add tag insertion proposals
	 * 
	 * @param contentAssistRequest
	 * @param childPosition
	 * @param context
	 */
	protected abstract void addTagInsertionProposals(ContentAssistRequest contentAssistRequest,
			int childPosition, CompletionProposalInvocationContext context);

	/**
	 * Add tag name proposals
	 * 
	 * @param contentAssistRequest
	 * @param childPosition
	 * @param context
	 */
	protected abstract void addTagNameProposals(ContentAssistRequest contentAssistRequest,
			int childPosition, CompletionProposalInvocationContext context);

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

	/**
	 * <p>This does all the magic of figuring out where in the XML type document
	 * the content assist was invoked and then calling the corresponding method
	 * to add the correct proposals</p>
	 * 
	 * <p><b>NOTE: </b>if overriding be sure to make super call back to this method otherwise
	 * you will loose all of the proposals generated by this method</p>
	 * 
	 * @param matchString
	 * @param completionRegion
	 * @param treeNode
	 * @param xmlnode
	 * @param context
	 * 
	 * @return {@link ContentAssistRequest} that now has all the proposals in it
	 */
	protected ContentAssistRequest computeCompletionProposals(String matchString, ITextRegion completionRegion,
			IDOMNode treeNode, IDOMNode xmlnode, CompletionProposalInvocationContext context) {
		int documentPosition = context.getInvocationOffset();

		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(matchString, completionRegion, treeNode, xmlnode, context);
			}
			else if (regionType == DOMRegionContext.XML_TAG_NAME) {
				contentAssistRequest = computeTagNameProposals(matchString, completionRegion,
						treeNode, xmlnode, context);
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				contentAssistRequest = computeAttributeProposals(matchString, completionRegion, treeNode, xmlnode, context);
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
				contentAssistRequest = computeEqualsProposals(matchString, completionRegion,
						treeNode, xmlnode, context);
			}
			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 = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
				addTagCloseProposals(contentAssistRequest, context);
			}
			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
				contentAssistRequest = computeAttributeValueProposals(matchString, completionRegion, treeNode, xmlnode, context);
			}
			else if ((regionType == DOMRegionContext.XML_TAG_CLOSE) || (regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE)) {

				contentAssistRequest = computeTagCloseProposals(matchString, completionRegion, treeNode, xmlnode, context);
			}
			else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) {
				contentAssistRequest = computeEndTagOpenProposals(matchString, completionRegion,
						treeNode, xmlnode, context);
			}
			else if ((regionType == DOMRegionContext.XML_CONTENT) || (regionType == DOMRegionContext.XML_CHAR_REFERENCE) ||
					(regionType == DOMRegionContext.XML_ENTITY_REFERENCE) || (regionType == DOMRegionContext.XML_PE_REFERENCE)) {

				contentAssistRequest = computeContentProposals(matchString, completionRegion,
						treeNode, xmlnode, context);
			}

			// 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 == DOMRegionContext.XML_DECLARATION_OPEN) ||
							(regionType == DOMRegionContext.XML_PI_OPEN) ||
							(regionType == DOMRegionContext.XML_COMMENT_OPEN) ||
							(regionType == DOMRegionContext.XML_CDATA_OPEN))) {

				contentAssistRequest = new ContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
				addTagInsertionProposals(contentAssistRequest, getElementPosition(treeNode), context);
				addStartDocumentProposals(contentAssistRequest, context);
			}
		}
		// Not a Document or Element
		else if (isCloseRegion(completionRegion)) {
			contentAssistRequest = new ContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion) + completionRegion.getLength(), 0, matchString);
			addStartDocumentProposals(contentAssistRequest, context);
			if (documentPosition >= sdRegion.getTextEndOffset(completionRegion)) {
				addTagInsertionProposals(contentAssistRequest, getElementPosition(treeNode) + 1, context);
			}
		}
		else if ((documentPosition == sdRegion.getStartOffset(completionRegion)) &&
				((regionType == DOMRegionContext.XML_DECLARATION_OPEN) ||
						(regionType == DOMRegionContext.XML_PI_OPEN) ||
						(regionType == DOMRegionContext.XML_COMMENT_OPEN) ||
						(regionType == DOMRegionContext.XML_CDATA_OPEN))) {

			contentAssistRequest = new ContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
			addTagInsertionProposals(contentAssistRequest, getElementPosition(treeNode), context);
			addStartDocumentProposals(contentAssistRequest, context);
		}
		return contentAssistRequest;
	}

	/**
	 * <p>Similar to {@link #computeCompletionProposals(CompletionProposalInvocationContext, IProgressMonitor)} only specificly for
	 * attribute proposals</p>
	 * 
	 * <p>Implementers should not override this method, it is made available to implementers so that if they override
	 * {@link #computeCompletionProposals(String, ITextRegion, IDOMNode, IDOMNode, CompletionProposalInvocationContext)}
	 * they can call this method if needed</p>
	 * 
	 * @param matchString
	 * @param completionRegion
	 * @param nodeAtOffset
	 * @param node
	 * @param context
	 * @return
	 */
	protected final ContentAssistRequest computeAttributeProposals(String matchString, ITextRegion completionRegion,
			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {

		int documentPosition = context.getInvocationOffset();
		ITextViewer viewer = context.getViewer();
		ContentAssistRequest contentAssistRequest = null;
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
		// if the attribute name is selected, replace it instead of creating a new attribute
		if (documentPosition <= sdRegion.getStartOffset(completionRegion) && (viewer != null && viewer.getSelectedRange().y != (sdRegion.getEndOffset(completionRegion) - sdRegion.getStartOffset(completionRegion)))) {
			// setup to insert new attributes
			contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
		}
		else {
			// Setup to replace an existing attribute name
			contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
		}
		addAttributeNameProposals(contentAssistRequest, context);
		contentAssistRequest.setReplacementBeginPosition(documentPosition);
		contentAssistRequest.setReplacementLength(0);
		if ((node.getFirstStructuredDocumentRegion() != null) && (!node.getFirstStructuredDocumentRegion().isEnded())) {
			addTagCloseProposals(contentAssistRequest, context);
		}
		return contentAssistRequest;
	}

	/**
	 * <p>this is the position the cursor should be in after the proposal is
	 * applied</p>
	 * 
	 * @param proposedText
	 * @return the position the cursor should be in after the proposal is
	 *         applied
	 */
	protected static 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;
	}

	/**
	 * <p>helpful utility method for determining if one string starts with another one.
	 * This is case insensitive. If either are null then result is <code>true</code></p>
	 * 
	 * @param aString the string to check to see if it starts with the given prefix
	 * @param prefix check that the given string starts with this prefix
	 * 
	 * @return <code>true</code> if the given string starts with the given prefix,
	 * <code>false</code> otherwise
	 */
	protected static boolean beginsWith(String aString, String prefix) {
		if ((aString == null) || (prefix == null)) {
			return true;
		}
		return aString.toLowerCase().startsWith(prefix.toLowerCase());
	}

	private ContentAssistRequest computeAttributeValueProposals(String matchString, ITextRegion completionRegion,
			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {

		int documentPosition = context.getInvocationOffset();

		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 = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
			addAttributeNameProposals(contentAssistRequest, context);
			if ((actualNode.getFirstStructuredDocumentRegion() != null) && !actualNode.getFirstStructuredDocumentRegion().isEnded()) {
				addTagCloseProposals(contentAssistRequest, context);
			}
		}
		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 = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
				addAttributeNameProposals(contentAssistRequest, context);
			}
			else {
				int replaceLength = completionRegion.getTextLength();

				//if container region, be sure replace length is only the attribute value region not the entire container
				if(completionRegion instanceof ITextRegionContainer){
					ITextRegion openRegion = ((ITextRegionContainer) completionRegion).getFirstRegion();
					ITextRegion closeRegion = ((ITextRegionContainer) completionRegion).getLastRegion();

					/*
					 * check to see if the container is opened the same way its closed.
					 * Such as:
					 * <img src=' '
					 * But not:
					 * <img src='
					 * 
					 * </body>
					 * </html>
					 * In the latter case we only want to replace the opening text of the container
					 * Admittedly crude test, but effective.
					 */
					if(openRegion.getType() != closeRegion.getType()) {
						replaceLength = openRegion.getTextLength();
					}
				} 

				contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion,
						completionRegion, sdRegion.getStartOffset(completionRegion),
						replaceLength, matchString);

				addAttributeValueProposals(contentAssistRequest, context);
			}
		}
		return contentAssistRequest;
	}

	private ContentAssistRequest computeContentProposals(String matchString, ITextRegion completionRegion,
			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {

		int documentPosition = context.getInvocationOffset();
		ContentAssistRequest contentAssistRequest = null;

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

	private ContentAssistRequest computeEndTagOpenProposals(String matchString, ITextRegion completionRegion,
			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {

		int documentPosition = context.getInvocationOffset();
		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 = new ContentAssistRequest(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 = new ContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
			}
			else {
				// normal case, this end tag is the parent
				contentAssistRequest = new ContentAssistRequest(nodeAtOffset, nodeAtOffset, sdRegion, completionRegion, documentPosition, 0, matchString);
			}
		}
		// if (documentPosition >= sdRegion.getStartOffset(completionRegion) +
		// completionRegion.getTextLength())
		addEndTagProposals(contentAssistRequest, context);
		// else
		if (completionRegionStart == documentPosition) {
			// positioned at start of end tag
			addTagInsertionProposals(contentAssistRequest, node.getChildNodes().getLength(), context);
		}
		return contentAssistRequest;
	}


	private ContentAssistRequest computeEqualsProposals(String matchString, ITextRegion completionRegion,
			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {

		int documentPosition = context.getInvocationOffset();
		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 = new ContentAssistRequest(nodeAtOffset, node, sdRegion, valueRegion, sdRegion.getStartOffset(valueRegion), valueRegion.getTextLength(), matchString);
		}
		else {
			// append an attribute value after the '='
			contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
		}
		addAttributeValueProposals(contentAssistRequest, context);
		return contentAssistRequest;
	}

	private ContentAssistRequest computeStartDocumentProposals(String matchString, ITextRegion completionRegion,
			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
		int documentPosition = context.getInvocationOffset();

		// setup for a non-empty document, but one that hasn't been formally started
		ContentAssistRequest contentAssistRequest = null;
		contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node,
				getStructuredDocumentRegion(documentPosition), completionRegion,
				documentPosition, 0, matchString);
		addStartDocumentProposals(contentAssistRequest, context);
		return contentAssistRequest;
	}

	private ContentAssistRequest computeTagCloseProposals(String matchString, ITextRegion completionRegion,
			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {

		int documentPosition = context.getInvocationOffset();
		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 = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
			addTagInsertionProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
			if ((node.getNodeType() != Node.DOCUMENT_NODE) && (node.getEndStructuredDocumentRegion() == null)) {
				addEndTagProposals(contentAssistRequest, context);
			}
		}
		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 = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
				if ((node.getNodeType() != Node.DOCUMENT_NODE) && (node.getEndStructuredDocumentRegion() != null)) {
					addTagCloseProposals(contentAssistRequest, context);
				}
				if (sdRegion == nodeAtOffset.getFirstStructuredDocumentRegion()) {
					contentAssistRequest.setReplacementBeginPosition(documentPosition);
					contentAssistRequest.setReplacementLength(0);
					addAttributeNameProposals(contentAssistRequest, context);
				}
			}
		}
		return contentAssistRequest;
	}

	private ContentAssistRequest computeTagNameProposals(String matchString, ITextRegion completionRegion,
			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {

		int documentPosition = context.getInvocationOffset();
		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 = new ContentAssistRequest(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, context);
						}
						addTagCloseProposals(contentAssistRequest, context);
					}
					else {
						// it's name
						contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
								sdRegion, completionRegion, documentPosition - matchString.length(),
								matchString.length(), matchString);
						addTagNameProposals(contentAssistRequest, getElementPosition(actualNode),
								context);
					}
				}
				else {
					if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
						// insert name
						contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
								sdRegion, completionRegion, documentPosition, 0, matchString);
					}
					else {
						// replace name
						contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
								sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion),
								completionRegion.getTextLength(), matchString);
					}
					addEndTagNameProposals(contentAssistRequest, context);
				}
			}
		}
		else {
			if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
				// unclosed tag with only a name; 
				//should prompt for attributes and a close instead
				contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion,
						documentPosition - matchString.length(), matchString.length(), matchString);
				addAttributeNameProposals(contentAssistRequest, context);
				addTagCloseProposals(contentAssistRequest, context);
			}
			else {
				if (sdRegion.getRegions().get(0).getType() != DOMRegionContext.XML_END_TAG_OPEN) {
					int replaceLength = documentPosition - sdRegion.getStartOffset(completionRegion);
					contentAssistRequest = new ContentAssistRequest(node, node.getParentNode(), sdRegion,
							completionRegion, sdRegion.getStartOffset(completionRegion), replaceLength, matchString);
					addTagNameProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
				}
				else {
					IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(documentPosition);
					if (actualNode != null) {
						if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
							contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
									sdRegion, completionRegion, documentPosition, 0, matchString);
						}
						else {
							contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
									sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion),
									completionRegion.getTextLength(), matchString);
						}
						addEndTagNameProposals(contentAssistRequest, context);
					}
				}
			}
		}
		return contentAssistRequest;
	}

	private ContentAssistRequest computeTagOpenProposals(String matchString, ITextRegion completionRegion,
			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {

		int documentPosition = context.getInvocationOffset();
		ContentAssistRequest contentAssistRequest = null;
		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
		if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion() || sdRegion.getPrevious() != null && sdRegion.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_TAG_OPEN) {
			// completing the *first* XML_TAG_OPEN in "<<tagname"
			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
			if (actualNode != null) {
				if(sdRegion.getFirstRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN) {
					contentAssistRequest = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
					if(actualNode.hasChildNodes())
						addTagNameProposals(contentAssistRequest,
								getElementPosition(actualNode.getLastChild()), context);
					else
						addTagNameProposals(contentAssistRequest, 0, context);
				}
				else {
					contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
					addTagNameProposals(contentAssistRequest, getElementPosition(actualNode), context);
				}
				addEndTagProposals(contentAssistRequest, context); // (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 = new ContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion,
							completionRegion, documentPosition, 0, matchString);
					addTagInsertionProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
					addEndTagProposals(contentAssistRequest, context);
				}
				else if (node.getNodeType() == Node.DOCUMENT_NODE) {
					// at the opening of the VERY first tag with a '<'
					contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion,
							completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
					addStartDocumentProposals(contentAssistRequest, context);
				}
			}
			else {
				// within the white space
				ITextRegion name = getNameRegion(node.getStartStructuredDocumentRegion());
				if ((name != null) &&
						((sdRegion.getStartOffset(name) <= documentPosition) && (sdRegion.getEndOffset(name) >= documentPosition)) &&
						(sdRegion.getLastRegion().getType() == DOMRegionContext.XML_TAG_CLOSE || sdRegion.getLastRegion().getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE)){ 

					// replace the existing name
					contentAssistRequest = new ContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(name), name.getTextLength(), matchString);
				}
				else {
					// insert a valid new name, or possibly an end tag
					contentAssistRequest = new ContentAssistRequest(nodeAtOffset, ((Node) nodeAtOffset).getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
					addEndTagProposals(contentAssistRequest, context);
					contentAssistRequest.setReplacementBeginPosition(documentPosition);
					contentAssistRequest.setReplacementLength(0);
				}
				addTagNameProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
			}
		}
		return contentAssistRequest;
	}

	private 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.
	 */
	private 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;
	}

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

	/**
	 * the returned string will be used as the filter to show the proposed values
	 * @throws BadLocationException 
	 */
	protected String getMatchString(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) throws BadLocationException {
		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 || regionType == DOMRegionContext.XML_END_TAG_OPEN) {
			int begin = parent.getPrevious().getStartOffset();
			int length = offset-parent.getPrevious().getStart();
			matchString = parent.getParentDocument().get(begin, length);

			// parent.getParentDocument().get(begin, length) could return
			// something likes <schema> or <schema>a or <schema>  a
			// get the substring as the match string
			if ((matchString.length() > 0) && (beginsWith(matchString, "<"))) {
				if (matchString.contains(">")) {
					matchString = parent.getParentDocument().get(begin + matchString.indexOf('>') + 1, length-matchString.indexOf('>')-1);
				} else {
					matchString ="";
				}
			}

			// chop off any leading whitespace(s) from the match string
			while ((matchString.length() > 0) && (Character.isWhitespace(matchString.charAt(0)))) { 
				matchString = matchString.substring(1);
			}
		}
		else {
			if ((parent.getText(aRegion).length() > 0) && (parent.getStartOffset(aRegion) < offset)) {
				matchString = parent.getText(aRegion).substring(0, offset - parent.getStartOffset(aRegion));
			} else {
				matchString = "";
			}
		}
		return matchString;
	}

	@SuppressWarnings("rawtypes")
	private 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;
	}

	private 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 == DOMRegionContext.XML_DECLARATION_CLOSE));
	}

	private boolean isNameRegion(ITextRegion region) {
		String type = region.getType();
		return ((type == DOMRegionContext.XML_TAG_NAME) ||
				(type == DOMRegionContext.XML_ELEMENT_DECL_NAME) ||
				(type == DOMRegionContext.XML_DOCTYPE_NAME) ||
				(type == DOMRegionContext.XML_ATTLIST_DECL_NAME));
	}

	/**
	 * StructuredTextViewer must be set before using this.
	 */
	private IStructuredDocumentRegion getStructuredDocumentRegion(int pos) {
		return ContentAssistUtils.getStructuredDocumentRegion(fTextViewer, pos);
	}
}
