Package org.eclipse.jst.jsp.ui.internal.contentassist

Source Code of org.eclipse.jst.jsp.ui.internal.contentassist.JSPContentAssistProcessor

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.TextUtilities;
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.jst.jsp.core.internal.contentmodel.JSPCMDocumentFactory;
import org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapter;
import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapterFactory;
import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
import org.eclipse.jst.jsp.core.internal.provisional.JSP12Namespace;
import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
import org.eclipse.jst.jsp.core.text.IJSPPartitions;
import org.eclipse.jst.jsp.ui.internal.JSPUIPlugin;
import org.eclipse.jst.jsp.ui.internal.Logger;
import org.eclipse.jst.jsp.ui.internal.editor.JSPEditorPluginImageHelper;
import org.eclipse.jst.jsp.ui.internal.editor.JSPEditorPluginImages;
import org.eclipse.jst.jsp.ui.internal.templates.TemplateContextTypeIdsJSP;
import org.eclipse.wst.css.ui.internal.contentassist.CSSContentAssistProcessor;
import org.eclipse.wst.html.core.internal.contentmodel.JSPCMDocument;
import org.eclipse.wst.html.core.text.IHTMLPartitions;
import org.eclipse.wst.html.ui.StructuredTextViewerConfigurationHTML;
import org.eclipse.wst.html.ui.internal.contentassist.HTMLContentAssistProcessor;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning;
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.text.IStructuredPartitions;
import org.eclipse.wst.sse.core.utils.StringUtils;
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.sse.ui.internal.contentassist.IRelevanceCompletionProposal;
import org.eclipse.wst.sse.ui.internal.contentassist.IRelevanceConstants;
import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryProvider;
import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryRegistry;
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.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocumentTracker;
import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMNodeWrapper;
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.core.text.IXMLPartitions;
import org.eclipse.wst.xml.ui.internal.contentassist.AbstractContentAssistProcessor;
import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
import org.eclipse.wst.xml.ui.internal.contentassist.ProposalComparator;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistUtilities;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentModelGenerator;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* Adds proposals not normally covered by the generic behavior with the
* content model
*
* @deprecated This class is no longer used locally and will be removed in the future
* @see JSPStructuredContentAssistProcessor
*/
public class JSPContentAssistProcessor extends AbstractContentAssistProcessor {

  protected int depthCount = 0;
  protected ITextViewer fViewer = null;
  protected boolean useEmbeddedResults = true;
  protected boolean isInternalAdapter = false;
  protected HashMap fNameToProcessorMap = null;
  protected HashMap fPartitionToProcessorMap = null;
  private final ICompletionProposal[] EMPTY_PROPOSAL_SET = new ICompletionProposal[0];
  private JSPTemplateCompletionProcessor fTemplateProcessor = null;
  private List fTemplateContexts = new ArrayList();
  private IContentAssistProcessor fJSContentAssistProcessor;

  public JSPContentAssistProcessor() {
    super();
    initNameToProcessorMap();
    initPartitionToProcessorMap();
  }

  /**
   * init map for extra content assist processors (useBean,
   * get/setProperty). points [tagname > processor]
   */
  protected void initNameToProcessorMap() {
    fNameToProcessorMap = new HashMap();
    JSPPropertyContentAssistProcessor jspPropertyCAP = new JSPPropertyContentAssistProcessor();
    fNameToProcessorMap.put(JSP11Namespace.ElementName.SETPROPERTY, jspPropertyCAP);
    fNameToProcessorMap.put(JSP11Namespace.ElementName.GETPROPERTY, jspPropertyCAP);
    fNameToProcessorMap.put(JSP11Namespace.ElementName.USEBEAN, new JSPUseBeanContentAssistProcessor());
    fNameToProcessorMap.put(JSP11Namespace.ElementName.DIRECTIVE_TAGLIB, new JSPTaglibDirectiveContentAssistProcessor());
  }

  /**
   * int map that points [partition > processor]. This takes place of
   * embedded adapters for now.
   */
  protected void initPartitionToProcessorMap() {
    fPartitionToProcessorMap = new HashMap();
    HTMLContentAssistProcessor htmlProcessor = new HTMLContentAssistProcessor();
    JSPJavaContentAssistProcessor jspJavaProcessor = new JSPJavaContentAssistProcessor();
    XMLContentAssistProcessor xmlProcessor = new XMLContentAssistProcessor();
    IContentAssistProcessor javascriptProcessor = getJSContentAssistProcessor();

    fPartitionToProcessorMap.put(IHTMLPartitions.HTML_DEFAULT, htmlProcessor);
    fPartitionToProcessorMap.put(IXMLPartitions.XML_DEFAULT, xmlProcessor);
    fPartitionToProcessorMap.put(IStructuredPartitions.DEFAULT_PARTITION, htmlProcessor);
    fPartitionToProcessorMap.put(IJSPPartitions.JSP_DEFAULT, jspJavaProcessor);
    fPartitionToProcessorMap.put(IJSPPartitions.JSP_DIRECTIVE, xmlProcessor);
    fPartitionToProcessorMap.put(IHTMLPartitions.HTML_COMMENT, htmlProcessor);
    fPartitionToProcessorMap.put(IJSPPartitions.JSP_DEFAULT_EL, jspJavaProcessor);
    if (javascriptProcessor != null) {
      fPartitionToProcessorMap.put(IJSPPartitions.JSP_CONTENT_JAVASCRIPT, javascriptProcessor);
      fPartitionToProcessorMap.put(IHTMLPartitions.SCRIPT, javascriptProcessor); // default
    }
    // to
    // javascript
    // for
    // all
    // script
  }

  protected void addCommentProposal(ContentAssistRequest contentAssistRequest) {
    // do nothing
  }

  protected void addDocTypeProposal(ContentAssistRequest contentAssistRequest) {
    // do nothing
  }

