[294079]: [editor] Content Assist for xpath expressions inside curly brackets
https://bugs.eclipse.org/bugs/show_bug.cgi?id=294079
diff --git a/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/AttributeContentAssist.java b/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/AttributeContentAssist.java
new file mode 100644
index 0000000..597727f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/AttributeContentAssist.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ *Copyright (c) 2008 Standards for Technology in Automotive Retail 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:
+ *    David Carver (STAR) - bug 240170 - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xsl.ui.internal.contentassist;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xsl.ui.provisional.contentassist.SelectAttributeContentAssist;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * This class provides content assistance for attributes that contain the "{" character attribute.
+ *  
+ * @author dcarver
+ * @since 1.1
+ */
+public class AttributeContentAssist extends SelectAttributeContentAssist {
+
+	/**
+	 * Constructor for the XSL content assistance for the test attribute.
+	 * 
+	 * @param node
+	 * @param documentRegion
+	 * @param completionRegion
+	 * @param begin
+	 * @param length
+	 * @param filter
+	 * @param textViewer
+	 */
+	public AttributeContentAssist(Node node, 
+			IStructuredDocumentRegion documentRegion,
+			ITextRegion completionRegion, int begin, int length, String filter,
+			ITextViewer textViewer) {
+		super(node, documentRegion, completionRegion, begin, length, filter,
+				textViewer);
+	}
+	
+	/** 
+	 * (non-Javadoc)
+	 * @see org.eclipse.wst.xsl.ui.provisional.contentassist.SelectAttributeContentAssist#getCompletionProposals()
+	 */
+	@Override
+	public ArrayList<ICompletionProposal> getCompletionProposals() {
+				
+		int offset = getReplacementBeginPosition();
+		
+		IDOMAttr attrNode = getAttributeAtOffset(offset);
+	    
+	    if (attrNode == null || !matchString.contains("{")) { //$NON-NLS-1$
+	    	return getAllCompletionProposals();
+	    }
+	    
+		adjustXPathStart(attrNode.getLocalName());
+		offset = getReplacementBeginPosition();
+		
+		matchString = extractXPathMatchString(attrNode, getRegion(), getReplacementBeginPosition());
+		
+	    addSelectProposals((Element)getNode().getParentNode(), offset);
+
+		return getAllCompletionProposals();
+    }
+
+	private IDOMAttr getAttributeAtOffset(int offset) {
+		NamedNodeMap nodeMap = getNode().getAttributes();
+		IDOMAttr attrNode = null;
+		
+		for (int i = 0; i < nodeMap.getLength(); i++) {
+			IDOMAttr tmpAttr = (IDOMAttr) nodeMap.item(i);
+			int start = tmpAttr.getStartOffset();
+			int end = tmpAttr.getEndOffset();
+			if (start <= offset ||
+				end  > offset) {
+				attrNode = tmpAttr;
+				break;
+			}	
+		}
+		return attrNode;
+	}
+	
+}
diff --git a/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistProcessor.java b/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistProcessor.java
index e291f70..1e92231 100644
--- a/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistProcessor.java
+++ b/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistProcessor.java
@@ -22,12 +22,16 @@
 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
 import org.eclipse.jface.text.contentassist.IContextInformation;
 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
 import org.eclipse.wst.xml.ui.internal.contentassist.AbstractContentAssistProcessor;
 import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor;
 import org.eclipse.wst.xsl.core.XSLCore;
 import org.eclipse.wst.xsl.ui.internal.Messages;
 import org.eclipse.wst.xsl.ui.provisional.contentassist.AbstractXSLContentAssistProcessor;
 import org.eclipse.wst.xsl.ui.provisional.contentassist.IContentAssistProposalRequest;
