Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal')
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlContentProposalProvider.java28
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlJavaCompletionProposalComputer.java129
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlSseCompletionProposalComputer.java63
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposal.java84
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposalComputer.java51
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlDefaultCompletionProposal.java65
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlJavaCompletionProposal.java65
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlSseCompletionProposal.java140
8 files changed, 492 insertions, 133 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlContentProposalProvider.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlContentProposalProvider.java
index bc3a95cdd4..6845c3a351 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlContentProposalProvider.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlContentProposalProvider.java
@@ -66,6 +66,7 @@ import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel;
import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
import org.eclipse.jpt.jpa.core.context.NamedQuery;
import org.eclipse.jpt.jpa.core.jpql.JpaJpqlQueryHelper;
+import org.eclipse.jpt.jpa.core.jpql.JpaJpqlQueryHelper.EscapeType;
import org.eclipse.jpt.jpa.ui.internal.JptUiMessages;
import org.eclipse.osgi.util.NLS;
import org.eclipse.persistence.jpa.jpql.JPQLQueryProblem;
@@ -347,19 +348,18 @@ public final class JpaJpqlContentProposalProvider extends JpqlCompletionProposal
Image image,
int cursorOffset) {
- return new JpqlCompletionProposal(
+ return new JpqlDefaultCompletionProposal(
contentAssistProposals,
proposal,
displayString,
additionalInfo,
image,
namedQuery,
- actualQuery,
jpqlQuery,
- offset,
+ tokenStart,
+ tokenEnd,
position,
- cursorOffset,
- false
+ cursorOffset
);
}
@@ -472,6 +472,9 @@ public final class JpaJpqlContentProposalProvider extends JpqlCompletionProposal
// Install a custom context menu to the widget
TextTransferHandler.installContextMenu(styledText, sourceViewer.getUndoManager());
+
+ // Make sure the document is up to date in case the text holder is already hooked to the model
+ sourceViewer.getDocument().set(textHolder.getValue());
}
/**
@@ -583,8 +586,8 @@ public final class JpaJpqlContentProposalProvider extends JpqlCompletionProposal
for (JPQLQueryProblem problem : sortProblems(queryHelper.validate())) {
- // Create the range
- int[] positions = queryHelper.buildPositions(problem, parsedJpqlQuery, jpqlQuery);
+ // Create the text range
+ int[] positions = queryHelper.buildPositions(problem, parsedJpqlQuery, jpqlQuery, jpqlQuery, 0, EscapeType.NONE);
// Add the problem to the tool tip
Annotation annotation = new Annotation(ERROR_TYPE, true, buildMessage(problem));
@@ -608,9 +611,16 @@ public final class JpaJpqlContentProposalProvider extends JpqlCompletionProposal
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
JpaJpqlContentProposalProvider.this.position = offset;
-
String jpqlQuery = viewer.getDocument().get();
- List<ICompletionProposal> proposals = buildProposals(query(), jpqlQuery, 0, position);
+
+ List<ICompletionProposal> proposals = buildProposals(
+ query(),
+ jpqlQuery,
+ 0,
+ jpqlQuery.length(),
+ position
+ );
+
return proposals.toArray(new ICompletionProposal[proposals.size()]);
}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlJavaCompletionProposalComputer.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlJavaCompletionProposalComputer.java
index 9aed1daa34..50f095a33d 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlJavaCompletionProposalComputer.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlJavaCompletionProposalComputer.java
@@ -13,6 +13,7 @@
******************************************************************************/
package org.eclipse.jpt.jpa.ui.internal.jpql;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IFile;
@@ -27,6 +28,7 @@ import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IExtendedModifier;
+import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
@@ -55,7 +57,7 @@ import org.eclipse.swt.graphics.Image;
* This computer adds content assist support when it is invoked inside the query element of {@link
* javax.persistence.NamedQuery &#64;NamedQuery}.
*
- * @version 3.2
+ * @version 3.3
* @since 3.0
* @author Pascal Filion
*/
@@ -80,22 +82,30 @@ public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionP
Image image,
int cursorOffset) {
- return new JpqlCompletionProposal(
+ return new JpqlJavaCompletionProposal(
contentAssistProposals,
proposal,
displayString,
additionalInfo,
image,
namedQuery,
- actualQuery,
jpqlQuery,
- offset + 1, // +1 is to skip the opening "
+ tokenStart + 1, // +1 is to skip the opening "
+ tokenEnd - 1, // -1 is to skip the closing "
position,
- cursorOffset,
- true
+ cursorOffset
);
}
+ @SuppressWarnings("unchecked")
+ private List<Expression> children(InfixExpression expression) {
+ List<Expression> children = new ArrayList<Expression>();
+ children.add(expression.getLeftOperand());
+ children.add(expression.getRightOperand());
+ children.addAll(expression.extendedOperands());
+ return children;
+ }
+
/**
* {@inheritDoc}
*/
@@ -129,10 +139,11 @@ public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionP
// - It is inside the string representation of a unicode character, \\u0|0E9 where | is the
// cursor, then -1 is returned;
// - The string is not valid (it has some invalid characters)
- int tokenStart = completionContext.getTokenStart();
- if (tokenStart == -1) return Collections.emptyList();
+ int tokenStart[] = { completionContext.getTokenStart() };
+ int tokenEnd[] = { completionContext.getTokenEnd() };
+ if (tokenStart[0] == -1) return Collections.emptyList();
- int[] position = { completionContext.getOffset() - tokenStart - 1 };
+ int[] position = { completionContext.getOffset() - tokenStart[0] - 1 };
if (position[0] < 0) return Collections.emptyList();
ICompilationUnit compilationUnit = context.getCompilationUnit();
@@ -149,15 +160,15 @@ public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionP
checkCanceled(monitor);
// Retrieve the JPA's model object
- NamedQuery namedQuery = namedQuery(jpaFile, tokenStart);
+ NamedQuery namedQuery = namedQuery(jpaFile, tokenStart[0]);
if (namedQuery == null) return Collections.emptyList();
// Retrieve the actual value of the element "query" since the content assist can be
// invoked before the model received the new content
- String jpqlQuery = jpqlQuery(astRoot, tokenStart, completionContext.getTokenEnd(), position);
+ String jpqlQuery = retrieveQuery(astRoot, tokenStart, tokenEnd, position);
// Now create the proposals
- return buildProposals(namedQuery, jpqlQuery, tokenStart, position[0]);
+ return buildProposals(namedQuery, jpqlQuery, tokenStart[0], tokenEnd[0], position[0]);
}
/**
@@ -178,10 +189,11 @@ public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionP
for (Query query : typeMapping.getQueries()){
if (query.getType().equals(NamedQuery.class)){
- JavaNamedQuery namedQuery = (JavaNamedQuery)query;
- TextRange textRange = namedQuery.getQueryAnnotation().getQueryTextRange();
- if ((textRange != null) && textRange.includes(tokenStart)) {
- return namedQuery;
+ JavaNamedQuery namedQuery = (JavaNamedQuery) query;
+ for (TextRange textRange : namedQuery.getQueryAnnotation().getQueryTextRanges()) {
+ if ((textRange != null) && textRange.includes(tokenStart)) {
+ return namedQuery;
+ }
}
}
}
@@ -206,20 +218,6 @@ public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionP
startPosition + node.getLength() >= tokenEnd;
}
- private String jpqlQuery(CompilationUnit astRoot, int tokenStart, int tokenEnd, int[] position) {
-
- String jpqlQuery = retrieveQuery(astRoot, tokenStart, tokenEnd);
-
- if (jpqlQuery == null) {
- jpqlQuery = StringTools.EMPTY_STRING;
- }
- else if (StringTools.isQuoted(jpqlQuery)) {
- jpqlQuery = jpqlQuery.substring(1, jpqlQuery.length() - 1);
- }
-
- return jpqlQuery;
- }
-
/**
* {@inheritDoc}
*/
@@ -254,12 +252,12 @@ public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionP
* @return The actual value retrieved from the query element
*/
@SuppressWarnings("unchecked")
- private String retrieveQuery(CompilationUnit astRoot, int tokenStart, int tokenEnd) {
+ private String retrieveQuery(CompilationUnit astRoot, int[] tokenStart, int[] tokenEnd, int[] position) {
// Dig into the TypeDeclarations
for (AbstractTypeDeclaration type : (List<AbstractTypeDeclaration>) astRoot.types()) {
- if (isInsideNode(type, tokenStart, tokenEnd)) {
+ if (isInsideNode(type, tokenStart[0], tokenEnd[0])) {
// Dig inside its modifiers and annotations
for (IExtendedModifier modifier : (List<IExtendedModifier>) type.modifiers()) {
@@ -271,7 +269,7 @@ public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionP
Annotation annotation = (Annotation) modifier;
// Dig inside the annotation
- if (isInsideNode(annotation, tokenStart, tokenEnd)) {
+ if (isInsideNode(annotation, tokenStart[0], tokenEnd[0])) {
// @NamedQueries({...})
if (annotation.isSingleMemberAnnotation()) {
@@ -282,22 +280,22 @@ public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionP
ArrayInitializer array = (ArrayInitializer) value;
for (Expression expression : (List<Expression>) array.expressions()) {
- if (isInsideNode(expression, tokenStart, tokenEnd)) {
- return retrieveQuery((NormalAnnotation) expression, tokenStart, tokenEnd);
+ if (isInsideNode(expression, tokenStart[0], tokenEnd[0])) {
+ return retrieveQuery((NormalAnnotation) expression, tokenStart, tokenEnd, position);
}
}
}
else {
NormalAnnotation childAnnotation = (NormalAnnotation) value;
- if (isInsideNode(childAnnotation, tokenStart, tokenEnd)) {
- return retrieveQuery(childAnnotation, tokenStart, tokenEnd);
+ if (isInsideNode(childAnnotation, tokenStart[0], tokenEnd[0])) {
+ return retrieveQuery(childAnnotation, tokenStart, tokenEnd, position);
}
}
}
// @NamedQuery()
else if (annotation.isNormalAnnotation()) {
- return retrieveQuery((NormalAnnotation) annotation, tokenStart, tokenEnd);
+ return retrieveQuery((NormalAnnotation) annotation, tokenStart, tokenEnd, position);
}
}
}
@@ -308,17 +306,62 @@ public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionP
}
@SuppressWarnings("unchecked")
- private String retrieveQuery(NormalAnnotation annotation, int tokenStart, int tokenEnd) {
+ private String retrieveQuery(NormalAnnotation annotation, int[] tokenStart, int[] tokenEnd, int[] position) {
for (MemberValuePair pair : (List<MemberValuePair>) annotation.values()) {
org.eclipse.jdt.core.dom.Expression expression = pair.getValue();
- if (isInsideNode(expression, tokenStart, tokenEnd)) {
- StringLiteral literal = (StringLiteral) pair.getValue();
- return literal.getEscapedValue();
+ if (isInsideNode(expression, tokenStart[0], tokenEnd[0])) {
+ Expression child = pair.getValue();
+
+ // Single string
+ if (child.getNodeType() == ASTNode.STRING_LITERAL) {
+ StringLiteral literal = (StringLiteral) pair.getValue();
+ return unquotedString(literal.getEscapedValue());
+ }
+
+ // Build the JPQL query from the concatenated strings
+ if (child.getNodeType() == ASTNode.INFIX_EXPRESSION) {
+
+ StringBuilder sb = new StringBuilder();
+ boolean adjustPosition = true;
+
+ for (Expression childNode : children((InfixExpression) child)) {
+
+ StringLiteral literal = (StringLiteral) childNode;
+ sb.append(unquotedString(literal.getEscapedValue()));
+
+ if (adjustPosition && !isInsideNode(literal, tokenEnd[0], tokenEnd[0])) {
+ position[0] += (literal.getLength() - 2);
+ }
+ else {
+ adjustPosition = false;
+ }
+ }
+
+ // Now adjust the start and end offsets so it includes the entire InfixExpression
+ // because content assist will only replace one string literal and right now we
+ // only support replacing the entire string
+ tokenStart[0] = child.getStartPosition();
+ tokenEnd[0] = child.getStartPosition() + child.getLength();
+
+ return sb.toString();
+ }
}
}
- return null;
+ return StringTools.EMPTY_STRING;
+ }
+
+ private String unquotedString(String value) {
+
+ if (value == null) {
+ value = StringTools.EMPTY_STRING;
+ }
+ else if (StringTools.isQuoted(value)) {
+ value = value.substring(1, value.length() - 1);
+ }
+
+ return value;
}
} \ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlSseCompletionProposalComputer.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlSseCompletionProposalComputer.java
index 92b4bb3fe9..e3299b054a 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlSseCompletionProposalComputer.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlSseCompletionProposalComputer.java
@@ -36,9 +36,9 @@ import org.eclipse.jpt.jpa.core.context.orm.EntityMappings;
import org.eclipse.jpt.jpa.core.context.orm.OrmEntity;
import org.eclipse.jpt.jpa.core.context.orm.OrmNamedQuery;
import org.eclipse.jpt.jpa.core.context.orm.OrmQueryContainer;
+import org.eclipse.jpt.jpa.core.jpql.XmlEscapeCharacterConverter;
import org.eclipse.jpt.jpa.ui.internal.JptUiMessages;
import org.eclipse.jpt.jpa.ui.internal.plugin.JptJpaUiPlugin;
-import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
import org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer;
@@ -47,13 +47,15 @@ import org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer;
* This computer adds content assist support when it is invoked inside the &lt;query&gt; element
* defined in a mapping file (ORM Configuration).
*
- * @version 3.2
+ * @version 3.3
* @since 3.0
* @author Pascal Filion
*/
public final class JpaJpqlSseCompletionProposalComputer extends JpqlCompletionProposalComputer<ICompletionProposal>
implements ICompletionProposalComputer {
+ private boolean cDATASection;
+
/**
* Creates a new <code>JpaJpqlSseCompletionProposalComputer</code>.
*/
@@ -71,19 +73,21 @@ public final class JpaJpqlSseCompletionProposalComputer extends JpqlCompletionPr
Image image,
int cursorOffset) {
- return new JpqlCompletionProposal(
+ return new JpqlSseCompletionProposal(
contentAssistProposals,
proposal,
displayString,
additionalInfo,
image,
namedQuery,
- actualQuery,
jpqlQuery,
- offset,
+ actualQuery,
+ tokenStart,
+ tokenEnd,
position,
+ actualPosition,
cursorOffset,
- false
+ cDATASection
);
}
@@ -117,12 +121,17 @@ public final class JpaJpqlSseCompletionProposalComputer extends JpqlCompletionPr
OrmNamedQuery namedQuery = namedQuery(jpaFile, offset, position);
if (namedQuery == null) return Collections.emptyList();
- // Keep track of the beginning of the text since the entire string is always replaced
+ // Retrieve the entire JPQL query from the document
+ Object[] info = jpqlQuery(namedQuery, context.getDocument());
+ String jpqlQuery = (String) info[0];
+ this.cDATASection = (Boolean) info[1];
+
+ // Keep track of the beginning and ending offsets since the entire string is always replaced
int tokenStart = offset - position[0];
+ int tokenEnd = tokenStart + jpqlQuery.length();
// Now create the proposals
- String jpqlQuery = jpqlQuery(namedQuery, context.getDocument());
- return buildProposals(namedQuery, jpqlQuery, tokenStart, position[0]);
+ return buildProposals(namedQuery, jpqlQuery, tokenStart, tokenEnd, position[0]);
}
catch (Exception ex) {
JptJpaUiPlugin.instance().logError(ex, JptUiMessages.JpaJpqlSseCompletionProposalComputer_Error);
@@ -175,24 +184,34 @@ public final class JpaJpqlSseCompletionProposalComputer extends JpqlCompletionPr
private OrmNamedQuery findNamedQuery(OrmQueryContainer container, int offset, int[] position) {
for (OrmNamedQuery namedQuery : container.getNamedQueries()) {
- TextRange textRange = namedQuery.getQueryTextRange();
- if (textRange.touches(offset)) {
- position[0] = offset - textRange.getOffset();
- return namedQuery;
+ for (TextRange textRange : namedQuery.getQueryTextRanges()) {
+
+ if (textRange.touches(offset)) {
+ position[0] = offset - textRange.getOffset();
+ return namedQuery;
+ }
}
}
return null;
}
- private String jpqlQuery(OrmNamedQuery namedQuery, IDocument document) {
+ private Object[] jpqlQuery(OrmNamedQuery namedQuery, IDocument document) {
+
try {
- TextRange range = namedQuery.getQueryTextRange();
- return document.get(range.getOffset(), range.getLength());
+ TextRange range = namedQuery.getQueryTextRanges().get(0);
+
+ return new Object[] {
+ document.get(range.getOffset(), range.getLength()),
+ namedQuery.getXmlQuery().isQueryInsideCDATASection()
+ };
}
catch (BadLocationException e) {
- return StringTools.EMPTY_STRING;
+ return new Object[] {
+ StringTools.EMPTY_STRING,
+ Boolean.FALSE
+ };
}
}
@@ -201,7 +220,15 @@ public final class JpaJpqlSseCompletionProposalComputer extends JpqlCompletionPr
*/
@Override
String modifyJpqlQuery(String jpqlQuery, int[] position) {
- return ExpressionTools.unescape(jpqlQuery, position);
+
+ // The JPQL query is not encapsulated by a CDATA section,
+ // converts any escape characters like &lt; into '<'
+ if (!cDATASection) {
+ // TODO: UPDATE TO USE ECLIPSELINK HERMES 2.5 M2 ONCE IT IS AVAILABLE
+ jpqlQuery = XmlEscapeCharacterConverter.unescape(jpqlQuery, position);
+ }
+
+ return jpqlQuery;
}
private OrmNamedQuery namedQuery(JpaFile jpaFile, int offset, int[] position) {
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposal.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposal.java
index aefd14b501..cf9b6f53f1 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposal.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposal.java
@@ -26,29 +26,28 @@ import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
/**
- * The concrete implementation of a {@link org.eclipse.jface.text.contentassist.ICompletionProposal
- * ICompletionProposal} that adds relevance and toggling the completion insertion property behavior.
+ * The abstract implementation of {@link org.eclipse.jface.text.contentassist.ICompletionProposal
+ * ICompletionProposal} which adds relevance and toggling the completion insertion property behavior.
*
- * @version 3.0
+ * @version 3.3
* @since 3.0
* @author Pascal Filion
*/
-final class JpqlCompletionProposal implements ICompletionProposal {
+abstract class JpqlCompletionProposal implements ICompletionProposal {
- private String actualQuery;
private String additionalInfo;
- private ContentAssistProposals proposals;
private int cursorOffset;
private String displayString;
- private boolean escapeCharacters;
private Image image;
- private String jpqlQuery;
+ String jpqlQuery;
private NamedQuery namedQuery;
- private int offset;
- private int position;
- private String proposal;
- private ResultQuery result;
- private boolean toggleCompletion;
+ int position;
+ String proposal;
+ ContentAssistProposals proposals;
+ ResultQuery result;
+ boolean toggleCompletion;
+ private int tokenEnd;
+ private int tokenStart;
JpqlCompletionProposal(ContentAssistProposals proposals,
String proposal,
@@ -56,27 +55,25 @@ final class JpqlCompletionProposal implements ICompletionProposal {
String additionalInfo,
Image image,
NamedQuery namedQuery,
- String actualQuery,
String jpqlQuery,
- int offset,
+ int tokenStart,
+ int tokenEnd,
int position,
- int cursorOffset,
- boolean escapeCharacters) {
+ int cursorOffset) {
super();
this.image = image;
- this.offset = offset;
+ this.tokenStart = tokenStart;
+ this.tokenEnd = tokenEnd;
this.position = position;
this.proposal = proposal;
this.jpqlQuery = jpqlQuery;
this.proposals = proposals;
this.namedQuery = namedQuery;
- this.actualQuery = actualQuery;
this.cursorOffset = cursorOffset;
this.displayString = displayString;
this.additionalInfo = additionalInfo;
- this.escapeCharacters = escapeCharacters;
}
/**
@@ -84,35 +81,19 @@ final class JpqlCompletionProposal implements ICompletionProposal {
*/
public void apply(IDocument document) {
try {
- ResultQuery result = buildResult();
- document.replace(offset, actualQuery.length(), result.getQuery());
+ document.replace(tokenStart, tokenEnd - tokenStart, getResult().getQuery());
}
catch (BadLocationException e) {
// Ignore
}
}
- private ResultQuery buildResult() {
- if (result == null) {
- if (escapeCharacters) {
- result = proposals.buildEscapedQuery(
- jpqlQuery,
- proposal,
- position,
- isCompletionInserts() ^ toggleCompletion
- );
- }
- else {
- result = proposals.buildQuery(
- jpqlQuery,
- proposal,
- position,
- isCompletionInserts() ^ toggleCompletion
- );
- }
- }
- return result;
- }
+ /**
+ * Creates
+ *
+ * @return
+ */
+ abstract ResultQuery buildResult();
/**
* {@inheritDoc}
@@ -143,14 +124,25 @@ final class JpqlCompletionProposal implements ICompletionProposal {
}
/**
+ * Returns
+ *
+ * @return
+ */
+ final ResultQuery getResult() {
+ if (result == null) {
+ result = buildResult();
+ }
+ return result;
+ }
+
+ /**
* {@inheritDoc}
*/
public Point getSelection(IDocument document) {
- ResultQuery result = buildResult();
- return new Point(offset + result.getPosition() + cursorOffset, 0);
+ return new Point(tokenStart + getResult().getPosition() + cursorOffset, 0);
}
- private boolean isCompletionInserts() {
+ final boolean isCompletionInserts() {
IJavaProject javaProject = namedQuery.getJpaProject().getJavaProject();
String value = PreferenceConstants.getPreference(PreferenceConstants.CODEASSIST_INSERT_COMPLETION, javaProject);
return Boolean.valueOf(value);
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposalComputer.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposalComputer.java
index 7517ff0c22..530173c2f9 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposalComputer.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposalComputer.java
@@ -47,6 +47,11 @@ import static org.eclipse.persistence.jpa.jpql.spi.IMappingType.*;
abstract class JpqlCompletionProposalComputer<T> {
/**
+ * The position of the cursor within the actual JPQL query (not modified).
+ */
+ int actualPosition;
+
+ /**
* The current value of the query element.
*/
String actualQuery;
@@ -73,17 +78,12 @@ abstract class JpqlCompletionProposalComputer<T> {
NamedQuery namedQuery;
/**
- * The start position of the query within the document.
- */
- int offset;
-
- /**
* The word before the position of the cursor.
*/
private String partialWord;
/**
- * The position of the cursor within {@link #actualQuery}.
+ * The position of the cursor within the adjusted JPQL query.
*/
int position;
@@ -94,6 +94,16 @@ abstract class JpqlCompletionProposalComputer<T> {
JpaJpqlQueryHelper queryHelper;
/**
+ * The end position of the query within the document.
+ */
+ int tokenEnd;
+
+ /**
+ * The start position of the query within the document.
+ */
+ int tokenStart;
+
+ /**
* Creates a new <code>JpqlCompletionProposalComputer</code>.
*/
public JpqlCompletionProposalComputer() {
@@ -219,6 +229,10 @@ abstract class JpqlCompletionProposalComputer<T> {
);
}
+ private ImageDescriptor buildImageDescriptor(String key) {
+ return JptJpaUiPlugin.instance().buildImageDescriptor(key);
+ }
+
private T buildMappingProposal(IMapping mapping) {
String proposal = mapping.getName();
return buildProposal(proposal, proposal, mappingImage(mapping));
@@ -252,19 +266,25 @@ abstract class JpqlCompletionProposalComputer<T> {
* the specified position.
*
* @param namedQuery The model object used to access the application metadata information
- * @param actualQuery The model object may sometimes be out of sync with the actual content, the
- * actual query is required for proper content assist
+ * @param actualQuery The string representation of the JPQL query that is coming from the
+ * document itself (Java source or XML)
* @param offset The beginning of the string within the document
* @param position The position of the cursor within the query, which starts at the beginning of
* that query and not the document
* @return The list of completion proposals
*/
- final List<T> buildProposals(NamedQuery namedQuery, String actualQuery, int offset, int position) {
+ final List<T> buildProposals(NamedQuery namedQuery,
+ String actualQuery,
+ int tokenStart,
+ int tokenEnd,
+ int position) {
try {
- this.offset = offset;
- this.actualQuery = actualQuery;
- this.namedQuery = namedQuery;
+ this.tokenStart = tokenStart;
+ this.tokenEnd = tokenEnd;
+ this.actualQuery = actualQuery;
+ this.actualPosition = position;
+ this.namedQuery = namedQuery;
// It's possible the string has literal representation of the escape characters, if required,
// convert them into actual escape characters and adjust the position accordingly
@@ -309,7 +329,8 @@ abstract class JpqlCompletionProposalComputer<T> {
*/
final void clearInformation() {
namedQuery = null;
- offset = -1;
+ tokenStart = -1;
+ tokenEnd = -1;
position = -1;
actualQuery = null;
namedQuery = null;
@@ -341,10 +362,6 @@ abstract class JpqlCompletionProposalComputer<T> {
return image;
}
- private ImageDescriptor buildImageDescriptor(String key) {
- return JptJpaUiPlugin.instance().buildImageDescriptor(key);
- }
-
private synchronized ImageRegistry getImageRegistry() {
if (imageRegistry == null) {
imageRegistry = new ImageRegistry(Display.getCurrent());
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlDefaultCompletionProposal.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlDefaultCompletionProposal.java
new file mode 100644
index 0000000000..8e3ee82187
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlDefaultCompletionProposal.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.persistence.jpa.jpql.ContentAssistProposals;
+import org.eclipse.persistence.jpa.jpql.ResultQuery;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * @version 3.3
+ * @since 3.3
+ * @author Pascal Filion
+ */
+final class JpqlDefaultCompletionProposal extends JpqlCompletionProposal {
+
+ JpqlDefaultCompletionProposal(ContentAssistProposals proposals,
+ String proposal,
+ String displayString,
+ String additionalInfo,
+ Image image,
+ NamedQuery namedQuery,
+ String jpqlQuery,
+ int tokenStart,
+ int tokenEnd,
+ int position,
+ int cursorOffset) {
+
+ super(proposals,
+ proposal,
+ displayString,
+ additionalInfo,
+ image,
+ namedQuery,
+ jpqlQuery,
+ tokenStart,
+ tokenEnd,
+ position,
+ cursorOffset);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ ResultQuery buildResult() {
+ return proposals.buildQuery(
+ jpqlQuery,
+ proposal,
+ position,
+ isCompletionInserts() ^ toggleCompletion
+ );
+ }
+} \ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlJavaCompletionProposal.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlJavaCompletionProposal.java
new file mode 100644
index 0000000000..a787b7a0a8
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlJavaCompletionProposal.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.persistence.jpa.jpql.ContentAssistProposals;
+import org.eclipse.persistence.jpa.jpql.ResultQuery;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * @version 3.3
+ * @since 3.3
+ * @author Pascal Filion
+ */
+final class JpqlJavaCompletionProposal extends JpqlCompletionProposal {
+
+ JpqlJavaCompletionProposal(ContentAssistProposals proposals,
+ String proposal,
+ String displayString,
+ String additionalInfo,
+ Image image,
+ NamedQuery namedQuery,
+ String jpqlQuery,
+ int tokenStart,
+ int tokenEnd,
+ int position,
+ int cursorOffset) {
+
+ super(proposals,
+ proposal,
+ displayString,
+ additionalInfo,
+ image,
+ namedQuery,
+ jpqlQuery,
+ tokenStart,
+ tokenEnd,
+ position,
+ cursorOffset);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ ResultQuery buildResult() {
+ return proposals.buildEscapedQuery(
+ jpqlQuery,
+ proposal,
+ position,
+ isCompletionInserts() ^ toggleCompletion
+ );
+ }
+} \ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlSseCompletionProposal.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlSseCompletionProposal.java
new file mode 100644
index 0000000000..992af926d7
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlSseCompletionProposal.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import java.lang.reflect.Method;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.jpt.jpa.core.jpql.XmlEscapeCharacterConverter;
+import org.eclipse.persistence.jpa.jpql.ContentAssistProposals;
+import org.eclipse.persistence.jpa.jpql.DefaultContentAssistProposals;
+import org.eclipse.persistence.jpa.jpql.ExpressionTools;
+import org.eclipse.persistence.jpa.jpql.ResultQuery;
+import org.eclipse.persistence.jpa.jpql.WordParser;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * @version 3.3
+ * @since 3.3
+ * @author Pascal Filion
+ */
+final class JpqlSseCompletionProposal extends JpqlCompletionProposal {
+
+ private boolean cDATASection;
+ private int actualPosition;
+ private String actualJpqlQuery;
+
+ JpqlSseCompletionProposal(ContentAssistProposals proposals,
+ String proposal,
+ String displayString,
+ String additionalInfo,
+ Image image,
+ NamedQuery namedQuery,
+ String jpqlQuery,
+ String actualJpqlQuery,
+ int tokenStart,
+ int tokenEnd,
+ int position,
+ int actualPosition,
+ int cursorOffset,
+ boolean cDATASection) {
+
+ super(proposals,
+ proposal,
+ displayString,
+ additionalInfo,
+ image,
+ namedQuery,
+ jpqlQuery,
+ tokenStart,
+ tokenEnd,
+ position,
+ cursorOffset);
+
+ this.actualPosition = actualPosition;
+ this.actualJpqlQuery = actualJpqlQuery;
+ this.cDATASection = cDATASection;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ ResultQuery buildResult() {
+
+ // No need to convert the JPQL query into an escaped version (like converting > into &gt;)
+ if (cDATASection) {
+ return proposals.buildQuery(
+ jpqlQuery,
+ proposal,
+ position,
+ isCompletionInserts() ^ toggleCompletion
+ );
+ }
+
+ // TODO: UPDATE ONCE THE NEXT ECLIPSELINK HERMES 2.5 MILESTONE IS AVAILABLE
+ return /*proposals.*/buildXmlQuery(
+ actualJpqlQuery,
+ proposal,
+ actualPosition,
+ isCompletionInserts() ^ toggleCompletion
+ );
+ }
+
+ /**
+ * TODO: TO DELETE ONCE USING THE NEXT ECLIPSELINK HERMES 2.5 MILESTONE
+ */
+ @SuppressWarnings("nls")
+ private ResultQuery buildXmlQuery(String jpqlQuery, String proposal, int position, boolean insert) {
+
+ // Nothing to replace
+ if (ExpressionTools.stringIsEmpty(proposal)) {
+ return proposals.buildQuery(jpqlQuery, StringTools.EMPTY_STRING, position, false);
+ }
+
+ int[] positions = { position };
+
+ // First convert the escape characters into their unicode characters
+ String query = XmlEscapeCharacterConverter.unescape(jpqlQuery, positions);
+
+ // Calculate the start and end positions
+ WordParser wordParser = new WordParser(query);
+ wordParser.setPosition(positions[0]);
+
+ // int[] proposalPositions = buildPositions(wordParser, proposal, insert);
+ int[] proposalPositions;
+ try {
+ Method buildPositionsMethod = DefaultContentAssistProposals.class.getDeclaredMethod("buildPositions", WordParser.class, String.class, boolean.class);
+ buildPositionsMethod.setAccessible(true);
+ proposalPositions = (int[]) buildPositionsMethod.invoke(proposals, wordParser, proposal, insert);
+ }
+ catch (Exception e) {
+ // This is temporary
+ proposalPositions = new int[2];
+ }
+
+ // Escape the proposal
+ proposal = XmlEscapeCharacterConverter.escape(proposal, new int[1]);
+
+ // Adjust the positions so it's in the original JPQL query, which may contain escaped characters
+ XmlEscapeCharacterConverter.reposition(jpqlQuery, proposalPositions);
+
+ // Create the new JPQL query
+ StringBuilder sb = new StringBuilder(jpqlQuery);
+ sb.replace(proposalPositions[0], proposalPositions[1], proposal);
+
+ // And simply create a new ResultQuery object
+ return proposals.buildQuery(sb.toString(), StringTools.EMPTY_STRING, proposalPositions[0] + proposal.length(), false);
+ }
+} \ No newline at end of file

Back to the top