  protected void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest) {
    if (ContentTypeIdForJSP.ContentTypeID_JSPTAG.equals(((IDOMNode) contentAssistRequest.getNode()).getModel().getContentTypeIdentifier())) {
      addTemplates(contentAssistRequest, TemplateContextTypeIdsJSP.NEW_TAG);
    }
    else {
      addTemplates(contentAssistRequest, TemplateContextTypeIdsJSP.NEW);
    }

    super.addEmptyDocumentProposals(contentAssistRequest);
    addTagInsertionProposals(contentAssistRequest, 0);
  }

  protected void addEndTagNameProposals(ContentAssistRequest contentAssistRequest) {
    // do nothing
  }

  protected void addPCDATAProposal(String nodeName, ContentAssistRequest contentAssistRequest) {
    // do nothing
  }

  protected void addStartDocumentProposals(ContentAssistRequest contentAssistRequest) {
    // do nothing
  }

  protected void addTagCloseProposals(ContentAssistRequest contentAssistRequest) {
    // do nothing
  }

  protected void addXMLProposal(ContentAssistRequest contentAssistRequest) {
    // do nothing
  }

  protected void addEndTagProposals(ContentAssistRequest contentAssistRequest) {
    // do nothing
  }

  protected void addAttributeNameProposals(ContentAssistRequest contentAssistRequest) {
    addTemplates(contentAssistRequest, TemplateContextTypeIdsJSP.ATTRIBUTE);
  }

  /**
   * add proposals for tags in attribute values
   */
  protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest) {
    addTemplates(contentAssistRequest, TemplateContextTypeIdsJSP.ATTRIBUTE_VALUE);

    IDOMNode node = (IDOMNode) contentAssistRequest.getNode();

    // add JSP extra proposals from JSPBeanInfoContentAssistProcessor
    // JSPPropertyContentAssistProcessor

    // 2.1
    // get results from JSPUseBean and JSPProperty here
    // (look up processor in a map based on node name)
    JSPDummyContentAssistProcessor extraProcessor = (JSPDummyContentAssistProcessor) fNameToProcessorMap.get(node.getNodeName());
    if (extraProcessor != null && contentAssistRequest != null) {
      extraProcessor.addAttributeValueProposals(contentAssistRequest);
    }

    ModelQuery mq = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
    if (mq != null) {
      CMDocument doc = mq.getCorrespondingCMDocument(node);
      // this shouldn't have to have the prefix coded in
      if (doc instanceof JSPCMDocument || doc instanceof CMNodeWrapper || node.getNodeName().startsWith("jsp:")) //$NON-NLS-1$
        return;
    }

    // Find the attribute name for which this position should have a value
    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;
    }
   
    // on an empty value, add all the JSP and taglib tags
    CMElementDeclaration elementDecl = getCMElementDeclaration(node);
    if (nameRegion != null && elementDecl != null) {
      String attributeName = open.getText(nameRegion);
      if (attributeName != null) {
        String currentValue = node.getAttributes().getNamedItem(attributeName).getNodeValue();
       
        if(currentValue == null || currentValue.length() == 0) { //$NON-NLS-1$
          List additionalElements = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, elementDecl, ModelQuery.INCLUDE_ATTRIBUTES);
          for (i = 0; i < additionalElements.size(); i++) {
            Object additionalElement = additionalElements.get(i);
            if(additionalElement instanceof CMElementDeclaration) {
              CMElementDeclaration ed = (CMElementDeclaration) additionalElement;
 
              String tagname = getContentGenerator().getRequiredName(node, ed);
              StringBuffer contents = new StringBuffer("\""); //$NON-NLS-1$
              getContentGenerator().generateTag(node, ed, contents);
              contents.append('"'); //$NON-NLS-1$
              CustomCompletionProposal proposal = new CustomCompletionProposal(contents.toString(), contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), contents.length(), JSPEditorPluginImageHelper.getInstance().getImage(JSPEditorPluginImages.IMG_OBJ_TAG_GENERIC), tagname, null, null, XMLRelevanceConstants.R_JSP_ATTRIBUTE_VALUE);
              contentAssistRequest.addProposal(proposal);
            }
          }
       
        }
      }
    }
    else if (contentAssistRequest.getRegion().getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
      try {
        // Create a new model for Content Assist to operate on. This
        // will simulate
        // a full Document and then adjust the offset numbers in the
        // list of results.
        IStructuredModel internalModel = null;
        IModelManager mmanager = StructuredModelManager.getModelManager();
        internalModel = mmanager.createUnManagedStructuredModelFor(ContentTypeIdForJSP.ContentTypeID_JSP);
        IDOMNode xmlNode = null;
        IDOMModel xmlOuterModel = null;
        if (contentAssistRequest.getNode() instanceof IDOMNode) {
          xmlNode = (IDOMNode) contentAssistRequest.getNode();
          xmlOuterModel = xmlNode.getModel();
          internalModel.setResolver(xmlOuterModel.getResolver());
          internalModel.setBaseLocation(xmlOuterModel.getBaseLocation());
        }
        String contents = StringUtils.strip(contentAssistRequest.getText());
        if (xmlNode != null && contents != null) {
          int additionalShifts = 0;
          // Be sure that custom tags from taglibs also show up
          // by
          // adding taglib declarations to the internal model.
          TLDCMDocumentManager mgr = TaglibController.getTLDCMDocumentManager(xmlOuterModel.getStructuredDocument());
          if (mgr != null) {
            List trackers = mgr.getCMDocumentTrackers(contentAssistRequest.getReplacementBeginPosition());
            if (trackers != null) {
              for (i = 0; i < trackers.size(); i++) {
                CMDocumentTracker tracker = (CMDocumentTracker) trackers.get(i);
                String declaration = tracker.getStructuredDocumentRegion().getText();
                if (declaration != null) {
                  contents = declaration + contents;
                  additionalShifts += declaration.length();
                }
              }
            }
          }
          // Also copy any jsp:useBean tags so that
          // jsp:[gs]etProperty will function
          Document doc = null;
          if (contentAssistRequest.getNode().getNodeType() == Node.DOCUMENT_NODE)
            doc = (Document) node;
          else
            doc = node.getOwnerDocument();
          NodeList useBeans = doc.getElementsByTagName(JSP12Namespace.ElementName.USEBEAN);
          for (int k = 0; k < useBeans.getLength(); k++) {
            IDOMNode useBean = (IDOMNode) useBeans.item(k);
            if (useBean.getStartOffset() < contentAssistRequest.getReplacementBeginPosition()) {
              StringBuffer useBeanText = new StringBuffer("<jsp:useBean"); //$NON-NLS-1$
              for (int j = 0; j < useBean.getAttributes().getLength(); j++) {
                Attr attr = (Attr) useBean.getAttributes().item(j);
                useBeanText.append(' ');
                useBeanText.append(attr.getName());
                useBeanText.append("=\""); //$NON-NLS-1$
                useBeanText.append(attr.getValue());
                useBeanText.append('"');
              }
              useBeanText.append("/>"); //$NON-NLS-1$
              additionalShifts += useBeanText.length();
              contents = useBeanText.toString() + contents;
            }
          }
          internalModel.getStructuredDocument().set(contents);
          int internalOffset = 0;
          boolean quoted = false;
          // if quoted, use position inside and shift by one
          if (contentAssistRequest.getMatchString().length() > 0 && (contentAssistRequest.getMatchString().charAt(0) == '\'' || contentAssistRequest.getMatchString().charAt(0) == '"')) {
            internalOffset = contentAssistRequest.getMatchString().length() - 1 + additionalShifts;
            quoted = true;
          }
          // if unquoted, use position inside
          else if (contentAssistRequest.getMatchString().length() > 0 && contentAssistRequest.getMatchString().charAt(0) == '<')
            internalOffset = contentAssistRequest.getMatchString().length() + additionalShifts;
          else
            internalOffset = contentAssistRequest.getReplacementBeginPosition() - contentAssistRequest.getStartOffset() + additionalShifts;
          depthCount++;
          IndexedRegion internalNode = null;
          int tmpOffset = internalOffset;
          while (internalNode == null && tmpOffset >= 0)
            internalNode = internalModel.getIndexedRegion(tmpOffset--);

          if (internalModel.getFactoryRegistry() != null) {
            // set up the internal model
            if (internalModel.getFactoryRegistry().getFactoryFor(PageDirectiveAdapter.class) == null) {
              internalModel.getFactoryRegistry().addFactory(new PageDirectiveAdapterFactory());
            }
            PageDirectiveAdapter outerEmbeddedTypeAdapter = (PageDirectiveAdapter) xmlOuterModel.getDocument().getAdapterFor(PageDirectiveAdapter.class);
            PageDirectiveAdapter internalEmbeddedTypeAdapter = (PageDirectiveAdapter) ((INodeNotifier) ((Node) internalNode).getOwnerDocument()).getAdapterFor(PageDirectiveAdapter.class);
            internalEmbeddedTypeAdapter.setEmbeddedType(outerEmbeddedTypeAdapter.getEmbeddedType());
          }

          AdapterFactoryRegistry adapterRegistry = JSPUIPlugin.getDefault().getAdapterFactoryRegistry();
          Iterator adapterList = adapterRegistry.getAdapterFactories();
          // And all those appropriate for this particular type
          // of content
          while (adapterList.hasNext()) {
            try {
              AdapterFactoryProvider provider = (AdapterFactoryProvider) adapterList.next();
              if (provider.isFor(internalModel.getModelHandler())) {
                provider.addAdapterFactories(internalModel);
              }
            }
            catch (Exception e) {
              Logger.logException(e);
            }
          }

          /**
           * the internal adapter does all the real work of using
           * the JSP content model to form proposals
           */
          ICompletionProposal[] results = null;
          depthCount--;
          if (results != null) {
            for (i = 0; i < results.length; i++) {
              contentAssistRequest.addProposal(new CustomCompletionProposal(((CustomCompletionProposal) results[i]).getReplacementString(), ((CustomCompletionProposal) results[i]).getReplacementOffset() - additionalShifts + contentAssistRequest.getStartOffset() + (quoted ? 1 : 0), ((CustomCompletionProposal) results[i]).getReplacementLength(), ((CustomCompletionProposal) results[i]).getCursorPosition(), results[i].getImage(), results[i].getDisplayString(), ((CustomCompletionProposal) results[i]).getContextInformation(), ((CustomCompletionProposal) results[i]).getAdditionalProposalInfo(), (results[i] instanceof IRelevanceCompletionProposal) ? ((IRelevanceCompletionProposal) results[i]).getRelevance() : IRelevanceConstants.R_NONE));
            }
          }
        }
      }
      catch (Exception e) {
        Logger.logException("Error in embedded JSP Content Assist", e); //$NON-NLS-1$
      }
    }


  }

  /**
   * For JSP files and segments, this is just the JSP
   *         document, but when editing tag files and their fragments, it
   *         should be the tag document.
   *
   * It may also vary based on the model being edited in the future.
   *
   * @return the default non-embedded CMDocument for the document being
   *         edited.
   */
  CMDocument getDefaultJSPCMDocument(IDOMNode node) {
    // handle tag files here
    String contentType = node.getModel().getContentTypeIdentifier();
    if (ContentTypeIdForJSP.ContentTypeID_JSPTAG.equals(contentType))
      return JSPCMDocumentFactory.getCMDocument(CMDocType.TAG20_DOC_TYPE);

    CMDocument jcmdoc = null;
    String modelPath = node.getModel().getBaseLocation();
    if (modelPath != null && !IModelManager.UNMANAGED_MODEL.equals(modelPath)) {
      float version = DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(new Path(modelPath));
      jcmdoc = JSPCMDocumentFactory.getCMDocument(version);
    }
    if (jcmdoc == null) {
      jcmdoc = JSPCMDocumentFactory.getCMDocument();
    }

    return jcmdoc;
  }

  protected void init() {
    super.init();
  }

  public void setErrorMessage(String errorMessage) {
    if (depthCount == 0)
      fErrorMessage = errorMessage;
  }

  /**
   * This method is acting as a "catch all" for pulling together content
   * assist proposals from different Processors when document partitioning
   * alone couldn't determine definitively what content assist should show
   * up at that particular position in the document
   *
   * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(ITextViewer,
   *      int)
   */
  public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentPosition) {
    fTemplateContexts.clear();

    IStructuredDocumentRegion sdRegion = ContentAssistUtils.getStructuredDocumentRegion(viewer, documentPosition);
    fViewer = viewer;
    ICompletionProposal[] jspResults = EMPTY_PROPOSAL_SET;
    ICompletionProposal[] embeddedResults = EMPTY_PROPOSAL_SET;

    // check the actual partition type
    String partitionType = getPartitionType(viewer, documentPosition);
    IStructuredDocument structuredDocument = (IStructuredDocument) viewer.getDocument();

    IStructuredDocumentRegion fn = structuredDocument.getRegionAtCharacterOffset(documentPosition);

    // ////////////////////////////////////////////////////////////////////////////
    // ANOTHER WORKAROUND UNTIL PARTITIONING TAKES CARE OF THIS
    // check for xml-jsp tags...
    if (partitionType == IJSPPartitions.JSP_DIRECTIVE && fn != null) {
      IStructuredDocumentRegion possibleXMLJSP = ((fn.getType() == DOMRegionContext.XML_CONTENT) && fn.getPrevious() != null) ? fn.getPrevious() : fn;
      ITextRegionList regions = possibleXMLJSP.getRegions();
      if (regions.size() > 1) {
        // check bounds cases
        ITextRegion xmlOpenOrClose = regions.get(0);
        if (xmlOpenOrClose.getType() == DOMRegionContext.XML_TAG_OPEN && documentPosition == possibleXMLJSP.getStartOffset()) {
          // do regular jsp content assist
        }
        else if (xmlOpenOrClose.getType() == DOMRegionContext.XML_END_TAG_OPEN && documentPosition > possibleXMLJSP.getStartOffset()) {
          // do regular jsp content assist
        }
        else {
          // possible xml-jsp
          ITextRegion nameRegion = regions.get(1);
          String name = possibleXMLJSP.getText(nameRegion);
          if (name.equals("jsp:scriptlet") || name.equals("jsp:expression") || name.equals("jsp:declaration")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            return getJSPJavaCompletionProposals(viewer, documentPosition);
          }
        }
      }
    }

    // ////////////////////////////////////////////////////////////////////////////
    // ** THIS IS A TEMP FIX UNTIL PARTITIONING TAKES CARE OF THIS...
    // check for XML-JSP in a <script> region
    if (partitionType == IJSPPartitions.JSP_CONTENT_JAVASCRIPT || partitionType == IHTMLPartitions.SCRIPT) {
      // fn should be block text
      IStructuredDocumentRegion decodedSDRegion = decodeScriptBlock(fn.getFullText());
      // System.out.println("decoded > " +
      // blockOfText.substring(decodedSDRegion.getStartOffset(),
      // decodedSDRegion.getEndOffset()));
      if (decodedSDRegion != null) {
        IStructuredDocumentRegion sdr = decodedSDRegion;
        while (sdr != null) {
          // System.out.println("sdr " + sdr.getType());
          // System.out.println("sdr > " +
          // blockOfText.substring(sdr.getStartOffset(),
          // sdr.getEndOffset()));
          if (sdr.getType() == DOMJSPRegionContexts.JSP_CONTENT) {
            if (documentPosition >= fn.getStartOffset() + sdr.getStartOffset() && documentPosition <= fn.getStartOffset() + sdr.getEndOffset()) {
              return getJSPJavaCompletionProposals(viewer, documentPosition);
            }
          }
          else if (sdr.getType() == DOMRegionContext.XML_TAG_NAME) {
            if (documentPosition > fn.getStartOffset() + sdr.getStartOffset() && documentPosition < fn.getStartOffset() + sdr.getEndOffset()) {
              return EMPTY_PROPOSAL_SET;
            }
            else if (documentPosition == fn.getStartOffset() + sdr.getEndOffset() && sdr.getNext() != null && sdr.getNext().getType() == DOMJSPRegionContexts.JSP_CONTENT) {
              // the end of an open tag <script>
              // <jsp:scriptlet>| blah </jsp:scriptlet>
              return getJSPJavaCompletionProposals(viewer, documentPosition);
            }
            else if (documentPosition == fn.getStartOffset() + sdr.getStartOffset() && sdr.getPrevious() != null && sdr.getPrevious().getType() == DOMRegionContext.XML_TAG_NAME) {
              return getJSPJavaCompletionProposals(viewer, documentPosition);
            }
          }
          sdr = sdr.getNext();
        }
      }
    }
    // /////////////////////////////////////////////////////////////////////////
    // check special JSP delimiter cases
    if (fn != null && partitionType == IJSPPartitions.JSP_CONTENT_DELIMITER) {
      IStructuredDocumentRegion fnDelim = fn;

      // if it's a nested JSP region, need to get the correct
      // StructuredDocumentRegion
      // not sure why this check was there...
      // if (fnDelim.getType() == XMLRegionContext.BLOCK_TEXT) {
      Iterator blockRegions = fnDelim.getRegions().iterator();
      ITextRegion temp = null;
      ITextRegionContainer trc;
      while (blockRegions.hasNext()) {
        temp = (ITextRegion) blockRegions.next();
        // we hit a nested
        if (temp instanceof ITextRegionContainer) {
          trc = (ITextRegionContainer) temp;
          // it's in this region
          if (documentPosition >= trc.getStartOffset() && documentPosition < trc.getEndOffset()) {
            Iterator nestedJSPRegions = trc.getRegions().iterator();
            while (nestedJSPRegions.hasNext()) {
              temp = (ITextRegion) nestedJSPRegions.next();
              if (XMLContentAssistUtilities.isJSPOpenDelimiter(temp.getType()) && documentPosition == trc.getStartOffset(temp)) {
                // HTML content assist
                // we actually want content assist for the
                // previous type of region,
                // well get those proposals from the embedded
                // adapter
                if (documentPosition > 0) {
                  partitionType = getPartitionType(viewer, documentPosition - 1);
                  break;
                }
              }
              else if (XMLContentAssistUtilities.isJSPCloseDelimiter(temp.getType()) && documentPosition == trc.getStartOffset(temp)) {
                // JSP content assist
                return getJSPJavaCompletionProposals(viewer, documentPosition);
              }
            }
          }
        }
        // }
      }

      // take care of XML-JSP delimter cases
      if (XMLContentAssistUtilities.isXMLJSPDelimiter(fnDelim)) {
        // since it's a delimiter, we know it's a ITextRegionContainer
        ITextRegion firstRegion = fnDelim.getRegions().get(0);
        if (fnDelim.getStartOffset() == documentPosition && (firstRegion.getType() == DOMRegionContext.XML_TAG_OPEN)) {
          // |<jsp:scriptlet> </jsp:scriptlet>
          // (pa) commented out so that we get regular behavior JSP
          // macros etc...
          // return getHTMLCompletionProposals(viewer,
          // documentPosition);
        }
        else if (fnDelim.getStartOffset() == documentPosition && (firstRegion.getType() == DOMRegionContext.XML_END_TAG_OPEN)) {
          // <jsp:scriptlet> |</jsp:scriptlet>
          // check previous partition type to see if it's JAVASCRIPT
          // if it is, we're just gonna let the embedded JAVASCRIPT
          // adapter get the proposals
          if (documentPosition > 0) {
            String checkType = getPartitionType(viewer, documentPosition - 1);
            if (checkType != IJSPPartitions.JSP_CONTENT_JAVASCRIPT) { // this
              // check
              // is
              // failing
              // for
              // XML-JSP
              // (region
              // is
              // not
              // javascript...)
              return getJSPJavaCompletionProposals(viewer, documentPosition);
            }
            partitionType = IJSPPartitions.JSP_CONTENT_JAVASCRIPT;
          }
        }
        else if ((firstRegion.getType() == DOMRegionContext.XML_TAG_OPEN) && documentPosition >= fnDelim.getEndOffset()) {
          // anything else inbetween
          return getJSPJavaCompletionProposals(viewer, documentPosition);
        }
      }
      else if (XMLContentAssistUtilities.isJSPDelimiter(fnDelim)) {
        // the delimiter <%, <%=, <%!, ...
        if (XMLContentAssistUtilities.isJSPCloseDelimiter(fnDelim)) {
          if (documentPosition == fnDelim.getStartOffset()) {
            // check previous partition type to see if it's
            // JAVASCRIPT
            // if it is, we're just gonna let the embedded
            // JAVASCRIPT adapter get the proposals
            if (documentPosition > 0) {
              String checkType = getPartitionType(viewer, documentPosition - 1);
              if (checkType != IJSPPartitions.JSP_CONTENT_JAVASCRIPT) {
                return getJSPJavaCompletionProposals(viewer, documentPosition);
              }
              partitionType = IJSPPartitions.JSP_CONTENT_JAVASCRIPT;
            }
          }
        }
        else if (XMLContentAssistUtilities.isJSPOpenDelimiter(fnDelim)) {
          // if it's the first position of open delimiter
          // use embedded HTML results
          if (documentPosition == fnDelim.getStartOffset()) {
            embeddedResults = getHTMLCompletionProposals(viewer, documentPosition);
          }
          else if (documentPosition == fnDelim.getEndOffset()) {
            // it's at the EOF <%|
            return getJSPJavaCompletionProposals(viewer, documentPosition);
          }
        }
      }
    }

    // need to check if it's JSP region inside of CDATA w/ no region
    // <![CDATA[ <%|%> ]]>
    // or a comment region
    // <!-- <% |%> -->
    if (fn != null && (fn.getType() == DOMRegionContext.XML_CDATA_TEXT || fn.getType() == DOMRegionContext.XML_COMMENT_TEXT)) {
      if (fn instanceof ITextRegionContainer) {
        Object[] cdataRegions = fn.getRegions().toArray();
        ITextRegion r = null;
        ITextRegion jspRegion = null;
        for (int i = 0; i < cdataRegions.length; i++) {
          r = (ITextRegion) cdataRegions[i];
          if (r instanceof ITextRegionContainer) {
            // CDATA embedded container, or comment container
            Object[] jspRegions = ((ITextRegionContainer) r).getRegions().toArray();
            for (int j = 0; j < jspRegions.length; j++) {
              jspRegion = (ITextRegion) jspRegions[j];
              if (jspRegion.getType() == DOMJSPRegionContexts.JSP_CLOSE) {
                if (sdRegion.getStartOffset(jspRegion) == documentPosition)
                  return getJSPJavaCompletionProposals(viewer, documentPosition);
              }
            }
          }
        }

      }
    }

    // check if it's in an attribute value, if so, don't add CDATA
    // proposal
    ITextRegion attrContainer = (fn != null) ? fn.getRegionAtCharacterOffset(documentPosition) : null;
    if (attrContainer != null && attrContainer instanceof ITextRegionContainer) {
      if (attrContainer.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
        // test location of the cursor
        // return null if it's in the middle of an open/close
        // delimeter
        Iterator attrRegions = ((ITextRegionContainer) attrContainer).getRegions().iterator();
        ITextRegion testRegion = null;
        while (attrRegions.hasNext()) {
          testRegion = (ITextRegion) attrRegions.next();
          // need to check for other valid attribute regions
          if (XMLContentAssistUtilities.isJSPOpenDelimiter(testRegion.getType())) {
            if (!(((ITextRegionContainer) attrContainer).getEndOffset(testRegion) <= documentPosition))
              return EMPTY_PROPOSAL_SET;
          }
          else if (XMLContentAssistUtilities.isJSPCloseDelimiter(testRegion.getType())) {
            if (!(((ITextRegionContainer) attrContainer).getStartOffset(testRegion) >= documentPosition))
              return EMPTY_PROPOSAL_SET;
          }
        }
        // TODO: handle non-Java code such as nested tags
        if (testRegion.getType().equals(DOMJSPRegionContexts.JSP_CONTENT))
          return getJSPJavaCompletionProposals(viewer, documentPosition);
        return EMPTY_PROPOSAL_SET;
      }
    }

    IContentAssistProcessor p = (IContentAssistProcessor) fPartitionToProcessorMap.get(partitionType);
    if (p != null) {
      embeddedResults = p.computeCompletionProposals(viewer, documentPosition);
      // get bean methods, objects, and constants if there are any...
      if (partitionType == IJSPPartitions.JSP_CONTENT_JAVASCRIPT || partitionType == IHTMLPartitions.SCRIPT) {
        ICompletionProposal[] beanResults = getJSPJavaBeanProposals(viewer, documentPosition);
        if (beanResults != null && beanResults.length > 0) {
          ICompletionProposal[] added = new ICompletionProposal[beanResults.length + embeddedResults.length];
          System.arraycopy(beanResults, 0, added, 0, beanResults.length);
          System.arraycopy(embeddedResults, 0, added, beanResults.length, embeddedResults.length);
          embeddedResults = added;
        }
      }
    }
    else {
      // the partition type is probably not mapped
    }

    // fix for:
    // HTML content assist give JSP tags in between empty script tags
    if (!((getJSContentAssistProcessor() != null && getJSContentAssistProcessor().getClass().isInstance(p)) || p instanceof CSSContentAssistProcessor)) {
      fTemplateContexts.clear();
      jspResults = super.computeCompletionProposals(viewer, documentPosition);
    }
   
    //merge the embedded results
    if (useEmbeddedResults && embeddedResults != null && embeddedResults.length > 0) {
      jspResults = merge(jspResults, embeddedResults);
    }
    if (jspResults == null)
      jspResults = EMPTY_PROPOSAL_SET;
    setErrorMessage(jspResults.length == 0 ? UNKNOWN_CONTEXT : null);

    // fix for:
    // check for |<%-- --%> first position of jsp comment
    if (partitionType == IJSPPartitions.JSP_COMMENT) {
      if (sdRegion.getStartOffset() == documentPosition) {
        ICompletionProposal[] htmlResults = getHTMLCompletionProposals(viewer, documentPosition);
        jspResults = merge(jspResults, htmlResults);
      }
    }

    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=86656
    if (partitionType == IJSPPartitions.JSP_DIRECTIVE) {
      ICompletionProposal[] importProposals = getImportProposals(viewer, documentPosition);
      if (importProposals.length > 0)
        jspResults = merge(jspResults, importProposals);
    }
    return jspResults;
  }

  private ICompletionProposal[] getImportProposals(ITextViewer viewer, int documentPosition) {
    List importProposals = new ArrayList();
    ICompletionProposal[] proposals = getJSPJavaCompletionProposals(viewer, documentPosition);
    for (int i = 0; i < proposals.length; i++) {
      if (proposals[i] instanceof JSPCompletionProposal) {

        ICompletionProposal importProposal = adjustImportProposal((JSPCompletionProposal) proposals[i]);
        importProposals.add(importProposal);
      }
    }
    return (ICompletionProposal[]) importProposals.toArray(new ICompletionProposal[importProposals.size()]);
  }


  private ICompletionProposal adjustImportProposal(JSPCompletionProposal importProposal) {

    // just need to remove the ";"
    // and adjust offsets for the change
    String newReplace = importProposal.getReplacementString().replaceAll(";", ""); //$NON-NLS-1$ //$NON-NLS-2$
    importProposal.setReplacementString(newReplace);

    String newDisplay = importProposal.getDisplayString().replaceAll(";", ""); //$NON-NLS-1$ //$NON-NLS-2$
    importProposal.setDisplayString(newDisplay);

    int newReplacementLength = importProposal.getReplacementLength() - 1;
    if (newReplacementLength >= 0)
      importProposal.setReplacementLength(newReplacementLength);

    int newCursorPosition = importProposal.getCursorPosition() - 1;
    importProposal.setCursorPosition(newCursorPosition);

    return importProposal;
  }

  /**
   * Adds 2 arrays of {@link ICompletionProposal}s to a {@link TreeSet}
   * eliminating duplicates and sorting with a {@link ProposalComparator}
   * then returning the new merged, filtered, sorted, array of {@link ICompletionProposal}s.
   *
   * @param proposalsOne
   * @param proposalsTwo
   * @return a new merged, filtered, sorted array of {@link ICompletionProposal}s created from
   * the two given arrays of {@link ICompletionProposal}s.
   */
  private ICompletionProposal[] merge(ICompletionProposal[] proposalsOne, ICompletionProposal[] proposalsTwo) {
    Set results = new TreeSet(new ProposalComparator());

    if (proposalsOne != null) {
      for (int i = 0; i < proposalsOne.length; i++)
        results.add(proposalsOne[i]);
    }
    if (proposalsTwo != null) {
      for (int i = 0; i < proposalsTwo.length; i++)
        results.add(proposalsTwo[i]);
    }

    return (ICompletionProposal[]) results.toArray(new ICompletionProposal[results.size()]);
  }

  private IContentAssistProcessor getJSContentAssistProcessor() {
    if (fJSContentAssistProcessor == null) {
      fJSContentAssistProcessor = new StructuredTextViewerConfigurationHTML().getContentAssistant(null).getContentAssistProcessor(IHTMLPartitions.SCRIPT);
    }
    return fJSContentAssistProcessor;
  }

  /*
   * This method will return JSPJava Proposals that are relevant to any java
   * beans that in scope at the documentPosition
   *
   * TODO (pa) are taglib vars getting filtered?
   *
   * @param viewer @param documentPosition @return ICompletionProposal[]
   */
  private ICompletionProposal[] getJSPJavaBeanProposals(ITextViewer viewer, int documentPosition) {
    ICompletionProposal[] regularJSPResults = getJSPJavaCompletionProposals(viewer, documentPosition);
    Vector filteredProposals = new Vector();
    ICompletionProposal[] finalResults = EMPTY_PROPOSAL_SET;
    for (int i = 0; i < regularJSPResults.length; i++) {
      ICompletionProposal test = regularJSPResults[i];

      System.out.println("proposal > " + test.getDisplayString()); //$NON-NLS-1$
      System.out.println("relevance > " + ((CustomCompletionProposal) test).getRelevance()); //$NON-NLS-1$

      if (isRelevanceAllowed(((CustomCompletionProposal) test).getRelevance())) {
        filteredProposals.add(test);
      }
    }
    if (filteredProposals.size() > 0) {
      finalResults = new ICompletionProposal[filteredProposals.size()];
      Iterator it = filteredProposals.iterator();
      int j = 0;
      while (it.hasNext()) {
        finalResults[j++] = (ICompletionProposal) it.next();
      }
    }
    return finalResults;
  }

  // These are the only things I'm allowing for use bean if the language is
  // JAVASCRIPT
  // I'm filtering based on JavaContentAssistProposal relevance
  //
  // 485 > method that belongs to the bean
  // 486 > bean object
  // 386 > bean CONSTANT
  private boolean isRelevanceAllowed(int relevance) {
    return (relevance == 485 || relevance == 486 || relevance == 326);
  }


  /**
   *
   * @param viewer
   * @param documentPosition
   * @return ICompletionProposal[]
   */
  private ICompletionProposal[] getHTMLCompletionProposals(ITextViewer viewer, int documentPosition) {

    IContentAssistProcessor p = (IContentAssistProcessor) fPartitionToProcessorMap.get(IHTMLPartitions.HTML_DEFAULT);
    return p.computeCompletionProposals(viewer, documentPosition);
  }

  /**
   *
   * @param viewer
   * @param documentPosition
   * @return ICompletionProposal[]
   */
  protected ICompletionProposal[] getJSPJavaCompletionProposals(ITextViewer viewer, int documentPosition) {
    JSPJavaContentAssistProcessor p = (JSPJavaContentAssistProcessor) fPartitionToProcessorMap.get(IJSPPartitions.JSP_DEFAULT);
    return p.computeCompletionProposals(viewer, documentPosition);
  }

  /**
   * @param viewer
   * @param documentPosition
   * @return String
   */
  protected String getPartitionType(ITextViewer viewer, int documentPosition) {
    String partitionType = null;
    try {
      if (viewer instanceof ITextViewerExtension5)
        partitionType = TextUtilities.getContentType(viewer.getDocument(), IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, ((ITextViewerExtension5) viewer).modelOffset2WidgetOffset(documentPosition), false);
      else
        partitionType = TextUtilities.getContentType(viewer.getDocument(), IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, documentPosition, false);
    }
    catch (BadLocationException e) {
      partitionType = IDocument.DEFAULT_CONTENT_TYPE;
    }
    return partitionType;
  }

  /*
   * ** TEMP WORKAROUND FOR CMVC 241882 Takes a String and blocks out
   * jsp:scriptlet, jsp:expression, and jsp:declaration @param blockText
   * @return
   */
  private IStructuredDocumentRegion decodeScriptBlock(String blockText) {
    XMLSourceParser parser = new XMLSourceParser();
    // use JSP_CONTENT for region type
    parser.addBlockMarker(new BlockMarker("jsp:scriptlet", null, DOMJSPRegionContexts.JSP_CONTENT, false, false)); //$NON-NLS-1$
    parser.addBlockMarker(new BlockMarker("jsp:expression", null, DOMJSPRegionContexts.JSP_CONTENT, false, false)); //$NON-NLS-1$
    parser.addBlockMarker(new BlockMarker("jsp:declaration", null, DOMJSPRegionContexts.JSP_CONTENT, false, false)); //$NON-NLS-1$
    parser.reset(blockText);
    return parser.getDocumentRegions();
  }

  /*
   * @see ContentAssistAdapter#computeContextInformation(ITextViewer, int,
   *      IndexedRegion)
   */
  public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset, IndexedRegion indexedNode) {
    return super.computeContextInformation(viewer, documentOffset);
  }

  /*
   * @see ContentAssistAdapter#getContextInformationAutoActivationCharacters()
   */
  public char[] getContextInformationAutoActivationCharacters() {
    return super.getContextInformationAutoActivationCharacters();
  }


  public char[] getCompletionProposalAutoActivationCharacters() {
    IContentAssistProcessor p = (IContentAssistProcessor) fPartitionToProcessorMap.get(IHTMLPartitions.HTML_DEFAULT);
    return p.getCompletionProposalAutoActivationCharacters();
  }

  /*
   * @see ContentAssistAdapter#getContextInformationValidator()
   */
  public IContextInformationValidator getContextInformationValidator() {
    return super.getContextInformationValidator();
  }

  protected boolean isXMLFormat(Document doc) {
    if (doc == null)
      return false;
    Element docElement = doc.getDocumentElement();
    return docElement != null && ((docElement.getNodeName().equals("jsp:root")) || ((((IDOMNode) docElement).getStartStructuredDocumentRegion() == null && ((IDOMNode) docElement).getEndStructuredDocumentRegion() == null))); //$NON-NLS-1$
  }

  /*
   * @see ContentAssistAdapter#release()
   */
  public void release() {
    super.release();
    // release *ContentAssistProcessors in maps
    // CMVC 254023
    releasePartitionToProcessorMap();
    releaseNameToProcessorMap();
  }

  protected void releasePartitionToProcessorMap() {
    releaseMap(fPartitionToProcessorMap);
  }

  protected void releaseNameToProcessorMap() {
    releaseMap(fNameToProcessorMap);
  }

  protected void releaseMap(HashMap map) {
    if (map != null) {
      if (!map.isEmpty()) {
        Iterator it = map.keySet().iterator();
        Object key = null;
        while (it.hasNext()) {
          key = it.next();
          if (map.get(key) instanceof IReleasable) {
            ((IReleasable) map.get(key)).release();
          }
        }
      }
      map.clear();
      map = null;
    }
  }

  /**
   * @see AbstractContentAssistProcessor#computeCompletionProposals(int,
   *      String, ITextRegion, IDOMNode, IDOMNode)
   */
  protected ContentAssistRequest computeCompletionProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode treeNode, IDOMNode xmlnode) {

    ContentAssistRequest request = super.computeCompletionProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
    IStructuredDocumentRegion sdRegion = ContentAssistUtils.getStructuredDocumentRegion(fTextViewer, documentPosition);

    Document doc = null;
    if (xmlnode != null) {
      if (xmlnode.getNodeType() == Node.DOCUMENT_NODE)
        doc = (Document) xmlnode;
      else
        doc = xmlnode.getOwnerDocument();
    }
    String[] directiveNames = {"page", "include", "taglib"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    // suggest JSP Expression inside of XML comments
    if (completionRegion.getType() == DOMRegionContext.XML_COMMENT_TEXT && !isXMLFormat(doc)) {
      if (request == null)
        request = newContentAssistRequest(treeNode, xmlnode, sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
      request.addProposal(new CustomCompletionProposal("<%=  %>", documentPosition, 0, 4, JSPEditorPluginImageHelper.getInstance().getImage(JSPEditorPluginImages.IMG_OBJ_TAG_GENERIC), "jsp:expression", null, "&lt;%= %&gt;", XMLRelevanceConstants.R_JSP)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
    }
    // handle proposals in and around JSP_DIRECTIVE_OPEN and
    // JSP_DIRECTIVE_NAME
    else if ((completionRegion.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN && documentPosition >= sdRegion.getTextEndOffset(completionRegion)) || (completionRegion.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME && documentPosition <= sdRegion.getTextEndOffset(completionRegion))) {
      if (completionRegion.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN) {
        if (request == null)
          request = newContentAssistRequest(xmlnode, xmlnode, sdRegion, completionRegion, documentPosition, 0, matchString);
        Iterator regions = sdRegion.getRegions().iterator();
        String nameString = null;
        int begin = request.getReplacementBeginPosition();
        int length = request.getReplacementLength();
        while (regions.hasNext()) {
          ITextRegion region = (ITextRegion) regions.next();
          if (region.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
            nameString = sdRegion.getText(region);
            begin = sdRegion.getStartOffset(region);
            length = region.getTextLength();
            break;
          }
        }
        if (nameString == null)
          nameString = ""; //$NON-NLS-1$
        for (int i = 0; i < directiveNames.length; i++) {
          if (directiveNames[i].startsWith(nameString) || documentPosition <= begin)
            request.addProposal(new CustomCompletionProposal(directiveNames[i], begin, length, directiveNames[i].length(), JSPEditorPluginImageHelper.getInstance().getImage(JSPEditorPluginImages.IMG_OBJ_TAG_GENERIC), directiveNames[i], null, null, XMLRelevanceConstants.R_JSP));
        }
      }
      else { // by default, JSP_DIRECTIVE_NAME
        if (request == null)
          request = newContentAssistRequest(xmlnode, xmlnode, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
        for (int i = 0; i < directiveNames.length; i++) {
          if (directiveNames[i].startsWith(matchString))
            request.addProposal(new CustomCompletionProposal(directiveNames[i], request.getReplacementBeginPosition(), request.getReplacementLength(), directiveNames[i].length(), JSPEditorPluginImageHelper.getInstance().getImage(JSPEditorPluginImages.IMG_OBJ_TAG_GENERIC), directiveNames[i], null, null, XMLRelevanceConstants.R_JSP));
        }
      }
    }
    else if ((completionRegion.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME && documentPosition > sdRegion.getTextEndOffset(completionRegion)) || (completionRegion.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE && documentPosition <= sdRegion.getStartOffset(completionRegion))) {
      if (request == null)
        request = computeAttributeProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
      super.addTagCloseProposals(request);
      // CMVC 274033, this is being added for all <jsp:* tags
      // in addAttributeNameProposals(contentAssistRequest)
      // super.addAttributeNameProposals(request);
    }
    // no name?: <%@ %>
    else if (completionRegion.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE && documentPosition <= sdRegion.getStartOffset(completionRegion)) {
      if (request != null)
        request = computeAttributeProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
      Iterator regions = sdRegion.getRegions().iterator();
      String nameString = null;
      while (regions.hasNext()) {
        ITextRegion region = (ITextRegion) regions.next();
        if (region.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
          nameString = sdRegion.getText(region);
          break;
        }
      }
      if (nameString == null) {
        for (int i = 0; i < directiveNames.length; i++) {
          request.addProposal(new CustomCompletionProposal(directiveNames[i], request.getReplacementBeginPosition(), request.getReplacementLength(), directiveNames[i].length(), JSPEditorPluginImageHelper.getInstance().getImage(JSPEditorPluginImages.IMG_OBJ_TAG_GENERIC), directiveNames[i], null, null, XMLRelevanceConstants.R_JSP));
        }
      }
    }

    // bug115927 use original document position for all/any region
    // templates
    addTemplates(request, TemplateContextTypeIdsJSP.ALL, documentPosition);
    return request;
  }

  private JSPTemplateCompletionProcessor getTemplateCompletionProcessor() {
    if (fTemplateProcessor == null) {
      fTemplateProcessor = new JSPTemplateCompletionProcessor();
    }
    return fTemplateProcessor;
  }

  /**
   * Adds templates to the list of proposals
   *
   * @param contentAssistRequest
   * @param context
   */
  private void addTemplates(ContentAssistRequest contentAssistRequest, String context) {
    addTemplates(contentAssistRequest, context, contentAssistRequest.getReplacementBeginPosition());
  }

  /**
   * Adds templates to the list of proposals
   *
   * @param contentAssistRequest
   * @param context
   */
  private void addTemplates(ContentAssistRequest contentAssistRequest, String context, int startOffset) {
    if (contentAssistRequest == null)
      return;

    // if already adding template proposals for a certain context type, do
    // not add again
    if (!fTemplateContexts.contains(context)) {
      fTemplateContexts.add(context);
      boolean useProposalList = !contentAssistRequest.shouldSeparate();

      if (getTemplateCompletionProcessor() != null) {
        getTemplateCompletionProcessor().setContextType(context);
        ICompletionProposal[] proposals = getTemplateCompletionProcessor().computeCompletionProposals(fTextViewer, startOffset);
        for (int i = 0; i < proposals.length; ++i) {
          if (useProposalList)
            contentAssistRequest.addProposal(proposals[i]);
          else
            contentAssistRequest.addMacro(proposals[i]);
        }
      }
    }
  }

  protected void addEntityProposals(ContentAssistRequest contentAssistRequest, int documentPosition, ITextRegion completionRegion, IDOMNode treeNode) {
    // ignore
  }

  protected void addTagInsertionProposals(ContentAssistRequest contentAssistRequest, int childPosition) {
    addTemplates(contentAssistRequest, TemplateContextTypeIdsJSP.TAG);
    //don't need to call super here because otherwise we duplicate what the HTMLCOntentAssistProcessor that is running is already doing
  }

  /**
   * Use the embedded content assist processor to determine the content generator
   *
   * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractContentAssistProcessor#getContentGenerator()
   */
  public XMLContentModelGenerator getContentGenerator() {
    if (fGenerator == null) {
      fGenerator = ((AbstractContentAssistProcessor) fPartitionToProcessorMap.get(IHTMLPartitions.HTML_DEFAULT)).getContentGenerator();
    }
    return fGenerator;
  }
}
TOP

Related Classes of org.eclipse.jst.jsp.ui.internal.contentassist.JSPContentAssistProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.