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 + -
显示快捷键?