+import org.w3c.dom.NamedNodeMap;
 
 /**
  * The XSL Content Assist Processor provides content assistance for various
@@ -38,9 +42,12 @@
  * @since 1.0
  */
 public class XSLContentAssistProcessor extends AbstractXSLContentAssistProcessor implements IContentAssistProcessor {
+	
+	private static final String attributeXpath = "{"; //$NON-NLS-1$
 
 	private ArrayList<ICompletionProposal> xslProposals;
 	private ArrayList<ICompletionProposal> additionalProposals;
+	private ArrayList<ICompletionProposal> attributeProposals;
 	private ArrayList<String> namespaces;
 	/**
 	 * Provides an XSL Content Assist Processor class that is XSL aware and XML
@@ -70,14 +77,19 @@
 	public ICompletionProposal[] computeCompletionProposals(
 			ITextViewer textViewer, int documentPosition) {
 		initializeProposalVariables(textViewer, documentPosition);
+		
+		
 
 		additionalProposals = getAdditionalXSLElementProposals();
 
 		xslProposals = getXSLNamespaceProposals();
+		
+		attributeProposals = getAttributeProposals();
 
 		ArrayList<ICompletionProposal> proposalList = new ArrayList<ICompletionProposal>();
 		proposalList.addAll(additionalProposals);
 		proposalList.addAll(xslProposals);
+		proposalList.addAll(attributeProposals);
 
 		ICompletionProposal[] combinedProposals = combineProposals(proposalList);
 
@@ -109,6 +121,12 @@
 		}
 		return additionalProposals;
 	}
+	
+	private ArrayList<ICompletionProposal> getAttributeProposals() {
+		attributeProposals = new AttributeContentAssist(xmlNode,
+				sdRegion, completionRegion, cursorPosition, 0, matchString, textViewer).getCompletionProposals();
+		return attributeProposals;
+	}
 
 	private ICompletionProposal[] combineProposals(
 			ArrayList<ICompletionProposal> proposalList) {
@@ -159,4 +177,18 @@
 		return null;
 	}
 
-}
+	protected boolean assistanceOnAttribute(IDOMNode node, ITextRegion aRegion) {
+		NamedNodeMap nodeMap = node.getAttributes();
+		for (int i = 0; i < nodeMap.getLength(); i++) {
+			IDOMAttr attrNode = (IDOMAttr) nodeMap.item(i);
+			if (attrNode.getValueRegion() != null &&
+				attrNode.getValueRegion().getStart() == aRegion.getStart()) {
+				if (attrNode.getValue().contains(attributeXpath)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+}	
+
diff --git a/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistRequestFactory.java b/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistRequestFactory.java
index ff8c228..630ee12 100644
--- a/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistRequestFactory.java
+++ b/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistRequestFactory.java
@@ -149,11 +149,11 @@
 					textViewer);
 		}
 
-		if (hasAttributeAtTextRegion(ATTR_MATCH, nodeMap, completionRegion)) {
-			return new SelectAttributeContentAssist(xmlNode, sdRegion,
-					completionRegion, documentPosition, 0, matchString,
-					textViewer);
-		}
+//		if (hasAttributeAtTextRegion(ATTR_MATCH, nodeMap, completionRegion)) {
+//			return new SelectAttributeContentAssist(xmlNode, sdRegion,
+//					completionRegion, documentPosition, 0, matchString,
+//					textViewer);
+//		}
 
 		if (hasAttributeAtTextRegion(ATTR_TEST, nodeMap, completionRegion)) {
 			return new TestAttributeContentAssist(xmlNode, sdRegion,
diff --git a/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/provisional/contentassist/SelectAttributeContentAssist.java b/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/provisional/contentassist/SelectAttributeContentAssist.java
index f60bc02..9438cec 100644
--- a/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/provisional/contentassist/SelectAttributeContentAssist.java
+++ b/bundles/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/provisional/contentassist/SelectAttributeContentAssist.java
@@ -165,7 +165,7 @@
 	}
 
 	protected int getXPathSeperatorPos(int column, String nodeValue) {
-		char[] keyTokens = { '/', '[', ']', '(', ')', ',', ' ' };
+		char[] keyTokens = { '{', '/', '[', ']', '(', ')', ',', ' ', };
 
 		int seperatorPos = 0;