Author: rhauch
Date: 2009-12-31 13:53:06 -0500 (Thu, 31 Dec 2009)
New Revision: 1507
Removed:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/EncodingNamespaceRegistry.java
trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/EncodingNamespaceRegistryTest.java
Modified:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchProcessor.java
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchSession.java
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchWorkspace.java
Log:
DNA-468 Simplified the design of the Lucene search indexes, which improves the performance
signifantly (the TCK unit tests run approximately 10% or more faster). The performance
improvement should be even higher when there's a lot of content and the queries have
more criteria.
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java 2009-12-31
16:13:57 UTC (rev 1506)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java 2009-12-31
18:53:06 UTC (rev 1507)
@@ -109,9 +109,16 @@
} finally {
stream.close();
}
+
+ // Prime creating a first XPath query and SQL query ...
+
session.getWorkspace().getQueryManager().createQuery("//element(*,nt:unstructured)",
Query.XPATH);
+ session.getWorkspace().getQueryManager().createQuery("SELECT * FROM
[nt:base]", JcrRepository.QueryLanguage.SQL);
} finally {
session.logout();
}
+
+ // Prime creating the schemata ...
+ repository.getRepositoryTypeManager().getRepositorySchemata();
}
@AfterClass
@@ -201,7 +208,7 @@
QueryResult result = query.execute();
assertThat(result, is(notNullValue()));
assertResultsHaveColumns(result, "jcr:primaryType");
- System.out.println(result);
+ // System.out.println(result);
}
//
----------------------------------------------------------------------------------------------------------------
@@ -238,7 +245,7 @@
assertThat(query, is(notNullValue()));
QueryResult result = query.execute();
assertThat(result, is(notNullValue()));
- System.out.println(result);
+ // System.out.println(result);
assertResultsHaveColumns(result,
"jcr:primaryType",
"jcr:path",
@@ -262,7 +269,7 @@
assertThat(query, is(notNullValue()));
QueryResult result = query.execute();
assertThat(result, is(notNullValue()));
- System.out.println(result);
+ // System.out.println(result);
assertResultsHaveColumns(result, "jcr:primaryType",
"jcr:path", "jcr:score");
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-12-31 16:13:57 UTC
(rev 1506)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-12-31 18:53:06 UTC
(rev 1507)
@@ -288,7 +288,7 @@
// addTest(org.apache.jackrabbit.test.api.observation.TestAll.suite());
// addTest(org.apache.jackrabbit.test.api.version.TestAll.suite());
addTest(org.apache.jackrabbit.test.api.lock.TestAll.suite());
- // addTest(org.apache.jackrabbit.test.api.util.TestAll.suite());
+ addTest(org.apache.jackrabbit.test.api.util.TestAll.suite());
}
}
Modified:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java
===================================================================
---
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java 2009-12-31
16:13:57 UTC (rev 1506)
+++
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java 2009-12-31
18:53:06 UTC (rev 1507)
@@ -30,7 +30,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import net.jcip.annotations.NotThreadSafe;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanQuery;
@@ -75,6 +74,7 @@
import org.jboss.dna.graph.query.model.FullTextSearch;
import org.jboss.dna.graph.query.model.FullTextSearchScore;
import org.jboss.dna.graph.query.model.Length;
+import org.jboss.dna.graph.query.model.Limit;
import org.jboss.dna.graph.query.model.Literal;
import org.jboss.dna.graph.query.model.LowerCase;
import org.jboss.dna.graph.query.model.NodeDepth;
@@ -425,6 +425,23 @@
SelectComponent selector = new SelectComponent(tuplesProcessor,
postProcessConstraint, request.variables());
tuples = selector.execute();
}
+
+ // Limit the tuples ...
+ Limit limit = request.limit();
+ if (!limit.isUnlimited()) {
+ int firstIndex = limit.getOffset();
+ int maxRows = Math.min(tuples.size(), limit.getRowLimit());
+ if (firstIndex > 0) {
+ if (firstIndex > tuples.size()) {
+ tuples.clear();
+ } else {
+ tuples = tuples.subList(firstIndex, maxRows);
+ }
+ } else {
+ tuples = tuples.subList(0, maxRows);
+ }
+ }
+
executingNanos = System.nanoTime() - executingNanos;
Statistics stats = new Statistics(planningNanos, 0L, 0L, executingNanos);
request.setResults(tuples, stats);
@@ -753,17 +770,10 @@
*/
TupleCollector createTupleCollector( Columns columns );
- /**
- * Utility method to create a query to find all of the documents representing
nodes with the supplied IDs.
- *
- * @param ids the IDs of the nodes that are to be found; may not be null
- * @return the query; never null
- * @throws IOException if there is a problem creating this query
- */
- Query findAllNodesWithIds( Set<String> ids ) throws IOException;
-
Query findAllNodesBelow( Path ancestorPath ) throws IOException;
+ Query findAllNodesAtOrBelow( Path ancestorPath ) throws IOException;
+
/**
* Return a query that can be used to find all of the documents that represent
nodes that are children of the node at the
* supplied path.
@@ -845,6 +855,6 @@
*
* @return the tuples; never null
*/
- public abstract LinkedList<Object[]> getTuples();
+ public abstract List<Object[]> getTuples();
}
}
Deleted:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/EncodingNamespaceRegistry.java
===================================================================
---
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/EncodingNamespaceRegistry.java 2009-12-31
16:13:57 UTC (rev 1506)
+++
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/EncodingNamespaceRegistry.java 2009-12-31
18:53:06 UTC (rev 1507)
@@ -1,233 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- * is licensed to you under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JBoss DNA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jboss.dna.search.lucene;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import net.jcip.annotations.GuardedBy;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.text.NoOpEncoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.JcrLexicon;
-import org.jboss.dna.graph.JcrMixLexicon;
-import org.jboss.dna.graph.JcrNtLexicon;
-import org.jboss.dna.graph.property.NamespaceRegistry;
-import org.jboss.dna.graph.property.basic.BasicNamespace;
-
-/**
- * A {@link NamespaceRegistry} implementation that uses encoded representations of the
namespace URIs for the namespace prefixes.
- */
-@ThreadSafe
-class EncodingNamespaceRegistry implements NamespaceRegistry {
-
- public static final Set<String> DEFAULT_FIXED_NAMESPACES =
Collections.unmodifiableSet(new HashSet<String>(
-
Arrays.asList(new String[] {
-
"",
-
DnaLexicon.Namespace.URI,
-
JcrLexicon.Namespace.URI,
-
JcrNtLexicon.Namespace.URI,
-
JcrMixLexicon.Namespace.URI})));
-
- private final NamespaceRegistry registry;
- private final TextEncoder encoder;
- private final ReadWriteLock lock = new ReentrantReadWriteLock();
- @GuardedBy( "lock" )
- private final Map<String, String> uriToEncodedPrefix = new HashMap<String,
String>();
- @GuardedBy( "lock" )
- private final Map<String, String> encodedPrefixToUri = new HashMap<String,
String>();
- private final Set<String> fixedNamespaceUris;
-
- /**
- * @param registry the original registry
- * @param encoder the encoder; may be null if no encoding should be used
- */
- EncodingNamespaceRegistry( NamespaceRegistry registry,
- TextEncoder encoder ) {
- this(registry, encoder, null);
- }
-
- /**
- * @param registry the original registry
- * @param encoder the encoder; may be null if no encoding should be used
- * @param fixedUris the set of URIs that is to be fixed and not encoded; or null if
the default namespaces are to be fixed
- */
- EncodingNamespaceRegistry( NamespaceRegistry registry,
- TextEncoder encoder,
- Set<String> fixedUris ) {
- this.registry = registry;
- this.encoder = encoder != null ? encoder : new NoOpEncoder();
- this.fixedNamespaceUris = fixedUris != null ? Collections.unmodifiableSet(new
HashSet<String>(fixedUris)) : DEFAULT_FIXED_NAMESPACES;
- assert this.registry != null;
- assert this.encoder != null;
- assert this.fixedNamespaceUris != null;
- }
-
- /**
- * @return fixedNamespaceUris
- */
- public Set<String> getFixedNamespaceUris() {
- return fixedNamespaceUris;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.graph.property.NamespaceRegistry#getDefaultNamespaceUri()
- */
- public String getDefaultNamespaceUri() {
- return this.registry.getDefaultNamespaceUri();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.graph.property.NamespaceRegistry#getNamespaceForPrefix(java.lang.String)
- */
- public String getNamespaceForPrefix( String prefix ) {
- // First look in the map ...
- String result = null;
- try {
- lock.readLock().lock();
- result = encodedPrefixToUri.get(prefix);
- if (result != null) return result;
- } finally {
- lock.readLock().unlock();
- }
-
- // Make sure we have encoded all the namespaces in the registry ...
- Set<Namespace> namespaces = new
HashSet<Namespace>(this.registry.getNamespaces());
- Set<Namespace> encodedNamespaces = this.getNamespaces();
- namespaces.removeAll(encodedNamespaces);
- try {
- lock.writeLock().lock();
- for (Namespace namespace : namespaces) {
- String namespaceUri = namespace.getNamespaceUri();
- String encoded = fixedNamespaceUris.contains(namespaceUri) ?
namespace.getPrefix() : encoder.encode(namespaceUri);
- uriToEncodedPrefix.put(namespaceUri, encoded);
- encodedPrefixToUri.put(encoded, namespaceUri);
- if (result == null && encoded.equals(prefix)) result =
namespaceUri;
- }
- } finally {
- lock.writeLock().unlock();
- }
- if (result != null) return result;
-
- // There's nothing, so just delegate to the registry ...
- return this.registry.getNamespaceForPrefix(prefix);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.graph.property.NamespaceRegistry#getRegisteredNamespaceUris()
- */
- public Set<String> getRegisteredNamespaceUris() {
- return this.registry.getRegisteredNamespaceUris();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.graph.property.NamespaceRegistry#isRegisteredNamespaceUri(java.lang.String)
- */
- public boolean isRegisteredNamespaceUri( String namespaceUri ) {
- return this.registry.isRegisteredNamespaceUri(namespaceUri);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.graph.property.NamespaceRegistry#getPrefixForNamespaceUri(java.lang.String,
boolean)
- */
- public String getPrefixForNamespaceUri( String namespaceUri,
- boolean generateIfMissing ) {
- if (fixedNamespaceUris.contains(namespaceUri)) {
- return this.registry.getPrefixForNamespaceUri(namespaceUri,
generateIfMissing);
- }
- String encoded = null;
- try {
- lock.readLock().lock();
- encoded = uriToEncodedPrefix.get(namespaceUri);
- } finally {
- lock.readLock().unlock();
- }
- if (encoded == null) {
- encoded = encoder.encode(namespaceUri);
- try {
- lock.writeLock().lock();
- uriToEncodedPrefix.put(namespaceUri, encoded);
- encodedPrefixToUri.put(encoded, namespaceUri);
- } finally {
- lock.writeLock().unlock();
- }
- }
- return encoded;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.graph.property.NamespaceRegistry#getNamespaces()
- */
- public Set<Namespace> getNamespaces() {
- Set<Namespace> results = new HashSet<Namespace>();
- try {
- lock.readLock().lock();
- for (Map.Entry<String, String> entry : uriToEncodedPrefix.entrySet())
{
- String uri = entry.getKey();
- String prefix = entry.getValue();
- results.add(new BasicNamespace(prefix, uri));
- }
- } finally {
- lock.readLock().unlock();
- }
- return results;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.graph.property.NamespaceRegistry#register(java.lang.String,
java.lang.String)
- */
- public String register( String prefix,
- String namespaceUri ) {
- return this.registry.register(prefix, namespaceUri);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.graph.property.NamespaceRegistry#unregister(java.lang.String)
- */
- public boolean unregister( String namespaceUri ) {
- return this.registry.unregister(namespaceUri);
- }
-}
Modified:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchProcessor.java
===================================================================
---
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchProcessor.java 2009-12-31
16:13:57 UTC (rev 1506)
+++
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchProcessor.java 2009-12-31
18:53:06 UTC (rev 1507)
@@ -29,24 +29,15 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import java.util.UUID;
import net.jcip.annotations.NotThreadSafe;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.NumericField;
import org.apache.lucene.queryParser.ParseException;
-import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
-import org.jboss.dna.common.text.SecureHashTextEncoder;
-import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.common.util.SecureHash.Algorithm;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.observe.Observer;
import org.jboss.dna.graph.property.DateTime;
import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.graph.property.Property;
import org.jboss.dna.graph.query.QueryResults.Columns;
import org.jboss.dna.graph.query.QueryResults.Statistics;
import org.jboss.dna.graph.query.process.FullTextSearchResultColumns;
@@ -69,7 +60,6 @@
import org.jboss.dna.graph.search.SearchEngineProcessor;
import org.jboss.dna.graph.search.AbstractSearchEngine.Workspaces;
import org.jboss.dna.search.lucene.AbstractLuceneSearchEngine.AbstractLuceneProcessor;
-import org.jboss.dna.search.lucene.LuceneSearchWorkspace.PathIndex;
/**
* Abstract {@link SearchEngineProcessor} implementation for the {@link
LuceneSearchEngine}.
@@ -77,15 +67,6 @@
@NotThreadSafe
public class LuceneSearchProcessor extends
AbstractLuceneProcessor<LuceneSearchWorkspace, LuceneSearchSession> {
- protected static final TextEncoder NAMESPACE_ENCODER = new
SecureHashTextEncoder(Algorithm.SHA_1, 10);
-
- protected static ExecutionContext contextWithEncodedNamespaces( ExecutionContext
context ) {
- return context;
- // NamespaceRegistry encodingRegistry = new
EncodingNamespaceRegistry(context.getNamespaceRegistry(), NAMESPACE_ENCODER);
- // ExecutionContext encodingContext = context.with(encodingRegistry);
- // return encodingContext;
- }
-
protected static final Columns FULL_TEXT_RESULT_COLUMNS = new
FullTextSearchResultColumns();
protected LuceneSearchProcessor( String sourceName,
@@ -94,7 +75,7 @@
Observer observer,
DateTime now,
boolean readOnly ) {
- super(sourceName, contextWithEncodedNamespaces(context), workspaces, observer,
now, readOnly);
+ super(sourceName, context, workspaces, observer, now, readOnly);
}
/**
@@ -117,15 +98,6 @@
return LuceneSearchWorkspace.FULL_TEXT_PREFIX + propertyName;
}
- protected void addIdProperties( Location location,
- Document doc ) {
- if (!location.hasIdProperties()) return;
- for (Property idProp : location.getIdProperties()) {
- String fieldValue = serializeProperty(idProp);
- doc.add(new Field(PathIndex.LOCATION_ID_PROPERTIES, fieldValue,
Field.Store.YES, Field.Index.NOT_ANALYZED));
- }
- }
-
/**
* {@inheritDoc}
*
@@ -157,7 +129,7 @@
if (session == null) return;
request.setActualWorkspaceName(session.getWorkspaceName());
try {
-
request.setActualRootLocation(session.getLocationFor(pathFactory.createRootPath()));
+ request.setActualRootLocation(session.getLocationForRoot());
} catch (IOException e) {
request.setError(e);
}
@@ -201,43 +173,13 @@
}
try {
- // Create a separate document for the path, which makes it easier to handle
moves since the path can
- // be changed without changing any other content fields ...
- Document doc = new Document();
- String idStr = createPathDocument(location, doc);
- session.getPathsWriter().addDocument(doc);
-
- // Now set the content ...
- session.setOrReplaceProperties(idStr, request.properties());
+ session.setOrReplaceProperties(location, request.properties());
session.recordChange();
} catch (IOException e) {
request.setError(e);
}
}
- protected String createPathDocument( Location location,
- Document doc ) {
- UUID uuid = location.getUuid();
- if (uuid == null) uuid = UUID.randomUUID();
- Path path = location.getPath();
- String idStr = stringFactory.create(uuid);
- String pathStr = pathAsString(path);
- String nameStr = path.isRoot() ? "" :
stringFactory.create(path.getLastSegment().getName());
- String localNameStr = path.isRoot() ? "" :
path.getLastSegment().getName().getLocalName();
- int sns = path.isRoot() ? 1 : path.getLastSegment().getIndex();
-
- // Create a separate document for the path, which makes it easier to handle moves
since the path can
- // be changed without changing any other content fields ...
- doc.add(new Field(PathIndex.PATH, pathStr, Field.Store.YES,
Field.Index.NOT_ANALYZED));
- doc.add(new Field(PathIndex.NODE_NAME, nameStr, Field.Store.YES,
Field.Index.NOT_ANALYZED));
- doc.add(new Field(PathIndex.LOCAL_NAME, localNameStr, Field.Store.YES,
Field.Index.NOT_ANALYZED));
- doc.add(new NumericField(PathIndex.SNS_INDEX, Field.Store.YES,
true).setIntValue(sns));
- doc.add(new Field(PathIndex.ID, idStr, Field.Store.YES,
Field.Index.NOT_ANALYZED));
- doc.add(new NumericField(PathIndex.DEPTH, Field.Store.YES,
true).setIntValue(path.size()));
- addIdProperties(location, doc);
- return idStr;
- }
-
/**
* {@inheritDoc}
*
@@ -251,25 +193,11 @@
Location location = request.getActualLocationOfNode();
assert location != null;
- UUID uuid = location.getUuid();
try {
- // If we're updating the root properties, make sure there is a document
in the path index ...
- String idStr = null;
- if (location.getPath() != null && location.getPath().isRoot()) {
- Document doc = new Document();
- idStr = createPathDocument(location, doc);
- session.getPathsWriter().addDocument(doc);
- } else if (uuid != null) {
- idStr = stringFactory.create(uuid);
- } else {
- // Need to look up the id string ...
- idStr = session.getIdFor(location.getPath());
- }
-
// We make a big assumption here: the UpdatePropertiesRequest created by the
SearchEngineProcessor have the
// actual locations set ...
- session.setOrReplaceProperties(idStr, request.properties().values());
+ session.setOrReplaceProperties(location, request.properties().values());
session.recordChange();
} catch (IOException e) {
request.setError(e);
@@ -289,21 +217,11 @@
Path path = request.at().getPath();
assert !readOnly;
try {
- Query query = null;
- int numChanges = 0;
- if (path.isRoot()) {
- query = new MatchAllDocsQuery();
- numChanges = LuceneSearchWorkspace.CHANGES_BEFORE_OPTIMIZATION + 100;
- } else {
- // Create a query to find all the nodes at or below the specified path
...
- Set<String> ids = session.getIdsForDescendantsOf(path, true);
- query = session.findAllNodesWithIds(ids);
- numChanges = ids.size();
- }
+ // Create a query to find all the nodes at or below the specified path (this
efficiently handles the root path) ...
+ Query query = session.findAllNodesAtOrBelow(path);
// Now delete the documents from each index using this query, which we can
reuse ...
- session.getPathsWriter().deleteDocuments(query);
session.getContentWriter().deleteDocuments(query);
- session.recordChanges(numChanges);
+ session.recordChanges(100);
} catch (FileNotFoundException e) {
// There are no index files yet, so nothing to delete ...
} catch (IOException e) {
@@ -322,7 +240,7 @@
if (workspace == null) return;
try {
LuceneSearchSession session = getSessionFor(request,
workspace.getWorkspaceName());
-
request.setActualRootLocation(session.getLocationFor(pathFactory.createRootPath()));
+ request.setActualRootLocation(session.getLocationForRoot());
workspace.destroy(getExecutionContext());
session.recordChanges(LuceneSearchWorkspace.CHANGES_BEFORE_OPTIMIZATION +
100);
} catch (IOException e) {
Modified:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchSession.java
===================================================================
---
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchSession.java 2009-12-31
16:13:57 UTC (rev 1506)
+++
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchSession.java 2009-12-31
18:53:06 UTC (rev 1507)
@@ -24,6 +24,7 @@
package org.jboss.dna.search.lucene;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@@ -44,8 +45,6 @@
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.Collector;
-import org.apache.lucene.search.FieldCache;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.NumericRangeQuery;
@@ -82,12 +81,10 @@
import org.jboss.dna.search.lucene.IndexRules.NumericRule;
import org.jboss.dna.search.lucene.IndexRules.Rule;
import org.jboss.dna.search.lucene.LuceneSearchWorkspace.ContentIndex;
-import org.jboss.dna.search.lucene.LuceneSearchWorkspace.PathIndex;
import org.jboss.dna.search.lucene.query.CompareLengthQuery;
import org.jboss.dna.search.lucene.query.CompareNameQuery;
import org.jboss.dna.search.lucene.query.ComparePathQuery;
import org.jboss.dna.search.lucene.query.CompareStringQuery;
-import org.jboss.dna.search.lucene.query.IdsQuery;
import org.jboss.dna.search.lucene.query.MatchNoneQuery;
import org.jboss.dna.search.lucene.query.NotQuery;
@@ -100,22 +97,11 @@
/**
* An immutable {@link FieldSelector} instance that accesses the UUID field.
*/
- protected static final FieldSelector DOC_ID_FIELD_SELECTOR = new FieldSelector() {
- private static final long serialVersionUID = 1L;
-
- public FieldSelectorResult accept( String fieldName ) {
- return ContentIndex.ID.equals(fieldName) ? FieldSelectorResult.LOAD_AND_BREAK
: FieldSelectorResult.NO_LOAD;
- }
- };
-
- /**
- * An immutable {@link FieldSelector} instance that accesses the UUID field.
- */
protected static final FieldSelector LOCATION_FIELDS_SELECTOR = new FieldSelector()
{
private static final long serialVersionUID = 1L;
public FieldSelectorResult accept( String fieldName ) {
- if (PathIndex.PATH.equals(fieldName) ||
PathIndex.LOCATION_ID_PROPERTIES.equals(fieldName)) {
+ if (ContentIndex.PATH.equals(fieldName) ||
ContentIndex.LOCATION_ID_PROPERTIES.equals(fieldName)) {
return FieldSelectorResult.LOAD;
}
return FieldSelectorResult.NO_LOAD;
@@ -129,11 +115,7 @@
private final LuceneSearchWorkspace workspace;
protected final LuceneSearchProcessor processor;
- private final Directory pathsIndexDirectory;
private final Directory contentIndexDirectory;
- private IndexReader pathsReader;
- private IndexWriter pathsWriter;
- private IndexSearcher pathsSearcher;
private IndexReader contentReader;
private IndexWriter contentWriter;
private IndexSearcher contentSearcher;
@@ -144,7 +126,6 @@
assert workspace != null;
assert processor != null;
this.workspace = workspace;
- this.pathsIndexDirectory = workspace.pathDirectory;
this.contentIndexDirectory = workspace.contentDirectory;
this.processor = processor;
}
@@ -165,21 +146,6 @@
return workspace;
}
- protected IndexReader getPathsReader() throws IOException {
- if (pathsReader == null) {
- try {
- pathsReader = IndexReader.open(pathsIndexDirectory, processor.readOnly);
- } catch (IOException e) {
- // try creating the workspace ...
- IndexWriter writer = new IndexWriter(pathsIndexDirectory,
workspace.analyzer, MaxFieldLength.UNLIMITED);
- writer.close();
- // And try reading again ...
- pathsReader = IndexReader.open(pathsIndexDirectory, processor.readOnly);
- }
- }
- return pathsReader;
- }
-
protected IndexReader getContentReader() throws IOException {
if (contentReader == null) {
try {
@@ -195,15 +161,6 @@
return contentReader;
}
- protected IndexWriter getPathsWriter() throws IOException {
- assert !processor.readOnly;
- if (pathsWriter == null) {
- // Don't overwrite, but create if missing ...
- pathsWriter = new IndexWriter(pathsIndexDirectory, workspace.analyzer,
MaxFieldLength.UNLIMITED);
- }
- return pathsWriter;
- }
-
protected IndexWriter getContentWriter() throws IOException {
assert !processor.readOnly;
if (contentWriter == null) {
@@ -213,13 +170,6 @@
return contentWriter;
}
- protected IndexSearcher getPathsSearcher() throws IOException {
- if (pathsSearcher == null) {
- pathsSearcher = new IndexSearcher(getPathsReader());
- }
- return pathsSearcher;
- }
-
public IndexSearcher getContentSearcher() throws IOException {
if (contentSearcher == null) {
contentSearcher = new IndexSearcher(getContentReader());
@@ -228,7 +178,7 @@
}
public boolean hasWriters() {
- return pathsWriter != null || contentWriter != null;
+ return contentWriter != null;
}
protected final void recordChange() {
@@ -261,47 +211,17 @@
IOException ioError = null;
RuntimeException runtimeError = null;
- if (pathsReader != null) {
+ if (contentReader != null) {
try {
- pathsReader.close();
+ contentReader.close();
} catch (IOException e) {
ioError = e;
} catch (RuntimeException e) {
runtimeError = e;
} finally {
- pathsReader = null;
- }
- }
- if (contentReader != null) {
- try {
- contentReader.close();
- } catch (IOException e) {
- if (ioError == null) ioError = e;
- } catch (RuntimeException e) {
- if (runtimeError == null) runtimeError = e;
- } finally {
contentReader = null;
}
}
- if (pathsWriter != null) {
- try {
- if (optimize) pathsWriter.optimize();
- } catch (IOException e) {
- if (ioError == null) ioError = e;
- } catch (RuntimeException e) {
- if (runtimeError == null) runtimeError = e;
- } finally {
- try {
- pathsWriter.close();
- } catch (IOException e) {
- if (ioError == null) ioError = e;
- } catch (RuntimeException e) {
- if (runtimeError == null) runtimeError = e;
- } finally {
- pathsWriter = null;
- }
- }
- }
if (contentWriter != null) {
try {
if (optimize) contentWriter.optimize();
@@ -339,45 +259,15 @@
numChanges = 0;
IOException ioError = null;
RuntimeException runtimeError = null;
- if (pathsReader != null) {
- try {
- pathsReader.close();
- } catch (IOException e) {
- ioError = e;
- } catch (RuntimeException e) {
- runtimeError = e;
- } finally {
- pathsReader = null;
- }
- }
if (contentReader != null) {
try {
contentReader.close();
} catch (IOException e) {
- if (ioError == null) ioError = e;
- } catch (RuntimeException e) {
- if (runtimeError == null) runtimeError = e;
- } finally {
- contentReader = null;
- }
- }
- if (pathsWriter != null) {
- try {
- pathsWriter.rollback();
- } catch (IOException e) {
ioError = e;
} catch (RuntimeException e) {
runtimeError = e;
} finally {
- try {
- pathsWriter.close();
- } catch (IOException e) {
- ioError = e;
- } catch (RuntimeException e) {
- runtimeError = e;
- } finally {
- pathsWriter = null;
- }
+ contentReader = null;
}
}
if (contentWriter != null) {
@@ -417,12 +307,10 @@
QueryParser parser = new QueryParser(Version.LUCENE_29, ContentIndex.FULL_TEXT,
workspace.analyzer);
Query query = parser.parse(fullTextSearchExpression);
planningNanos = System.nanoTime() - planningNanos;
- TopDocs docs = getContentSearcher().search(query, maxRows + offset);
- // Collect the results ...
+ // Execute the search and place the results into the supplied list ...
+ TopDocs docs = getContentSearcher().search(query, maxRows + offset);
IndexReader contentReader = getContentReader();
- IndexReader pathReader = getPathsReader();
- IndexSearcher pathSearcher = getPathsSearcher();
ScoreDoc[] scoreDocs = docs.scoreDocs;
int numberOfResults = scoreDocs.length;
if (numberOfResults > offset) {
@@ -431,14 +319,8 @@
ScoreDoc result = scoreDocs[i];
int docId = result.doc;
// Find the UUID of the node (this UUID might be artificial, so we have
to find the path) ...
- Document doc = contentReader.document(docId, DOC_ID_FIELD_SELECTOR);
- String id = doc.get(ContentIndex.ID);
- Document pathDoc = getPathDocument(id, pathReader, pathSearcher,
LOCATION_FIELDS_SELECTOR);
- Location location = readLocation(pathDoc);
- if (location == null) {
- // No path record found ...
- continue;
- }
+ Document doc = contentReader.document(docId, LOCATION_FIELDS_SELECTOR);
+ Location location = readLocation(doc);
// Now add the location ...
results.add(new Object[] {location, result.score});
}
@@ -449,10 +331,10 @@
protected Location readLocation( Document doc ) {
// Read the path ...
- String pathString = doc.get(PathIndex.PATH);
+ String pathString = doc.get(ContentIndex.PATH);
Path path = processor.pathFactory.create(pathString);
// Look for the Location's ID properties ...
- String[] idProps = doc.getValues(PathIndex.LOCATION_ID_PROPERTIES);
+ String[] idProps = doc.getValues(ContentIndex.LOCATION_ID_PROPERTIES);
if (idProps.length == 0) {
return Location.create(path);
}
@@ -472,11 +354,33 @@
return properties.isEmpty() ? Location.create(path) : Location.create(path,
properties);
}
- protected void setOrReplaceProperties( String idString,
+ protected void setOrReplaceProperties( Location location,
Iterable<Property> properties ) throws
IOException {
// Create the document for the content (properties) ...
Document doc = new Document();
- doc.add(new Field(ContentIndex.ID, idString, Field.Store.YES,
Field.Index.NOT_ANALYZED));
+
+ // Add the information every node has ...
+ Path path = location.getPath();
+ String pathStr = processor.pathAsString(path);
+ String nameStr = path.isRoot() ? "" :
processor.stringFactory.create(path.getLastSegment().getName());
+ String localNameStr = path.isRoot() ? "" :
path.getLastSegment().getName().getLocalName();
+ int sns = path.isRoot() ? 1 : path.getLastSegment().getIndex();
+
+ // Create a separate document for the path, which makes it easier to handle moves
since the path can
+ // be changed without changing any other content fields ...
+ doc.add(new Field(ContentIndex.PATH, pathStr, Field.Store.YES,
Field.Index.NOT_ANALYZED));
+ doc.add(new Field(ContentIndex.NODE_NAME, nameStr, Field.Store.YES,
Field.Index.NOT_ANALYZED));
+ doc.add(new Field(ContentIndex.LOCAL_NAME, localNameStr, Field.Store.YES,
Field.Index.NOT_ANALYZED));
+ doc.add(new NumericField(ContentIndex.SNS_INDEX, Field.Store.YES,
true).setIntValue(sns));
+ doc.add(new NumericField(ContentIndex.DEPTH, Field.Store.YES,
true).setIntValue(path.size()));
+ if (location.hasIdProperties()) {
+ for (Property idProp : location.getIdProperties()) {
+ String fieldValue = processor.serializeProperty(idProp);
+ doc.add(new Field(ContentIndex.LOCATION_ID_PROPERTIES, fieldValue,
Field.Store.YES, Field.Index.NOT_ANALYZED));
+ }
+ }
+
+ // Index the properties
String stringValue = null;
StringBuilder fullTextSearchValue = null;
for (Property property : properties) {
@@ -559,193 +463,90 @@
if (fullTextSearchValue != null && fullTextSearchValue.length() != 0) {
doc.add(new Field(ContentIndex.FULL_TEXT, fullTextSearchValue.toString(),
Field.Store.NO, Field.Index.ANALYZED));
}
- getContentWriter().updateDocument(new Term(ContentIndex.ID, idString), doc);
+ getContentWriter().updateDocument(new Term(ContentIndex.PATH, pathStr), doc);
}
- protected Document getPathDocument( String id,
- IndexReader pathReader,
- IndexSearcher pathSearcher,
- FieldSelector selector ) throws IOException {
- // Find the path for this node (is there a better way to do this than one search
per ID?) ...
- TopDocs pathDocs = pathSearcher.search(new TermQuery(new Term(PathIndex.ID, id)),
1);
- if (pathDocs.scoreDocs.length < 1) {
- // No path record found ...
- return null;
- }
- return pathReader.document(pathDocs.scoreDocs[0].doc, selector);
- }
-
/**
- * Get the set of IDs for the children of the node at the given path.
+ * {@inheritDoc}
*
- * @param parentPath the path to the parent node; may not be null
- * @return the doc IDs of the child nodes; never null but possibly empty
- * @throws IOException if there is an error accessing the indexes
+ * @see
org.jboss.dna.search.lucene.AbstractLuceneSearchEngine.WorkspaceSession#createTupleCollector(org.jboss.dna.graph.query.QueryResults.Columns)
*/
- protected Set<String> getIdsForChildrenOf( Path parentPath ) throws IOException
{
- // Find the path of the parent ...
- String stringifiedPath = processor.pathAsString(parentPath);
- // Append a '/' to the parent path, so we'll only get decendants ...
- stringifiedPath = stringifiedPath + '/';
+ public TupleCollector createTupleCollector( Columns columns ) {
+ return new DualIndexTupleCollector(this, columns);
+ }
- // Create a query to find all the nodes below the parent path ...
- Query query = new PrefixQuery(new Term(PathIndex.PATH, stringifiedPath));
- // Include only the children ...
- int childrenDepth = parentPath.size() + 1;
- Query depthQuery = NumericRangeQuery.newIntRange(PathIndex.DEPTH, childrenDepth,
childrenDepth, true, true);
- // And combine ...
- BooleanQuery combinedQuery = new BooleanQuery();
- combinedQuery.add(query, Occur.MUST);
- combinedQuery.add(depthQuery, Occur.MUST);
- query = combinedQuery;
+ public Location getLocationForRoot() throws IOException {
+ // Look for the root node ...
+ Query query = NumericRangeQuery.newIntRange(ContentIndex.DEPTH, 0, 0, true,
true);
- // Now execute and collect the IDs ...
- IdCollector idCollector = new IdCollector();
- IndexSearcher searcher = getPathsSearcher();
- searcher.search(query, idCollector);
- return idCollector.getIds();
+ // Execute the search and place the results into the supplied list ...
+ List<Object[]> tuples = new ArrayList<Object[]>(1);
+ FullTextSearchTupleCollector collector = new FullTextSearchTupleCollector(this,
tuples);
+ getContentSearcher().search(query, collector);
+
+ // Extract the location from the results ...
+ return tuples.isEmpty() ? Location.create(processor.pathFactory.createRootPath())
: (Location)tuples.get(0)[0];
}
- /**
- * Get the set of IDs for the nodes that are descendants of the node at the given
path.
- *
- * @param parentPath the path to the parent node; may not be null and <i>may
not be the root node</i>
- * @param includeParent true if the parent node should be included in the results, or
false if only the descendants should be
- * included
- * @return the IDs of the nodes; never null but possibly empty
- * @throws IOException if there is an error accessing the indexes
- */
- protected Set<String> getIdsForDescendantsOf( Path parentPath,
- boolean includeParent ) throws
IOException {
- assert !parentPath.isRoot();
-
+ public Query findAllNodesBelow( Path parentPath ) {
// Find the path of the parent ...
String stringifiedPath = processor.pathAsString(parentPath);
- if (!includeParent) {
- // Append a '/' to the parent path, and we'll only get decendants
...
- stringifiedPath = stringifiedPath + '/';
- }
+ // Append a '/' to the parent path, and we'll only get decendants
...
+ stringifiedPath = stringifiedPath + '/';
// Create a prefix query ...
- Query query = new PrefixQuery(new Term(PathIndex.PATH, stringifiedPath));
-
- // Now execute and collect the IDs ...
- IdCollector idCollector = new IdCollector();
- IndexSearcher searcher = getPathsSearcher();
- searcher.search(query, idCollector);
- return idCollector.getIds();
+ return new PrefixQuery(new Term(ContentIndex.PATH, stringifiedPath));
}
- /**
- * Get the set containing the single ID for the node at the given path.
- *
- * @param path the path to the node; may not be null
- * @return the ID of the supplied node; or null if the node cannot be found
- * @throws IOException if there is an error accessing the indexes
- */
- protected String getIdFor( Path path ) throws IOException {
- // Create a query to find all the nodes below the parent path ...
- IndexSearcher searcher = getPathsSearcher();
- Query query = null;
- if (path.isRoot()) {
- // Look for the query
- query = NumericRangeQuery.newIntRange(PathIndex.DEPTH, 0, 0, true, true);
- } else {
- String stringifiedPath = processor.pathAsString(path);
- query = new TermQuery(new Term(PathIndex.PATH, stringifiedPath));
+ public Query findAllNodesAtOrBelow( Path parentPath ) {
+ if (parentPath.isRoot()) {
+ return new MatchAllDocsQuery();
}
+ // Find the path of the parent ...
+ String stringifiedPath = processor.pathAsString(parentPath);
- // Now execute and collect the UUIDs ...
- TopDocs topDocs = searcher.search(query, 1);
- if (topDocs.totalHits == 0) return null;
- Document pathDoc = getPathsReader().document(topDocs.scoreDocs[0].doc);
- String idString = pathDoc.get(PathIndex.ID);
- assert idString != null;
- return idString;
+ // Create a prefix query ...
+ return new PrefixQuery(new Term(ContentIndex.PATH, stringifiedPath));
}
- protected Location getLocationFor( Path path ) throws IOException {
- // Create a query to find all the nodes below the parent path ...
- IndexSearcher searcher = getPathsSearcher();
- String stringifiedPath = processor.pathAsString(path);
- TermQuery query = new TermQuery(new Term(PathIndex.PATH, stringifiedPath));
-
- // Now execute and collect the UUIDs ...
- TopDocs topDocs = searcher.search(query, 1);
- if (topDocs.totalHits == 0) return null;
- Document pathDoc = getPathsReader().document(topDocs.scoreDocs[0].doc);
- return readLocation(pathDoc);
- }
-
/**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.search.lucene.AbstractLuceneSearchEngine.WorkspaceSession#createTupleCollector(org.jboss.dna.graph.query.QueryResults.Columns)
- */
- public TupleCollector createTupleCollector( Columns columns ) {
- return new DualIndexTupleCollector(this, columns);
- }
-
- public Query findAllNodesWithIds( Set<String> ids ) {
- if (ids.isEmpty()) {
- // There are no children, so return a null query ...
- return new MatchNoneQuery();
- }
- if (ids.size() == 1) {
- String id = ids.iterator().next();
- if (id == null) return new MatchNoneQuery();
- return new TermQuery(new Term(ContentIndex.ID, id));
- }
- if (ids.size() < 50) {
- // Create an OR boolean query for all the UUIDs, since this is probably more
efficient ...
- BooleanQuery query = new BooleanQuery();
- for (String id : ids) {
- Query uuidQuery = new TermQuery(new Term(ContentIndex.ID, id));
- query.add(uuidQuery, Occur.SHOULD);
- }
- return query;
- }
- // Return a query that will always find all of the UUIDs ...
- return new IdsQuery(ContentIndex.ID, ids);
- }
-
- public Query findAllNodesBelow( Path ancestorPath ) throws IOException {
- if (ancestorPath.isRoot()) {
- return new MatchAllDocsQuery();
- }
- Set<String> ids = getIdsForDescendantsOf(ancestorPath, false);
- return findAllNodesWithIds(ids);
- }
-
- /**
* Return a query that can be used to find all of the documents that represent nodes
that are children of the node at the
* supplied path.
*
* @param parentPath the path of the parent node.
* @return the query; never null
- * @throws IOException if there is an error finding the UUIDs of the child nodes
*/
- public Query findChildNodes( Path parentPath ) throws IOException {
- if (parentPath.isRoot()) {
- return new MatchAllDocsQuery();
- }
- Set<String> childIds = getIdsForChildrenOf(parentPath);
- return findAllNodesWithIds(childIds);
+ public Query findChildNodes( Path parentPath ) {
+ // Find the path of the parent ...
+ String stringifiedPath = processor.pathAsString(parentPath);
+ // Append a '/' to the parent path, so we'll only get decendants ...
+ stringifiedPath = stringifiedPath + '/';
+
+ // Create a query to find all the nodes below the parent path ...
+ Query query = new PrefixQuery(new Term(ContentIndex.PATH, stringifiedPath));
+ // Include only the children ...
+ int childrenDepth = parentPath.size() + 1;
+ Query depthQuery = NumericRangeQuery.newIntRange(ContentIndex.DEPTH,
childrenDepth, childrenDepth, true, true);
+ // And combine ...
+ BooleanQuery combinedQuery = new BooleanQuery();
+ combinedQuery.add(query, Occur.MUST);
+ combinedQuery.add(depthQuery, Occur.MUST);
+ return combinedQuery;
}
/**
- * Create a query that can be used to find the one document (or node) that exists at
the exact path supplied. This method
- * first queries the {@link PathIndex path index} to find the ID of the node at the
supplied path, and then returns a query
- * that matches the ID.
+ * Create a query that can be used to find the one document (or node) that exists at
the exact path supplied.
*
* @param path the path of the node
* @return the query; never null
- * @throws IOException if there is an error finding the ID for the supplied path
*/
- public Query findNodeAt( Path path ) throws IOException {
- String id = getIdFor(path);
- if (id == null) return null;
- return new TermQuery(new Term(ContentIndex.ID, id));
+ public Query findNodeAt( Path path ) {
+ if (path.isRoot()) {
+ // Look for the root node ...
+ return NumericRangeQuery.newIntRange(ContentIndex.DEPTH, 0, 0, true, true);
+ }
+ String stringifiedPath = processor.pathAsString(path);
+ return new TermQuery(new Term(ContentIndex.PATH, stringifiedPath));
}
public Query findNodesLike( String fieldName,
@@ -1037,7 +838,7 @@
Object upperValue,
boolean includesLower,
boolean includesUpper ) {
- return findNodesWithNumericRange(PathIndex.DEPTH, lowerValue, upperValue,
includesLower, includesUpper);
+ return findNodesWithNumericRange(ContentIndex.DEPTH, lowerValue, upperValue,
includesLower, includesUpper);
}
protected Query findNodesWithNumericRange( String field,
@@ -1085,7 +886,7 @@
public Query findNodesWith( NodePath nodePath,
Operator operator,
Object value,
- boolean caseSensitive ) throws IOException {
+ boolean caseSensitive ) {
if (!caseSensitive) value = processor.stringFactory.create(value).toLowerCase();
Path pathValue = operator != Operator.LIKE ? processor.pathFactory.create(value)
: null;
Query query = null;
@@ -1096,44 +897,40 @@
return new NotQuery(findNodeAt(pathValue));
case LIKE:
String likeExpression = processor.stringFactory.create(value);
- query = findNodesLike(PathIndex.PATH, likeExpression, caseSensitive);
+ query = findNodesLike(ContentIndex.PATH, likeExpression, caseSensitive);
break;
case GREATER_THAN:
query =
ComparePathQuery.createQueryForNodesWithPathGreaterThan(pathValue,
-
PathIndex.PATH,
+
ContentIndex.PATH,
processor.valueFactories,
caseSensitive);
break;
case GREATER_THAN_OR_EQUAL_TO:
query =
ComparePathQuery.createQueryForNodesWithPathGreaterThanOrEqualTo(pathValue,
-
PathIndex.PATH,
+
ContentIndex.PATH,
processor.valueFactories,
caseSensitive);
break;
case LESS_THAN:
query = ComparePathQuery.createQueryForNodesWithPathLessThan(pathValue,
-
PathIndex.PATH,
+
ContentIndex.PATH,
processor.valueFactories,
caseSensitive);
break;
case LESS_THAN_OR_EQUAL_TO:
query =
ComparePathQuery.createQueryForNodesWithPathLessThanOrEqualTo(pathValue,
-
PathIndex.PATH,
+
ContentIndex.PATH,
processor.valueFactories,
caseSensitive);
break;
}
- // Now execute and collect the IDs ...
- IdCollector idCollector = new IdCollector();
- IndexSearcher searcher = getPathsSearcher();
- searcher.search(query, idCollector);
- return findAllNodesWithIds(idCollector.getIds());
+ return query;
}
public Query findNodesWith( NodeName nodeName,
Operator operator,
Object value,
- boolean caseSensitive ) throws IOException {
+ boolean caseSensitive ) {
ValueFactories factories = processor.valueFactories;
String stringValue = processor.stringFactory.create(value);
if (!caseSensitive) stringValue = stringValue.toLowerCase();
@@ -1143,39 +940,41 @@
switch (operator) {
case EQUAL_TO:
BooleanQuery booleanQuery = new BooleanQuery();
- booleanQuery.add(new TermQuery(new Term(PathIndex.NODE_NAME,
stringValue)), Occur.MUST);
- booleanQuery.add(NumericRangeQuery.newIntRange(PathIndex.SNS_INDEX,
snsIndex, snsIndex, true, false), Occur.MUST);
+ booleanQuery.add(new TermQuery(new Term(ContentIndex.NODE_NAME,
stringValue)), Occur.MUST);
+ booleanQuery.add(NumericRangeQuery.newIntRange(ContentIndex.SNS_INDEX,
snsIndex, snsIndex, true, false),
+ Occur.MUST);
return booleanQuery;
case NOT_EQUAL_TO:
booleanQuery = new BooleanQuery();
- booleanQuery.add(new TermQuery(new Term(PathIndex.NODE_NAME,
stringValue)), Occur.MUST);
- booleanQuery.add(NumericRangeQuery.newIntRange(PathIndex.SNS_INDEX,
snsIndex, snsIndex, true, false), Occur.MUST);
+ booleanQuery.add(new TermQuery(new Term(ContentIndex.NODE_NAME,
stringValue)), Occur.MUST);
+ booleanQuery.add(NumericRangeQuery.newIntRange(ContentIndex.SNS_INDEX,
snsIndex, snsIndex, true, false),
+ Occur.MUST);
return new NotQuery(booleanQuery);
case GREATER_THAN:
query = CompareNameQuery.createQueryForNodesWithNameGreaterThan(segment,
-
PathIndex.NODE_NAME,
-
PathIndex.SNS_INDEX,
+
ContentIndex.NODE_NAME,
+
ContentIndex.SNS_INDEX,
factories,
caseSensitive);
break;
case GREATER_THAN_OR_EQUAL_TO:
query =
CompareNameQuery.createQueryForNodesWithNameGreaterThanOrEqualTo(segment,
-
PathIndex.NODE_NAME,
-
PathIndex.SNS_INDEX,
+
ContentIndex.NODE_NAME,
+
ContentIndex.SNS_INDEX,
factories,
caseSensitive);
break;
case LESS_THAN:
query = CompareNameQuery.createQueryForNodesWithNameLessThan(segment,
-
PathIndex.NODE_NAME,
-
PathIndex.SNS_INDEX,
+
ContentIndex.NODE_NAME,
+
ContentIndex.SNS_INDEX,
factories,
caseSensitive);
break;
case LESS_THAN_OR_EQUAL_TO:
query =
CompareNameQuery.createQueryForNodesWithNameLessThanOrEqualTo(segment,
-
PathIndex.NODE_NAME,
-
PathIndex.SNS_INDEX,
+
ContentIndex.NODE_NAME,
+
ContentIndex.SNS_INDEX,
factories,
caseSensitive);
break;
@@ -1187,7 +986,7 @@
String localNameExpression = likeExpression.substring(0,
openBracketIndex);
String snsIndexExpression =
likeExpression.substring(openBracketIndex);
Query localNameQuery =
CompareStringQuery.createQueryForNodesWithFieldLike(localNameExpression,
-
PathIndex.NODE_NAME,
+
ContentIndex.NODE_NAME,
factories,
caseSensitive);
Query snsQuery = createSnsIndexQuery(snsIndexExpression);
@@ -1213,120 +1012,98 @@
} else {
// There is no SNS expression ...
query =
CompareStringQuery.createQueryForNodesWithFieldLike(likeExpression,
-
PathIndex.NODE_NAME,
+
ContentIndex.NODE_NAME,
factories,
caseSensitive);
}
assert query != null;
break;
}
-
- // Now execute and collect the IDs ...
- IdCollector idCollector = new IdCollector();
- IndexSearcher searcher = getPathsSearcher();
- searcher.search(query, idCollector);
- return findAllNodesWithIds(idCollector.getIds());
+ return query;
}
public Query findNodesWith( NodeLocalName nodeName,
Operator operator,
Object value,
- boolean caseSensitive ) throws IOException {
+ boolean caseSensitive ) {
String nameValue = processor.stringFactory.create(value);
Query query = null;
switch (operator) {
case LIKE:
String likeExpression = processor.stringFactory.create(value);
- query = findNodesLike(PathIndex.LOCAL_NAME, likeExpression,
caseSensitive);
+ query = findNodesLike(ContentIndex.LOCAL_NAME, likeExpression,
caseSensitive);
break;
case EQUAL_TO:
query =
CompareStringQuery.createQueryForNodesWithFieldEqualTo(nameValue,
-
PathIndex.LOCAL_NAME,
+
ContentIndex.LOCAL_NAME,
processor.valueFactories,
caseSensitive);
break;
case NOT_EQUAL_TO:
query =
CompareStringQuery.createQueryForNodesWithFieldEqualTo(nameValue,
-
PathIndex.LOCAL_NAME,
+
ContentIndex.LOCAL_NAME,
processor.valueFactories,
caseSensitive);
query = new NotQuery(query);
break;
case GREATER_THAN:
query =
CompareStringQuery.createQueryForNodesWithFieldGreaterThan(nameValue,
-
PathIndex.LOCAL_NAME,
+
ContentIndex.LOCAL_NAME,
processor.valueFactories,
caseSensitive);
break;
case GREATER_THAN_OR_EQUAL_TO:
query =
CompareStringQuery.createQueryForNodesWithFieldGreaterThanOrEqualTo(nameValue,
-
PathIndex.LOCAL_NAME,
+
ContentIndex.LOCAL_NAME,
processor.valueFactories,
caseSensitive);
break;
case LESS_THAN:
query =
CompareStringQuery.createQueryForNodesWithFieldLessThan(nameValue,
-
PathIndex.LOCAL_NAME,
+
ContentIndex.LOCAL_NAME,
processor.valueFactories,
caseSensitive);
break;
case LESS_THAN_OR_EQUAL_TO:
query =
CompareStringQuery.createQueryForNodesWithFieldLessThanOrEqualTo(nameValue,
-
PathIndex.LOCAL_NAME,
+
ContentIndex.LOCAL_NAME,
processor.valueFactories,
caseSensitive);
break;
}
-
- // Now execute and collect the IDs ...
- IdCollector idCollector = new IdCollector();
- IndexSearcher searcher = getPathsSearcher();
- searcher.search(query, idCollector);
- return findAllNodesWithIds(idCollector.getIds());
+ return query;
}
public Query findNodesWith( NodeDepth depthConstraint,
Operator operator,
- Object value ) throws IOException {
+ Object value ) {
int depth = processor.valueFactories.getLongFactory().create(value).intValue();
- Query query = null;
switch (operator) {
case EQUAL_TO:
- query = NumericRangeQuery.newIntRange(PathIndex.DEPTH, depth, depth,
true, true);
- break;
+ return NumericRangeQuery.newIntRange(ContentIndex.DEPTH, depth, depth,
true, true);
case NOT_EQUAL_TO:
- query = NumericRangeQuery.newIntRange(PathIndex.DEPTH, depth, depth,
true, true);
- query = new NotQuery(query);
- break;
+ Query query = NumericRangeQuery.newIntRange(ContentIndex.DEPTH, depth,
depth, true, true);
+ return new NotQuery(query);
case GREATER_THAN:
- query = NumericRangeQuery.newIntRange(PathIndex.DEPTH, depth, MAX_DEPTH,
false, true);
- break;
+ return NumericRangeQuery.newIntRange(ContentIndex.DEPTH, depth,
MAX_DEPTH, false, true);
case GREATER_THAN_OR_EQUAL_TO:
- query = NumericRangeQuery.newIntRange(PathIndex.DEPTH, depth, MAX_DEPTH,
true, true);
- break;
+ return NumericRangeQuery.newIntRange(ContentIndex.DEPTH, depth,
MAX_DEPTH, true, true);
case LESS_THAN:
- query = NumericRangeQuery.newIntRange(PathIndex.DEPTH, MIN_DEPTH, depth,
true, false);
- break;
+ return NumericRangeQuery.newIntRange(ContentIndex.DEPTH, MIN_DEPTH,
depth, true, false);
case LESS_THAN_OR_EQUAL_TO:
- query = NumericRangeQuery.newIntRange(PathIndex.DEPTH, MIN_DEPTH, depth,
true, true);
- break;
+ return NumericRangeQuery.newIntRange(ContentIndex.DEPTH, MIN_DEPTH,
depth, true, true);
case LIKE:
// This is not allowed ...
return null;
}
-
- // Now execute and collect the IDs ...
- IdCollector idCollector = new IdCollector();
- IndexSearcher searcher = getPathsSearcher();
- searcher.search(query, idCollector);
- return findAllNodesWithIds(idCollector.getIds());
+ return null;
}
protected Query createLocalNameQuery( String likeExpression,
boolean caseSensitive ) {
if (likeExpression == null) return null;
return CompareStringQuery.createQueryForNodesWithFieldLike(likeExpression,
- PathIndex.LOCAL_NAME,
+
ContentIndex.LOCAL_NAME,
processor.valueFactories,
caseSensitive);
}
@@ -1358,16 +1135,16 @@
}
if (likeExpression.equals("_")) {
// The SNS expression can only be one digit ...
- return NumericRangeQuery.newIntRange(PathIndex.SNS_INDEX, MIN_SNS_INDEX, 9,
true, true);
+ return NumericRangeQuery.newIntRange(ContentIndex.SNS_INDEX, MIN_SNS_INDEX,
9, true, true);
}
if (likeExpression.equals("%")) {
// The SNS expression can be any digits ...
- return NumericRangeQuery.newIntRange(PathIndex.SNS_INDEX, MIN_SNS_INDEX,
MAX_SNS_INDEX, true, true);
+ return NumericRangeQuery.newIntRange(ContentIndex.SNS_INDEX, MIN_SNS_INDEX,
MAX_SNS_INDEX, true, true);
}
if (likeExpression.indexOf('_') != -1) {
if (likeExpression.indexOf('%') != -1) {
// Contains both ...
- return findNodesLike(PathIndex.SNS_INDEX, likeExpression, true);
+ return findNodesLike(ContentIndex.SNS_INDEX, likeExpression, true);
}
// It presumably contains some numbers and at least one '_' character
...
int firstWildcardChar = likeExpression.indexOf('_');
@@ -1376,7 +1153,7 @@
int secondWildcardChar = likeExpression.indexOf('_',
firstWildcardChar + 1);
if (secondWildcardChar != -1) {
// There are multiple '_' characters ...
- return findNodesLike(PathIndex.SNS_INDEX, likeExpression, true);
+ return findNodesLike(ContentIndex.SNS_INDEX, likeExpression, true);
}
}
// There's only one '_', so parse the lowermost value and
uppermost value ...
@@ -1386,7 +1163,7 @@
// This SNS is just a number ...
int lowerSns = Integer.parseInt(lowerExpression);
int upperSns = Integer.parseInt(upperExpression);
- return NumericRangeQuery.newIntRange(PathIndex.SNS_INDEX, lowerSns,
upperSns, true, true);
+ return NumericRangeQuery.newIntRange(ContentIndex.SNS_INDEX, lowerSns,
upperSns, true, true);
} catch (NumberFormatException e) {
// It's not a number but it's in the SNS field, so there will be
no results ...
return new MatchNoneQuery();
@@ -1394,13 +1171,13 @@
}
if (likeExpression.indexOf('%') != -1) {
// It presumably contains some numbers and at least one '%' character
...
- return findNodesLike(PathIndex.SNS_INDEX, likeExpression, true);
+ return findNodesLike(ContentIndex.SNS_INDEX, likeExpression, true);
}
// This is not a LIKE expression but an exact value specification and should be a
number ...
try {
// This SNS is just a number ...
int sns = Integer.parseInt(likeExpression);
- return NumericRangeQuery.newIntRange(PathIndex.SNS_INDEX, sns, sns, true,
true);
+ return NumericRangeQuery.newIntRange(ContentIndex.SNS_INDEX, sns, sns, true,
true);
} catch (NumberFormatException e) {
// It's not a number but it's in the SNS field, so there will be no
results ...
return new MatchNoneQuery();
@@ -1408,82 +1185,10 @@
}
/**
- * A {@link Collector} implementation that only captures the UUID of the documents
returned by a query. Score information is
- * not recorded. This is often used when querying the {@link PathIndex} to collect
the UUIDs of a set of nodes satisfying some
- * path constraint.
- *
- * @see LuceneSearchSession#findChildNodes(Path)
- */
- protected static class IdCollector extends Collector {
- private final Set<String> ids = new HashSet<String>();
- private String[] idsByDocId;
-
- // private int baseDocId;
-
- protected IdCollector() {
- }
-
- /**
- * Get the UUIDs that have been collected.
- *
- * @return the set of UUIDs; never null
- */
- public Set<String> getIds() {
- return ids;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.apache.lucene.search.Collector#acceptsDocsOutOfOrder()
- */
- @Override
- public boolean acceptsDocsOutOfOrder() {
- return true;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.apache.lucene.search.Collector#setScorer(org.apache.lucene.search.Scorer)
- */
- @Override
- public void setScorer( Scorer scorer ) {
- // we don't care about scoring
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.apache.lucene.search.Collector#collect(int)
- */
- @Override
- public void collect( int docId ) {
- assert docId >= 0;
- String idString = idsByDocId[docId];
- assert idString != null;
- ids.add(idString);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.apache.lucene.search.Collector#setNextReader(org.apache.lucene.index.IndexReader,
int)
- */
- @Override
- public void setNextReader( IndexReader reader,
- int docBase ) throws IOException {
- this.idsByDocId = FieldCache.DEFAULT.getStrings(reader, ContentIndex.ID); //
same value as PathIndex.ID
- // this.baseDocId = docBase;
- }
- }
-
- /**
* This collector is responsible for loading the value for each of the columns into
each tuple array.
*/
protected static class DualIndexTupleCollector extends TupleCollector {
private final LuceneSearchSession session;
- private final LuceneSearchProcessor processor;
private final LinkedList<Object[]> tuples = new
LinkedList<Object[]>();
private final Columns columns;
private final int numValues;
@@ -1494,14 +1199,11 @@
private Scorer scorer;
private IndexReader currentReader;
private int docOffset;
- private boolean resolvedLocations = false;
protected DualIndexTupleCollector( LuceneSearchSession session,
Columns columns ) {
this.session = session;
- this.processor = session.processor;
this.columns = columns;
- assert this.processor != null;
assert this.columns != null;
this.numValues = this.columns.getTupleSize();
assert this.numValues >= 0;
@@ -1510,13 +1212,16 @@
this.locationIndex = this.columns.getLocationIndex(selectorName);
this.recordScore = this.columns.hasFullTextSearchScores();
this.scoreIndex = this.recordScore ?
this.columns.getFullTextSearchScoreIndexFor(selectorName) : -1;
- final Set<String> columnNames = new
HashSet<String>(this.columns.getColumnNames());
- columnNames.add(ContentIndex.ID); // add the UUID, which we'll put into
the Location ...
+
+ // Create the set of field names that we need to load from the document ...
+ final Set<String> fieldNames = new
HashSet<String>(this.columns.getColumnNames());
+ fieldNames.add(ContentIndex.LOCATION_ID_PROPERTIES); // add the UUID, which
we'll put into the Location ...
+ fieldNames.add(ContentIndex.PATH); // add the UUID, which we'll put into
the Location ...
this.fieldSelector = new FieldSelector() {
private static final long serialVersionUID = 1L;
public FieldSelectorResult accept( String fieldName ) {
- return columnNames.contains(fieldName) ? FieldSelectorResult.LOAD :
FieldSelectorResult.NO_LOAD;
+ return fieldNames.contains(fieldName) ? FieldSelectorResult.LOAD :
FieldSelectorResult.NO_LOAD;
}
};
}
@@ -1526,43 +1231,9 @@
*/
@Override
public LinkedList<Object[]> getTuples() {
- resolveLocations();
return tuples;
}
- protected void resolveLocations() {
- if (resolvedLocations) return;
- try {
- // The Location field in the tuples all contain the ID of the document,
so we need to replace these
- // with the appropriate Location objects, using the content from the
PathIndex ...
- IndexReader pathReader = session.getPathsReader();
- IndexSearcher pathSearcher = session.getPathsSearcher();
- for (Object[] tuple : tuples) {
- String id = (String)tuple[locationIndex];
- assert id != null;
- Location location = getLocationForDocument(id, pathReader,
pathSearcher);
- if (location == null) continue;
- tuple[locationIndex] = location;
- }
- resolvedLocations = true;
- } catch (IOException e) {
- throw new LuceneException(e);
- }
- }
-
- protected Location getLocationForDocument( String id,
- IndexReader pathReader,
- IndexSearcher pathSearcher ) throws
IOException {
- // Find the path for this node (is there a better way to do this than one
search per ID?) ...
- TopDocs pathDocs = pathSearcher.search(new TermQuery(new Term(PathIndex.ID,
id)), 1);
- if (pathDocs.scoreDocs.length < 1) {
- // No path record found ...
- return null;
- }
- Document pathDoc = pathReader.document(pathDocs.scoreDocs[0].doc);
- return session.readLocation(pathDoc);
- }
-
/**
* {@inheritDoc}
*
@@ -1626,10 +1297,88 @@
tuple[scoreIndex] = scorer.score();
}
- // Load the document ID (which is a stringified UUID) into the Location
slot,
- // which will be replaced later with a real Location ...
- tuple[locationIndex] = document.get(ContentIndex.ID);
+ // Read the location ...
+ tuple[locationIndex] = session.readLocation(document);
tuples.add(tuple);
}
}
+
+ /**
+ * This collector is responsible for loading the value for each of the columns into
each tuple array.
+ */
+ protected static class FullTextSearchTupleCollector extends TupleCollector {
+ private final List<Object[]> tuples;
+ private final FieldSelector fieldSelector;
+ private final LuceneSearchSession session;
+ private Scorer scorer;
+ private IndexReader currentReader;
+ private int docOffset;
+
+ protected FullTextSearchTupleCollector( LuceneSearchSession session,
+ List<Object[]> tuples ) {
+ assert session != null;
+ assert tuples != null;
+ this.session = session;
+ this.tuples = tuples;
+ this.fieldSelector = LOCATION_FIELDS_SELECTOR;
+ }
+
+ /**
+ * @return tuples
+ */
+ @Override
+ public List<Object[]> getTuples() {
+ return tuples;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.lucene.search.Collector#acceptsDocsOutOfOrder()
+ */
+ @Override
+ public boolean acceptsDocsOutOfOrder() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.apache.lucene.search.Collector#setNextReader(org.apache.lucene.index.IndexReader,
int)
+ */
+ @Override
+ public void setNextReader( IndexReader reader,
+ int docBase ) {
+ this.currentReader = reader;
+ this.docOffset = docBase;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.apache.lucene.search.Collector#setScorer(org.apache.lucene.search.Scorer)
+ */
+ @Override
+ public void setScorer( Scorer scorer ) {
+ this.scorer = scorer;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.lucene.search.Collector#collect(int)
+ */
+ @Override
+ public void collect( int doc ) throws IOException {
+ int docId = doc + docOffset;
+ Object[] tuple = new Object[2];
+ Document document = currentReader.document(docId, fieldSelector);
+ // Read the Location ...
+ tuple[0] = session.readLocation(document);
+ // And read the score ...
+ tuple[1] = scorer.score();
+ // And add the tuple ...
+ tuples.add(tuple);
+ }
+ }
}
Modified:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchWorkspace.java
===================================================================
---
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchWorkspace.java 2009-12-31
16:13:57 UTC (rev 1506)
+++
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchWorkspace.java 2009-12-31
18:53:06 UTC (rev 1507)
@@ -45,8 +45,7 @@
*/
protected static final int CHANGES_BEFORE_OPTIMIZATION = 1;
- protected static final String PATHS_INDEX_NAME = "paths";
- protected static final String CONTENT_INDEX_NAME = "content";
+ protected static final String INDEX_NAME = "content";
/**
* Given the name of a property field of the form
"<namespace>:<local>" (where <namespace> can be
zero-length), this
@@ -57,24 +56,16 @@
protected static final String FULL_TEXT_PREFIX = ":ft:";
/**
- * This index stores only these fields, so we can use the most obvious names and not
worry about clashes.
- */
- static class PathIndex {
- public static final String PATH = "pth";
- public static final String NODE_NAME = "nam";
- public static final String LOCAL_NAME = "loc";
- public static final String SNS_INDEX = "sns";
- public static final String LOCATION_ID_PROPERTIES = "idp";
- public static final String ID = ContentIndex.ID;
- public static final String DEPTH = "dep";
- }
-
- /**
- * This index stores these two fields <i>plus</i> all properties.
Therefore, we have to worry about name clashes, which is why
+ * This index stores these fields <i>plus</i> all properties. Therefore,
we have to worry about name clashes, which is why
* these field names are prefixed with '::', which is something that does
appear in property names as they are serialized.
*/
static class ContentIndex {
- public static final String ID = "::id";
+ public static final String PATH = "::pth";
+ public static final String NODE_NAME = "::nam";
+ public static final String LOCAL_NAME = "::loc";
+ public static final String SNS_INDEX = "::sns";
+ public static final String LOCATION_ID_PROPERTIES = "::idp";
+ public static final String DEPTH = "::dep";
public static final String FULL_TEXT = "::fts";
}
@@ -82,7 +73,6 @@
private final String workspaceDirectoryName;
protected final IndexRules rules;
private final LuceneConfiguration configuration;
- protected final Directory pathDirectory;
protected final Directory contentDirectory;
protected final Analyzer analyzer;
private final Lock changesLock = new ReentrantLock();
@@ -99,8 +89,7 @@
this.analyzer = analyzer != null ? analyzer : new
StandardAnalyzer(Version.LUCENE_30);
this.rules = rules != null ? rules : LuceneSearchEngine.DEFAULT_RULES;
this.configuration = configuration;
- this.pathDirectory = this.configuration.getDirectory(workspaceDirectoryName,
PATHS_INDEX_NAME);
- this.contentDirectory = this.configuration.getDirectory(workspaceDirectoryName,
CONTENT_INDEX_NAME);
+ this.contentDirectory = this.configuration.getDirectory(workspaceDirectoryName,
INDEX_NAME);
}
/**
@@ -118,8 +107,7 @@
* @see
org.jboss.dna.graph.search.SearchEngineWorkspace#destroy(org.jboss.dna.graph.ExecutionContext)
*/
public void destroy( ExecutionContext context ) {
- configuration.destroyDirectory(workspaceDirectoryName, PATHS_INDEX_NAME);
- configuration.destroyDirectory(workspaceDirectoryName, CONTENT_INDEX_NAME);
+ configuration.destroyDirectory(workspaceDirectoryName, INDEX_NAME);
}
/**
Deleted:
trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/EncodingNamespaceRegistryTest.java
===================================================================
---
trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/EncodingNamespaceRegistryTest.java 2009-12-31
16:13:57 UTC (rev 1506)
+++
trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/EncodingNamespaceRegistryTest.java 2009-12-31
18:53:06 UTC (rev 1507)
@@ -1,102 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- * is licensed to you under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JBoss DNA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jboss.dna.search.lucene;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.util.Collection;
-import org.jboss.dna.common.text.SecureHashTextEncoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.common.util.SecureHash.Algorithm;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.property.NamespaceRegistry;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.graph.property.NamespaceRegistry.Namespace;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- *
- */
-public class EncodingNamespaceRegistryTest {
-
- private ExecutionContext context;
- private NamespaceRegistry registry;
- private EncodingNamespaceRegistry encodedRegistry;
- private TextEncoder encoder;
- private ExecutionContext encodedContext;
-
- @Before
- public void beforeEach() {
- this.context = new ExecutionContext();
- this.registry = this.context.getNamespaceRegistry();
- this.encoder = new SecureHashTextEncoder(Algorithm.SHA_1, 10);
- this.encodedRegistry = new EncodingNamespaceRegistry(registry, encoder);
- this.encodedContext = context.with(encodedRegistry);
- }
-
- @Test
- public void shouldHaveEncodedPrefixesForAllRegisteredNamespacesExceptFixedOnes() {
- Collection<Namespace> namespaces = registry.getNamespaces();
- assertThat(namespaces.size() > 4, is(true));
- for (Namespace namespace : namespaces) {
- String uri = namespace.getNamespaceUri();
- String actualEncodedPrefix = encodedRegistry.getPrefixForNamespaceUri(uri,
false);
- if (encodedRegistry.getFixedNamespaceUris().contains(uri)) {
- assertThat(actualEncodedPrefix, is(namespace.getPrefix()));
- } else {
- String expectedEncodedPrefix = encoder.encode(uri);
- assertThat(expectedEncodedPrefix, is(actualEncodedPrefix));
- }
- String actualUri =
encodedRegistry.getNamespaceForPrefix(actualEncodedPrefix);
- assertThat(uri, is(actualUri));
- }
- }
-
- @Test
- public void shouldAllowPathConversionToAndFromString() {
- String uri1 = "http://acme.com/wabbler";
- String uri2 = "http://troublemakers.com/contixity";
- String uri3 = "http://example.com/infinitiy";
- String ns1 = "wab";
- String ns2 = "ctx";
- String ns3 = "inf";
- registry.register(ns1, uri1);
- registry.register(ns2, uri2);
- registry.register(ns3, uri3);
- String pathStr = "/wab:part1/wab:part2/ctx:part3/inf:part4/dna:part5";
- Path actualPath = context.getValueFactories().getPathFactory().create(pathStr);
- String actualPathStr =
context.getValueFactories().getStringFactory().create(actualPath);
- assertThat(pathStr, is(actualPathStr));
- String encodedPathStr =
encodedContext.getValueFactories().getStringFactory().create(actualPath);
- String encodedPrefix1 = encoder.encode(uri1);
- String encodedPrefix2 = encoder.encode(uri2);
- String encodedPrefix3 = encoder.encode(uri3);
- String expectedPathStr = "/" + encodedPrefix1 + ":part1/" +
encodedPrefix1 + ":part2/" + encodedPrefix2 + ":part3/"
- + encodedPrefix3 + ":part4/dna:part5";
- assertThat(expectedPathStr, is(encodedPathStr));
- Path actualPath2 =
encodedContext.getValueFactories().getPathFactory().create(encodedPathStr);
- assertThat(actualPath, is(actualPath2));
- }
-}