xpathquerybuilder.java

来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 1,077 行 · 第 1/4 页

JAVA
1,077
字号
        } catch (Throwable t) {            // also catch any other exception            throw new InvalidQueryException(t.getMessage(), t);        }        if (exceptions.size() > 0) {            // simply report the first one            Exception e = (Exception) exceptions.get(0);            if (e instanceof InvalidQueryException) {                // just re-throw                throw (InvalidQueryException) e;            } else {                // otherwise package                throw new InvalidQueryException(e.getMessage(), e);            }        }    }    /**     * Creates a <code>QueryNode</code> tree from a XPath statement.     *     * @param statement the XPath statement.     * @param resolver  the namespace resolver to use.     * @return the <code>QueryNode</code> tree for the XPath statement.     * @throws InvalidQueryException if the XPath statement is malformed.     */    public static QueryRootNode createQuery(String statement,                                            NamespaceResolver resolver)            throws InvalidQueryException {        return new XPathQueryBuilder(statement, resolver).getRootNode();    }    /**     * Creates a String representation of the query node tree in XPath syntax.     *     * @param root     the root of the query node tree.     * @param resolver to resolve QNames.     * @return a String representation of the query node tree.     * @throws InvalidQueryException if the query node tree cannot be converted     *                               into a String representation due to restrictions in XPath.     */    public static String toString(QueryRootNode root, NamespaceResolver resolver)            throws InvalidQueryException {        return QueryFormat.toString(root, resolver);    }    /**     * Returns the root node of the <code>QueryNode</code> tree.     *     * @return the root node of the <code>QueryNode</code> tree.     */    QueryRootNode getRootNode() {        return root;    }    //---------------------< XPathVisitor >-------------------------------------    /**     * Implements the generic visit method for this <code>XPathVisitor</code>.     *     * @param node the current node as created by the XPath parser.     * @param data the current <code>QueryNode</code> created by this     *             <code>XPathVisitor</code>.     * @return the current <code>QueryNode</code>. Can be different from     *         <code>data</code>.     */    public Object visit(SimpleNode node, Object data) {        QueryNode queryNode = (QueryNode) data;        switch (node.getId()) {            case JJTXPATH2:                queryNode = createPathQueryNode(node);                break;            case JJTROOT:            case JJTROOTDESCENDANTS:                if (queryNode instanceof PathQueryNode) {                    ((PathQueryNode) queryNode).setAbsolute(true);                } else {                    exceptions.add(new InvalidQueryException(                            "Unsupported root level query node: " + queryNode));                }                break;            case JJTSTEPEXPR:                if (isAttributeAxis(node)) {                    if (queryNode.getType() == QueryNode.TYPE_RELATION                            || (queryNode.getType() == QueryNode.TYPE_DEREF && ((DerefQueryNode) queryNode).getRefProperty() == null)                            || queryNode.getType() == QueryNode.TYPE_ORDER                            || queryNode.getType() == QueryNode.TYPE_PATH                            || queryNode.getType() == QueryNode.TYPE_TEXTSEARCH) {                        // traverse                        node.childrenAccept(this, queryNode);                    } else if (queryNode.getType() == QueryNode.TYPE_NOT) {                        // is null expression                        RelationQueryNode isNull                                = new RelationQueryNode(queryNode,                                        RelationQueryNode.OPERATION_NULL);                        applyRelativePath(isNull);                        node.childrenAccept(this, isNull);                        NotQueryNode notNode = (NotQueryNode) queryNode;                        NAryQueryNode parent = (NAryQueryNode) notNode.getParent();                        parent.removeOperand(notNode);                        parent.addOperand(isNull);                    } else {                        // not null expression                        RelationQueryNode notNull =                                new RelationQueryNode(queryNode,                                        RelationQueryNode.OPERATION_NOT_NULL);                        applyRelativePath(notNull);                        node.childrenAccept(this, notNull);                        ((NAryQueryNode) queryNode).addOperand(notNull);                    }                } else {                    if (queryNode.getType() == QueryNode.TYPE_PATH) {                        createLocationStep(node, (NAryQueryNode) queryNode);                    } else if (queryNode.getType() == QueryNode.TYPE_TEXTSEARCH                            || queryNode.getType() == QueryNode.TYPE_RELATION) {                        node.childrenAccept(this, queryNode);                    } else {                        // step within a predicate                        RelationQueryNode tmp = new RelationQueryNode(                                null, RelationQueryNode.OPERATION_NOT_NULL);                        node.childrenAccept(this, tmp);                        if (tmpRelPath == null) {                            tmpRelPath = new Path.PathBuilder();                        }                        tmpRelPath.addLast(tmp.getRelativePath().getNameElement());                    }                }                break;            case JJTNAMETEST:                if (queryNode.getType() == QueryNode.TYPE_LOCATION                        || queryNode.getType() == QueryNode.TYPE_DEREF                        || queryNode.getType() == QueryNode.TYPE_RELATION                        || queryNode.getType() == QueryNode.TYPE_TEXTSEARCH                        || queryNode.getType() == QueryNode.TYPE_PATH) {                    createNodeTest(node, queryNode);                } else if (queryNode.getType() == QueryNode.TYPE_ORDER) {                    createOrderSpec(node, (OrderQueryNode) queryNode);                } else {                    // traverse                    node.childrenAccept(this, queryNode);                }                break;            case JJTELEMENTNAMEORWILDCARD:                if (queryNode.getType() == QueryNode.TYPE_LOCATION) {                    SimpleNode child = (SimpleNode) node.jjtGetChild(0);                    if (child.getId() != JJTANYNAME) {                        createNodeTest(child, queryNode);                    }                }                break;            case JJTTEXTTEST:                if (queryNode.getType() == QueryNode.TYPE_LOCATION) {                    LocationStepQueryNode loc = (LocationStepQueryNode) queryNode;                    loc.setNameTest(JCR_XMLTEXT);                }                break;            case JJTTYPENAME:                if (queryNode.getType() == QueryNode.TYPE_LOCATION) {                    LocationStepQueryNode loc = (LocationStepQueryNode) queryNode;                    String ntName = ((SimpleNode) node.jjtGetChild(0)).getValue();                    try {                        QName nt = NameFormat.parse(ntName, resolver);                        NodeTypeQueryNode nodeType = new NodeTypeQueryNode(loc, nt);                        loc.addPredicate(nodeType);                    } catch (NameException e) {                        exceptions.add(new InvalidQueryException("Not a valid name: " + ntName));                    }                }                break;            case JJTOREXPR:                NAryQueryNode parent = (NAryQueryNode) queryNode;                QueryNode orQueryNode = new OrQueryNode(parent);                parent.addOperand(orQueryNode);                // traverse                node.childrenAccept(this, orQueryNode);                break;            case JJTANDEXPR:                parent = (NAryQueryNode) queryNode;                QueryNode andQueryNode = new AndQueryNode(parent);                parent.addOperand(andQueryNode);                // traverse                node.childrenAccept(this, andQueryNode);                break;            case JJTCOMPARISONEXPR:                createExpression(node, (NAryQueryNode) queryNode);                break;            case JJTSTRINGLITERAL:            case JJTDECIMALLITERAL:            case JJTDOUBLELITERAL:            case JJTINTEGERLITERAL:                if (queryNode.getType() == QueryNode.TYPE_RELATION) {                    assignValue(node, (RelationQueryNode) queryNode);                } else if (queryNode.getType() == QueryNode.TYPE_LOCATION) {                    if (node.getId() == JJTINTEGERLITERAL) {                        int index = Integer.parseInt(node.getValue());                        ((LocationStepQueryNode) queryNode).setIndex(index);                    } else {                        exceptions.add(new InvalidQueryException("LocationStep only allows integer literal as position index"));                    }                } else {                    exceptions.add(new InvalidQueryException("Parse error: data is not a RelationQueryNode"));                }                break;            case JJTUNARYMINUS:                if (queryNode.getType() == QueryNode.TYPE_RELATION) {                    ((RelationQueryNode) queryNode).setUnaryMinus(true);                } else {                    exceptions.add(new InvalidQueryException("Parse error: data is not a RelationQueryNode"));                }                break;            case JJTFUNCTIONCALL:                queryNode = createFunction(node, queryNode);                break;            case JJTORDERBYCLAUSE:                root.setOrderNode(new OrderQueryNode(root));                queryNode = root.getOrderNode();                node.childrenAccept(this, queryNode);                break;            case JJTORDERMODIFIER:                if (node.jjtGetNumChildren() > 0                        && ((SimpleNode) node.jjtGetChild(0)).getId() == JJTDESCENDING) {                    OrderQueryNode.OrderSpec[] specs = ((OrderQueryNode) queryNode).getOrderSpecs();                    specs[specs.length - 1].setAscending(false);                }                break;            case JJTPREDICATELIST:                if (queryNode.getType() == QueryNode.TYPE_PATH) {                    // switch to last location                    QueryNode[] operands = ((PathQueryNode) queryNode).getOperands();                    queryNode = operands[operands.length - 1];                }                node.childrenAccept(this, queryNode);                break;            case JJTPREDICATE:                if (queryNode.getType() == QueryNode.TYPE_LOCATION                        || queryNode.getType() == QueryNode.TYPE_DEREF) {                    node.childrenAccept(this, queryNode);                } else {                    // predicate not allowed here                    exceptions.add(new InvalidQueryException("Unsupported location for predicate"));                }                break;            case JJTDOTDOT:                exceptions.add(new InvalidQueryException("Parent axis is not supported"));                break;            default:                // per default traverse                node.childrenAccept(this, queryNode);        }        return queryNode;    }    //----------------------< internal >----------------------------------------    /**     * Applies {@link #tmpRelPath} to <code>node</code> and reset the path to     * <code>null</code>.     *     * @param node a relation query node.     */    private void applyRelativePath(RelationQueryNode node) {        if (tmpRelPath != null) {            try {                Path relPath = tmpRelPath.getPath();                for (int i = 0; i < relPath.getLength(); i++) {                    node.addPathElement(relPath.getElement(i));                }            } catch (MalformedPathException e) {                // should never happen            }            tmpRelPath = null;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?