001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.xml.xpath.impl;
043:
044: import java.util.ArrayList;
045: import java.util.Iterator;
046: import java.util.logging.Level;
047: import java.util.logging.Logger;
048: import javax.xml.namespace.QName;
049:
050: import org.apache.commons.jxpath.JXPathException;
051: import org.apache.commons.jxpath.ri.Compiler;
052: import org.apache.commons.jxpath.ri.Parser;
053: import org.apache.commons.jxpath.ri.compiler.Constant;
054: import org.apache.commons.jxpath.ri.compiler.CoreFunction;
055: import org.apache.commons.jxpath.ri.compiler.CoreOperation;
056: import org.apache.commons.jxpath.ri.compiler.CoreOperationAdd;
057: import org.apache.commons.jxpath.ri.compiler.CoreOperationAnd;
058: import org.apache.commons.jxpath.ri.compiler.CoreOperationDivide;
059: import org.apache.commons.jxpath.ri.compiler.CoreOperationEqual;
060: import org.apache.commons.jxpath.ri.compiler.CoreOperationGreaterThan;
061: import org.apache.commons.jxpath.ri.compiler.CoreOperationGreaterThanOrEqual;
062: import org.apache.commons.jxpath.ri.compiler.CoreOperationLessThan;
063: import org.apache.commons.jxpath.ri.compiler.CoreOperationLessThanOrEqual;
064: import org.apache.commons.jxpath.ri.compiler.CoreOperationMod;
065: import org.apache.commons.jxpath.ri.compiler.CoreOperationMultiply;
066: import org.apache.commons.jxpath.ri.compiler.CoreOperationNegate;
067: import org.apache.commons.jxpath.ri.compiler.CoreOperationNotEqual;
068: import org.apache.commons.jxpath.ri.compiler.CoreOperationOr;
069: import org.apache.commons.jxpath.ri.compiler.CoreOperationSubtract;
070: import org.apache.commons.jxpath.ri.compiler.Expression;
071: import org.apache.commons.jxpath.ri.compiler.ExpressionPath;
072: import org.apache.commons.jxpath.ri.compiler.ExtensionFunction;
073: import org.apache.commons.jxpath.ri.compiler.LocationPath;
074: import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
075: import org.apache.commons.jxpath.ri.compiler.NodeTest;
076: import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
077: import org.apache.commons.jxpath.ri.compiler.Step;
078: import org.apache.commons.jxpath.ri.compiler.TreeCompiler;
079: import org.apache.commons.jxpath.ri.compiler.VariableReference;
080: import org.netbeans.modules.xml.xpath.AbstractXPathModelHelper;
081: import org.netbeans.modules.xml.xpath.LocationStep;
082: import org.netbeans.modules.xml.xpath.StepNodeTest;
083: import org.netbeans.modules.xml.xpath.StepNodeNameTest;
084: import org.netbeans.modules.xml.xpath.StepNodeTypeTest;
085: import org.netbeans.modules.xml.xpath.XPathCoreFunction;
086: import org.netbeans.modules.xml.xpath.XPathCoreOperation;
087: import org.netbeans.modules.xml.xpath.XPathException;
088: import org.netbeans.modules.xml.xpath.XPathExpression;
089: import org.netbeans.modules.xml.xpath.XPathExpressionPath;
090: import org.netbeans.modules.xml.xpath.XPathLocationPath;
091: import org.netbeans.modules.xml.xpath.XPathModel;
092: import org.netbeans.modules.xml.xpath.XPathNumericLiteral;
093: import org.netbeans.modules.xml.xpath.XPathOperationOrFuntion;
094: import org.netbeans.modules.xml.xpath.XPathPredicateExpression;
095: import org.netbeans.modules.xml.xpath.common.MessageManager;
096:
097: /**
098: * Implementation of the XPathModel interface using Apache's JXPath.
099: * JXPath does not validate function arguments, i.e., whether the
100: * number of arguments is correct, so we may have to do that validation
101: * ourselves or wait for a later version.
102: * <p>
103: * We also implement extensions to handle
104: * <a href="http://www-106.ibm.com/developerworks/webservices/library/ws-bpel/#Expressions">
105: * expressions in BPEL4WS</a>.
106: *
107: * @author Enrico Lelina
108: * @version
109: */
110: public class XPathModelImpl implements XPathModel {
111:
112: /** The XPath tree compiler. */
113: private Compiler mCompiler;
114:
115: /** The logger. */
116: private static final Logger mLogger = Logger
117: .getLogger(XPathModelImpl.class.getName());
118:
119: /** The message manager. */
120: private static MessageManager mMsgMgr = MessageManager
121: .getManager(XPathModelImpl.class);
122:
123: /** Instantiates a new object. */
124: public XPathModelImpl() {
125: mCompiler = new XPathTreeCompiler();
126: }
127:
128: /**
129: * Parses an XPath expression.
130: * @param expression the XPath expression to parse
131: * @return an instance of XPathExpression
132: * @throws XPathException for any parsing errors
133: */
134: public XPathExpression parseExpression(String expression)
135: throws XPathException {
136: try {
137: Object expr = Parser.parseExpression(expression, mCompiler);
138: if (expr instanceof Expression) {
139: return processExpression((Expression) expr);
140: } else {
141: XPathException xpe = new XPathException(mMsgMgr
142: .getString("Unhandled_XPath_Expression",
143: expression, expr.toString()));
144: mLogger.log(Level.FINEST, "parseExpression", xpe);
145: throw xpe;
146: }
147: } catch (JXPathException jxe) {
148: mLogger.log(Level.FINEST, "parseExpression", jxe);
149: throw new XPathException(jxe);
150: }
151: }
152:
153: /**
154: * Processes the parsed expression to build an XPathExpression.
155: * @param expression the parsed expression
156: * @return an instance of XPathExpression
157: * @throws XPathException for any errors
158: */
159: XPathExpression processExpression(Expression expression)
160: throws XPathException {
161: if (expression instanceof LocationPath) {
162: return processLocationPath((LocationPath) expression);
163: } else if (expression instanceof CoreFunction) {
164: return processCoreFunction((CoreFunction) expression);
165: } else if (expression instanceof ExtensionFunction) {
166: return processExtensionFunction((ExtensionFunction) expression);
167: } else if (expression instanceof CoreOperation) {
168: return processCoreOperation((CoreOperation) expression);
169: } else if (expression instanceof Constant) {
170: return processConstant((Constant) expression);
171: } else if (expression instanceof VariableReference) {
172: return processVariableReference((VariableReference) expression);
173: } else if (expression instanceof ExpressionPath) {
174: return processExpressionPath((ExpressionPath) expression);
175: } else {
176: XPathException xpe = new XPathException(mMsgMgr.getString(
177: "Unhandled_Expression_Type", expression.toString()));
178: mLogger.log(Level.FINEST, "processExpression", xpe);
179: throw xpe;
180: }
181: }
182:
183: XPathExpression processVariableReference(VariableReference varRef)
184: throws XPathException {
185:
186: // String qNameStr = varRef.getVariableName().toString();
187: // QName varQName = QName.valueOf(qNameStr);
188: //String name = QName.getQNameFromString(qName).toString();
189: return AbstractXPathModelHelper.getInstance()
190: .newXPathVariableReference(varRef);
191: }
192:
193: /**
194: * Processes a Constant expression.
195: * @param constant the constant
196: * @return the constant expression
197: * @throws XPathException for any errors
198: */
199: XPathExpression processConstant(Constant constant)
200: throws XPathException {
201: Object value = constant.computeValue(null);
202: XPathExpression xpexpr;
203:
204: if (value instanceof String) {
205: xpexpr = AbstractXPathModelHelper.getInstance()
206: .newXPathStringLiteral((String) value);
207: } else if (value instanceof Number) {
208: xpexpr = AbstractXPathModelHelper.getInstance()
209: .newXPathNumericLiteral((Number) value);
210: } else {
211: XPathException xpe = new XPathException(mMsgMgr.getString(
212: "Invalid_XPath_Constant", value));
213: mLogger.log(Level.FINEST, "processConstant", xpe);
214: throw xpe;
215: }
216:
217: mLogger.finer("constant=" + constant + " value=" + value);
218:
219: return xpexpr;
220: }
221:
222: /**
223: * Processes a CoreFunction expression. Converts the CoreFunction into an
224: * XPathExpression and then adds it into the list of values. Then each
225: * argument of the CoreFunction is processed.
226: * @param coreFunction the core function
227: * @return the core function expression
228: * @throws XPathException for any errors
229: */
230: XPathExpression processCoreFunction(CoreFunction coreFunction)
231: throws XPathException {
232: int code = getCoreFunctionCode(coreFunction);
233: Expression[] arguments = coreFunction.getArguments();
234:
235: if (-1 == code) {
236: XPathException xpe = new XPathException(mMsgMgr
237: .getString("Unhandled_XPath_Function", coreFunction
238: .toString()));
239: mLogger.log(Level.FINEST, "processCoreFunction", xpe);
240: throw xpe;
241: }
242:
243: XPathOperationOrFuntion xpexpr = AbstractXPathModelHelper
244: .getInstance().newXPathCoreFunction(code);
245:
246: // Process the arguments, if any.
247: if (arguments != null) {
248: for (int i = 0; i < arguments.length; i++) {
249: xpexpr.addChild(processExpression(arguments[i]));
250: }
251: }
252:
253: mLogger.finer("coreFunction=" + coreFunction);
254:
255: return xpexpr;
256: }
257:
258: /**
259: * Processes a CoreOperation expression. Converts the CoreOperation into an
260: * XPathExpression and then adds it into the list of values. Then each
261: * argument of the CoreOperation is processed.
262: * @param coreOperation the core operation
263: * @return the core operation expression
264: * @throws XPathException for any errors
265: */
266: XPathExpression processCoreOperation(CoreOperation coreOperation)
267: throws XPathException {
268: int code = getCoreOperationCode(coreOperation);
269: Expression[] arguments = coreOperation.getArguments();
270:
271: if (-1 == code) {
272: XPathException xpe = new XPathException(mMsgMgr.getString(
273: "Unhandled_XPath_Operator", coreOperation
274: .toString()));
275: mLogger.log(Level.FINEST, "processCoreOperation", xpe);
276: throw xpe;
277: }
278:
279: XPathOperationOrFuntion xpexpr = AbstractXPathModelHelper
280: .getInstance().newXPathCoreOperation(code);
281:
282: // Process the arguments. All core operations require arguments.
283: // If arguments is null, it means there is a bug -- the error
284: // should have been caught in parse expression.
285: for (int i = 0; i < arguments.length; i++) {
286: xpexpr.addChild(processExpression(arguments[i]));
287: }
288:
289: mLogger.finer("coreOperation=" + coreOperation);
290:
291: return xpexpr;
292: }
293:
294: /**
295: * Processes an ExtensionFunction expression. Converts the ExtensionFunction
296: * into an XPathExpression and then adds it into the list of values. Then
297: * each argument of the ExtensionFunction is processed.
298: * @param extensionFunction the extension function
299: * @return the extension function expression
300: * @throws XPathException for any errors
301: */
302: XPathExpression processExtensionFunction(
303: ExtensionFunction extensionFunction) throws XPathException {
304: String name = extensionFunction.getFunctionName().toString();
305: Expression[] arguments = extensionFunction.getArguments();
306:
307: if (null == name) {
308: XPathException xpe = new XPathException(mMsgMgr.getString(
309: "Unhandled_XPath_Function", extensionFunction
310: .toString()));
311: mLogger.log(Level.FINEST, "processExtensionFunction", xpe);
312: throw xpe;
313: } else if (!isValidFunction(name)) {
314: XPathException xpe = new XPathException(mMsgMgr.getString(
315: "Invalid_XPath_Function", extensionFunction
316: .toString()));
317: mLogger.log(Level.FINEST, "processExtensionFunction", xpe);
318: throw xpe;
319: }
320:
321: XPathOperationOrFuntion xpexpr = AbstractXPathModelHelper
322: .getInstance().newXPathExtensionFunction(name);
323:
324: // Process the arguments, if any.
325: if (arguments != null) {
326: for (int i = 0; i < arguments.length; i++) {
327: xpexpr.addChild(processExpression(arguments[i]));
328: }
329: }
330:
331: mLogger.finer("extensionFunction=" + extensionFunction
332: + " name=" + name);
333:
334: return xpexpr;
335: }
336:
337: /**
338: * Processes a LocationPath expression. Converts the LocationPath into a
339: * TreePath whose components are nodes in the given schema model. Adds the
340: * TreePath into the list of values. Each step in the location path is
341: * equivalent to a TreePath component. TO DO: handle predicates! TO DO:
342: * special handling for relative paths!
343: * @param locationPath the location path
344: * @return the location path expression
345: * @throws XPathException for any errors
346: */
347: XPathExpression processLocationPath(LocationPath locationPath)
348: throws XPathException {
349: Step[] steps = locationPath.getSteps();
350:
351: ArrayList stepList = new ArrayList();
352: if (steps != null) {
353: for (int i = 0; i < steps.length; i++) {
354: stepList.add(processStep(steps[i]));
355: }
356: }
357:
358: LocationStep[] locSteps = new LocationStepImpl[stepList.size()];
359: Iterator iter = stepList.iterator();
360: for (int i = 0; iter.hasNext(); i++) {
361: locSteps[i] = (LocationStep) iter.next();
362: }
363:
364: XPathLocationPath path = AbstractXPathModelHelper.getInstance()
365: .newXPathLocationPath(locSteps);
366: path.setAbsolute(locationPath.isAbsolute());
367: path.setSimplePath(locationPath.isSimplePath());
368:
369: return path;
370: }
371:
372: /**
373: * Processes a ExpressionPath expression. Converts the ExpressionPath into a
374: * TreePath whose components are nodes in the given schema model. Adds the
375: * TreePath into the list of values. Each step in the location path is
376: * equivalent to a TreePath component. TO DO: handle predicates! TO DO:
377: * special handling for relative paths!
378: * @param expressionPath the location path
379: * @return the expression path expression
380: * @throws XPathException for any errors
381: */
382: XPathExpression processExpressionPath(ExpressionPath expressionPath)
383: throws XPathException {
384: Expression rootExpression = expressionPath.getExpression();
385: XPathExpression rExpression = null;
386: if (rootExpression != null) {
387: rExpression = processExpression(rootExpression);
388: }
389:
390: Step[] steps = expressionPath.getSteps();
391:
392: ArrayList stepList = new ArrayList();
393: if (steps != null) {
394: for (int i = 0; i < steps.length; i++) {
395: stepList.add(processStep(steps[i]));
396: }
397: }
398:
399: LocationStep[] locSteps = new LocationStepImpl[stepList.size()];
400: Iterator iter = stepList.iterator();
401: for (int i = 0; iter.hasNext(); i++) {
402: locSteps[i] = (LocationStep) iter.next();
403: }
404:
405: XPathExpressionPath path = AbstractXPathModelHelper
406: .getInstance().newXPathExpressionPath(rExpression,
407: locSteps);
408: path.setSimplePath(expressionPath.isSimplePath());
409:
410: return path;
411: }
412:
413: /**
414: * Processes a step in a location path.
415: * @param step the step in the location path
416: * @return the location step
417: * @throws XPathException for any errors
418: */
419: LocationStep processStep(Step step) throws XPathException {
420: int axis = getAxis(step.getAxis());
421: NodeTest nodeTest = step.getNodeTest();
422: Expression[] predicates = step.getPredicates();
423: String name = null;
424: StepNodeTest stepNodeTest = null;
425:
426: if (nodeTest instanceof NodeNameTest) {
427: stepNodeTest = new StepNodeNameTest(
428: ((NodeNameTest) nodeTest).getNodeName().toString());
429: } else if (nodeTest instanceof NodeTypeTest) {
430: stepNodeTest = new StepNodeTypeTest(
431: getNodeType(((NodeTypeTest) nodeTest).getNodeType()));
432: } else {
433: XPathException xpe = new XPathException(mMsgMgr.getString(
434: "Invalid_Location_Step", step.toString()));
435: mLogger.log(Level.FINEST, "processStep", xpe);
436: throw xpe;
437: }
438:
439: XPathPredicateExpression[] xpathPredicateExpressions = null;
440: if (predicates != null && predicates.length > 0) {
441: XPathExpression[] xpathPredicates = null;
442: xpathPredicates = new XPathExpression[predicates.length];
443: xpathPredicateExpressions = new XPathPredicateExpression[predicates.length];
444: for (int i = 0, length = predicates.length; i < length; i++) {
445: xpathPredicates[i] = processExpression(predicates[i]);
446: if (xpathPredicates[i] instanceof XPathNumericLiteral) {
447: xpathPredicates[i] = AbstractXPathModelHelper
448: .getInstance()
449: .newXPathPredicateNumericLiteral(
450: new Long(
451: ((XPathNumericLiteral) xpathPredicates[i])
452: .getValue()
453: .longValue()));
454: }
455:
456: //now wrap expression which are predicates inside XPathPredicateExpression
457: xpathPredicateExpressions[i] = AbstractXPathModelHelper
458: .getInstance().newXPathPredicateExpression(
459: xpathPredicates[i]);
460: }
461: }
462: return new LocationStepImpl(axis, stepNodeTest,
463: xpathPredicateExpressions);
464: }
465:
466: /**
467: * Gets the axis.
468: * @param code the axis code
469: * @return the axis type or -1 if invalid
470: */
471: int getAxis(int code) {
472: switch (code) {
473: case Compiler.AXIS_SELF:
474: return LocationStep.AXIS_SELF;
475: case Compiler.AXIS_CHILD:
476: return LocationStep.AXIS_CHILD;
477: case Compiler.AXIS_PARENT:
478: return LocationStep.AXIS_PARENT;
479: case Compiler.AXIS_ANCESTOR:
480: return LocationStep.AXIS_ANCESTOR;
481: case Compiler.AXIS_ATTRIBUTE:
482: return LocationStep.AXIS_ATTRIBUTE;
483: case Compiler.AXIS_NAMESPACE:
484: return LocationStep.AXIS_NAMESPACE;
485: case Compiler.AXIS_PRECEDING:
486: return LocationStep.AXIS_PRECEDING;
487: case Compiler.AXIS_FOLLOWING:
488: return LocationStep.AXIS_FOLLOWING;
489: case Compiler.AXIS_DESCENDANT:
490: return LocationStep.AXIS_DESCENDANT;
491: case Compiler.AXIS_ANCESTOR_OR_SELF:
492: return LocationStep.AXIS_ANCESTOR_OR_SELF;
493: case Compiler.AXIS_DESCENDANT_OR_SELF:
494: return LocationStep.AXIS_DESCENDANT_OR_SELF;
495: case Compiler.AXIS_FOLLOWING_SIBLING:
496: return LocationStep.AXIS_FOLLOWING_SIBLING;
497: case Compiler.AXIS_PRECEDING_SIBLING:
498: return LocationStep.AXIS_PRECEDING_SIBLING;
499: }
500:
501: return -1;
502: }
503:
504: /**
505: * Gets the node type.
506: * @param code the node type code
507: * @return the node type or -1 if invalid
508: */
509: int getNodeType(int code) {
510: switch (code) {
511: case Compiler.NODE_TYPE_NODE:
512: return LocationStep.NODETYPE_NODE;
513: case Compiler.NODE_TYPE_TEXT:
514: return LocationStep.NODETYPE_TEXT;
515: case Compiler.NODE_TYPE_COMMENT:
516: return LocationStep.NODETYPE_COMMENT;
517: case Compiler.NODE_TYPE_PI:
518: return LocationStep.NODETYPE_PI;
519: }
520:
521: return -1;
522: }
523:
524: /**
525: * Gets the core function code
526: * @param coreFunction the core function
527: * @return the function code or -1 if invalid
528: * @throws XPathException invalid operation
529: */
530: int getCoreFunctionCode(CoreFunction coreFunction) {
531: int code = coreFunction.getFunctionCode();
532:
533: switch (code) {
534: case Compiler.FUNCTION_LAST:
535: return XPathCoreFunction.FUNC_LAST;
536: case Compiler.FUNCTION_POSITION:
537: return XPathCoreFunction.FUNC_POSITION;
538: case Compiler.FUNCTION_COUNT:
539: return XPathCoreFunction.FUNC_COUNT;
540: case Compiler.FUNCTION_ID:
541: return XPathCoreFunction.FUNC_ID;
542: case Compiler.FUNCTION_LOCAL_NAME:
543: return XPathCoreFunction.FUNC_LOCAL_NAME;
544: case Compiler.FUNCTION_NAMESPACE_URI:
545: return XPathCoreFunction.FUNC_NAMESPACE_URI;
546: case Compiler.FUNCTION_NAME:
547: return XPathCoreFunction.FUNC_NAME;
548: case Compiler.FUNCTION_STRING:
549: return XPathCoreFunction.FUNC_STRING;
550: case Compiler.FUNCTION_CONCAT:
551: return XPathCoreFunction.FUNC_CONCAT;
552: case Compiler.FUNCTION_STARTS_WITH:
553: return XPathCoreFunction.FUNC_STARTS_WITH;
554: case Compiler.FUNCTION_CONTAINS:
555: return XPathCoreFunction.FUNC_CONTAINS;
556: case Compiler.FUNCTION_SUBSTRING_BEFORE:
557: return XPathCoreFunction.FUNC_SUBSTRING_BEFORE;
558: case Compiler.FUNCTION_SUBSTRING_AFTER:
559: return XPathCoreFunction.FUNC_SUBSTRING_AFTER;
560: case Compiler.FUNCTION_SUBSTRING:
561: return XPathCoreFunction.FUNC_SUBSTRING;
562: case Compiler.FUNCTION_STRING_LENGTH:
563: return XPathCoreFunction.FUNC_STRING_LENGTH;
564: case Compiler.FUNCTION_NORMALIZE_SPACE:
565: return XPathCoreFunction.FUNC_NORMALIZE_SPACE;
566: case Compiler.FUNCTION_TRANSLATE:
567: return XPathCoreFunction.FUNC_TRANSLATE;
568: case Compiler.FUNCTION_BOOLEAN:
569: return XPathCoreFunction.FUNC_BOOLEAN;
570: case Compiler.FUNCTION_NOT:
571: return XPathCoreFunction.FUNC_NOT;
572: case Compiler.FUNCTION_TRUE:
573: return XPathCoreFunction.FUNC_TRUE;
574: case Compiler.FUNCTION_FALSE:
575: return XPathCoreFunction.FUNC_FALSE;
576: case Compiler.FUNCTION_LANG:
577: return XPathCoreFunction.FUNC_LANG;
578: case Compiler.FUNCTION_NUMBER:
579: return XPathCoreFunction.FUNC_NUMBER;
580: case Compiler.FUNCTION_SUM:
581: return XPathCoreFunction.FUNC_SUM;
582: case Compiler.FUNCTION_FLOOR:
583: return XPathCoreFunction.FUNC_FLOOR;
584: case Compiler.FUNCTION_CEILING:
585: return XPathCoreFunction.FUNC_CEILING;
586: case Compiler.FUNCTION_ROUND:
587: return XPathCoreFunction.FUNC_ROUND;
588: case Compiler.FUNCTION_NULL:
589: return XPathCoreFunction.FUNC_NULL;
590: case Compiler.FUNCTION_KEY:
591: return XPathCoreFunction.FUNC_KEY;
592: case Compiler.FUNCTION_FORMAT_NUMBER:
593: return XPathCoreFunction.FUNC_FORMAT_NUMBER;
594: case Compiler.FUNCTION_EXISTS:
595: return XPathCoreFunction.FUNC_EXISTS;
596: }
597:
598: return -1;
599: }
600:
601: /**
602: * Gets the core operation code.
603: *
604: * @param coreOperation the core operation
605: * @return the operation code or -1 if invalid
606: * @throws XPathException invalid operation
607: */
608: int getCoreOperationCode(CoreOperation coreOperation) {
609: if (coreOperation instanceof CoreOperationAdd) {
610: return XPathCoreOperation.OP_SUM;
611: } else if (coreOperation instanceof CoreOperationSubtract) {
612: return XPathCoreOperation.OP_MINUS;
613: } else if (coreOperation instanceof CoreOperationMultiply) {
614: return XPathCoreOperation.OP_MULT;
615: } else if (coreOperation instanceof CoreOperationDivide) {
616: return XPathCoreOperation.OP_DIV;
617: } else if (coreOperation instanceof CoreOperationMod) {
618: return XPathCoreOperation.OP_MOD;
619: } else if (coreOperation instanceof CoreOperationNegate) {
620: return XPathCoreOperation.OP_NEGATIVE;
621: } else if (coreOperation instanceof CoreOperationAnd) {
622: return XPathCoreOperation.OP_AND;
623: } else if (coreOperation instanceof CoreOperationOr) {
624: return XPathCoreOperation.OP_OR;
625: } else if (coreOperation instanceof CoreOperationEqual) {
626: return XPathCoreOperation.OP_EQ;
627: } else if (coreOperation instanceof CoreOperationNotEqual) {
628: return XPathCoreOperation.OP_NE;
629: } else if (coreOperation instanceof CoreOperationLessThan) {
630: return XPathCoreOperation.OP_LT;
631: } else if (coreOperation instanceof CoreOperationLessThanOrEqual) {
632: return XPathCoreOperation.OP_LE;
633: } else if (coreOperation instanceof CoreOperationGreaterThan) {
634: return XPathCoreOperation.OP_GT;
635: } else if (coreOperation instanceof CoreOperationGreaterThanOrEqual) {
636: return XPathCoreOperation.OP_GE;
637: }
638: return -1;
639: }
640:
641: /**
642: * Determines if a function name is valid. Assumes the function name is
643: * not one of the core functions.
644: * @param functionName the name of the function
645: * @return true if the function name is valid, false otherwise
646: */
647: static boolean isValidFunction(String functionName) {
648: for (int i = 0; i < VALID_FUNCTION_NAMES.length; i++) {
649: if (functionName.equals(VALID_FUNCTION_NAMES[i])) {
650: return true;
651: }
652: }
653:
654: // For bpws, strip out the prefix because there's no guarantee that
655: // the prefix is bpws.
656: String name = functionName;
657: int colon = name.indexOf(':');
658: if (colon != -1) {
659: name = name.substring(colon + 1, name.length());
660: }
661: for (int i = 0; i < VALID_BPWS_FUNCTION_NAMES.length; i++) {
662: if (name.equals(VALID_BPWS_FUNCTION_NAMES[i])) {
663: return true;
664: }
665: }
666:
667: return false;
668: }
669: }
|