lucenequerybuilder.java

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

JAVA
986
字号
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.jackrabbit.core.query.lucene;import org.apache.jackrabbit.core.SessionImpl;import org.apache.jackrabbit.core.query.AndQueryNode;import org.apache.jackrabbit.core.query.DerefQueryNode;import org.apache.jackrabbit.core.query.ExactQueryNode;import org.apache.jackrabbit.core.query.LocationStepQueryNode;import org.apache.jackrabbit.core.query.NodeTypeQueryNode;import org.apache.jackrabbit.core.query.NotQueryNode;import org.apache.jackrabbit.core.query.OrQueryNode;import org.apache.jackrabbit.core.query.OrderQueryNode;import org.apache.jackrabbit.core.query.PathQueryNode;import org.apache.jackrabbit.core.query.PropertyTypeRegistry;import org.apache.jackrabbit.core.query.QueryConstants;import org.apache.jackrabbit.core.query.QueryNode;import org.apache.jackrabbit.core.query.QueryNodeVisitor;import org.apache.jackrabbit.core.query.QueryRootNode;import org.apache.jackrabbit.core.query.RelationQueryNode;import org.apache.jackrabbit.core.query.TextsearchQueryNode;import org.apache.jackrabbit.core.query.PropertyFunctionQueryNode;import org.apache.jackrabbit.core.query.DefaultQueryNodeVisitor;import org.apache.jackrabbit.core.query.lucene.fulltext.QueryParser;import org.apache.jackrabbit.core.query.lucene.fulltext.ParseException;import org.apache.jackrabbit.core.state.ItemStateManager;import org.apache.jackrabbit.name.MalformedPathException;import org.apache.jackrabbit.name.NameException;import org.apache.jackrabbit.name.NoPrefixDeclaredException;import org.apache.jackrabbit.name.Path;import org.apache.jackrabbit.name.QName;import org.apache.jackrabbit.name.NameFormat;import org.apache.jackrabbit.name.PathFormat;import org.apache.jackrabbit.util.ISO8601;import org.apache.jackrabbit.util.XMLChar;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.index.Term;import org.apache.lucene.search.BooleanQuery;import org.apache.lucene.search.Query;import org.apache.lucene.search.TermQuery;import org.apache.lucene.search.BooleanClause.Occur;import javax.jcr.NamespaceException;import javax.jcr.PropertyType;import javax.jcr.RepositoryException;import javax.jcr.nodetype.NodeType;import javax.jcr.nodetype.NodeTypeIterator;import javax.jcr.nodetype.NodeTypeManager;import javax.jcr.query.InvalidQueryException;import java.util.ArrayList;import java.util.Arrays;import java.util.Calendar;import java.util.Iterator;import java.util.List;/** * Implements a query builder that takes an abstract query tree and creates * a lucene {@link org.apache.lucene.search.Query} tree that can be executed * on an index. * todo introduce a node type hierarchy for efficient translation of NodeTypeQueryNode */public class LuceneQueryBuilder implements QueryNodeVisitor {    /**     * Logger for this class     */    private static final Logger log = LoggerFactory.getLogger(LuceneQueryBuilder.class);    /**     * Root node of the abstract query tree     */    private QueryRootNode root;    /**     * Session of the user executing this query     */    private SessionImpl session;    /**     * The shared item state manager of the workspace.     */    private ItemStateManager sharedItemMgr;    /**     * Namespace mappings to internal prefixes     */    private NamespaceMappings nsMappings;    /**     * The analyzer instance to use for contains function query parsing     */    private Analyzer analyzer;    /**     * The property type registry.     */    private PropertyTypeRegistry propRegistry;    /**     * Exceptions thrown during tree translation     */    private List exceptions = new ArrayList();    /**     * Creates a new <code>LuceneQueryBuilder</code> instance.     *     * @param root          the root node of the abstract query tree.     * @param session       of the user executing this query.     * @param sharedItemMgr the shared item state manager of the workspace.     * @param nsMappings    namespace resolver for internal prefixes.     * @param analyzer      for parsing the query statement of the contains function.     * @param propReg       the property type registry.     */    private LuceneQueryBuilder(QueryRootNode root,                               SessionImpl session,                               ItemStateManager sharedItemMgr,                               NamespaceMappings nsMappings,                               Analyzer analyzer,                               PropertyTypeRegistry propReg) {        this.root = root;        this.session = session;        this.sharedItemMgr = sharedItemMgr;        this.nsMappings = nsMappings;        this.analyzer = analyzer;        this.propRegistry = propReg;    }    /**     * Creates a lucene {@link org.apache.lucene.search.Query} tree from an     * abstract query tree.     *     * @param root          the root node of the abstract query tree.     * @param session       of the user executing the query.     * @param sharedItemMgr the shared item state manager of the workspace.     * @param nsMappings    namespace resolver for internal prefixes.     * @param analyzer      for parsing the query statement of the contains function.     * @param propReg       the property type registry to lookup type information.     * @return the lucene query tree.     * @throws RepositoryException if an error occurs during the translation.     */    public static Query createQuery(QueryRootNode root,                                    SessionImpl session,                                    ItemStateManager sharedItemMgr,                                    NamespaceMappings nsMappings,                                    Analyzer analyzer,                                    PropertyTypeRegistry propReg)            throws RepositoryException {        LuceneQueryBuilder builder = new LuceneQueryBuilder(root, session,                sharedItemMgr, nsMappings, analyzer, propReg);        Query q = builder.createLuceneQuery();        if (builder.exceptions.size() > 0) {            StringBuffer msg = new StringBuffer();            for (Iterator it = builder.exceptions.iterator(); it.hasNext();) {                msg.append(it.next().toString()).append('\n');            }            throw new RepositoryException("Exception building query: " + msg.toString());        }        return q;    }    /**     * Starts the tree traversal and returns the lucene     * {@link org.apache.lucene.search.Query}.     *     * @return the lucene <code>Query</code>.     */    private Query createLuceneQuery() {        return (Query) root.accept(this, null);    }    //---------------------< QueryNodeVisitor interface >-----------------------    public Object visit(QueryRootNode node, Object data) {        BooleanQuery root = new BooleanQuery();        Query wrapped = root;        if (node.getLocationNode() != null) {            wrapped = (Query) node.getLocationNode().accept(this, root);        }        return wrapped;    }    public Object visit(OrQueryNode node, Object data) {        BooleanQuery orQuery = new BooleanQuery();        Object[] result = node.acceptOperands(this, null);        for (int i = 0; i < result.length; i++) {            Query operand = (Query) result[i];            orQuery.add(operand, Occur.SHOULD);        }        return orQuery;    }    public Object visit(AndQueryNode node, Object data) {        Object[] result = node.acceptOperands(this, null);        if (result.length == 0) {            return null;        }        BooleanQuery andQuery = new BooleanQuery();        for (int i = 0; i < result.length; i++) {            Query operand = (Query) result[i];            andQuery.add(operand, Occur.MUST);        }        return andQuery;    }    public Object visit(NotQueryNode node, Object data) {        Object[] result = node.acceptOperands(this, null);        if (result.length == 0) {            return data;        }        // join the results        BooleanQuery b = new BooleanQuery();        for (int i = 0; i < result.length; i++) {            b.add((Query) result[i], Occur.SHOULD);        }        // negate        return new NotQuery(b);    }    public Object visit(ExactQueryNode node, Object data) {        String field = "";        String value = "";        try {            field = NameFormat.format(node.getPropertyName(), nsMappings);            value = NameFormat.format(node.getValue(), nsMappings);        } catch (NoPrefixDeclaredException e) {            // will never happen, prefixes are created when unknown        }        return new TermQuery(new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value)));    }    public Object visit(NodeTypeQueryNode node, Object data) {        List terms = new ArrayList();        try {            String mixinTypesField = NameFormat.format(QName.JCR_MIXINTYPES, nsMappings);            String primaryTypeField = NameFormat.format(QName.JCR_PRIMARYTYPE, nsMappings);            NodeTypeManager ntMgr = session.getWorkspace().getNodeTypeManager();            NodeType base = ntMgr.getNodeType(session.getJCRName(node.getValue()));            if (base.isMixin()) {                // search for nodes where jcr:mixinTypes is set to this mixin                Term t = new Term(FieldNames.PROPERTIES,                        FieldNames.createNamedValue(mixinTypesField,                                NameFormat.format(node.getValue(), nsMappings)));                terms.add(t);            } else {                // search for nodes where jcr:primaryType is set to this type                Term t = new Term(FieldNames.PROPERTIES,                        FieldNames.createNamedValue(primaryTypeField,                                NameFormat.format(node.getValue(), nsMappings)));                terms.add(t);            }            // now search for all node types that are derived from base            NodeTypeIterator allTypes = ntMgr.getAllNodeTypes();            while (allTypes.hasNext()) {                NodeType nt = allTypes.nextNodeType();                NodeType[] superTypes = nt.getSupertypes();                if (Arrays.asList(superTypes).contains(base)) {                    String ntName = nsMappings.translatePropertyName(nt.getName(),                            session.getNamespaceResolver());                    Term t;                    if (nt.isMixin()) {                        // search on jcr:mixinTypes                        t = new Term(FieldNames.PROPERTIES,                                FieldNames.createNamedValue(mixinTypesField, ntName));                    } else {                        // search on jcr:primaryType                        t = new Term(FieldNames.PROPERTIES,                                FieldNames.createNamedValue(primaryTypeField, ntName));                    }                    terms.add(t);                }            }        } catch (NameException e) {            exceptions.add(e);        } catch (RepositoryException e) {            exceptions.add(e);        }        if (terms.size() == 0) {            // exception occured            return new BooleanQuery();        } else if (terms.size() == 1) {            return new TermQuery((Term) terms.get(0));        } else {            BooleanQuery b = new BooleanQuery();            for (Iterator it = terms.iterator(); it.hasNext();) {                b.add(new TermQuery((Term) it.next()), Occur.SHOULD);            }            return b;        }    }    public Object visit(TextsearchQueryNode node, Object data) {        try {            Path relPath = node.getRelativePath();            String fieldname;            if (relPath == null || !node.getReferencesProperty()) {                // fulltext on node                fieldname = FieldNames.FULLTEXT;            } else {                // final path element is a property name                QName propName = relPath.getNameElement().getName();                StringBuffer tmp = new StringBuffer();                tmp.append(nsMappings.getPrefix(propName.getNamespaceURI()));                tmp.append(":").append(FieldNames.FULLTEXT_PREFIX);                tmp.append(propName.getLocalName());                fieldname = tmp.toString();

⌨️ 快捷键说明

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