You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by mr...@apache.org on 2009/03/25 05:15:17 UTC
svn commit: r758138 [2/3] - in
/xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl: xpath/
xs/ xs/alternative/
Modified: xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl/xpath/XPath20.java
URL: http://svn.apache.org/viewvc/xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl/xpath/XPath20.java?rev=758138&r1=758137&r2=758138&view=diff
==============================================================================
--- xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl/xpath/XPath20.java (original)
+++ xerces/java/branches/xml-schema-1.1-dev/src/org/apache/xerces/impl/xpath/XPath20.java Wed Mar 25 04:15:15 2009
@@ -17,29 +17,22 @@
package org.apache.xerces.impl.xpath;
-import org.apache.xerces.impl.Constants;
-import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import java.io.StringReader;
+
import org.apache.xerces.impl.dv.SchemaDVFactory;
import org.apache.xerces.impl.dv.XSSimpleType;
import org.apache.xerces.impl.dv.xs.TypeValidator;
import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
-import org.apache.xerces.impl.xs.AttributePSVImpl;
-import org.apache.xerces.impl.xs.SchemaSymbols;
-import org.apache.xerces.util.IntStack;
import org.apache.xerces.util.SymbolTable;
-import org.apache.xerces.util.XMLChar;
-import org.apache.xerces.util.XMLSymbols;
-import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xs.ShortList;
import org.apache.xerces.xs.XSConstants;
-import org.apache.xerces.xs.XSSimpleTypeDefinition;
/**
* Bare minimal XPath 2.0 implementation for schema
- * type alternatives
+ * type alternatives.
*
* @author Hiranya Jayathilaka, University of Moratuwa
* @version $Id$
@@ -47,1820 +40,480 @@
public class XPath20 {
protected final String fExpression;
- protected final SymbolTable fSymbolTable;
- protected NodeTest fSyntaxTree;
protected final NamespaceContext fContext;
+ private XPathSyntaxTreeNode fRootNode;
+
public XPath20(String xpath, SymbolTable symbolTable,
NamespaceContext context) throws XPathException {
fExpression = xpath;
- fSymbolTable = symbolTable;
fContext = context;
- fSyntaxTree = null;
- parseExpression();
+
+ //The parser expects '\n' at the end of the expression. So insert it.
+ StringReader reader = new StringReader(fExpression + "\n");
+ XPath20Parser parser = new XPath20Parser(reader);
+ fRootNode = parser.parseExpression();
}
/**
- * Traverse the syntax tree recursively and evaluates the tests stored in each of
- * the nodes. Finally combines the test results and returns the overall result of
- * the test expression as a boolean value.
+ * Evaluate the test XPath expression using the attribute information and
+ * element information.
+ *
+ * @param element QName of the current element
+ * @param attributes attributes collection of the current element
+ * @return true if the test evaluates successfully and false otherwise
*/
- public boolean traverseTree(QName element, XMLAttributes attributes) {
- if (fSyntaxTree == null) {
- return false;
- }
- return visitNode(fSyntaxTree.getChildren()[0], element, attributes);
- }
-
- private boolean visitNode(NodeTest node, QName element, XMLAttributes attributes) {
- int nodeType = node.getType();
- if (nodeType == SyntaxTreeBuilder.TEST_CONJUNCTION_AND ||
- node.getType() == SyntaxTreeBuilder.TEST_CONJUNCTION_OR) {
- NodeTest[] children = node.getChildren();
- //recursively traverse the left sub tree
- boolean result1 = visitNode(children[0], element, attributes);
- //recursively traverse the right sub tree
- boolean result2 = visitNode(children[1], element, attributes);
- //combine the results
- if (nodeType == SyntaxTreeBuilder.TEST_CONJUNCTION_AND) {
- return result1 && result2;
- }
- else {
- return result1 || result2;
- }
- }
- else {
- return node.evaluateNodeTest(element, attributes);
- }
- }
-
- /**
- * Parses the XPath expression and builds a tree model out of it.
- */
- private void parseExpression()
- throws XPathException {
- XPath20.Scanner scanner = new Scanner();
- XPath20.Tokens tokens = new Tokens();
+ public boolean evaluateTest(QName element, XMLAttributes attributes) {
try {
- scanner.scanExpr(fExpression, 0, fExpression.length(), tokens);
- fSyntaxTree = XPath20.Parser.parse(tokens, fContext, fSymbolTable);
- }
- catch (XPathException e) {
- fSyntaxTree = null; //reset the tree
- throw e;
+ return fRootNode.evaluate(element, attributes);
+ } catch (Exception e) {
+ return false;
}
}
- /**
- * The Scanner implementation for XPath 2.0 expressions used in
- * the type alternatives.
- *
- * @author Hiranya Jayathilaka, University of Moratuwa
- */
- private static class Scanner {
-
- /**
- * 7-bit ASCII subset
- *
- * 0 1 2 3 4 5 6 7 8 9 A B C D E F
- * 0, 0, 0, 0, 0, 0, 0, 0, 0, HT, LF, 0, 0, CR, 0, 0, // 0
- * 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
- * SP, !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, // 2
- * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ;, <, =, >, ?, // 3
- * @, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, // 4
- * P, Q, R, S, T, U, V, W, X, Y, Z, [, \, ], ^, _, // 5
- * `, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, // 6
- * p, q, r, s, t, u, v, w, x, y, z, {, |, }, ~, DEL // 7
- */
- private static final byte
- CHARTYPE_INVALID = 0, // invalid XML character
- CHARTYPE_OTHER = 1, // not special - one of "#%&;?\^`{}~" or DEL
- CHARTYPE_WHITESPACE = 2, // one of "\t\n\r " (0x09, 0x0A, 0x0D, 0x20)
- CHARTYPE_EXCLAMATION = 3, // '!' (0x21)
- CHARTYPE_QUOTE = 4, // '\"' or '\'' (0x22 and 0x27)
- CHARTYPE_DOLLAR = 5, // '$' (0x24)
- CHARTYPE_OPEN_PAREN = 6, // '(' (0x28)
- CHARTYPE_CLOSE_PAREN = 7, // ')' (0x29)
- CHARTYPE_STAR = 8, // '*' (0x2A)
- CHARTYPE_PLUS = 9, // '+' (0x2B)
- CHARTYPE_COMMA = 10, // ',' (0x2C)
- CHARTYPE_MINUS = 11, // '-' (0x2D)
- CHARTYPE_PERIOD = 12, // '.' (0x2E)
- CHARTYPE_SLASH = 13, // '/' (0x2F)
- CHARTYPE_DIGIT = 14, // '0'-'9' (0x30 to 0x39)
- CHARTYPE_COLON = 15, // ':' (0x3A)
- CHARTYPE_LESS = 16, // '<' (0x3C)
- CHARTYPE_EQUAL = 17, // '=' (0x3D)
- CHARTYPE_GREATER = 18, // '>' (0x3E)
- CHARTYPE_ATSIGN = 19, // '@' (0x40)
- CHARTYPE_LETTER = 20, // 'A'-'Z' or 'a'-'z' (0x41 to 0x5A and 0x61 to 0x7A)
- CHARTYPE_OPEN_BRACKET = 21, // '[' (0x5B)
- CHARTYPE_CLOSE_BRACKET = 22, // ']' (0x5D)
- CHARTYPE_UNDERSCORE = 23, // '_' (0x5F)
- CHARTYPE_UNION = 24, // '|' (0x7C)
- CHARTYPE_NONASCII = 25; // Non-ASCII Unicode codepoint (>= 0x80)
-
- private static final byte[] fASCIICharMap = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 3, 4, 1, 5, 1, 1, 4, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 1, 16, 17, 18, 1,
- 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 1, 22, 1, 23,
- 1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1, 24, 1, 1, 1
- };
-
- // symbols
- private static final String fAndSymbol = "and".intern();
- private static final String fOrSymbol = "or".intern();
- private static final String fCastSymbol = "cast".intern();
- private static final String fAsSymbol = "as".intern();
-
- /**
- * Scans the given XPath expression one character at a time and break it
- * up into a series of tokens.
- */
- public void scanExpr(String data, int currentOffset, int endOffset, XPath20.Tokens tokens)
- throws XPathException {
-
- int ch, nameOffset;
- String nameHandle, prefixHandle;
-
- while (true) {
- if (currentOffset == endOffset) {
- break;
- }
- ch = data.charAt(currentOffset); //read a character from the expression
-
- //check for whitespace(s)token
- while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) {
- if (++currentOffset == endOffset) {
- break;
- }
- ch = data.charAt(currentOffset);
- }
-
- if (currentOffset == endOffset) {
- break;
- }
-
- byte chartype = (ch >= 0x80) ? CHARTYPE_NONASCII : fASCIICharMap[ch];
-
- switch (chartype) {
-
- case CHARTYPE_ATSIGN:
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_AT_SIGN);
- if (++currentOffset == endOffset) {
- //an expression cannot end with an '@' sign
- throw new XPathException("c-general-xpath");
- }
- break;
-
- case CHARTYPE_EQUAL:
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_COMPARATOR_EQUAL);
- if (++currentOffset == endOffset) {
- //an expression cannot end with '=' sign
- throw new XPathException("c-general-xpath");
- }
- break;
-
- case CHARTYPE_EXCLAMATION:
- if (++currentOffset == endOffset) {
- //an expression cannot end with '!' sign
- throw new XPathException("c-general-xpath");
- }
- ch = data.charAt(currentOffset);
- if (ch != '=') {
- throw new XPathException("c-general-xpath");
- }
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_COMPARATOR_NOT_EQUAL);
- if (++currentOffset == endOffset) {
- //an expression cannot end with '!=' sign
- throw new XPathException("c-general-xpath");
- }
- break;
-
- case CHARTYPE_LESS:
- //the token could be '<' or '<='.
- //we need to read the next character to be sure
- if (++currentOffset == endOffset) {
- throw new XPathException("c-general-xpath");
- }
- ch = data.charAt(currentOffset);
- if (ch == '=') {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_COMPARATOR_LESS_EQUAL);
- if (++currentOffset == endOffset) {
- throw new XPathException("c-general-xpath");
- }
- } else {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_COMPARATOR_LESS);
- if (currentOffset + 1 == endOffset) {
- throw new XPathException("c-general-xpath");
- }
- }
- break;
-
- case CHARTYPE_GREATER:
- //the token could be '>' or '>='
- if (++currentOffset == endOffset) {
- throw new XPathException("c-general-xpath");
- }
- ch = data.charAt(currentOffset);
- if (ch == '=') {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_COMPARATOR_GREATER_EQUAL);
- if (++currentOffset == endOffset) {
- throw new XPathException("c-general-xpath");
- }
- } else {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_COMPARATOR_GREATER);
- if (currentOffset + 1 == endOffset) {
- //we have the last read character still
- //to be processed and so we don't touch
- //the value of currentOffset
- throw new XPathException("c-general-xpath");
- }
- }
- break;
-
- case CHARTYPE_QUOTE:
- int qchar = ch;
- if (++currentOffset == endOffset) {
- throw new XPathException("c-general-xpath");
- }
- ch = data.charAt(currentOffset);
- int litOffset = currentOffset;
- while (ch != qchar) {
- if (++currentOffset == endOffset) {
- //no matching quote
- throw new XPathException("c-general-xpath");
- }
- ch = data.charAt(currentOffset);
- }
-
- int litLength = currentOffset - litOffset;
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_STRING_LITERAL, data.substring
- (litOffset, litOffset + litLength));
- ++currentOffset;
- break;
-
- case CHARTYPE_OPEN_PAREN:
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_OPEN_PAREN);
- if (++currentOffset == endOffset) {
- throw new XPathException("c-general-xpath");
- }
- break;
-
- case CHARTYPE_CLOSE_PAREN:
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_CLOSE_PAREN);
- ++currentOffset;
- break;
-
- case CHARTYPE_STAR:
- //if '*' is encountered treat it as if it was a NameTest
- if (++currentOffset == endOffset) {
- break;
- }
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_NAMETEST_ANY);
- break;
-
- case CHARTYPE_OTHER:
- if (ch == '?') {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_QUESTION_SIGN);
- }
- else {
- throw new XPathException("c-general-xpath");
- }
-
- ++currentOffset;
- break;
-
- case CHARTYPE_DIGIT:
- nameOffset = currentOffset;
- currentOffset = scanNumber(data, currentOffset, endOffset);
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_NUMERIC_LITERAL, data.
- substring(nameOffset, currentOffset));
- break;
-
- case CHARTYPE_LETTER:
- nameOffset = currentOffset;
- currentOffset = scanNCName(data, currentOffset, endOffset);
- if (currentOffset == nameOffset) {
- throw new XPathException("c-general-xpath");
- }
-
- //read the string of characters
- nameHandle = data.substring(nameOffset, currentOffset);
-
- //we read the next character to see whether we have hit a
- //QName or a NameTest
- if (currentOffset < endOffset) {
- ch = data.charAt(currentOffset);
- }
- else {
- ch = -1;
- }
- boolean isNameTest = false;
- boolean isQName = false;
- prefixHandle = XMLSymbols.EMPTY_STRING;
- if (ch == ':') {
- if (++currentOffset == endOffset) {
- throw new XPathException("c-general-xpath");
- }
- ch = data.charAt(currentOffset);
- if (ch == '*') {
- //we are at a NameTest
- if (++currentOffset < endOffset) {
- ch = data.charAt(currentOffset);
- }
- isNameTest = true;
- }
- else {
- prefixHandle = nameHandle;
- nameOffset = currentOffset;
- currentOffset = scanNCName(data, currentOffset, endOffset);
- if (currentOffset == nameOffset) {
- throw new XPathException("c-general-xpath");
- }
- if (currentOffset < endOffset) {
- ch = data.charAt(currentOffset);
- }
- else {
- ch = -1;
- }
- //we have more text, ie we are at a QName
- nameHandle = data.substring(nameOffset, currentOffset);
- isQName = true;
- }
- }
- else {
- //if nothing special was found we treat what we have
- //read so far as a QName and continue
- isQName = true;
- }
-
- //deal with any whitespace
- while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) {
- if (++currentOffset == endOffset) {
- break;
- }
- ch = data.charAt(currentOffset);
- }
-
- if (nameHandle.equals(fAndSymbol)) {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_KEYWORD_AND);
- }
- else if (nameHandle.equals(fOrSymbol)) {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_KEYWORD_OR);
- }
- else if (nameHandle.equals(fCastSymbol)) {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_KEYWORD_CAST);
- }
- else if (nameHandle.equals(fAsSymbol)) {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_KEYWORD_AS);
- }
- else {
- if (isNameTest) {
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_NAMETEST_NS, nameHandle);
- }
- else if (isQName) {
- if (prefixHandle !=XMLSymbols.EMPTY_STRING) {
- nameHandle = prefixHandle + ":" +nameHandle;
- }
- tokens.addToken(XPath20.Tokens.EXPRTOKEN_QNAME, nameHandle);
- }
- else {
- throw new XPathException("c-general-xpath");
- }
- }
- break;
-
- case CHARTYPE_INVALID:
- case CHARTYPE_DOLLAR:
- case CHARTYPE_PLUS:
- case CHARTYPE_UNION:
- case CHARTYPE_OPEN_BRACKET:
- case CHARTYPE_CLOSE_BRACKET:
- case CHARTYPE_COLON:
- case CHARTYPE_COMMA:
- case CHARTYPE_SLASH:
- throw new XPathException("c-general-xpath");
-
- default:
- throw new XPathException("c-general-xpath");
- }
- }
- }
-
- /*
- * Reads a numeric literal in a test XPath expression.
- */
- private int scanNumber(String data, int currentOffset, int endOffset) throws XPathException {
- int ch = data.charAt(currentOffset);
- while (ch >= '0' && ch <= '9') {
- if (++currentOffset == endOffset) {
- break;
- }
- ch = data.charAt(currentOffset);
- }
-
- if (ch == '.') {
- if (++currentOffset < endOffset) {
- ch = data.charAt(currentOffset);
- while (ch >= '0' && ch <= '9') {
- if (++currentOffset == endOffset) {
- break;
- }
- ch = data.charAt(currentOffset);
- }
- }
- }
-
- if (ch == 'e' || ch == 'E') {
- if (++currentOffset < endOffset) {
- ch = data.charAt(currentOffset);
- if (ch == '+' || ch == '-') {
- ch = data.charAt(++currentOffset);
- }
-
- if (ch < '0' || ch > '9') {
- throw new XPathException("c-general-xpath");
- }
-
- while (ch >= '0' && ch <= '9') {
- if (++currentOffset == endOffset) {
- break;
- }
- ch = data.charAt(currentOffset);
- }
- }
- else {
- throw new XPathException("c-general-xpath");
- }
- }
- return currentOffset;
- }
-
- /*
- * Reads a NCName in a test XPath expression
- */
- private int scanNCName(String data, int currentOffset, int endOffset) {
- int ch = data.charAt(currentOffset);
- if (ch >= 0x80) {
- if (!XMLChar.isNameStart(ch)) {
- return currentOffset;
- }
- }
- else {
- byte chartype = fASCIICharMap[ch];
- if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_UNDERSCORE) {
- return currentOffset;
- }
- }
+}
- while (++currentOffset < endOffset) {
- ch = data.charAt(currentOffset);
- if (ch >= 0x80) {
- if (!XMLChar.isName(ch)) {
- break;
- }
- }
- else {
- byte chartype = fASCIICharMap[ch];
- if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_DIGIT &&
- chartype != CHARTYPE_PERIOD && chartype != CHARTYPE_MINUS &&
- chartype != CHARTYPE_UNDERSCORE) {
- break;
- }
- }
- }
- return currentOffset;
- }
+abstract class XPathSyntaxTreeNode {
+ public static final int TYPE_UNDEFINED = -1;
+ public static final int TYPE_DOUBLE = 0; //for all numerics (double, integer, float, decimal etc)
+ public static final int TYPE_STRING = 1; //for strings (xs:string)
+ public static final int TYPE_UNTYPED = 2; //for attributes (untypedAtomic)
+ public static final int TYPE_OTHER = 3; //for everything else which should have some valid type
+
+ public abstract boolean evaluate(QName element, XMLAttributes attributes) throws Exception;
+
+ public Object getValue(XMLAttributes attributes) throws Exception {
+ return null;
}
-
- /**
- * Used by the XPath20.Tokenizer to store a set of tokens. Generally
- * only the token type is stored. But in certain situations the textual
- * value of the tokens can be saved.
- *
- * @author Hiranya Jayathilaka, University of Moratuwa
- */
- private static class Tokens {
-
- public static final int
- EXPRTOKEN_OPEN_PAREN = 0,
- EXPRTOKEN_CLOSE_PAREN = 1,
-
- EXPRTOKEN_KEYWORD_OR = 2,
- EXPRTOKEN_KEYWORD_AND = 3,
- EXPRTOKEN_KEYWORD_CAST = 4,
- EXPRTOKEN_KEYWORD_AS = 5,
-
- EXPRTOKEN_COMPARATOR_EQUAL = 6,
- EXPRTOKEN_COMPARATOR_NOT_EQUAL = 7,
- EXPRTOKEN_COMPARATOR_LESS = 8,
- EXPRTOKEN_COMPARATOR_LESS_EQUAL = 9,
- EXPRTOKEN_COMPARATOR_GREATER = 10,
- EXPRTOKEN_COMPARATOR_GREATER_EQUAL = 11,
-
- EXPRTOKEN_AT_SIGN = 12,
- EXPRTOKEN_QUESTION_SIGN = 13,
- EXPRTOKEN_STAR_SIGN = 14,
- EXPRTOKEN_COLON_SIGN = 15,
-
- EXPRTOKEN_NUMERIC_LITERAL = 16,
- EXPRTOKEN_STRING_LITERAL = 17,
-
- //[7] QName ::= PrefixedName | UnprefixedName
- EXPRTOKEN_QNAME = 18,
- EXPRTOKEN_ATTR_NAME = 19,
-
- //[4] NameTest ::= QName | '*' | NCName ':' '*'
- EXPRTOKEN_NAMETEST_ANY = 20, //'*' scenario
- EXPRTOKEN_NAMETEST_NS = 21; //NCName:* scenario
-
-
- private static final int INITIAL_TOKEN_COUNT = 8;
-
- //the token list
- private int[] fTokens = new int[INITIAL_TOKEN_COUNT];
-
- //stores the textual values of tokens (indexed by the corresponding index in the token list)
- private String[] fTokenNames = new String[INITIAL_TOKEN_COUNT];
- //private Hashtable<Integer, String> fTokenNames = new Hashtable<Integer, String>();
- private int fTokenCount = 0;
- private int fCurrentTokenIndex = 0;
-
- /**
- * Adds the specified token to the list of tokens. Only the token
- * type is saved.
- */
- public void addToken(int token) {
- addToken(token, null);
- }
- /*public void addToken(int token) {
-
- if (fTokenCount == fTokens.length) {
- int[] oldArray = fTokens;
- fTokens = new int[fTokenCount << 1];
- System.arraycopy(oldArray, 0, fTokens, 0, fTokenCount);
- }
- fTokens[fTokenCount] = token;
- fTokenCount++;
- }*/
-
- /**
- * Adds the specified token to the list of tokens along with its
- * textual value.
- */
- public void addToken(int token, String tokenStr) {
-
- if (fTokenCount == fTokens.length) {
- int[] oldArray = fTokens;
- fTokens = new int[fTokenCount << 1];
- System.arraycopy(oldArray, 0, fTokens, 0, fTokenCount);
-
- String[] oldNames = fTokenNames;
- fTokenNames = new String[fTokenCount << 1];
- System.arraycopy(oldNames, 0, fTokenNames, 0, fTokenCount);
- }
- fTokens[fTokenCount] = token;
- fTokenNames[fTokenCount] = tokenStr;
- fTokenCount++;
- }
- /*public void addToken(int token, String tokenStr) {
- addToken(token);
- fTokenNames.put(fTokenCount - 1, tokenStr);
- }*/
-
- /**
- * Checks whether there are any more tokens in the list
- */
- public boolean hasNext() {
- return fCurrentTokenIndex < fTokenCount;
- }
-
- /**
- * Returns the next token in the token list
- */
- public int next() throws XPathException {
- if (fCurrentTokenIndex == fTokenCount) {
- throw new XPathException("c-general-xpath");
- }
- return fTokens[fCurrentTokenIndex++];
- }
-
- public int peek() {
- if (fCurrentTokenIndex != fTokenCount) {
- return fTokens[fCurrentTokenIndex];
- }
- else {
- return -1;
- }
- }
-
- /**
- * Reset the position indicator in the token list to be 0
- */
- public void rewind() {
- fCurrentTokenIndex = 0;
- }
-
- /**
- * Gets the textual value of a token. If the text value for
- * the specified token is not in the Map will return null.
- */
- public String getTokenValue(int tokenIndex) {
- return fTokenNames[tokenIndex];
- }
+
+ public String getStringValue() {
+ return null;
}
+ public int getType() {
+ return TYPE_UNDEFINED;
+ }
- /**
- * The parser implementation for the test XPath expressions
- * used in type alternatives. Processes a set of tokens given
- * by the XPath20.Tokenizer and checks whether they expression
- * conforms to the XML Schema 1.1 Structures specification.
- *
- * @author Hiranya Jayathilaka, University of Moratuwa
- */
- private static class Parser {
-
- /**
- * Parses a set of tokens to see whether the test XPath expression
- * represented by the tokens is valid. Valid tokens are passed to the
- * SyntaxTreeBuilder in order to construct the abstract syntax tree
- * representation of the expression.
- */
- public static NodeTest parse(XPath20.Tokens tokens, NamespaceContext context,
- SymbolTable symbolTable) throws XPathException {
-
- boolean expectingNameTest = false;
- boolean expectingQName = true;
- boolean attrAxis = false;
- boolean inCastExpr = false;
-
- int i = 0;
- int openBrackets = 0;
- int prevToken = -1;
-
- //init the content model builder
- SyntaxTreeBuilder treeBuilder = new SyntaxTreeBuilder();
-
- while (tokens.hasNext()) {
- int token = tokens.next();
-
- switch (token) {
-
- case XPath20.Tokens.EXPRTOKEN_AT_SIGN:
- //we are at the beginning of an attribute name
- check(!expectingNameTest);
- //must be followed by a nametest
- expectingNameTest = true;
- expectingQName = false;
- attrAxis = true;
- break;
-
- case XPath20.Tokens.EXPRTOKEN_QNAME:
- check(expectingNameTest || expectingQName);
- if (prevToken == XPath20.Tokens.EXPRTOKEN_AT_SIGN) {
- //if the '@' sign was detected previously
- //we should let the tree builder know that we
- //are dealing with an attribute name here
- treeBuilder.addToken(Tokens.EXPRTOKEN_ATTR_NAME, tokens.getTokenValue(i));
- }
- else {
- treeBuilder.addToken(token, tokens.getTokenValue(i));
- }
- expectingNameTest = false;
- if (inCastExpr) {
- //any explicit casts must be to built-in types
- if (!isBuiltInType(tokens.getTokenValue(i), context, symbolTable)) {
- throw new XPathException("c-general-xpath");
- }
-
- //if we are in a cast expression the QName can be followed by
- //a '?'
- token = tokens.peek();
- if (token == XPath20.Tokens.EXPRTOKEN_QUESTION_SIGN) {
- token = tokens.next();
- treeBuilder.addToken(token, null);
- i++;
- }
- else {
- treeBuilder.addToken(XPath20.Tokens.EXPRTOKEN_QUESTION_SIGN, null);
- }
- //end of cast expression
- inCastExpr = false;
- expectingQName = false;
- }
- break;
-
- //handle comparator signs (=, >, <, <=, >=, !=)
- case XPath20.Tokens.EXPRTOKEN_COMPARATOR_EQUAL:
- case XPath20.Tokens.EXPRTOKEN_COMPARATOR_NOT_EQUAL:
- case XPath20.Tokens.EXPRTOKEN_COMPARATOR_GREATER:
- case XPath20.Tokens.EXPRTOKEN_COMPARATOR_GREATER_EQUAL:
- case XPath20.Tokens.EXPRTOKEN_COMPARATOR_LESS:
- case XPath20.Tokens.EXPRTOKEN_COMPARATOR_LESS_EQUAL:
- check(!expectingNameTest && !expectingQName);
- if (!tokens.hasNext()) {
- //the test must not end here
- //if it does something's wrong
- throw new XPathException("c-general-xpath");
- }
- else if (prevToken == XPath20.Tokens.EXPRTOKEN_STRING_LITERAL ||
- prevToken == XPath20.Tokens.EXPRTOKEN_NUMERIC_LITERAL ||
- prevToken == XPath20.Tokens.EXPRTOKEN_QUESTION_SIGN ||
- attrAxis) {
- //the previous token must be a literal or a
- //cast expression
- treeBuilder.addToken(token, null);
- attrAxis = false;
- }
- else {
- throw new XPathException("c-general-xpath");
- }
- break;
-
- case XPath20.Tokens.EXPRTOKEN_NUMERIC_LITERAL:
- case XPath20.Tokens.EXPRTOKEN_STRING_LITERAL:
- treeBuilder.addToken(token, tokens.getTokenValue(i));
- expectingNameTest = false;
- expectingQName = false;
- break;
-
- case XPath20.Tokens.EXPRTOKEN_KEYWORD_CAST:
- if (prevToken == XPath20.Tokens.EXPRTOKEN_STRING_LITERAL ||
- prevToken == XPath20.Tokens.EXPRTOKEN_NUMERIC_LITERAL ||
- prevToken == XPath20.Tokens.EXPRTOKEN_NAMETEST_NS ||
- prevToken == XPath20.Tokens.EXPRTOKEN_NAMETEST_ANY ||
- prevToken == XPath20.Tokens.EXPRTOKEN_QNAME) {
-
- treeBuilder.addToken(token, null);
- token = tokens.next();
- if (token == XPath20.Tokens.EXPRTOKEN_KEYWORD_AS) {
- //keyword 'cast' must be followed by the keyword 'as'
- treeBuilder.addToken(token, null);
- //should be followed by a QName
- expectingQName = true;
- expectingNameTest = false;
- inCastExpr = true;
- i++;
- }
- else {
- throw new XPathException("c-general-xpath");
- }
- }
- else {
- throw new XPathException("c-general-xpath");
- }
- break;
-
- case XPath20.Tokens.EXPRTOKEN_KEYWORD_OR:
- case XPath20.Tokens.EXPRTOKEN_KEYWORD_AND:
- //might be followed by a QName
- expectingQName = true;
- treeBuilder.addToken(token, null);
- break;
-
- case XPath20.Tokens.EXPRTOKEN_OPEN_PAREN:
- openBrackets++;
- expectingQName = true;
- treeBuilder.addToken(token, null);
- break;
-
- case XPath20.Tokens.EXPRTOKEN_CLOSE_PAREN:
- if (openBrackets > 0) {
- treeBuilder.addToken(token, null);
- expectingQName = expectingNameTest = false;
- openBrackets--;
- }
- else {
- throw new XPathException("c-general-xpath");
- }
- break;
-
- default:
- throw new XPathException("c-general-xpath");
- }
+ public String getTypeName() {
+ return null;
+ }
+}
- //'cache' the current token for the next iteration
- prevToken = token;
- i++;
- }
- if (openBrackets > 0) {
- //check for bracket inconsistency
- throw new XPathException("c-general-xpath");
- }
- return treeBuilder.markEnd();
- }
+class LiteralNode extends XPathSyntaxTreeNode {
+ private String value;
+ private boolean isNumeric;
+
+ public LiteralNode(String value, boolean isNumeric) {
+ this.value = value;
+ this.isNumeric = isNumeric;
+ }
- /**
- * Checks whether a specified boolean condition is satisfied by the current
- * state of the parser. If the conditions are not satisfied throws an XPath
- * exception
- */
- private static void check( boolean b ) throws XPathException {
- if(!b) throw new XPathException("c-general-xpath");
+ public boolean evaluate(QName element, XMLAttributes attributes) throws Exception {
+ Object obj = getValue(attributes);
+ if (isNumeric) {
+ return obj != null && 0.0 != ((Double) obj).doubleValue();
+ }
+ else {
+ return obj != null;
}
+ }
- /**
- * Checks whether a given QName represents a valid built-in type
- */
- private static boolean isBuiltInType(String qname, NamespaceContext context,
- SymbolTable symbolTable) {
- boolean builtIn = false;
- final int colonIndex = qname.indexOf(':');
- if (colonIndex != -1) {
- final String prefix = symbolTable.addSymbol(qname.substring(0, colonIndex));
- final String uri = context.getURI(prefix);
- if (SchemaSymbols.URI_SCHEMAFORSCHEMA == uri) {
- final String local = qname.substring(colonIndex + 1);
- XSSimpleType type = SchemaDVFactory.getInstance().getBuiltInType(local);
- if (type != null) {
- builtIn = true;
- }
- }
- }
- return builtIn;
+ public Object getValue(XMLAttributes attributes) throws Exception {
+ SchemaDVFactory validator = SchemaDVFactory.getInstance();
+ XSSimpleType type;
+ if (isNumeric) {
+ type = validator.getBuiltInType("double");
+ } else {
+ type = validator.getBuiltInType("string");
}
+ return type.validate(value, null, null);
+ }
+
+ public String getStringValue() {
+ return value;
}
+ public int getType() {
+ return isNumeric ? TYPE_DOUBLE : TYPE_STRING;
+ }
+}
- /**
- * The syntax tree builder implementation for the test XPath expressions used in
- * the type alternatives.
- *
- * @author Hiranya Jayathilaka, University of Moratuwa
- */
- private static class SyntaxTreeBuilder {
-
- public static final int
- TEST_CATEGORY_ROOT = 0,
+class ConjunctionNode extends XPathSyntaxTreeNode {
+ private int conjunction;
+ private XPathSyntaxTreeNode child1;
+ private XPathSyntaxTreeNode child2;
+
+ public static final int OR = 0;
+ public static final int AND = 1;
+
+ public ConjunctionNode(int conjunction, XPathSyntaxTreeNode child1,
+ XPathSyntaxTreeNode child2) {
+ this.conjunction = conjunction;
+ this.child1 = child1;
+ this.child2 = child2;
+ }
- TEST_CATEGORY_VALUE = 1,
- TEST_CATEGORY_VALUE_AS_CAST = 2,
- TEST_CATEGORY_ATTR = 3,
- TEST_CATEGORY_ATTR_AS_CAST = 4,
-
- TEST_CATEGORY_ATTR_VALUE = 5,
- TEST_CATEGORY_ATTR_VALUE_AS_CAST = 6,
- TEST_CATEGORY_ATTR_AS_CAST_VALUE = 7,
- TEST_CATEGORY_ATTR_AS_CAST_VALUE_AS_CAST = 8,
-
- TEST_CATEGORY_VALUE_VALUE = 9,
- TEST_CATEGORY_VALUE_VALUE_AS_CAST = 10,
- TEST_CATEGORY_VALUE_AS_CAST_VALUE = 11,
- TEST_CATEGORY_VALUE_AS_CAST_VALUE_AS_CAST = 12,
-
- TEST_CATEGORY_ATTR_ATTR = 13,
- TEST_CATEGORY_ATTR_ATTR_AS_CAST = 14,
- TEST_CATEGORY_ATTR_AS_CAST_ATTR = 15,
- TEST_CATEGORY_ATTR_AS_CAST_ATTR_AS_CAST = 16,
-
- TEST_CONJUNCTION_OR = 17,
- TEST_CONJUNCTION_AND = 18,
- TEST_OPEN_PAREN = 19,
- TEST_CLOSE_PAREN = 20;
-
- private static final int INITIAL_TOKEN_COUNT = 8;
-
- private NodeTest fCurrentNode;
- private int[] fTokensBuffer = new int[INITIAL_TOKEN_COUNT];
- private String[] fTokenNames = new String[INITIAL_TOKEN_COUNT];
- private int fTokenCount = 0;
- //private ArrayList<Integer> fTokensBuffer;
- //private ArrayList<String> fTokenNames;
-
- private boolean fExcessBrackets;
- private IntStack fBracketStates;
-
- private String fLHS, fRHS;
- private int fComparator;
- private boolean fNumeric;
-
- public SyntaxTreeBuilder() {
- fCurrentNode = null;
- //fTokensBuffer = new ArrayList<Integer>();
- //fTokenNames = new ArrayList<String>();
- fBracketStates = new IntStack();
- fExcessBrackets = false;
- fNumeric = false;
+ public boolean evaluate(QName element, XMLAttributes attributes) throws Exception {
+ boolean lhs = child1.evaluate(element, attributes);
+ boolean rhs = child2.evaluate(element, attributes);
+ if (conjunction == OR) {
+ return lhs || rhs;
+ } else {
+ return lhs && rhs;
}
+ }
+}
- /**
- * Processes the given token and adds it to the syntax tree
- */
- public void addToken(int token, String text) throws XPathException{
- NodeTest node = null;
- NodeTest conjunction = null;
-
- switch (token) {
-
- case Tokens.EXPRTOKEN_KEYWORD_AND:
- node = getNodeTest();
- conjunction = new NodeTest(TEST_CONJUNCTION_AND);
- if (fExcessBrackets) {
- fExcessBrackets = false;
- }
- break;
-
- case Tokens.EXPRTOKEN_KEYWORD_OR:
- node = getNodeTest();
- conjunction = new NodeTest(TEST_CONJUNCTION_OR);
- if (fExcessBrackets) {
- fExcessBrackets = false;
- }
- break;
-
- case Tokens.EXPRTOKEN_OPEN_PAREN:
- fBracketStates.push(fExcessBrackets ? 1 : 0);
- fExcessBrackets = true;
- break;
-
- case Tokens.EXPRTOKEN_CLOSE_PAREN:
- if (!fExcessBrackets) {
- node = getNodeTest();
- }
- fExcessBrackets = fBracketStates.pop() == 1;
- break;
-
- default:
- {
- if (fTokenCount == fTokensBuffer.length) {
- int[] oldArray = fTokensBuffer;
- fTokensBuffer = new int[fTokenCount << 1];
- System.arraycopy(oldArray, 0, fTokensBuffer, 0, fTokenCount);
-
- String[] oldNames = fTokenNames;
- fTokenNames = new String[fTokenCount << 1];
- System.arraycopy(oldNames, 0, fTokenNames, 0, fTokenCount);
- }
- fTokensBuffer[fTokenCount] = token;
- fTokenNames[fTokenCount] = text;
- fTokenCount++;
- //fTokensBuffer.add(token);
- //fTokenNames.add(text);
- }
- break;
- }
- connectToTree(conjunction, node);
- }
+class AttrNode extends XPathSyntaxTreeNode {
+ private String name;
- /**
- * Attach the two given nodes to the syntax tree
- */
- private void connectToTree(NodeTest conjunction, NodeTest node) {
- if (fCurrentNode == null && node != null) {
- if (conjunction != null) {
- fCurrentNode = conjunction;
- fCurrentNode.setFirstChild(node);
- }
- else {
- fCurrentNode = node;
- }
- }
- else if (fCurrentNode != null && !fCurrentNode.isComplete()) {
- if (node != null) {
- if (conjunction != null) {
- fCurrentNode.setSecondChild(conjunction);
- conjunction.setFirstChild(node);
- fCurrentNode = conjunction;
- }
- else {
- fCurrentNode.setSecondChild(node);
- while (fCurrentNode.getParent() != null &&
- fCurrentNode.isComplete()) {
- fCurrentNode = fCurrentNode.getParent();
- }
- }
- }
- }
- else if (fCurrentNode != null && fCurrentNode.isComplete()) {
- if (conjunction != null && node == null) {
- conjunction.setFirstChild(fCurrentNode);
- fCurrentNode = conjunction;
- }
- }
- }
+ public AttrNode(String name) {
+ this.name = name;
+ }
- /**
- * Call this method to complete building the syntax tree. Once called
- * this method will create the root node of the tree and attach the tree
- * constructed so far to the tree.
- */
- public NodeTest markEnd() throws XPathException {
- connectToTree(null, getNodeTest());
- NodeTest root = new NodeTest(TEST_CATEGORY_ROOT);
- root.setFirstChild(fCurrentNode);
- return root;
+ public boolean evaluate(QName element, XMLAttributes attributes) throws Exception {
+ String attrValue = attributes.getValue(name);
+ if (attrValue == null || attrValue.length() == 0) {
+ return false;
}
+ return true;
+ }
- private NodeTest getNodeTest() throws XPathException {
- int testType = getTestCategory();
- if (testType < 0) {
- return null;
- }
- NodeTest node = new NodeTest(testType);
- node.setLHS(fLHS);
- if (testType != TEST_CATEGORY_ATTR &&
- testType != TEST_CATEGORY_VALUE) {
- node.setRHS(fRHS);
- node.setComparator(fComparator);
- }
-
- node.setNumeric(fNumeric);
- fTokenCount = 0;
- //fTokensBuffer.clear();
- //fTokenNames.clear();
- return node;
+ public Object getValue(XMLAttributes attributes) throws Exception {
+ String attrValue = attributes.getValue(name);
+ if (attrValue == null) {
+ throw new XPathException("Attribute value is null");
}
+ return attrValue;
+ }
- /**
- * Analyzes the content currently in the tokens buffer and tries to
- * classify the expression into one of the test categories. Looks at
- * the number of tokens in the buffer, their order and types. While
- * doing so extracts the LHS, RHS and comparator components from the
- * test expression.
- */
- private int getTestCategory() throws XPathException {
- int testCategory;
- final int size = fTokenCount;
-
- switch (size) {
- case 0:
- return -1;
- case 1:
- //Only one token in the test
- if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_ATTR;
- }
- else {
- testCategory = TEST_CATEGORY_VALUE;
- if (fTokensBuffer[0] == Tokens.EXPRTOKEN_NUMERIC_LITERAL) {
- fNumeric = true;
- }
- }
- fLHS = fTokenNames[0];
- break;
-
- case 3:
- //3 tokens in the test
- if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[2] == Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_ATTR_ATTR;
- }
- else if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[2] != Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_ATTR_VALUE;
- }
- else if ((fTokensBuffer[0] == Tokens.EXPRTOKEN_NUMERIC_LITERAL &&
- fTokensBuffer[2] == Tokens.EXPRTOKEN_NUMERIC_LITERAL) ||
- (fTokensBuffer[0] == Tokens.EXPRTOKEN_STRING_LITERAL &&
- fTokensBuffer[2] == Tokens.EXPRTOKEN_STRING_LITERAL)) {
- testCategory = TEST_CATEGORY_VALUE_VALUE;
- }
- else {
- throw new XPathException("c-general-xpath");
- }
- fLHS = fTokenNames[0];
- fRHS = fTokenNames[2];
- fComparator = fTokensBuffer[1];
- break;
-
- case 5:
- //5 tokens in the test
- if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[1] == Tokens.EXPRTOKEN_KEYWORD_CAST) {
- testCategory = TEST_CATEGORY_ATTR_AS_CAST;
- fLHS = fTokenNames[0] + " cast as " + fTokenNames[3] + " ?";
- }
- else {
- testCategory = TEST_CATEGORY_VALUE_AS_CAST;
- fLHS = fTokenNames[0] + " cast as " + fTokenNames[3] + " ?";
- }
- break;
-
- case 7:
- //7 tokens in the test (one explicit cast is in the test)
- if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[1] == Tokens.EXPRTOKEN_KEYWORD_CAST &&
- fTokensBuffer[6] == Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_ATTR_AS_CAST_ATTR;
- fLHS = fTokenNames[0] + " cast as " + fTokenNames[3] + " ?";
- fRHS = fTokenNames[6];
- fComparator = fTokensBuffer[5];
- }
- else if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[3] == Tokens.EXPRTOKEN_KEYWORD_CAST &&
- fTokensBuffer[2] == Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_ATTR_ATTR_AS_CAST;
- fLHS = fTokenNames[0];
- fRHS = fTokenNames[2] + " cast as " + fTokenNames[5] + " ?";
- fComparator = fTokensBuffer[1];
- }
- else if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[1] == Tokens.EXPRTOKEN_KEYWORD_CAST &&
- fTokensBuffer[6] != Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_ATTR_AS_CAST_VALUE;
- fLHS = fTokenNames[0] + " cast as " + fTokenNames[3] + " ?";
- fRHS = fTokenNames[6];
- fComparator = fTokensBuffer[5];
- }
- else if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[3] == Tokens.EXPRTOKEN_KEYWORD_CAST &&
- fTokensBuffer[2] != Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_ATTR_VALUE_AS_CAST;
- fLHS = fTokenNames[0];
- fRHS = fTokenNames[2] + " cast as " + fTokenNames[5] + " ?";
- fComparator = fTokensBuffer[1];
- }
- else if (fTokensBuffer[0] != Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[1] == Tokens.EXPRTOKEN_KEYWORD_CAST &&
- fTokensBuffer[6] != Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_VALUE_AS_CAST_VALUE;
- fLHS = fTokenNames[0] + " cast as " + fTokenNames[3] + " ?";
- fRHS = fTokenNames[6];
- fComparator = fTokensBuffer[5];
- }
- else if (fTokensBuffer[0] != Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[3] == Tokens.EXPRTOKEN_KEYWORD_CAST &&
- fTokensBuffer[2] != Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_VALUE_VALUE_AS_CAST;
- fLHS = fTokenNames[0];
- fRHS = fTokenNames[2] + " cast as " + fTokenNames[5] + " ?";
- fComparator = fTokensBuffer[1];
- }
- else {
- throw new XPathException("c-general-xpath");
- }
- break;
-
- case 11:
- //11 tokens in the test (two explicit casts in the test)
- if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[6] == Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_ATTR_AS_CAST_ATTR_AS_CAST;
- }
- else if (fTokensBuffer[0] == Tokens.EXPRTOKEN_ATTR_NAME &&
- fTokensBuffer[6] != Tokens.EXPRTOKEN_ATTR_NAME) {
- testCategory = TEST_CATEGORY_ATTR_AS_CAST_VALUE_AS_CAST;
- }
- else {
- testCategory = TEST_CATEGORY_VALUE_AS_CAST_VALUE_AS_CAST;
- }
- fLHS = fTokenNames[0] + " cast as " + fTokenNames[3] + " ?";
- fRHS = fTokenNames[6] + " cast as " + fTokenNames[9] + " ?";
- fComparator = fTokensBuffer[5];
- break;
-
- default:
- throw new XPathException("c-general-xpath");
+ public int getType() {
+ return TYPE_UNTYPED;
+ }
+}
- }
+class CompNode extends XPathSyntaxTreeNode {
+ private int comp;
+ private XPathSyntaxTreeNode child1;
+ private XPathSyntaxTreeNode child2;
+
+ public static final int EQ = 0;
+ public static final int NE = 1;
+ public static final int LT = 2;
+ public static final int GT = 3;
+ public static final int LE = 4;
+ public static final int GE = 5;
+
+ public CompNode(int comp, XPathSyntaxTreeNode child1,
+ XPathSyntaxTreeNode child2) {
+ this.comp = comp;
+ this.child1 = child1;
+ this.child2 = child2;
+ }
- if (fTokensBuffer[0] == Tokens.EXPRTOKEN_NUMERIC_LITERAL) {
- fNumeric = true;
- }
- return testCategory;
+ public boolean evaluate(QName element, XMLAttributes attributes) throws Exception {
+ int type1 = child1.getType();
+ int type2 = child2.getType();
+ Object obj1, obj2;
+ XSSimpleTypeDecl simpleType;
+ SchemaDVFactory validator = SchemaDVFactory.getInstance();
+
+ if (type1 == TYPE_UNTYPED && type2 == TYPE_DOUBLE) {
+ // attribute and numeral
+ String attrValue = child1.getValue(attributes).toString();
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType("double");
+ //cast the attribute value into double as per the XPath 2.0 general comparison rules
+ obj1 = simpleType.validate(attrValue, null, null);
+ obj2 = child2.getValue(attributes);
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+
+ } else if (type1 == TYPE_UNTYPED && type2 == TYPE_STRING) {
+ // attribute and string
+ String attrValue = child1.getValue(attributes).toString();
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType("string");
+ //cast the attribute value into string as per the XPath 2.0 general comparison rules
+ obj1 = simpleType.validate(attrValue, null, null);
+ obj2 = child2.getValue(attributes);
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+
+ } else if (type1 == TYPE_DOUBLE && type2 == TYPE_UNTYPED) {
+ // numeral and attribute
+ String attrValue = child2.getValue(attributes).toString();
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType("double");
+ obj1 = child1.getValue(attributes);
+ //cast the attribute value into double as per the XPath 2.0 general comparison rules
+ obj2 = simpleType.validate(attrValue, null, null);
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+
+ } else if (type1 == TYPE_STRING && type2 == TYPE_UNTYPED) {
+ // string and attribute
+ String attrValue = child2.getValue(attributes).toString();
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType("string");
+ obj1 = child1.getValue(attributes);
+ //cast the attribute value into string as per the XPath 2.0 general comparison rules
+ obj2 = simpleType.validate(attrValue, null, null);
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+
+ } else if (type1 == TYPE_UNTYPED && type2 == TYPE_UNTYPED) {
+ // attr and attr
+ String attrVal1 = child1.getValue(attributes).toString();
+ String attrVal2 = child2.getValue(attributes).toString();
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType("string");
+ //cast the both attribute values into string as per the XPath 2.0 general comparison rules
+ obj1 = simpleType.validate(attrVal1, null, null);
+ obj2 = simpleType.validate(attrVal2, null, null);
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+
+ } else if (type1 == TYPE_UNTYPED && type2 == TYPE_OTHER) {
+ // attr and cast expr
+ String type = child2.getTypeName();
+ String attrVal = child1.getValue(attributes).toString();
+
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType(type);
+ if (simpleType == null) {
+ throw new XPathException("Casted type is not a built-in type");
+ }
+ //try to cast the attribute value into the type of the cast expression
+ obj1 = simpleType.validate(attrVal, null, null);
+ obj2 = child2.getValue(attributes);
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+
+ } else if (type1 == TYPE_OTHER && type2 == TYPE_UNTYPED) {
+ // cast expr and attr
+ String type = child1.getTypeName();
+ String attrVal = child2.getValue(attributes).toString();
+
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType(type);
+ if (simpleType == null) {
+ throw new XPathException("Casted type is not a built-in type");
+ }
+ obj1 = child1.getValue(attributes);
+ //try to cast the attribute value into the type of the cast expression
+ obj2 = simpleType.validate(attrVal, null, null);
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+
+ } else if (type1 == TYPE_OTHER && type2 == TYPE_OTHER) {
+ //cast expr and cast expr
+ String typeName1 = child1.getTypeName();
+ String typeName2 = child2.getTypeName();
+
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType(typeName1);
+ if (simpleType == null) {
+ throw new XPathException("Casted type is not a built-in type");
+ }
+ short dt1 = simpleType.getBuiltInKind();
+
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType(typeName2);
+ if (simpleType == null) {
+ throw new XPathException("Casted type is not a built-in type");
+ }
+ short dt2 = simpleType.getBuiltInKind();
+
+ // check whether the two types are comparable
+ if (DataMatcher.isComparable(dt1, dt2, null, null)) {
+ obj1 = simpleType.validate(child1.getValue(attributes), null, null);
+ obj2 = child2.getValue(attributes);
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+ } else {
+ throw new XPathException("Invalid comparison between incompatible types");
+ }
+
+ } else if (type1 == TYPE_DOUBLE && type2 == TYPE_DOUBLE) {
+ // numeric and numeric
+ obj1 = child1.getValue(attributes);
+ obj2 = child2.getValue(attributes);
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType("double");
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+
+ } else if (type1 == TYPE_STRING && type2 == TYPE_STRING) {
+ // string and string
+ obj1 = child1.getValue(attributes);
+ obj2 = child2.getValue(attributes);
+ simpleType = (XSSimpleTypeDecl) validator.getBuiltInType("string");
+ return DataMatcher.compareActualValues(obj1, obj2, comp, simpleType);
+
+ } else {
+ throw new XPathException("Invalid comparison");
}
+
}
+}
- /**
- * The syntax tree for test XPath expressions is composed of NodeTests.
- * A NodeTest encapsulates all the necessary information regarding a
- * simple test expressed in XPath 2.0 language.
- *
- * @author Hiranya Jayathilaka, University of Moratuwa
- */
- private static class NodeTest {
-
- private int fNodeType;
- private NodeTest fParentNode = null;
- private NodeTest[] fChildNodes = null;
-
- private String fLHS = null;
- private String fRHS = null;
- private int fComparator;
- private boolean fNumeric = false;
-
- public NodeTest(int nodeType) {
- this.fNodeType = nodeType;
- if (nodeType == SyntaxTreeBuilder.TEST_CONJUNCTION_OR ||
- nodeType == SyntaxTreeBuilder.TEST_CONJUNCTION_AND) {
- fChildNodes = new NodeTest[2];
- }
- else if (nodeType == SyntaxTreeBuilder.TEST_CATEGORY_ROOT) {
- fChildNodes = new NodeTest[1];
- }
- }
+class CastNode extends XPathSyntaxTreeNode {
+ private String castedType;
+ private XPathSyntaxTreeNode child;
+
+ public CastNode(XPathSyntaxTreeNode child, String castedType) {
+ this.child = child;
+ this.castedType = castedType;
+ }
- public int getType() {
- return fNodeType;
+ public boolean evaluate(QName element, XMLAttributes attributes) throws Exception {
+ Object obj = getValue(attributes);
+ SchemaDVFactory validator = SchemaDVFactory.getInstance();
+ XSSimpleTypeDecl simpleType = (XSSimpleTypeDecl) validator.getBuiltInType(getTypeName());
+ if (simpleType.getNumeric()) {
+ return obj != null && 0.0 != ((Double) obj).doubleValue();
+ }
+ else {
+ return obj != null;
}
+ }
- public NodeTest[] getChildren() {
- return fChildNodes;
+ public Object getValue(XMLAttributes attributes) throws Exception {
+ SchemaDVFactory validator = SchemaDVFactory.getInstance();
+ XSSimpleType type = validator.getBuiltInType(getTypeName());
+ if (type == null) {
+ throw new XPathException("Casted type is not a built-in type");
+ }
+
+ Object obj;
+ if (child.getType() == TYPE_UNTYPED) {
+ //attribute cast
+ String attrValue = child.getValue(attributes).toString();
+ obj = type.validate(attrValue, null, null);
+ } else {
+ //literal cast (perform using the string value of the literal node)
+ obj = type.validate(child.getStringValue(), null, null);
+ }
+
+ //Workaround (this is here because double validator can only validate double values)
+ if (type.getNumeric()) {
+ obj = validator.getBuiltInType("double").validate(obj, null, null);
}
+ return obj;
+ }
- public void setLHS(String text) {
- fLHS = text;
+ public String getTypeName() {
+ String localname = castedType;
+ int index = localname.indexOf(':');
+ if (index != -1) {
+ localname = localname.substring(index + 1);
}
+ return localname;
+ }
- public String getLHS() {
- return fLHS;
+ public int getType() {
+ String type = getTypeName();
+ SchemaDVFactory validator = SchemaDVFactory.getInstance();
+ XSSimpleTypeDecl simpleType = (XSSimpleTypeDecl) validator.getBuiltInType(type);
+ if (simpleType.getNumeric()) {
+ return TYPE_DOUBLE;
+ } else if (type.equals("string")) {
+ return TYPE_STRING;
+ } else {
+ return TYPE_OTHER;
}
+ }
+}
- public void setRHS(String text) {
- fRHS = text;
- }
+class FunctionNode extends XPathSyntaxTreeNode {
+ private String name;
+ private XPathSyntaxTreeNode child;
+
+ public FunctionNode(String name, XPathSyntaxTreeNode child) {
+ this.name = name;
+ this.child = child;
+ }
- public String getRHS() {
- return fRHS;
- }
+ public boolean evaluate(QName element, XMLAttributes attributes) {
+ return false;
+ }
- public void setComparator(int comp) {
- fComparator = comp;
- }
+ public String getValue(QName element, XMLAttributes attributes) {
+ return null;
+ }
+}
- public NodeTest getParent() {
- return fParentNode;
- }
+class DataMatcher {
- private void setParent(NodeTest parentNode) {
- this.fParentNode = parentNode;
- }
+ public static boolean compareActualValues(Object value1, Object value2, int comparator,
+ XSSimpleTypeDecl type) {
- public void setFirstChild(NodeTest test1) {
- if (fChildNodes != null) {
- fChildNodes[0] = test1;
- fChildNodes[0].setParent(this);
- }
- }
+ TypeValidator typeValidator = type.getTypeValidator();
+ short ordered = type.getOrdered();
- public void setSecondChild(NodeTest test2) {
- if (fChildNodes != null) {
- fChildNodes[1] = test2;
- fChildNodes[1].setParent(this);
+ if (ordered == XSSimpleTypeDecl.ORDERED_FALSE) {
+ //if the type is not ordered then only equality can be tested
+ //delegate the test to the type
+ if (comparator == CompNode.EQ) {
+ return type.isEqual(value1, value2);
}
- }
-
- public boolean getNumeric() {
- return fNumeric;
- }
-
- public void setNumeric(boolean numeric) {
- fNumeric = numeric;
- }
-
- /**
- * Checks whether the NodeTest is complete. A NodeTest is complete if it has both
- * an LHS and an RHS.
- */
- public boolean isComplete() {
- if (fNodeType != SyntaxTreeBuilder.TEST_CONJUNCTION_AND &&
- fNodeType != SyntaxTreeBuilder.TEST_CONJUNCTION_OR) {
- return true;
+ else if (comparator == CompNode.NE) {
+ return !type.isEqual(value1, value2);
}
else {
- if (fChildNodes[0] != null && fChildNodes[1] != null) {
- return true;
- }
+ //only equality can be tested upon unordered types
return false;
}
}
- /**
- * Evaluates the test expression stored in the node and returns a boolean
- * value.
- */
- public boolean evaluateNodeTest(QName element, XMLAttributes attributes) {
- Object actualVal1, actualVal2;
- Augmentations aug1, aug2;
- AttributePSVImpl attr1, attr2;
- short variety;
- XSSimpleTypeDecl type1, type2;
-
- switch (fNodeType) {
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR_VALUE:
- aug1 = attributes.getAugmentations(fLHS);
- if (aug1 == null) {
- return false;
- }
-
- attr1 = (AttributePSVImpl) aug1.getItem(Constants.ATTRIBUTE_PSVI);
- type1 = (XSSimpleTypeDecl) attr1.getTypeDefinition();
- variety = type1.getVariety();
- if (variety == XSSimpleTypeDefinition.VARIETY_UNION) {
- type1 = (XSSimpleTypeDecl) attr1.getMemberTypeDefinition();
- }
-
- actualVal1 = attr1.getActualNormalizedValue();
- try {
- actualVal2 = type1.validate(fRHS, null, null); //convert the value to the type of the attribute
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR_VALUE_AS_CAST:
- aug1 = attributes.getAugmentations(fLHS);
- if (aug1 == null) {
- return false;
- }
-
- attr1 = (AttributePSVImpl) aug1.getItem(Constants.ATTRIBUTE_PSVI);
- type1 = (XSSimpleTypeDecl) attr1.getTypeDefinition();
- variety = type1.getVariety();
- if (variety == XSSimpleTypeDefinition.VARIETY_UNION) {
- type1 = (XSSimpleTypeDecl) attr1.getMemberTypeDefinition();
- }
-
- actualVal1 = attr1.getActualNormalizedValue();
- type2 = getCastedType(fRHS); //get the casted type
- try {
- //cast the value into the specified type
- actualVal2 = type2.validate(getCastedValue(fRHS), null, null);
- //check whether the casted type and the attribute type are comparable
- if (DataMatcher.isComparable(
- attr1.getActualNormalizedValueType(),
- type2.getBuiltInKind(),
- attr1.getItemValueTypes(),
- null)) {
-
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- return false;
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR_AS_CAST_VALUE:
- aug1 = attributes.getAugmentations(getCastedValue(fLHS));
- if (aug1 == null) {
- return false;
- }
-
- attr1 = (AttributePSVImpl) aug1.getItem(Constants.ATTRIBUTE_PSVI);
- type1 = (XSSimpleTypeDecl) attr1.getTypeDefinition();
- variety = type1.getVariety();
- if (variety == XSSimpleTypeDefinition.VARIETY_UNION) {
- type1 = (XSSimpleTypeDecl) attr1.getMemberTypeDefinition();
- }
-
- type2 = getCastedType(fLHS);
- try {
- //perform the specified cast on the attribute value
- actualVal1 = type2.validate(attributes.getValue(getCastedValue(fLHS)), null, null);
- //convert the given value into the attribute's casted type
- actualVal2 = type2.validate(fRHS, null, null);
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type2);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR_AS_CAST_VALUE_AS_CAST:
- aug1 = attributes.getAugmentations(getCastedValue(fLHS));
- if (aug1 == null) {
- return false;
- }
-
- type1 = getCastedType(fLHS);
- type2 = getCastedType(fRHS);
-
- //check whether the two casted types are comparable
- if (DataMatcher.isComparable(
- type1.getBuiltInKind(),
- type2.getBuiltInKind(),
- null,
- null)) {
-
- try {
- //perform the two casts
- actualVal1 = type1.validate(attributes.getValue(getCastedValue(fLHS)), null, null);
- actualVal2 = type2.validate(getCastedValue(fRHS), null, null);
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
- }
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR_ATTR:
- aug1 = attributes.getAugmentations(fLHS);
- aug2 = attributes.getAugmentations(fRHS);
- if (aug1 == null || aug2 == null) {
- return false;
- }
-
- attr1 = (AttributePSVImpl) aug1.getItem(Constants.ATTRIBUTE_PSVI);
- attr2 = (AttributePSVImpl) aug2.getItem(Constants.ATTRIBUTE_PSVI);
- type1 = (XSSimpleTypeDecl) attr1.getTypeDefinition();
- type2 = (XSSimpleTypeDecl) attr2.getTypeDefinition();
-
- //check whether the two attribute types are comparable
- if (DataMatcher.isComparable(
- attr1.getActualNormalizedValueType(),
- attr2.getActualNormalizedValueType(),
- attr1.getItemValueTypes(),
- attr2.getItemValueTypes())) {
-
- actualVal1 = attr1.getActualNormalizedValue();
- actualVal2 = attr2.getActualNormalizedValue();
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- return false;
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR_ATTR_AS_CAST:
- aug1 = attributes.getAugmentations(fLHS);
- aug2 = attributes.getAugmentations(fRHS);
- if (aug1 == null || aug2 == null) {
- return false;
- }
-
- attr1 = (AttributePSVImpl) aug1.getItem(Constants.ATTRIBUTE_PSVI);
- type1 = (XSSimpleTypeDecl) attr1.getTypeDefinition();
- type2 = getCastedType(fRHS);
-
- //check whether the two attribute types are comparable
- if (DataMatcher.isComparable(
- attr1.getActualNormalizedValueType(),
- type2.getBuiltInKind(),
- attr1.getItemValueTypes(),
- null)) {
-
- actualVal1 = attr1.getActualNormalizedValue();
- try {
- //perform the cast
- actualVal2 = type2.validate(attributes.getValue(getCastedValue(fRHS)), null, null);
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
- }
- return false;
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR_AS_CAST_ATTR:
- aug1 = attributes.getAugmentations(fLHS);
- aug2 = attributes.getAugmentations(fRHS);
- if (aug1 == null || aug2 == null) {
- return false;
- }
-
- attr2 = (AttributePSVImpl) aug2.getItem(Constants.ATTRIBUTE_PSVI);
- type2 = (XSSimpleTypeDecl) attr2.getTypeDefinition();
- type1 = getCastedType(fLHS);
-
- //check whether the two attribute types are comparable
- if (DataMatcher.isComparable(
- type1.getBuiltInKind(),
- attr2.getActualNormalizedValueType(),
- null,
- attr2.getItemValueTypes())) {
-
- actualVal2 = attr2.getActualNormalizedValue();
- try {
- //perform the cast
- actualVal1 = type1.validate(attributes.getValue(getCastedValue(fRHS)), null, null);
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
- }
- return false;
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR_AS_CAST_ATTR_AS_CAST:
- aug1 = attributes.getAugmentations(fLHS);
- aug2 = attributes.getAugmentations(fRHS);
- if (aug1 == null || aug2 == null) {
- return false;
- }
-
- attr1 = (AttributePSVImpl) aug1.getItem(Constants.ATTRIBUTE_PSVI);
- type1 = getCastedType(fLHS);
- type2 = getCastedType(fRHS);
-
- //check whether the two casted types are comparable
- if (DataMatcher.isComparable(
- type1.getBuiltInKind(),
- type2.getBuiltInKind(),
- null,
- null)) {
-
- try {
- //perform the two casts
- actualVal1 = type1.validate(attributes.getValue(getCastedValue(fLHS)), null, null);
- actualVal2 = type2.validate(attributes.getValue(getCastedValue(fRHS)), null, null);
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
- }
- return false;
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_VALUE_VALUE:
- //treat both values as strings and compare
- if (!fNumeric) {
- return DataMatcher.compareActualValues(fLHS, fRHS, fComparator,
- (XSSimpleTypeDecl) SchemaDVFactory.getInstance().getBuiltInType("string"));
- }
- else {
- type1 = (XSSimpleTypeDecl) SchemaDVFactory.getInstance().
- getBuiltInType("decimal");
- try {
- actualVal1 = type1.validate(fLHS, null, null);
- actualVal2 = type1.validate(fRHS, null, null);
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
- }
-
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_VALUE_VALUE_AS_CAST:
- type2 = getCastedType(fRHS);
- try {
- //convert both values to the casted type
- actualVal1 = type2.validate(getCastedValue(fLHS), null, null);
- actualVal2 = type2.validate(getCastedValue(fRHS), null, null);
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type2);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_VALUE_AS_CAST_VALUE:
- type1 = getCastedType(fLHS);
- try {
- //convert both values to the casted type
- actualVal1 = type1.validate(getCastedValue(fLHS), null, null);
- actualVal2 = type1.validate(getCastedValue(fRHS), null, null);
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_VALUE_AS_CAST_VALUE_AS_CAST:
- type1 = getCastedType(fLHS);
- type2 = getCastedType(fRHS);
-
- //check whether the two casted types are comparable
- if (DataMatcher.isComparable(
- type1.getBuiltInKind(),
- type2.getBuiltInKind(),
- null,
- null)) {
- try {
- actualVal1 = type1.validate(getCastedValue(fLHS), null, null);
- actualVal2 = type1.validate(getCastedValue(fRHS), null, null);
- return DataMatcher.compareActualValues(actualVal1, actualVal2, fComparator, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
- }
- return false;
-
- case SyntaxTreeBuilder.TEST_CATEGORY_VALUE:
- if (fNumeric) {
- //if numeric treat as decimal
- type1 = (XSSimpleTypeDecl) SchemaDVFactory.getInstance().getBuiltInType("decimal");
- try {
- //see whether the value is numerically equal to 0
- actualVal1 = type1.validate(fLHS, null, null);
- actualVal2 = type1.validate("0", null, null);
- return !DataMatcher.compareActualValues(actualVal1, actualVal2,
- Tokens.EXPRTOKEN_COMPARATOR_EQUAL, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
- }
- return true;
-
- case SyntaxTreeBuilder.TEST_CATEGORY_VALUE_AS_CAST:
- type1 = getCastedType(fLHS);
- try {
- //perform the cast
- actualVal1 = type1.validate(getCastedValue(fLHS), null, null);
- actualVal2 = type1.validate("0", null, null);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
-
- if (actualVal1 == null) {
- return false;
- }
- else if (type1.getNumeric()) {
- return !DataMatcher.compareActualValues(actualVal1, actualVal2,
- Tokens.EXPRTOKEN_COMPARATOR_EQUAL, type1);
- }
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR:
- aug1 = attributes.getAugmentations(fLHS);
- if (aug1 == null) {
- return false;
- }
- attr1 = (AttributePSVImpl) aug1.getItem(Constants.ATTRIBUTE_PSVI);
- type1 = (XSSimpleTypeDecl) attr1.getTypeDefinition();
- actualVal1 = attr1.getActualNormalizedValue();
- if (actualVal1 == null) {
- return false;
- }
-
- if (type1.getNumeric()) {
- try {
- actualVal2 = type1.validate("0", null, null);
- return !DataMatcher.compareActualValues(actualVal1, actualVal2,
- Tokens.EXPRTOKEN_COMPARATOR_EQUAL, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
- }
- return true;
-
-
- case SyntaxTreeBuilder.TEST_CATEGORY_ATTR_AS_CAST:
- aug1 = attributes.getAugmentations(getCastedValue(fLHS));
- if (aug1 == null) {
- return false;
- }
- attr1 = (AttributePSVImpl) aug1.getItem(Constants.ATTRIBUTE_PSVI);
- type1 = getCastedType(fLHS);
- actualVal1 = attr1.getActualNormalizedValue();
- if (actualVal1 == null) {
- return false;
- }
-
- if (type1.getNumeric()) {
- try {
- actualVal1 = type1.validate(attributes.getValue(getCastedValue(fLHS)), null, null);
- actualVal2 = type1.validate("0", null, null);
- return !DataMatcher.compareActualValues(actualVal1, actualVal2,
- Tokens.EXPRTOKEN_COMPARATOR_EQUAL, type1);
- }
- catch (InvalidDatatypeValueException e) {
- return false;
- }
- }
- return true;
- }
- return false;
- }
-
- private XSSimpleTypeDecl getCastedType(String castExpr) {
- int start = castExpr.indexOf(" cast as ", 0) + 9;
- int end = castExpr.indexOf(" ?", start);
- String qname = castExpr.substring(start, end);
- String local = qname;
- int colonIndex = qname.indexOf(':');
- if (colonIndex != -1) {
- local = qname.substring(colonIndex + 1);
- }
- return (XSSimpleTypeDecl) SchemaDVFactory.getInstance().getBuiltInType(local);
+ //if the type is ordered then the corresponding TypeValidator should
+ //know how to compare the values
+ switch (comparator) {
+
+ case CompNode.EQ: return typeValidator.compare(value1, value2) == 0;
+ case CompNode.NE: return typeValidator.compare(value1, value2) != 0;
+ case CompNode.GT: return typeValidator.compare(value1, value2) > 0;
+ case CompNode.GE: return typeValidator.compare(value1, value2) >= 0;
+ case CompNode.LT: return typeValidator.compare(value1, value2) < 0;
+ case CompNode.LE: return typeValidator.compare(value1, value2) <= 0;
}
-
- private String getCastedValue(String castExpr) {
- int end = castExpr.indexOf(" cast as ", 0);
[... 158 lines stripped ...]
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xerces.apache.org
For additional commands, e-mail: commits-help@xerces.apache.org