Author: epbernard
Date: 2010-06-30 09:44:30 -0400 (Wed, 30 Jun 2010)
New Revision: 19871
Added:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/IncrementalSearchFactory.java
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/C.java
Modified:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/MutableSearchFactory.java
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryBuilder.java
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/A.java
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/MutableFactoryTest.java
Log:
HSEARCH-397 Add simpler IncrementalSearchFactory contract
For now, only allow entities addition
Added:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/IncrementalSearchFactory.java
===================================================================
---
search/trunk/hibernate-search/src/main/java/org/hibernate/search/IncrementalSearchFactory.java
(rev 0)
+++
search/trunk/hibernate-search/src/main/java/org/hibernate/search/IncrementalSearchFactory.java 2010-06-30
13:44:30 UTC (rev 19871)
@@ -0,0 +1,19 @@
+package org.hibernate.search;
+
+/**
+ * This contract is considered experimental
+ * Allow modifications of the SearchFactory internals
+ *
+ * As of today allow addition of new indexed classes.
+ *
+ * @author Emmanuel Bernard
+ */
+public interface IncrementalSearchFactory extends SearchFactory {
+ /**
+ * Add the following classes to the SearchFactory
+ *
+ */
+ void addClasses(Class<?>... classes);
+
+ //TODO consider accepting SearchConfiguration or SearchMapping
+}
Modified:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/MutableSearchFactory.java
===================================================================
---
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/MutableSearchFactory.java 2010-06-30
13:43:49 UTC (rev 19870)
+++
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/MutableSearchFactory.java 2010-06-30
13:44:30 UTC (rev 19871)
@@ -3,11 +3,13 @@
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.search.Similarity;
+import org.hibernate.search.IncrementalSearchFactory;
import org.hibernate.search.backend.BackendQueueProcessorFactory;
import org.hibernate.search.backend.LuceneIndexingParameters;
import org.hibernate.search.backend.Worker;
@@ -33,8 +35,10 @@
*
* @author Emmanuel Bernard
*/
-public class MutableSearchFactory implements StateSearchFactoryImplementor {
+public class MutableSearchFactory implements StateSearchFactoryImplementor,
IncrementalSearchFactory {
private volatile StateSearchFactoryImplementor delegate;
+ //lock to be acquired every time the underlying searchFactory is rebuilt
+ private final Lock mutating = new ReentrantLock( );
void setDelegate(StateSearchFactoryImplementor delegate) {
this.delegate = delegate;
@@ -179,4 +183,19 @@
public Map<DirectoryProvider<?>, DirectoryProviderData>
getDirectoryProviderData() {
return delegate.getDirectoryProviderData();
}
+
+ public void addClasses(Class<?>... classes) {
+ //todo optimize the list of
+ final SearchFactoryBuilder builder = new SearchFactoryBuilder().rootFactory( this );
+ for (Class<?> type : classes) {
+ builder.addClass( type );
+ }
+ try {
+ mutating.lock();
+ builder.buildSearchFactory();
+ }
+ finally {
+ mutating.unlock();
+ }
+ }
}
Modified:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryBuilder.java
===================================================================
---
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryBuilder.java 2010-06-30
13:43:49 UTC (rev 19870)
+++
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryBuilder.java 2010-06-30
13:44:30 UTC (rev 19871)
@@ -5,6 +5,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -122,17 +123,13 @@
}
private SearchFactoryImplementor buildIncrementalSearchFactory() {
+ removeClassesAlreadyManaged();
+ if (classes.size() == 0) {
+ return rootFactory;
+ }
+
BuildContext buildContext = new BuildContext();
copyStateFromOldFactory(rootFactory);
- List<Class<?>> remove = new ArrayList<Class<?>>();
- for (Class<?> entity : classes) {
- if ( documentBuildersIndexedEntities.containsKey( entity ) ||
documentBuildersContainedEntities.containsKey(entity) ) {
- remove.add( entity );
- }
- }
- for(Class<?> entity : remove) {
- classes.remove( entity );
- }
//TODO we don't keep the reflectionManager. Is that an issue?
IncrementalSearchConfiguration cfg = new IncrementalSearchConfiguration( classes,
configurationProperties );
reflectionManager = getReflectionManager( cfg );
@@ -168,6 +165,20 @@
}
+ private void removeClassesAlreadyManaged() {
+ Set<Class<?>> remove = new HashSet<Class<?>>();
+ final Map<Class<?>, DocumentBuilderContainedEntity<?>>
containedEntities = rootFactory.getDocumentBuildersContainedEntities();
+ final Map<Class<?>, DocumentBuilderIndexedEntity<?>> indexedEntities
= rootFactory.getDocumentBuildersIndexedEntities();
+ for (Class<?> entity : classes) {
+ if ( indexedEntities.containsKey( entity ) || containedEntities.containsKey(entity) )
{
+ remove.add( entity );
+ }
+ }
+ for(Class<?> entity : remove) {
+ classes.remove( entity );
+ }
+ }
+
private void copyStateFromOldFactory(StateSearchFactoryImplementor stateFactory) {
indexingStrategy = stateFactory.getIndexingStrategy();
documentBuildersIndexedEntities = stateFactory.getDocumentBuildersIndexedEntities();
Modified:
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/A.java
===================================================================
---
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/A.java 2010-06-30
13:43:49 UTC (rev 19870)
+++
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/A.java 2010-06-30
13:44:30 UTC (rev 19871)
@@ -16,6 +16,11 @@
private Integer id;
private String name;
+ public A(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
@DocumentId
public Integer getId() {
return id;
Copied:
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/C.java
(from rev 19869,
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/A.java)
===================================================================
---
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/C.java
(rev 0)
+++
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/C.java 2010-06-30
13:44:30 UTC (rev 19871)
@@ -0,0 +1,37 @@
+package org.hibernate.search.test.configuration.mutablefactory;
+
+import org.hibernate.search.annotations.DocumentId;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Indexed;
+
+/**
+ * @author Emmanuel Bernard
+ */
+@Indexed
+public class C {
+ private Integer id;
+ private String name;
+
+ public C(Integer id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ @DocumentId
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ @Field
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
Modified:
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/MutableFactoryTest.java
===================================================================
---
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/MutableFactoryTest.java 2010-06-30
13:43:49 UTC (rev 19870)
+++
search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/configuration/mutablefactory/MutableFactoryTest.java 2010-06-30
13:44:30 UTC (rev 19871)
@@ -6,6 +6,7 @@
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
+import org.hibernate.search.IncrementalSearchFactory;
import org.hibernate.search.backend.Work;
import org.hibernate.search.backend.WorkType;
import org.hibernate.search.engine.SearchFactoryImplementor;
@@ -28,7 +29,7 @@
sf.close();
}
- public void testAddingClass() throws Exception {
+ public void testAddingClassFullModel() throws Exception {
ManualConfiguration configuration = new ManualConfiguration()
.addProperty( "hibernate.search.default.directory_provider",
RAMDirectoryProvider.class.getName() );
//FIXME downcasting of MSF. create a getDelegate() ?
@@ -38,14 +39,9 @@
.addClass( A.class )
.buildSearchFactory();
- A a = new A();
- a.setId( 1 );
- a.setName( "Emmanuel" );
-
ManualTransactionContext tc = new ManualTransactionContext();
- Work<A> work = new Work<A>( a, 1, WorkType.INDEX );
- sf.getWorker().performWork( work, tc );
+ doIndexWork( new A(1, "Emmanuel"), 1, sf, tc );
tc.end();
@@ -67,8 +63,7 @@
tc = new ManualTransactionContext();
- Work<B> workB = new Work<B>( new B(1, "Noel"), 1, WorkType.INDEX
);
- sf.getWorker().performWork( workB, tc );
+ doIndexWork( new B(1, "Noel"), 1, sf, tc );
tc.end();
@@ -84,4 +79,64 @@
sf.close();
}
+
+ public void testAddingClassSimpleAPI() throws Exception {
+ ManualConfiguration configuration = new ManualConfiguration()
+ .addProperty( "hibernate.search.default.directory_provider",
RAMDirectoryProvider.class.getName() );
+ //FIXME downcasting of MSF. create a getDelegate() ?
+ IncrementalSearchFactory sf = (IncrementalSearchFactory) new
SearchFactoryBuilder().configuration( configuration ).buildSearchFactory();
+ SearchFactoryImplementor sfi = (SearchFactoryImplementor) sf;
+ sf.addClasses( A.class );
+
+ ManualTransactionContext tc = new ManualTransactionContext();
+
+ doIndexWork( new A(1, "Emmanuel"), 1, sfi, tc );
+
+ tc.end();
+
+ QueryParser parser = new QueryParser( SearchTestCase.getTargetLuceneVersion(),
"name", SearchTestCase.standardAnalyzer );
+ Query luceneQuery = parser.parse( "Emmanuel" );
+
+ //we know there is only one DP
+ DirectoryProvider provider = sfi
+ .getDirectoryProviders( A.class )[0];
+ IndexSearcher searcher = new IndexSearcher( provider.getDirectory(), true );
+ TopDocs hits = searcher.search( luceneQuery, 1000 );
+ assertEquals( 1, hits.totalHits );
+
+ searcher.close();
+
+ sf.addClasses( B.class, C.class );
+
+ tc = new ManualTransactionContext();
+
+ doIndexWork( new B(1, "Noel"), 1, sfi, tc );
+ doIndexWork( new C(1, "Vincent"), 1, sfi, tc );
+
+ tc.end();
+
+ luceneQuery = parser.parse( "Noel" );
+
+ //we know there is only one DP
+ provider = sfi.getDirectoryProviders( B.class )[0];
+ searcher = new IndexSearcher( provider.getDirectory(), true );
+ hits = searcher.search( luceneQuery, 1000 );
+ assertEquals( 1, hits.totalHits );
+
+ luceneQuery = parser.parse( "Vincent" );
+
+ provider = sfi.getDirectoryProviders( C.class )[0];
+ searcher = new IndexSearcher( provider.getDirectory(), true );
+ hits = searcher.search( luceneQuery, 1000 );
+ assertEquals( 1, hits.totalHits );
+
+ searcher.close();
+
+ sfi.close();
+ }
+
+ private void doIndexWork(Object entity, Integer id, SearchFactoryImplementor sfi,
ManualTransactionContext tc) {
+ Work<?> work = new Work<Object>( entity, id, WorkType.INDEX );
+ sfi.getWorker().performWork( work, tc );
+ }
}