Search in sources :

Example 1 with PathQueryNode

use of org.apache.jackrabbit.spi.commons.query.PathQueryNode in project jackrabbit by apache.

the class QueryFormat method visit.

public Object visit(RelationQueryNode node, Object data) throws RepositoryException {
    StringBuffer sb = (StringBuffer) data;
    try {
        StringBuffer propName = new StringBuffer();
        PathQueryNode relPath = node.getRelativePath();
        if (relPath == null) {
            propName.append(".");
        } else if (relPath.getPathSteps().length > 1) {
            exceptions.add(new InvalidQueryException("Child axis not supported in SQL"));
            return data;
        } else {
            visit(relPath, data);
        }
        // surround name with property function
        node.acceptOperands(this, propName);
        if (node.getOperation() == OPERATION_EQ_VALUE || node.getOperation() == OPERATION_EQ_GENERAL) {
            sb.append(propName);
            sb.append(" = ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_GE_VALUE || node.getOperation() == OPERATION_GE_GENERAL) {
            sb.append(propName);
            sb.append(" >= ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_GT_VALUE || node.getOperation() == OPERATION_GT_GENERAL) {
            sb.append(propName);
            sb.append(" > ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_LE_VALUE || node.getOperation() == OPERATION_LE_GENERAL) {
            sb.append(propName);
            sb.append(" <= ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_LIKE) {
            sb.append(propName);
            sb.append(" LIKE ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_LT_VALUE || node.getOperation() == OPERATION_LT_GENERAL) {
            sb.append(propName);
            sb.append(" < ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_NE_VALUE || node.getOperation() == OPERATION_NE_GENERAL) {
            sb.append(propName);
            sb.append(" <> ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_NULL) {
            sb.append(propName);
            sb.append(" IS NULL");
        } else if (node.getOperation() == OPERATION_NOT_NULL) {
            sb.append(propName);
            sb.append(" IS NOT NULL");
        } else if (node.getOperation() == OPERATION_SIMILAR) {
            sb.append("SIMILAR(");
            sb.append(propName);
            sb.append(", ");
            appendValue(node, sb);
            sb.append(")");
        } else if (node.getOperation() == OPERATION_SPELLCHECK) {
            sb.append("SPELLCHECK(");
            appendValue(node, sb);
            sb.append(")");
        } else {
            exceptions.add(new InvalidQueryException("Invalid operation: " + node.getOperation()));
        }
        if (node.getOperation() == OPERATION_LIKE && node.getStringValue().indexOf('\\') > -1) {
            sb.append(" ESCAPE '\\'");
        }
    } catch (NamespaceException e) {
        exceptions.add(e);
    }
    return sb;
}
Also used : PathQueryNode(org.apache.jackrabbit.spi.commons.query.PathQueryNode) NamespaceException(javax.jcr.NamespaceException) InvalidQueryException(javax.jcr.query.InvalidQueryException)

Example 2 with PathQueryNode

use of org.apache.jackrabbit.spi.commons.query.PathQueryNode in project jackrabbit by apache.

the class XPathQueryBuilder method visit.

//---------------------< 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 = factory.createRelationQueryNode(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 = factory.createRelationQueryNode(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 = factory.createRelationQueryNode(null, RelationQueryNode.OPERATION_NOT_NULL);
                    node.childrenAccept(this, tmp);
                    if (tmpRelPath == null) {
                        tmpRelPath = new PathBuilder();
                    }
                    PathQueryNode relPath = tmp.getRelativePath();
                    LocationStepQueryNode[] steps = relPath.getPathSteps();
                    Name nameTest = steps[steps.length - 1].getNameTest();
                    if (nameTest == null) {
                        // see LocationStepQueryNode javadoc on when getNameTest()==null: when it was a star (asterisk)
                        nameTest = RelationQueryNode.STAR_NAME_TEST;
                    }
                    tmpRelPath.addLast(nameTest);
                }
            }
            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) {
                setOrderSpecPath(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 {
                    Name nt = resolver.getQName(ntName);
                    NodeTypeQueryNode nodeType = factory.createNodeTypeQueryNode(loc, nt);
                    loc.addPredicate(nodeType);
                } catch (NameException e) {
                    exceptions.add(new InvalidQueryException("Not a valid name: " + ntName));
                } catch (NamespaceException e) {
                    exceptions.add(new InvalidQueryException("Not a valid name: " + ntName));
                }
            }
            break;
        case JJTOREXPR:
            NAryQueryNode parent = (NAryQueryNode) queryNode;
            QueryNode orQueryNode = factory.createOrQueryNode(parent);
            parent.addOperand(orQueryNode);
            // traverse
            node.childrenAccept(this, orQueryNode);
            break;
        case JJTANDEXPR:
            parent = (NAryQueryNode) queryNode;
            QueryNode andQueryNode = factory.createAndQueryNode(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(factory.createOrderQueryNode(root));
            queryNode = root.getOrderNode();
            node.childrenAccept(this, queryNode);
            break;
        case JJTORDERSPEC:
            OrderQueryNode orderQueryNode = (OrderQueryNode) queryNode;
            orderQueryNode.newOrderSpec();
            node.childrenAccept(this, queryNode);
            if (!orderQueryNode.isValid()) {
                exceptions.add(new InvalidQueryException("Invalid order specification. (Missing @?)"));
            }
            break;
        case JJTORDERMODIFIER:
            if (node.jjtGetNumChildren() > 0 && ((SimpleNode) node.jjtGetChild(0)).getId() == JJTDESCENDING) {
                ((OrderQueryNode) queryNode).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:
            if (queryNode instanceof LocationStepQueryNode) {
                ((LocationStepQueryNode) queryNode).setNameTest(PATH_FACTORY.getParentElement().getName());
            } else {
                ((RelationQueryNode) queryNode).addPathElement(PATH_FACTORY.getParentElement());
            }
            break;
        default:
            // per default traverse
            node.childrenAccept(this, queryNode);
    }
    return queryNode;
}
Also used : NAryQueryNode(org.apache.jackrabbit.spi.commons.query.NAryQueryNode) OrderQueryNode(org.apache.jackrabbit.spi.commons.query.OrderQueryNode) LocationStepQueryNode(org.apache.jackrabbit.spi.commons.query.LocationStepQueryNode) RelationQueryNode(org.apache.jackrabbit.spi.commons.query.RelationQueryNode) Name(org.apache.jackrabbit.spi.Name) PathQueryNode(org.apache.jackrabbit.spi.commons.query.PathQueryNode) PathBuilder(org.apache.jackrabbit.spi.commons.name.PathBuilder) NameException(org.apache.jackrabbit.spi.commons.conversion.NameException) IllegalNameException(org.apache.jackrabbit.spi.commons.conversion.IllegalNameException) RelationQueryNode(org.apache.jackrabbit.spi.commons.query.RelationQueryNode) OrderQueryNode(org.apache.jackrabbit.spi.commons.query.OrderQueryNode) QueryNode(org.apache.jackrabbit.spi.commons.query.QueryNode) DerefQueryNode(org.apache.jackrabbit.spi.commons.query.DerefQueryNode) NAryQueryNode(org.apache.jackrabbit.spi.commons.query.NAryQueryNode) NotQueryNode(org.apache.jackrabbit.spi.commons.query.NotQueryNode) NodeTypeQueryNode(org.apache.jackrabbit.spi.commons.query.NodeTypeQueryNode) PathQueryNode(org.apache.jackrabbit.spi.commons.query.PathQueryNode) TextsearchQueryNode(org.apache.jackrabbit.spi.commons.query.TextsearchQueryNode) PropertyFunctionQueryNode(org.apache.jackrabbit.spi.commons.query.PropertyFunctionQueryNode) LocationStepQueryNode(org.apache.jackrabbit.spi.commons.query.LocationStepQueryNode) NamespaceException(javax.jcr.NamespaceException) NotQueryNode(org.apache.jackrabbit.spi.commons.query.NotQueryNode) InvalidQueryException(javax.jcr.query.InvalidQueryException) NodeTypeQueryNode(org.apache.jackrabbit.spi.commons.query.NodeTypeQueryNode)

Example 3 with PathQueryNode

use of org.apache.jackrabbit.spi.commons.query.PathQueryNode in project jackrabbit by apache.

the class QueryFormat method visit.

public Object visit(RelationQueryNode node, Object data) throws RepositoryException {
    StringBuffer sb = (StringBuffer) data;
    try {
        StringBuffer propPath = new StringBuffer();
        // only encode if not position function
        PathQueryNode relPath = node.getRelativePath();
        if (relPath == null) {
            propPath.append(".");
        } else if (relPath.getNumOperands() > 0 && XPathQueryBuilder.FN_POSITION_FULL.equals(relPath.getPathSteps()[0].getNameTest())) {
            propPath.append(resolver.getJCRName(XPathQueryBuilder.FN_POSITION_FULL));
        } else {
            LocationStepQueryNode[] steps = relPath.getPathSteps();
            String slash = "";
            for (int i = 0; i < steps.length; i++) {
                propPath.append(slash);
                slash = "/";
                if (i == steps.length - 1 && node.getOperation() != OPERATION_SIMILAR) {
                    // last step
                    propPath.append("@");
                }
                visit(steps[i], propPath);
            }
        }
        // surround name with property function
        node.acceptOperands(this, propPath);
        if (node.getOperation() == OPERATION_EQ_VALUE) {
            sb.append(propPath).append(" eq ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_EQ_GENERAL) {
            sb.append(propPath).append(" = ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_GE_GENERAL) {
            sb.append(propPath).append(" >= ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_GE_VALUE) {
            sb.append(propPath).append(" ge ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_GT_GENERAL) {
            sb.append(propPath).append(" > ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_GT_VALUE) {
            sb.append(propPath).append(" gt ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_LE_GENERAL) {
            sb.append(propPath).append(" <= ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_LE_VALUE) {
            sb.append(propPath).append(" le ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_LIKE) {
            sb.append(resolver.getJCRName(XPathQueryBuilder.JCR_LIKE));
            sb.append("(").append(propPath).append(", ");
            appendValue(node, sb);
            sb.append(")");
        } else if (node.getOperation() == OPERATION_LT_GENERAL) {
            sb.append(propPath).append(" < ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_LT_VALUE) {
            sb.append(propPath).append(" lt ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_NE_GENERAL) {
            sb.append(propPath).append(" != ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_NE_VALUE) {
            sb.append(propPath).append(" ne ");
            appendValue(node, sb);
        } else if (node.getOperation() == OPERATION_NULL) {
            sb.append(resolver.getJCRName(XPathQueryBuilder.FN_NOT));
            sb.append("(").append(propPath).append(")");
        } else if (node.getOperation() == OPERATION_NOT_NULL) {
            sb.append(propPath);
        } else if (node.getOperation() == OPERATION_SIMILAR) {
            sb.append(resolver.getJCRName(XPathQueryBuilder.REP_SIMILAR));
            sb.append("(").append(propPath).append(", ");
            appendValue(node, sb);
            sb.append(")");
        } else if (node.getOperation() == OPERATION_SPELLCHECK) {
            sb.append(resolver.getJCRName(XPathQueryBuilder.REP_SPELLCHECK));
            sb.append("(");
            appendValue(node, sb);
            sb.append(")");
        } else {
            exceptions.add(new InvalidQueryException("Invalid operation: " + node.getOperation()));
        }
    } catch (NamespaceException e) {
        exceptions.add(e);
    }
    return sb;
}
Also used : PathQueryNode(org.apache.jackrabbit.spi.commons.query.PathQueryNode) NamespaceException(javax.jcr.NamespaceException) InvalidQueryException(javax.jcr.query.InvalidQueryException)

Example 4 with PathQueryNode

use of org.apache.jackrabbit.spi.commons.query.PathQueryNode in project jackrabbit by apache.

the class LuceneQueryBuilder method visit.

public Object visit(RelationQueryNode node, Object data) throws RepositoryException {
    PathQueryNode relPath = node.getRelativePath();
    if (relPath == null && node.getOperation() != QueryConstants.OPERATION_SIMILAR && node.getOperation() != QueryConstants.OPERATION_SPELLCHECK) {
        exceptions.add(new InvalidQueryException("@* not supported in predicate"));
        return data;
    }
    LocationStepQueryNode[] steps = relPath.getPathSteps();
    Name propertyName;
    if (node.getOperation() == QueryConstants.OPERATION_SIMILAR) {
        // this is a bit ugly:
        // use the name of a dummy property because relPath actually
        // references a property. whereas the relPath of the similar
        // operation references a node
        propertyName = NameConstants.JCR_PRIMARYTYPE;
    } else {
        propertyName = steps[steps.length - 1].getNameTest();
    }
    Query query;
    String[] stringValues = new String[1];
    switch(node.getValueType()) {
        case 0:
            // not set: either IS NULL or IS NOT NULL
            break;
        case QueryConstants.TYPE_DATE:
            stringValues[0] = DateField.dateToString(node.getDateValue());
            break;
        case QueryConstants.TYPE_DOUBLE:
            stringValues[0] = DoubleField.doubleToString(node.getDoubleValue());
            break;
        case QueryConstants.TYPE_LONG:
            stringValues[0] = LongField.longToString(node.getLongValue());
            break;
        case QueryConstants.TYPE_STRING:
            if (node.getOperation() == QueryConstants.OPERATION_EQ_GENERAL || node.getOperation() == QueryConstants.OPERATION_EQ_VALUE || node.getOperation() == QueryConstants.OPERATION_NE_GENERAL || node.getOperation() == QueryConstants.OPERATION_NE_VALUE) {
                // only use coercing on non-range operations
                stringValues = getStringValues(propertyName, node.getStringValue());
            } else {
                stringValues[0] = node.getStringValue();
            }
            break;
        case QueryConstants.TYPE_POSITION:
            // ignore position. is handled in the location step
            return null;
        default:
            throw new IllegalArgumentException("Unknown relation type: " + node.getValueType());
    }
    // get property transformation
    final int[] transform = new int[] { TransformConstants.TRANSFORM_NONE };
    node.acceptOperands(new DefaultQueryNodeVisitor() {

        public Object visit(PropertyFunctionQueryNode node, Object data) {
            if (node.getFunctionName().equals(PropertyFunctionQueryNode.LOWER_CASE)) {
                transform[0] = TransformConstants.TRANSFORM_LOWER_CASE;
            } else if (node.getFunctionName().equals(PropertyFunctionQueryNode.UPPER_CASE)) {
                transform[0] = TransformConstants.TRANSFORM_UPPER_CASE;
            }
            return data;
        }
    }, null);
    String field = "";
    try {
        field = resolver.getJCRName(propertyName);
    } catch (NamespaceException e) {
        // should never happen
        exceptions.add(e);
    }
    // support for fn:name()
    if (propertyName.equals(FN_NAME)) {
        if (node.getValueType() != QueryConstants.TYPE_STRING) {
            exceptions.add(new InvalidQueryException("Name function can " + "only be used in conjunction with a string literal"));
            return data;
        }
        if (node.getOperation() == QueryConstants.OPERATION_EQ_VALUE || node.getOperation() == QueryConstants.OPERATION_EQ_GENERAL) {
            // check if string literal is a valid XML Name
            if (XMLChar.isValidName(node.getStringValue())) {
                // parse string literal as JCR Name
                try {
                    Name n = session.getQName(ISO9075.decode(node.getStringValue()));
                    query = new NameQuery(n, indexFormatVersion, nsMappings);
                } catch (NameException e) {
                    exceptions.add(e);
                    return data;
                } catch (NamespaceException e) {
                    exceptions.add(e);
                    return data;
                }
            } else {
                // will never match -> create dummy query
                query = new BooleanQuery();
            }
        } else if (node.getOperation() == QueryConstants.OPERATION_LIKE) {
            // no coercing, see above
            if (stringValues[0].equals("%")) {
                query = new org.apache.lucene.search.MatchAllDocsQuery();
            } else {
                query = new WildcardNameQuery(stringValues[0], transform[0], session, nsMappings, cache);
            }
        } else {
            exceptions.add(new InvalidQueryException("Name function can " + "only be used in conjunction with the following operators: equals, like"));
            return data;
        }
    } else {
        switch(node.getOperation()) {
            // =
            case QueryConstants.OPERATION_EQ_VALUE:
            case QueryConstants.OPERATION_EQ_GENERAL:
                BooleanQuery or = new BooleanQuery();
                for (String value : stringValues) {
                    Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
                    Query q;
                    if (transform[0] == TransformConstants.TRANSFORM_UPPER_CASE) {
                        q = new CaseTermQuery.Upper(t);
                    } else if (transform[0] == TransformConstants.TRANSFORM_LOWER_CASE) {
                        q = new CaseTermQuery.Lower(t);
                    } else {
                        q = new JackrabbitTermQuery(t);
                    }
                    or.add(q, Occur.SHOULD);
                }
                query = or;
                if (node.getOperation() == QueryConstants.OPERATION_EQ_VALUE) {
                    query = createSingleValueConstraint(or, field);
                }
                break;
            // >=
            case QueryConstants.OPERATION_GE_VALUE:
            case QueryConstants.OPERATION_GE_GENERAL:
                or = new BooleanQuery();
                for (String value : stringValues) {
                    Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
                    Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, "￿"));
                    or.add(new RangeQuery(lower, upper, true, transform[0], cache), Occur.SHOULD);
                }
                query = or;
                if (node.getOperation() == QueryConstants.OPERATION_GE_VALUE) {
                    query = createSingleValueConstraint(or, field);
                }
                break;
            // >
            case QueryConstants.OPERATION_GT_VALUE:
            case QueryConstants.OPERATION_GT_GENERAL:
                or = new BooleanQuery();
                for (String value : stringValues) {
                    Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
                    Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, "￿"));
                    or.add(new RangeQuery(lower, upper, false, transform[0], cache), Occur.SHOULD);
                }
                query = or;
                if (node.getOperation() == QueryConstants.OPERATION_GT_VALUE) {
                    query = createSingleValueConstraint(or, field);
                }
                break;
            // <=
            case QueryConstants.OPERATION_LE_VALUE:
            case // <=
            QueryConstants.OPERATION_LE_GENERAL:
                or = new BooleanQuery();
                for (String value : stringValues) {
                    Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
                    Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
                    or.add(new RangeQuery(lower, upper, true, transform[0], cache), Occur.SHOULD);
                }
                query = or;
                if (node.getOperation() == QueryConstants.OPERATION_LE_VALUE) {
                    query = createSingleValueConstraint(query, field);
                }
                break;
            case // LIKE
            QueryConstants.OPERATION_LIKE:
                // no coercing, see above
                if (stringValues[0].equals("%")) {
                    query = Util.createMatchAllQuery(field, indexFormatVersion, cache);
                } else {
                    query = new WildcardQuery(FieldNames.PROPERTIES, field, stringValues[0], transform[0], cache);
                }
                break;
            // <
            case QueryConstants.OPERATION_LT_VALUE:
            case QueryConstants.OPERATION_LT_GENERAL:
                or = new BooleanQuery();
                for (String value : stringValues) {
                    Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
                    Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
                    or.add(new RangeQuery(lower, upper, false, transform[0], cache), Occur.SHOULD);
                }
                query = or;
                if (node.getOperation() == QueryConstants.OPERATION_LT_VALUE) {
                    query = createSingleValueConstraint(or, field);
                }
                break;
            case // !=
            QueryConstants.OPERATION_NE_VALUE:
                // match nodes with property 'field' that includes svp and mvp
                BooleanQuery notQuery = new BooleanQuery();
                notQuery.add(Util.createMatchAllQuery(field, indexFormatVersion, cache), Occur.SHOULD);
                // exclude all nodes where 'field' has the term in question
                for (String value : stringValues) {
                    Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
                    Query q;
                    if (transform[0] == TransformConstants.TRANSFORM_UPPER_CASE) {
                        q = new CaseTermQuery.Upper(t);
                    } else if (transform[0] == TransformConstants.TRANSFORM_LOWER_CASE) {
                        q = new CaseTermQuery.Lower(t);
                    } else {
                        q = new JackrabbitTermQuery(t);
                    }
                    notQuery.add(q, Occur.MUST_NOT);
                }
                // and exclude all nodes where 'field' is multi valued
                notQuery.add(new JackrabbitTermQuery(new Term(FieldNames.MVP, field)), Occur.MUST_NOT);
                query = notQuery;
                break;
            case // !=
            QueryConstants.OPERATION_NE_GENERAL:
                // that's:
                // all nodes with property 'field'
                // minus the nodes that have a single property 'field' that is
                //    not equal to term in question
                // minus the nodes that have a multi-valued property 'field' and
                //    all values are equal to term in question
                notQuery = new BooleanQuery();
                notQuery.add(Util.createMatchAllQuery(field, indexFormatVersion, cache), Occur.SHOULD);
                for (String value : stringValues) {
                    // exclude the nodes that have the term and are single valued
                    Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
                    Query svp = new NotQuery(new JackrabbitTermQuery(new Term(FieldNames.MVP, field)));
                    BooleanQuery and = new BooleanQuery();
                    Query q;
                    if (transform[0] == TransformConstants.TRANSFORM_UPPER_CASE) {
                        q = new CaseTermQuery.Upper(t);
                    } else if (transform[0] == TransformConstants.TRANSFORM_LOWER_CASE) {
                        q = new CaseTermQuery.Lower(t);
                    } else {
                        q = new JackrabbitTermQuery(t);
                    }
                    and.add(q, Occur.MUST);
                    and.add(svp, Occur.MUST);
                    notQuery.add(and, Occur.MUST_NOT);
                }
                // todo above also excludes multi-valued properties that contain
                //      multiple instances of only stringValues. e.g. text={foo, foo}
                query = notQuery;
                break;
            case QueryConstants.OPERATION_NULL:
                query = new NotQuery(Util.createMatchAllQuery(field, indexFormatVersion, cache));
                break;
            case QueryConstants.OPERATION_SIMILAR:
                try {
                    NodeId id = hmgr.resolveNodePath(session.getQPath(node.getStringValue()));
                    if (id != null) {
                        query = new SimilarityQuery(id.toString(), analyzer);
                    } else {
                        query = new BooleanQuery();
                    }
                } catch (Exception e) {
                    exceptions.add(e);
                    query = new BooleanQuery();
                }
                break;
            case QueryConstants.OPERATION_NOT_NULL:
                query = Util.createMatchAllQuery(field, indexFormatVersion, cache);
                break;
            case QueryConstants.OPERATION_SPELLCHECK:
                query = Util.createMatchAllQuery(field, indexFormatVersion, cache);
                break;
            default:
                throw new IllegalArgumentException("Unknown relation operation: " + node.getOperation());
        }
    }
    if (steps.length > 1) {
        // child axis in relation
        // elements.length - 1 = property name
        // elements.length - 2 = last child axis name test
        boolean selectParent = true;
        for (int i = steps.length - 2; i >= 0; i--) {
            LocationStepQueryNode step = steps[i];
            Name name = steps[i].getNameTest();
            if (i == steps.length - 2) {
                if (step instanceof DerefQueryNode) {
                    query = createPredicateDeref(query, (DerefQueryNode) step, data);
                    if (steps.length == 2) {
                        selectParent = false;
                    }
                } else if (step != null) {
                    // join name test with property query if there is one
                    if (name != null) {
                        if (!name.equals(PARENT_ELEMENT_NAME)) {
                            Query nameTest = new NameQuery(name, indexFormatVersion, nsMappings);
                            BooleanQuery and = new BooleanQuery();
                            and.add(query, Occur.MUST);
                            and.add(nameTest, Occur.MUST);
                            query = and;
                        } else {
                            // If we're searching the parent, we want to return the child axis,
                            // not the parent because this is part of the predicate. For instance,
                            // if the query is //child[../base], this part of the code is operating
                            // on the "../base" portion. So we want to return all the child nodes
                            // of "base", which will then be matched against the non predicate part.
                            query = new ChildAxisQuery(sharedItemMgr, query, null, indexFormatVersion, nsMappings);
                            selectParent = false;
                        }
                    } else {
                    // otherwise the query can be used as is
                    }
                }
            } else if (name != null && name.equals(PARENT_ELEMENT_NAME)) {
                // We need to select one of the properties if we haven't already.
                if (selectParent) {
                    query = new ParentAxisQuery(query, null, indexFormatVersion, nsMappings);
                    selectParent = false;
                }
                // See the note above on searching parents
                query = new ChildAxisQuery(sharedItemMgr, query, null, indexFormatVersion, nsMappings);
            } else {
                if (step != null) {
                    query = new ParentAxisQuery(query, name, indexFormatVersion, nsMappings);
                } else {
                    throw new UnsupportedOperationException();
                }
            }
        }
        // finally select the parent of the selected nodes
        if (selectParent) {
            query = new ParentAxisQuery(query, null, indexFormatVersion, nsMappings);
        }
    }
    return query;
}
Also used : PropertyFunctionQueryNode(org.apache.jackrabbit.spi.commons.query.PropertyFunctionQueryNode) DerefQueryNode(org.apache.jackrabbit.spi.commons.query.DerefQueryNode) Name(org.apache.jackrabbit.spi.Name) PathQueryNode(org.apache.jackrabbit.spi.commons.query.PathQueryNode) DefaultQueryNodeVisitor(org.apache.jackrabbit.spi.commons.query.DefaultQueryNodeVisitor) LocationStepQueryNode(org.apache.jackrabbit.spi.commons.query.LocationStepQueryNode) Term(org.apache.lucene.index.Term) NameException(org.apache.jackrabbit.spi.commons.conversion.NameException) ParseException(org.apache.lucene.queryParser.ParseException) RepositoryException(javax.jcr.RepositoryException) NamespaceException(javax.jcr.NamespaceException) InvalidQueryException(javax.jcr.query.InvalidQueryException) NameException(org.apache.jackrabbit.spi.commons.conversion.NameException) NodeId(org.apache.jackrabbit.core.id.NodeId) NamespaceException(javax.jcr.NamespaceException) InvalidQueryException(javax.jcr.query.InvalidQueryException)

Example 5 with PathQueryNode

use of org.apache.jackrabbit.spi.commons.query.PathQueryNode in project jackrabbit by apache.

the class LuceneQueryBuilder method visit.

public Object visit(LocationStepQueryNode node, Object data) throws RepositoryException {
    Query context = (Query) data;
    BooleanQuery andQuery = new BooleanQuery();
    if (context == null) {
        exceptions.add(new IllegalArgumentException("Unsupported query"));
    }
    // predicate on step?
    Object[] predicates = node.acceptOperands(this, data);
    for (Object predicate : predicates) {
        andQuery.add((Query) predicate, Occur.MUST);
    }
    // check for position predicate
    QueryNode[] pred = node.getPredicates();
    for (QueryNode aPred : pred) {
        if (aPred.getType() == QueryNode.TYPE_RELATION) {
            RelationQueryNode pos = (RelationQueryNode) aPred;
            if (pos.getValueType() == QueryConstants.TYPE_POSITION) {
                node.setIndex(pos.getPositionValue());
            }
        }
    }
    NameQuery nameTest = null;
    if (node.getNameTest() != null) {
        if (node.getNameTest().equals(PARENT_ELEMENT_NAME)) {
            andQuery.add(new ParentAxisQuery(context, null, indexFormatVersion, nsMappings), Occur.MUST);
            return andQuery;
        }
        nameTest = new NameQuery(node.getNameTest(), indexFormatVersion, nsMappings);
    }
    if (node.getIncludeDescendants()) {
        if (nameTest != null) {
            andQuery.add(new DescendantSelfAxisQuery(context, nameTest, false), Occur.MUST);
        } else {
            // descendant-or-self with nametest=*
            if (predicates.length > 0) {
                // if we have a predicate attached, the condition acts as
                // the sub query.
                // only use descendant axis if path is not //*
                // otherwise the query for the predicate can be used itself
                PathQueryNode pathNode = (PathQueryNode) node.getParent();
                if (pathNode.getPathSteps()[0] != node) {
                    Query subQuery = new DescendantSelfAxisQuery(context, andQuery, false);
                    andQuery = new BooleanQuery();
                    andQuery.add(subQuery, Occur.MUST);
                }
            } else {
                // todo this will traverse the whole index, optimize!
                // only use descendant axis if path is not //*
                PathQueryNode pathNode = (PathQueryNode) node.getParent();
                if (pathNode.getPathSteps()[0] != node) {
                    if (node.getIndex() == LocationStepQueryNode.NONE) {
                        context = new DescendantSelfAxisQuery(context, false);
                        andQuery.add(context, Occur.MUST);
                    } else {
                        context = new DescendantSelfAxisQuery(context, true);
                        andQuery.add(new ChildAxisQuery(sharedItemMgr, context, null, node.getIndex(), indexFormatVersion, nsMappings), Occur.MUST);
                    }
                } else {
                    andQuery.add(new MatchAllDocsQuery(), Occur.MUST);
                }
            }
        }
    } else {
        // name test
        if (nameTest != null) {
            andQuery.add(new ChildAxisQuery(sharedItemMgr, context, nameTest.getName(), node.getIndex(), indexFormatVersion, nsMappings), Occur.MUST);
        } else {
            // select child nodes
            andQuery.add(new ChildAxisQuery(sharedItemMgr, context, null, node.getIndex(), indexFormatVersion, nsMappings), Occur.MUST);
        }
    }
    return andQuery;
}
Also used : RelationQueryNode(org.apache.jackrabbit.spi.commons.query.RelationQueryNode) PathQueryNode(org.apache.jackrabbit.spi.commons.query.PathQueryNode) RelationQueryNode(org.apache.jackrabbit.spi.commons.query.RelationQueryNode) OrderQueryNode(org.apache.jackrabbit.spi.commons.query.OrderQueryNode) QueryNode(org.apache.jackrabbit.spi.commons.query.QueryNode) AndQueryNode(org.apache.jackrabbit.spi.commons.query.AndQueryNode) NotQueryNode(org.apache.jackrabbit.spi.commons.query.NotQueryNode) NodeTypeQueryNode(org.apache.jackrabbit.spi.commons.query.NodeTypeQueryNode) TextsearchQueryNode(org.apache.jackrabbit.spi.commons.query.TextsearchQueryNode) ExactQueryNode(org.apache.jackrabbit.spi.commons.query.ExactQueryNode) OrQueryNode(org.apache.jackrabbit.spi.commons.query.OrQueryNode) DerefQueryNode(org.apache.jackrabbit.spi.commons.query.DerefQueryNode) PathQueryNode(org.apache.jackrabbit.spi.commons.query.PathQueryNode) PropertyFunctionQueryNode(org.apache.jackrabbit.spi.commons.query.PropertyFunctionQueryNode) LocationStepQueryNode(org.apache.jackrabbit.spi.commons.query.LocationStepQueryNode)

Aggregations

PathQueryNode (org.apache.jackrabbit.spi.commons.query.PathQueryNode)8 LocationStepQueryNode (org.apache.jackrabbit.spi.commons.query.LocationStepQueryNode)6 NamespaceException (javax.jcr.NamespaceException)5 InvalidQueryException (javax.jcr.query.InvalidQueryException)5 DerefQueryNode (org.apache.jackrabbit.spi.commons.query.DerefQueryNode)5 NodeTypeQueryNode (org.apache.jackrabbit.spi.commons.query.NodeTypeQueryNode)5 PropertyFunctionQueryNode (org.apache.jackrabbit.spi.commons.query.PropertyFunctionQueryNode)5 NotQueryNode (org.apache.jackrabbit.spi.commons.query.NotQueryNode)4 OrderQueryNode (org.apache.jackrabbit.spi.commons.query.OrderQueryNode)4 QueryNode (org.apache.jackrabbit.spi.commons.query.QueryNode)4 RelationQueryNode (org.apache.jackrabbit.spi.commons.query.RelationQueryNode)4 TextsearchQueryNode (org.apache.jackrabbit.spi.commons.query.TextsearchQueryNode)4 Name (org.apache.jackrabbit.spi.Name)3 NameException (org.apache.jackrabbit.spi.commons.conversion.NameException)3 NAryQueryNode (org.apache.jackrabbit.spi.commons.query.NAryQueryNode)3 IllegalNameException (org.apache.jackrabbit.spi.commons.conversion.IllegalNameException)2 Calendar (java.util.Calendar)1 Iterator (java.util.Iterator)1 NoSuchElementException (java.util.NoSuchElementException)1 RepositoryException (javax.jcr.RepositoryException)1