001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.modules.xslt.mapper.methoid;
021:
022: import java.awt.Component;
023: import java.awt.Window;
024: import javax.swing.JOptionPane;
025: import org.openide.util.NbBundle;
026: import org.openide.windows.WindowManager;
027: import org.netbeans.modules.soa.mapper.common.basicmapper.IBasicMapper;
028: import org.netbeans.modules.soa.mapper.common.basicmapper.literal.ILiteralEditor;
029: import org.netbeans.modules.soa.mapper.common.basicmapper.methoid.IFieldNode;
030: import org.netbeans.modules.xml.xpath.AbstractXPathModelHelper;
031: import org.netbeans.modules.xml.xpath.XPathException;
032: import org.netbeans.modules.xml.xpath.XPathExpression;
033: import org.netbeans.modules.xml.xpath.XPathModel;
034: import org.netbeans.modules.xml.xpath.XPathStringLiteral;
035: import org.netbeans.modules.xslt.mapper.xpatheditor.XPathLiteralEditor;
036: import org.netbeans.modules.xslt.mapper.model.nodes.LiteralCanvasNode;
037:
038: /**
039: * Updates the xpath expression for string literals.
040: *
041: * @author jsandusky
042: */
043: public class XPathLiteralUpdater extends AbstractLiteralUpdater {
044:
045: public ILiteralEditor getEditor(IBasicMapper basicMapper,
046: IFieldNode field) {
047: return new XPathLiteralEditor(getWindowOwner(basicMapper),
048: basicMapper, field, this );
049: }
050:
051: private static Window getWindowOwner(IBasicMapper basicMapper) {
052: Window window = null;
053: Component parent = basicMapper.getMapperViewManager()
054: .getCanvasView().getCanvas().getUIComponent();
055: while (parent != null && !(parent instanceof Window)) {
056: parent = parent.getParent();
057: }
058: if (parent == null) {
059: parent = WindowManager.getDefault().getMainWindow();
060: }
061: return (Window) parent;
062: }
063:
064: public String getLiteralDisplayText(String literalText) {
065: return getQuotedString(literalText).string;
066: }
067:
068: public String literalSet(IFieldNode fieldNode, String newValue) {
069: if (!isValidStringLiteral(newValue)) {
070: String title = NbBundle.getMessage(
071: StringLiteralUpdater.class,
072: "STR_INVALID_STRING_LITERAL_TITLE"); // NOI18N
073: String msg = NbBundle.getMessage(
074: StringLiteralUpdater.class,
075: "STR_INVALID_STRING_LITERAL_MSG", newValue); // NOI18N
076: JOptionPane.showMessageDialog(WindowManager.getDefault()
077: .getMainWindow(), msg, title,
078: JOptionPane.ERROR_MESSAGE);
079: return null;
080: }
081: // TODO reimplement
082: // XPathLiteralNodeImpl literalNode = (XPathLiteralNodeImpl) fieldNode.getNodeObject();
083: // if (literalNode == null) {
084: // XPathStringLiteral stringLiteral = AbstractXPathModelHelper.getInstance().newXPathStringLiteral(newValue);
085: // literalNode = new XPathLiteralNodeImpl(stringLiteral);
086: // } else {
087: // XPathStringLiteral stringLiteral = (XPathStringLiteral) literalNode.getLiteral();
088: // stringLiteral.setValue(newValue);
089: // }
090: // super.applyLiteral(fieldNode, newValue, literalNode);
091:
092: LiteralCanvasNode literalNode = (LiteralCanvasNode) fieldNode
093: .getGroupNode().getNodeObject();
094: if (literalNode != null) {
095: XPathExpression newXPathExpr = null;
096: XPathModel xpModel = AbstractXPathModelHelper.getInstance()
097: .newXPathModel();
098: try {
099: newXPathExpr = xpModel.parseExpression(newValue);
100: } catch (XPathException xpe) {
101: newXPathExpr = AbstractXPathModelHelper.getInstance()
102: .newXPathStringLiteral(newValue);
103: }
104: //
105: if (newXPathExpr != null) {
106: literalNode.setDataObject(newXPathExpr);
107: }
108: }
109: mProcessor.updateNodeExpression(fieldNode);
110:
111: return newValue;
112: }
113:
114: private boolean isValidStringLiteral(String literal) {
115: // by this point, string is quoted
116: // now we validate that the string follows xpath 1.0 spec
117: // - josh
118: QuotedString quotedString = getQuotedString(literal);
119: return quotedString.quote.isQuotingValid(quotedString.string);
120:
121: }
122:
123: private QuotedString getQuotedString(String literal) {
124: QuoteType quoteType = QuoteType.getQuoteType(literal);
125: if (quoteType == QuoteType.UNQUOTED) {
126: if (literal.indexOf(QuoteType.SINGLE.quote) >= 0) {
127: // string contains a single-quote,
128: // it must be quoted with double-quotes
129: literal = QuoteType.DOUBLE.quote + literal
130: + QuoteType.DOUBLE.quote;
131: quoteType = QuoteType.DOUBLE;
132: } else {
133: // by default, single-quote the string
134: literal = QuoteType.SINGLE.quote + literal
135: + QuoteType.SINGLE.quote;
136: quoteType = QuoteType.SINGLE;
137: }
138: }
139: return new QuotedString(literal, quoteType);
140: }
141:
142: private static final class QuotedString {
143: public final String string;
144: public final QuoteType quote;
145:
146: public QuotedString(String quotedString, QuoteType quoteType) {
147: string = quotedString;
148: quote = quoteType;
149: }
150: }
151:
152: private static final class QuoteType {
153: private static final QuoteType SINGLE = new QuoteType("'"); // NOI18N
154: private static final QuoteType DOUBLE = new QuoteType("\""); // NOI18N
155: private static final QuoteType UNQUOTED = new QuoteType();
156: public final String quote;
157:
158: private QuoteType(String quoteString) {
159: quote = quoteString;
160: }
161:
162: private QuoteType() {
163: quote = null;
164: }
165:
166: public boolean isStringQuoted(String literal) {
167: if (quote == null) {
168: return false;
169: }
170: if (literal.length() >= 2) {
171: if (literal.startsWith(quote)
172: && literal.endsWith(quote)) {
173: return true;
174: }
175: }
176: return false;
177: }
178:
179: public boolean isQuotingValid(String literal) {
180: if (quote == null) {
181: return false;
182: }
183: // ensure that we have only our beginning quote and end quote
184: // any more than that and our number of sections will be greater than 3
185: // any less than that and our number of sections will be less than 3
186: String[] quoteSections = literal.split(quote, 4);
187: return quoteSections.length == 3;
188: }
189:
190: public static QuoteType getQuoteType(String literal) {
191: QuoteType quoteType = UNQUOTED;
192: // if string is already quoted, mark as such
193: if (SINGLE.isStringQuoted(literal)) {
194: quoteType = SINGLE;
195: } else if (DOUBLE.isStringQuoted(literal)) {
196: quoteType = DOUBLE;
197: }
198: return quoteType;
199: }
200: }
201: }
|