You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2009/02/26 14:24:08 UTC
svn commit: r748139 - in
/jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene:
ChildAxisQuery.java DescendantSelfAxisQuery.java LuceneQueryBuilder.java
NameQuery.java
Author: mreutegg
Date: Thu Feb 26 13:24:08 2009
New Revision: 748139
URL: http://svn.apache.org/viewvc?rev=748139&view=rev
Log:
JCR-1872: Improve performance of simple path queries
Added:
jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NameQuery.java (with props)
Modified:
jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java
jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DescendantSelfAxisQuery.java
jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java
Modified: jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java?rev=748139&r1=748138&r2=748139&view=diff
==============================================================================
--- jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java (original)
+++ jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java Thu Feb 26 13:24:08 2009
@@ -20,12 +20,12 @@
import org.apache.jackrabbit.core.query.LocationStepQueryNode;
import org.apache.jackrabbit.core.query.lucene.hits.AdaptingHits;
import org.apache.jackrabbit.core.query.lucene.hits.Hits;
-import org.apache.jackrabbit.core.query.lucene.hits.HitsIntersection;
import org.apache.jackrabbit.core.query.lucene.hits.ScorerHits;
import org.apache.jackrabbit.core.state.ItemStateException;
import org.apache.jackrabbit.core.state.ItemStateManager;
import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.uuid.UUID;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
@@ -36,14 +36,18 @@
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.Weight;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.HashSet;
/**
* Implements a lucene <code>Query</code> which returns the child nodes of the
@@ -52,6 +56,17 @@
class ChildAxisQuery extends Query {
/**
+ * The logger instance for this class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(ChildAxisQuery.class);
+
+ /**
+ * Threshold when children calculation is switched to
+ * {@link HierarchyResolvingChildrenCalculator}.
+ */
+ private static int CONTEXT_SIZE_THRESHOLD = 10;
+
+ /**
* The item state manager containing persistent item states.
*/
private final ItemStateManager itemMgr;
@@ -65,7 +80,7 @@
* The nameTest to apply on the child axis, or <code>null</code> if all
* child nodes should be selected.
*/
- private final String nameTest;
+ private final Name nameTest;
/**
* The context position for the selected child node, or
@@ -74,6 +89,11 @@
private final int position;
/**
+ * The internal namespace mappings.
+ */
+ private final NamespaceMappings nsMappings;
+
+ /**
* The scorer of the context query
*/
private Scorer contextScorer;
@@ -91,9 +111,13 @@
* @param context the context for this query.
* @param nameTest a name test or <code>null</code> if any child node is
* selected.
+ * @param nsMappings the internal namespace mappings.
*/
- ChildAxisQuery(ItemStateManager itemMgr, Query context, String nameTest) {
- this(itemMgr, context, nameTest, LocationStepQueryNode.NONE);
+ ChildAxisQuery(ItemStateManager itemMgr,
+ Query context,
+ Name nameTest,
+ NamespaceMappings nsMappings) {
+ this(itemMgr, context, nameTest, LocationStepQueryNode.NONE, nsMappings);
}
/**
@@ -107,12 +131,48 @@
* @param position the context position of the child node to select. If
* <code>position</code> is {@link LocationStepQueryNode#NONE}, the context
* position of the child node is not checked.
+ * @param nsMapping the internal namespace mappings.
*/
- ChildAxisQuery(ItemStateManager itemMgr, Query context, String nameTest, int position) {
+ ChildAxisQuery(ItemStateManager itemMgr,
+ Query context,
+ Name nameTest,
+ int position,
+ NamespaceMappings nsMapping) {
this.itemMgr = itemMgr;
this.contextQuery = context;
this.nameTest = nameTest;
this.position = position;
+ this.nsMappings = nsMapping;
+ }
+
+ /**
+ * @return the context query of this child axis query.
+ */
+ Query getContextQuery() {
+ return contextQuery;
+ }
+
+ /**
+ * @return <code>true</code> if this child axis query matches any child
+ * node; <code>false</code> otherwise.
+ */
+ boolean matchesAnyChildNode() {
+ return nameTest == null && position == LocationStepQueryNode.NONE;
+ }
+
+ /**
+ * @return the name test or <code>null</code> if none was specified.
+ */
+ Name getNameTest() {
+ return nameTest;
+ }
+
+ /**
+ * @return the position check or {@link LocationStepQueryNode#NONE} is none
+ * was specified.
+ */
+ int getPosition() {
+ return position;
}
/**
@@ -140,18 +200,26 @@
if (cQuery == contextQuery) {
return this;
} else {
- return new ChildAxisQuery(itemMgr, cQuery, nameTest, position);
+ return new ChildAxisQuery(itemMgr, cQuery, nameTest,
+ position, nsMappings);
}
}
/**
- * Always returns 'ChildAxisQuery'.
- *
- * @param field the name of a field.
- * @return 'ChildAxisQuery'.
+ * {@inheritDoc}
*/
public String toString(String field) {
- return "ChildAxisQuery";
+ StringBuffer sb = new StringBuffer();
+ sb.append("ChildAxisQuery(");
+ sb.append(contextQuery);
+ sb.append(", ");
+ sb.append(nameTest);
+ if (position != LocationStepQueryNode.NONE) {
+ sb.append(", ");
+ sb.append(position);
+ }
+ sb.append(")");
+ return sb.toString();
}
//-------------------< ChildAxisWeight >------------------------------------
@@ -215,9 +283,10 @@
public Scorer scorer(IndexReader reader) throws IOException {
contextScorer = contextQuery.weight(searcher).scorer(reader);
if (nameTest != null) {
- nameTestScorer = new TermQuery(new Term(FieldNames.LABEL, nameTest)).weight(searcher).scorer(reader);
+ nameTestScorer = new NameQuery(nameTest, nsMappings).weight(searcher).scorer(reader);
}
- return new ChildAxisScorer(searcher.getSimilarity(), reader);
+ return new ChildAxisScorer(searcher.getSimilarity(),
+ reader, (HierarchyResolver) reader);
}
/**
@@ -241,6 +310,11 @@
private final IndexReader reader;
/**
+ * The <code>HierarchyResolver</code> of the index.
+ */
+ private final HierarchyResolver hResolver;
+
+ /**
* The next document id to return
*/
private int nextDoc = -1;
@@ -255,10 +329,14 @@
*
* @param similarity the <code>Similarity</code> instance to use.
* @param reader for index access.
+ * @param hResolver the hierarchy resolver of <code>reader</code>.
*/
- protected ChildAxisScorer(Similarity similarity, IndexReader reader) {
+ protected ChildAxisScorer(Similarity similarity,
+ IndexReader reader,
+ HierarchyResolver hResolver) {
super(similarity);
this.reader = reader;
+ this.hResolver = hResolver;
}
/**
@@ -269,7 +347,7 @@
do {
nextDoc = hits.next();
} while (nextDoc > -1 && !indexIsValid(nextDoc));
-
+
return nextDoc > -1;
}
@@ -293,9 +371,10 @@
public boolean skipTo(int target) throws IOException {
calculateChildren();
nextDoc = hits.skipTo(target);
- while (nextDoc > -1 && !indexIsValid(nextDoc))
+ while (nextDoc > -1 && !indexIsValid(nextDoc)) {
next();
- return nextDoc > -1;
+ }
+ return nextDoc > -1;
}
/**
@@ -310,50 +389,49 @@
private void calculateChildren() throws IOException {
if (hits == null) {
-
- // collect all context nodes
- List uuids = new ArrayList();
- final Hits contextHits = new AdaptingHits();
- contextScorer.score(new HitCollector() {
- public void collect(int doc, float score) {
- contextHits.set(doc);
- }
- });
-
- // read the uuids of the context nodes
- int i = contextHits.next();
- while (i > -1) {
- String uuid = reader.document(i).get(FieldNames.UUID);
- uuids.add(uuid);
- i = contextHits.next();
- }
-
- // collect all children of the context nodes
- Hits childrenHits = new AdaptingHits();
- TermDocs docs = reader.termDocs();
- try {
- for (Iterator it = uuids.iterator(); it.hasNext();) {
- docs.seek(new Term(FieldNames.PARENT, (String) it.next()));
- while (docs.next()) {
- childrenHits.set(docs.doc());
+ final ChildrenCalculator[] calc = new ChildrenCalculator[1];
+ if (nameTestScorer == null) {
+ // always use simple in that case
+ calc[0] = new SimpleChildrenCalculator(reader, hResolver);
+ contextScorer.score(new HitCollector() {
+ public void collect(int doc, float score) {
+ calc[0].collectContextHit(doc);
}
- }
- } finally {
- docs.close();
- }
-
- if (nameTestScorer != null) {
- hits = new HitsIntersection(childrenHits, new ScorerHits(nameTestScorer));
+ });
} else {
- hits = childrenHits;
+ // start simple but switch once threshold is reached
+ calc[0] = new SimpleChildrenCalculator(reader, hResolver);
+ contextScorer.score(new HitCollector() {
+
+ private List docIds = new ArrayList();
+
+ public void collect(int doc, float score) {
+ calc[0].collectContextHit(doc);
+ if (docIds != null) {
+ docIds.add(new Integer(doc));
+ if (docIds.size() > CONTEXT_SIZE_THRESHOLD) {
+ // switch
+ calc[0] = new HierarchyResolvingChildrenCalculator(
+ reader, hResolver);
+ for (Iterator it = docIds.iterator(); it.hasNext(); ) {
+ calc[0].collectContextHit(((Integer) it.next()).intValue());
+ }
+ // indicate that we switched
+ docIds = null;
+ }
+ }
+ }
+ });
}
+
+ hits = calc[0].getHits();
}
}
private boolean indexIsValid(int i) throws IOException {
if (position != LocationStepQueryNode.NONE) {
- Document node = reader.document(i);
+ Document node = reader.document(i, FieldSelectors.UUID_AND_PARENT);
NodeId parentId = NodeId.valueOf(node.get(FieldNames.PARENT));
NodeId id = NodeId.valueOf(node.get(FieldNames.UUID));
try {
@@ -418,4 +496,172 @@
return true;
}
}
+
+ /**
+ * Base class to calculate the children for a context query.
+ */
+ private abstract class ChildrenCalculator {
+
+ /**
+ * The current index reader.
+ */
+ protected final IndexReader reader;
+
+ /**
+ * The current hierarchy resolver.
+ */
+ protected final HierarchyResolver hResolver;
+
+ /**
+ * Creates a new children calculator with the given index reader and
+ * hierarchy resolver.
+ *
+ * @param reader the current index reader.
+ * @param hResolver the current hierarchy resolver.
+ */
+ public ChildrenCalculator(IndexReader reader,
+ HierarchyResolver hResolver) {
+ this.reader = reader;
+ this.hResolver = hResolver;
+ }
+
+ /**
+ * Collects a context hit.
+ *
+ * @param doc the lucene document number of the context hit.
+ */
+ protected abstract void collectContextHit(int doc);
+
+ /**
+ * @return the hits that contains the children.
+ * @throws IOException if an error occurs while reading from the index.
+ */
+ public abstract Hits getHits() throws IOException;
+ }
+
+ /**
+ * An implementation of a children calculator using the item state manager.
+ */
+ private final class SimpleChildrenCalculator extends ChildrenCalculator {
+
+ /**
+ * The context hits.
+ */
+ private final Hits contextHits = new AdaptingHits();
+
+ /**
+ * Creates a new simple children calculator.
+ *
+ * @param reader the current index reader.
+ * @param hResolver the current hierarchy resolver.
+ */
+ public SimpleChildrenCalculator(IndexReader reader,
+ HierarchyResolver hResolver) {
+ super(reader, hResolver);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void collectContextHit(int doc) {
+ contextHits.set(doc);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Hits getHits() throws IOException {
+ // read the uuids of the context nodes
+ Map uuids = new HashMap();
+ for (int i = contextHits.next(); i > -1; i = contextHits.next()) {
+ String uuid = reader.document(i, FieldSelectors.UUID).get(FieldNames.UUID);
+ uuids.put(new Integer(i), uuid);
+ }
+
+ // get child node entries for each hit
+ Hits childrenHits = new AdaptingHits();
+ for (Iterator it = uuids.values().iterator(); it.hasNext(); ) {
+ String uuid = (String) it.next();
+ NodeId id = new NodeId(UUID.fromString(uuid));
+ try {
+ long time = System.currentTimeMillis();
+ NodeState state = (NodeState) itemMgr.getItemState(id);
+ time = System.currentTimeMillis() - time;
+ log.debug("got NodeState with id {} in {} ms.", id, new Long(time));
+ Iterator entries;
+ if (nameTest != null) {
+ entries = state.getChildNodeEntries(nameTest).iterator();
+ } else {
+ // get all children
+ entries = state.getChildNodeEntries().iterator();
+ }
+ while (entries.hasNext()) {
+ NodeId childId = ((NodeState.ChildNodeEntry) entries.next()).getId();
+ Term uuidTerm = new Term(FieldNames.UUID, childId.getUUID().toString());
+ TermDocs docs = reader.termDocs(uuidTerm);
+ try {
+ if (docs.next()) {
+ childrenHits.set(docs.doc());
+ }
+ } finally {
+ docs.close();
+ }
+ }
+ } catch (ItemStateException e) {
+ // does not exist anymore -> ignore
+ }
+ }
+ return childrenHits;
+ }
+ }
+
+ /**
+ * An implementation of a children calculator that uses the hierarchy
+ * resolver. This implementation requires that
+ * {@link ChildAxisQuery#nameTestScorer} is non null.
+ */
+ private final class HierarchyResolvingChildrenCalculator
+ extends ChildrenCalculator {
+
+ /**
+ * The document numbers of the context hits.
+ */
+ private final Set docIds = new HashSet();
+
+ /**
+ * Creates a new hierarchy resolving children calculator.
+ *
+ * @param reader the current index reader.
+ * @param hResolver the current hierarchy resolver.
+ */
+ public HierarchyResolvingChildrenCalculator(IndexReader reader,
+ HierarchyResolver hResolver) {
+ super(reader, hResolver);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void collectContextHit(int doc) {
+ docIds.add(new Integer(doc));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Hits getHits() throws IOException {
+ long time = System.currentTimeMillis();
+ Hits childrenHits = new AdaptingHits();
+ Hits nameHits = new ScorerHits(nameTestScorer);
+ for (int h = nameHits.next(); h > -1; h = nameHits.next()) {
+ if (docIds.contains(new Integer(hResolver.getParent(h)))) {
+ childrenHits.set(h);
+ }
+ }
+ time = System.currentTimeMillis() - time;
+
+ log.debug("Filtered hits in {} ms.", new Long(time));
+ return childrenHits;
+ }
+ }
}
Modified: jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DescendantSelfAxisQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DescendantSelfAxisQuery.java?rev=748139&r1=748138&r2=748139&view=diff
==============================================================================
--- jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DescendantSelfAxisQuery.java (original)
+++ jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DescendantSelfAxisQuery.java Thu Feb 26 13:24:08 2009
@@ -24,6 +24,9 @@
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.Similarity;
import org.apache.lucene.search.Weight;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.BitSet;
@@ -37,6 +40,11 @@
class DescendantSelfAxisQuery extends Query {
/**
+ * The logger instance for this class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(DescendantSelfAxisQuery.class);
+
+ /**
* The context query
*/
private final Query contextQuery;
@@ -90,6 +98,14 @@
}
/**
+ * @return <code>true</code> if the sub query of this <code>DescendantSelfAxisQuery</code>
+ * matches all nodes.
+ */
+ boolean subQueryMatchesAll() {
+ return subQuery instanceof MatchAllDocsQuery;
+ }
+
+ /**
* Creates a <code>Weight</code> instance for this query.
*
* @param searcher the <code>Searcher</code> instance to use.
@@ -106,7 +122,13 @@
* @return 'DescendantSelfAxisQuery'.
*/
public String toString(String field) {
- return "DescendantSelfAxisQuery";
+ StringBuffer sb = new StringBuffer();
+ sb.append("DescendantSelfAxisQuery(");
+ sb.append(contextQuery);
+ sb.append(", ");
+ sb.append(subQuery);
+ sb.append(")");
+ return sb.toString();
}
/**
@@ -256,14 +278,27 @@
return false;
}
int nextDoc = subScorer.doc();
+ int numInvalid = 0;
+ long time = System.currentTimeMillis();
while (nextDoc > -1) {
if (isValid(nextDoc)) {
+ if (numInvalid > 0) {
+ time = System.currentTimeMillis() - time;
+ log.debug("Skipped {} nodes in {} ms. Not matching hierarchy constraint.",
+ new Integer(numInvalid), new Long(time));
+ }
return true;
}
// try next
nextDoc = subScorer.next() ? subScorer.doc() : -1;
+ numInvalid++;
+ }
+ if (numInvalid > 0) {
+ time = System.currentTimeMillis() - time;
+ log.debug("Skipped {} nodes in {} ms. Not matching hierarchy constraint.",
+ new Integer(numInvalid), new Long(time));
}
return false;
}
@@ -302,12 +337,22 @@
private void collectContextHits() throws IOException {
if (!contextHitsCalculated) {
+ long time = System.currentTimeMillis();
contextScorer.score(new HitCollector() {
public void collect(int doc, float score) {
contextHits.set(doc);
}
}); // find all
contextHitsCalculated = true;
+ time = System.currentTimeMillis() - time;
+ if (log.isDebugEnabled()) {
+ log.debug("Collected {} context hits in {} ms for {}",
+ new Object[]{
+ new Integer(contextHits.cardinality()),
+ new Long(time),
+ DescendantSelfAxisQuery.this
+ });
+ }
}
}
Modified: jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java?rev=748139&r1=748138&r2=748139&view=diff
==============================================================================
--- jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java (original)
+++ jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java Thu Feb 26 13:24:08 2009
@@ -59,6 +59,7 @@
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.MatchAllDocsQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -525,15 +526,9 @@
}
}
- TermQuery nameTest = null;
+ NameQuery nameTest = null;
if (node.getNameTest() != null) {
- try {
- String internalName = resolver.getJCRName(node.getNameTest());
- nameTest = new TermQuery(new Term(FieldNames.LABEL, internalName));
- } catch (NamespaceException e) {
- // should never happen
- exceptions.add(e);
- }
+ nameTest = new NameQuery(node.getNameTest(), nsMappings);
}
if (node.getIncludeDescendants()) {
@@ -555,17 +550,12 @@
}
} else {
// todo this will traverse the whole index, optimize!
- Query subQuery = null;
- try {
- subQuery = createMatchAllQuery(resolver.getJCRName(NameConstants.JCR_PRIMARYTYPE));
- } catch (NamespaceException e) {
- // will never happen, prefixes are created when unknown
- }
+ Query subQuery = new MatchAllDocsQuery();
// only use descendant axis if path is not //*
PathQueryNode pathNode = (PathQueryNode) node.getParent();
if (pathNode.getPathSteps()[0] != node) {
context = new DescendantSelfAxisQuery(context, subQuery);
- andQuery.add(new ChildAxisQuery(sharedItemMgr, context, null, node.getIndex()), Occur.MUST);
+ andQuery.add(new ChildAxisQuery(sharedItemMgr, context, null, node.getIndex(), nsMappings), Occur.MUST);
} else {
andQuery.add(subQuery, Occur.MUST);
}
@@ -574,10 +564,10 @@
} else {
// name test
if (nameTest != null) {
- andQuery.add(new ChildAxisQuery(sharedItemMgr, context, nameTest.getTerm().text(), node.getIndex()), Occur.MUST);
+ andQuery.add(new ChildAxisQuery(sharedItemMgr, context, nameTest.getName(), node.getIndex(), nsMappings), Occur.MUST);
} else {
// select child nodes
- andQuery.add(new ChildAxisQuery(sharedItemMgr, context, null, node.getIndex()), Occur.MUST);
+ andQuery.add(new ChildAxisQuery(sharedItemMgr, context, null, node.getIndex(), nsMappings), Occur.MUST);
}
}
Added: jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NameQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NameQuery.java?rev=748139&view=auto
==============================================================================
--- jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NameQuery.java (added)
+++ jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NameQuery.java Thu Feb 26 13:24:08 2009
@@ -0,0 +1,88 @@
+/*
+ * 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.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * <code>NameQuery</code> implements a query for the name of a node.
+ */
+public class NameQuery extends Query {
+
+ /**
+ * The node name.
+ */
+ private final Name nodeName;
+
+ /**
+ * The internal namespace mappings of the index.
+ */
+ private final NamespaceMappings nsMappings;
+
+ /**
+ * Creates a new <code>NameQuery</code>.
+ *
+ * @param nodeName the name of the nodes to return.
+ * @param nsMappings the namespace mappings of the index.
+ */
+ public NameQuery(Name nodeName,
+ NamespaceMappings nsMappings) {
+ this.nodeName = nodeName;
+ this.nsMappings = nsMappings;
+ }
+
+ /**
+ * @return the name of the nodes to return.
+ */
+ public Name getName() {
+ return nodeName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Query rewrite(IndexReader reader) throws IOException {
+ // use LABEL field
+ try {
+ return new TermQuery(new Term(FieldNames.LABEL,
+ nsMappings.translatePropertyName(nodeName)));
+ } catch (IllegalNameException e) {
+ throw (IOException) new IOException().initCause(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void extractTerms(Set terms) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString(String field) {
+ return "name() = " + nodeName.toString();
+ }
+}
Propchange: jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NameQuery.java
------------------------------------------------------------------------------
svn:eol-style = native