| author | Nan Li | 2012-09-24 16:57:50 (EDT) |
|---|---|---|
| committer | Brian Vosburgh | 2012-09-24 17:40:40 (EDT) |
| commit | 93ea11f7623b388b2c1149b7ff66b6e10fb57c1a (patch) (side-by-side diff) | |
| tree | 0a5fe57605bd3b564aed13855a7d5092e973fc9f | |
| parent | 8741e266f5eb8aea773ae450fec7722772220423 (diff) | |
| download | webtools.dali-93ea11f7623b388b2c1149b7ff66b6e10fb57c1a.zip webtools.dali-93ea11f7623b388b2c1149b7ff66b6e10fb57c1a.tar.gz webtools.dali-93ea11f7623b388b2c1149b7ff66b6e10fb57c1a.tar.bz2 | |
[382644] XML code assist for database identifiers with special
characters
4 files changed, 143 insertions, 35 deletions
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/StringTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/StringTools.java index 6e27dbe..affdf30 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/StringTools.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/StringTools.java @@ -36,7 +36,13 @@ public final class StringTools { /** XML double quote */ public static final String XML_QUOTE = """; //$NON-NLS-1$ - + + /** XML apostrophe */ + public static final String XML_APOSTROPHE = "'"; + + /** XML ampersand */ + public static final String XML_AMPERSAND = "&"; + /** parenthesis */ public static final char OPEN_PARENTHESIS = '('; public static final char CLOSE_PARENTHESIS = ')'; @@ -53,6 +59,10 @@ public final class StringTools { public static final char OPEN_CHEVRON = '<'; public static final char CLOSE_CHEVRON = '>'; + /** XML angle brackets */ + public static final String XML_OPEN_CHEVRON= "<"; + public static final String XML_CLOSE_CHEVRON = ">"; + /** empty string */ public static final String EMPTY_STRING = ""; //$NON-NLS-1$ @@ -5140,32 +5150,76 @@ public final class StringTools { // ********** convert to XML string literal ********** public static String convertToXmlStringLiteral(String string) { + return convertToXmlStringLiteralQuote(string); + } + + public static String convertToXmlStringLiteralQuote(String string) { + return convertToXmlStringLiteral(string, '"'); + } + + public static String convertToXmlStringLiteralApostrophe(String string) { + return convertToXmlStringLiteral(string, '\''); + } + + public static String convertToXmlStringLiteral(String string, char delimiter) { int len = string.length(); if (len == 0) { return EMPTY_JAVA_STRING_LITERAL; } StringBuilder sb = new StringBuilder(len + 5); - convertToXmlStringLiteralOn_(string.toCharArray(), sb, len); + convertToXmlStringLiteralOn_(string.toCharArray(), sb, len, delimiter); return sb.toString(); } - //TODO need to add the rest of the predifende entities to this switch (amp, apos, lt, and gt) - private static void convertToXmlStringLiteralOn_(char[] string, StringBuilder sb, int len) { + //TODO need to add the rest of the predifende entities to this switch (amp, lt, and gt) + private static void convertToXmlStringLiteralOn_(char[] string, StringBuilder sb, int len, char delimiter) { sb.ensureCapacity(sb.length() + len + 5); - sb.append(QUOTE); + sb.append(delimiter); for (char c : string) { switch (c) { case '"': // double-quote - sb.append(XML_QUOTE); - break; + sb.append((delimiter == '"') ? XML_QUOTE : '"'); + break; + case '\'': // apostrophe + sb.append((delimiter == '\'') ? XML_APOSTROPHE : '\''); + break; default: sb.append(c); break; } } - sb.append(QUOTE); + sb.append(delimiter); } + public static String convertToXmlElementStringLiteral(String string) { + int len = string.length(); + if (len == 0) { + return EMPTY_JAVA_STRING_LITERAL; + } + StringBuilder sb = new StringBuilder(len + 5); + convertToXmlElementStringLiteralOn_(string.toCharArray(), sb, len); + return sb.toString(); + } + + private static void convertToXmlElementStringLiteralOn_(char[] string, StringBuilder sb, int len) { + sb.ensureCapacity(sb.length() + len + 5); + for (char c : string) { + switch (c) { + case '&': // ampersand + sb.append(XML_AMPERSAND); + break; + case '<': // less-than sign + sb.append(XML_OPEN_CHEVRON); + break; + case '>': // greater-than sign + sb.append(XML_CLOSE_CHEVRON); + break; + default: + sb.append(c); + break; + } + } + } // ********** convenience ********** diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui.properties b/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui.properties index 85e4283..fff5c3a 100644 --- a/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui.properties +++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui.properties @@ -206,3 +206,5 @@ SelectJpaProjectWizardPage_msg=Select a JPA project. SynchronizingClasses_TaskName=Synchronizing classes... SetJpaSelection_jobName=Setting JPA selection... + +JpaXmlCompletionProposalComputer_SpecialNameMsg=Special name will be written in the XML differently from what is shown in the proposal list for its legal usage. diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JpaXmlCompletionProposalComputer.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JpaXmlCompletionProposalComputer.java index 64d9265..b107ac9 100644 --- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JpaXmlCompletionProposalComputer.java +++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JpaXmlCompletionProposalComputer.java @@ -29,13 +29,11 @@ import org.eclipse.jpt.jpa.core.JpaStructureNode; import org.eclipse.jpt.jpa.core.context.XmlFile; import org.eclipse.jpt.jpa.ui.internal.plugin.JptJpaUiPlugin; import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext; -import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; import org.eclipse.wst.xml.ui.internal.XMLUIMessages; import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest; -import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -50,21 +48,21 @@ public class JpaXmlCompletionProposalComputer extends DefaultJpaXmlCompletionPro public JpaXmlCompletionProposalComputer() { } - @Override - public List<ICompletionProposal> computeCompletionProposals( - CompletionProposalInvocationContext context, - IProgressMonitor monitor) { - try { - return super.computeCompletionProposals(context, monitor); - } catch (RuntimeException ex) { - // When we run into any unexpected exception, we will log the exception - // and then return an empty list to prevent code completion process from - // crashing. We need to determine if runtime exceptions should be - // expected. If so, we could remove the log(ex) in the future. - JptJpaUiPlugin.instance().logError(ex); - return Collections.emptyList(); - } + @Override + public List<ICompletionProposal> computeCompletionProposals( + CompletionProposalInvocationContext context, + IProgressMonitor monitor) { + try { + return super.computeCompletionProposals(context, monitor); + } catch (RuntimeException ex) { + // When we run into any unexpected exception, we will log the exception + // and then return an empty list to prevent code completion process from + // crashing. We need to determine if runtime exceptions should be + // expected. If so, we could remove the log(ex) in the future. + JptJpaUiPlugin.instance().logError(ex); + return Collections.emptyList(); } + } @Override protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest, @@ -77,17 +75,53 @@ public class JpaXmlCompletionProposalComputer extends DefaultJpaXmlCompletionPro if (matchString == null) { matchString = ""; //$NON-NLS-1$ } + + // initialize newMatchingString to an empty string to handle the case when user invokes code assist without giving delimiter + String newMatchString = ""; if ((matchString.length() > 0) && (matchString.startsWith("\"") || matchString.startsWith("'"))) { //$NON-NLS-1$ //$NON-NLS-2$ - matchString = matchString.substring(1); + newMatchString = matchString.substring(1); } - //create suggestions for this attribute value declaration + //create completion proposals for this attribute value declaration int rOffset = contentAssistRequest.getReplacementBeginPosition(); int rLength = contentAssistRequest.getReplacementLength(); for (String possibleValue : proposedValues) { - if ((matchString.length() == 0) || StringTools.stringStartsWithIgnoreCase(possibleValue, matchString)) { - String rString = "\"" + possibleValue + "\""; //$NON-NLS-1$ //$NON-NLS-2$ - CompletionProposal proposal = new CompletionProposal( - rString, rOffset, rLength, rString.length()); + if ((newMatchString.length() == 0) || StringTools.stringStartsWithIgnoreCase(possibleValue, newMatchString)) { + + // handle values that include special characters like double-quote or apostrophe + String convertedPossibleValue = null; + if (matchString.startsWith("\"")) { + convertedPossibleValue = StringTools.convertToXmlStringLiteralQuote(possibleValue); + } else if (matchString.startsWith("'")) { + convertedPossibleValue = StringTools.convertToXmlStringLiteralApostrophe(possibleValue); + } else { + // convert to XML string literal with quotes by default + convertedPossibleValue = StringTools.convertToXmlStringLiteralQuote(possibleValue); + } + + CompletionProposal proposal = null; + // give users an additional message if value includes special characters since what is written + // to XML is most likely different from what is shown in the proposal list with this case + if (possibleValue.startsWith("\"")) { + // handle the case when user does ""<invoke code assist here>" trying to get these special values + // User cannot do ""F<invoke code assist here>" or ""F<invoke code assist here>"" trying to + // get these values that are special and start with F because XML would regard the F as the + // start of another attribute since there are two double-quotes exist before F. + if (matchString.startsWith("\"") && newMatchString.startsWith("\"")) { + proposal = new CompletionProposal( + convertedPossibleValue, rOffset, rLength + 1, convertedPossibleValue.length(), null, + possibleValue, null, JptUiMessages.JpaXmlCompletionProposalComputer_SpecialNameMsg); + } else { + proposal = new CompletionProposal( + convertedPossibleValue, rOffset, rLength, convertedPossibleValue.length(), null, + possibleValue, null, JptUiMessages.JpaXmlCompletionProposalComputer_SpecialNameMsg); + } + } else { + // do not give the addition message with normal values + proposal = new CompletionProposal( + convertedPossibleValue, rOffset, rLength, convertedPossibleValue.length(), null, + possibleValue, null, null ); + } + contentAssistRequest.addProposal(proposal); } } @@ -141,11 +175,27 @@ public class JpaXmlCompletionProposalComputer extends DefaultJpaXmlCompletionPro } for (String possibleValue : proposedValues) { + + String convertedPossibleValue = null; if ((matchString.length() == 0) || StringTools.stringStartsWithIgnoreCase(possibleValue, matchString)) { - CustomCompletionProposal proposal = new CustomCompletionProposal( - possibleValue, begin, length, possibleValue.length(), - JptJpaUiPlugin.instance().getImage(JptUiIcons.JPA_CONTENT), - possibleValue, null, null, XMLRelevanceConstants.R_TAG_INSERTION); + if (possibleValue.startsWith("\"")) { + convertedPossibleValue = StringTools.convertToXmlElementStringLiteral(possibleValue); + } else { + convertedPossibleValue = possibleValue; + } + + CompletionProposal proposal = null; + if (possibleValue.startsWith("\"")) { + proposal = new CompletionProposal( + convertedPossibleValue, begin, length, convertedPossibleValue.length(), + JptJpaUiPlugin.instance().getImage(JptUiIcons.JPA_CONTENT), possibleValue, null, + JptUiMessages.JpaXmlCompletionProposalComputer_SpecialNameMsg); + } else { + proposal = new CompletionProposal( + convertedPossibleValue, begin, length, convertedPossibleValue.length(), + JptJpaUiPlugin.instance().getImage(JptUiIcons.JPA_CONTENT), possibleValue, null, null); + } + contentAssistRequest.addProposal(proposal); } } @@ -154,7 +204,7 @@ public class JpaXmlCompletionProposalComputer extends DefaultJpaXmlCompletionPro setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_); } } - + /** * Retrieves all of the possible valid values for this attribute/element declaration */ diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiMessages.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiMessages.java index eb4c5ef..521c432 100644 --- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiMessages.java +++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiMessages.java @@ -193,6 +193,8 @@ public class JptUiMessages { public static String JavaQueryConversionWizardPage_description; public static String SetJpaSelection_jobName; + + public static String JpaXmlCompletionProposalComputer_SpecialNameMsg; private JptUiMessages() { throw new UnsupportedOperationException(); |

