Author: epbernard
Date: 2010-06-30 09:41:20 -0400 (Wed, 30 Jun 2010)
New Revision: 19866
Added:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/IncrementalSearchConfiguration.java
Modified:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryBuilder.java
Log:
HSEARCH-397 SearchFactoryBuilder contract for mutable SearchFactories
Create contract to add new classes and update an SearchFactory
Added:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/IncrementalSearchConfiguration.java
===================================================================
---
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/IncrementalSearchConfiguration.java
(rev 0)
+++
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/IncrementalSearchConfiguration.java 2010-06-30
13:41:20 UTC (rev 19866)
@@ -0,0 +1,53 @@
+package org.hibernate.search.impl;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.hibernate.annotations.common.reflection.ReflectionManager;
+import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
+import org.hibernate.search.cfg.SearchConfiguration;
+import org.hibernate.search.cfg.SearchMapping;
+
+/**
+ * @author Emmanuel Bernard
+ */
+class IncrementalSearchConfiguration implements SearchConfiguration {
+ private final ReflectionManager reflectionManager = new JavaReflectionManager();
+ private final List<Class<?>> classes;
+ private final Map<String, Class<?>> classesByName = new HashMap<String,
Class<?>>();
+ private Properties properties;
+
+ public IncrementalSearchConfiguration(List<Class<?>> classes, Properties
properties) {
+ this.properties = properties;
+ this.classes = classes;
+ for ( Class<?> entity : classes ) {
+ classesByName.put( entity.getName(), entity );
+ }
+ }
+ public Iterator<Class<?>> getClassMappings() {
+ return classes.iterator();
+ }
+
+ public Class<?> getClassMapping(String name) {
+ return classesByName.get( name );
+ }
+
+ public String getProperty(String propertyName) {
+ return properties.getProperty(propertyName );
+ }
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+ public ReflectionManager getReflectionManager() {
+ return reflectionManager;
+ }
+
+ public SearchMapping getProgrammaticMapping() {
+ return null;
+ }
+}
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:40:44 UTC (rev 19865)
+++
search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryBuilder.java 2010-06-30
13:41:20 UTC (rev 19866)
@@ -2,9 +2,11 @@
import java.beans.Introspector;
import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@@ -12,6 +14,8 @@
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.search.Similarity;
+
+import org.hibernate.search.backend.UpdatableBackendQueueProcessorFactory;
import org.hibernate.search.spi.WorkerBuildContext;
import org.hibernate.search.spi.WritableBuildContext;
import org.hibernate.search.spi.internals.DirectoryProviderData;
@@ -65,10 +69,11 @@
* Build a search factory
* @author Emmanuel Bernard
*/
-public class SearchFactoryBuilder implements WritableBuildContext, WorkerBuildContext {
+public class SearchFactoryBuilder {
private static final Logger log = LoggerFactory.make();
- SearchConfiguration cfg;
- MutableSearchFactory rootFactory;
+ private SearchConfiguration cfg;
+ private MutableSearchFactory rootFactory;
+ private final List<Class<?>> classes = new
ArrayList<Class<?>>();
public SearchFactoryBuilder configuration(SearchConfiguration configuration) {
this.cfg = configuration;
@@ -80,6 +85,11 @@
return this;
}
+ public SearchFactoryBuilder addClass(Class<?> clazz) {
+ classes.add( clazz );
+ return this;
+ }
+
//processing properties
ReflectionManager reflectionManager;
String indexingStrategy;
@@ -101,6 +111,9 @@
public SearchFactoryImplementor buildSearchFactory() {
if (rootFactory == null) {
+ if (classes.size() > 0) {
+ throw new SearchException( "Cannot add a class if the original SearchFactory is
not passed");
+ }
return buildNewSearchFactory();
}
else {
@@ -109,9 +122,50 @@
}
private SearchFactoryImplementor buildIncrementalSearchFactory() {
+ BuildContext buildContext = new BuildContext();
copyStateFromOldFactory(rootFactory);
- //FIXME next step for implementation
- return null;
+ 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 );
+ //TODO programmatic mapping support
+
+ //FIXME The current initDocumentBuilders
+ initDocumentBuilders( cfg, reflectionManager, buildContext );
+
+ Set<Class<?>> indexedClasses = documentBuildersIndexedEntities.keySet();
+ for ( DocumentBuilderIndexedEntity builder : documentBuildersIndexedEntities.values() )
{
+ //FIXME improve this algorithm to deal with adding new classes to the class
hierarchy.
+ //Today it seems only safe when a class outside the hierarchy is incrementally added.
+ builder.postInitialize( indexedClasses );
+ }
+ //not really necessary today
+ for ( DocumentBuilderContainedEntity builder :
documentBuildersContainedEntities.values() ) {
+ builder.postInitialize( indexedClasses );
+ }
+ fillSimilarityMapping();
+
+ //update backend
+ final BackendQueueProcessorFactory backend = this.backendQueueProcessorFactory;
+ if ( backend instanceof UpdatableBackendQueueProcessorFactory) {
+ final UpdatableBackendQueueProcessorFactory updatableBackend = (
UpdatableBackendQueueProcessorFactory ) backend;
+ updatableBackend.updateDirectoryProviders( this.dirProviderData.keySet(), buildContext
);
+ }
+ //safe for incremental init at least the ShredBufferReaderProvider
+ //this.readerProvider = ReaderProviderFactory.createReaderProvider( cfg, this );
+ StateSearchFactoryImplementor factory = new ImmutableSearchFactory( this );
+ rootFactory.setDelegate( factory );
+ return rootFactory;
+
+
}
private void copyStateFromOldFactory(StateSearchFactoryImplementor stateFactory) {
@@ -138,6 +192,7 @@
configurationProperties = cfg.getProperties();
errorHandler = createErrorHandler( configurationProperties );
reflectionManager = getReflectionManager(cfg);
+ BuildContext buildContext = new BuildContext();
final SearchMapping mapping = SearchMappingBuilder.getSearchMapping(cfg);
if ( mapping != null) {
@@ -152,7 +207,7 @@
indexingStrategy = defineIndexingStrategy( cfg );//need to be done before the document
builds
dirProviderIndexingParams = new HashMap<DirectoryProvider,
LuceneIndexingParameters>();
- initDocumentBuilders( cfg, reflectionManager );
+ initDocumentBuilders( cfg, reflectionManager, buildContext );
Set<Class<?>> indexedClasses = documentBuildersIndexedEntities.keySet();
for ( DocumentBuilderIndexedEntity builder : documentBuildersIndexedEntities.values() )
{
@@ -165,8 +220,8 @@
fillSimilarityMapping();
//build back end
- this.worker = WorkerFactory.createWorker( cfg, this );
- this.readerProvider = ReaderProviderFactory.createReaderProvider( cfg, this );
+ this.worker = WorkerFactory.createWorker( cfg, buildContext );
+ this.readerProvider = ReaderProviderFactory.createReaderProvider( cfg, buildContext );
this.filterCachingStrategy = buildFilterCachingStrategy( cfg.getProperties() );
this.cacheBitResultsSize = ConfigurationParseHelper.getIntValue(
cfg.getProperties(), Environment.CACHE_DOCIDRESULTS_SIZE,
CachingWrapperFilter.DEFAULT_SIZE
@@ -219,7 +274,11 @@
}
}
- private void initDocumentBuilders(SearchConfiguration cfg, ReflectionManager
reflectionManager) {
+ /*
+ * Initialize the document builder
+ * This algorithm seems to be safe for incremental search factories.
+ */
+ private void initDocumentBuilders(SearchConfiguration cfg, ReflectionManager
reflectionManager, BuildContext buildContext) {
ConfigContext context = new ConfigContext( cfg );
Iterator<Class<?>> iter = cfg.getClassMappings();
DirectoryProviderFactory factory = new DirectoryProviderFactory();
@@ -228,7 +287,7 @@
initProgrammaticallyDefinedFilterDef(reflectionManager);
while ( iter.hasNext() ) {
- Class mappedClass = iter.next();
+ Class<?> mappedClass = iter.next();
if ( mappedClass == null ) {
continue;
}
@@ -246,7 +305,7 @@
}
DirectoryProviderFactory.DirectoryProviders providers =
factory.createDirectoryProviders(
- mappedXClass, cfg, this, reflectionManager
+ mappedXClass, cfg, buildContext, reflectionManager
);
//FIXME DocumentBuilderIndexedEntity needs to be built by a helper method receiving
Class<T> to infer T properly
//XClass unfortunately is not (yet) genericized: TODO?
@@ -388,6 +447,10 @@
private ReflectionManager getReflectionManager(SearchConfiguration cfg) {
ReflectionManager reflectionManager = cfg.getReflectionManager();
+ return geReflectionManager( reflectionManager );
+ }
+
+ private ReflectionManager geReflectionManager(ReflectionManager reflectionManager) {
if ( reflectionManager == null ) {
reflectionManager = new JavaReflectionManager();
}
@@ -402,77 +465,80 @@
return indexingStrategy;
}
- public void addOptimizerStrategy(DirectoryProvider<?> provider, OptimizerStrategy
optimizerStrategy) {
- DirectoryProviderData data = dirProviderData.get( provider );
- if ( data == null ) {
- data = new DirectoryProviderData();
- dirProviderData.put( provider, data );
+ private class BuildContext implements WritableBuildContext, WorkerBuildContext {
+ public void addOptimizerStrategy(DirectoryProvider<?> provider, OptimizerStrategy
optimizerStrategy) {
+ DirectoryProviderData data = dirProviderData.get( provider );
+ if ( data == null ) {
+ data = new DirectoryProviderData();
+ dirProviderData.put( provider, data );
+ }
+ data.setOptimizerStrategy( optimizerStrategy );
}
- data.setOptimizerStrategy( optimizerStrategy );
- }
- public void addIndexingParameters(DirectoryProvider<?> provider,
LuceneIndexingParameters indexingParams) {
- dirProviderIndexingParams.put( provider, indexingParams );
- }
+ public void addIndexingParameters(DirectoryProvider<?> provider,
LuceneIndexingParameters indexingParams) {
+ dirProviderIndexingParams.put( provider, indexingParams );
+ }
- public void addClassToDirectoryProvider(Class<?> entity,
DirectoryProvider<?> directoryProvider, boolean exclusiveIndexUsage) {
- DirectoryProviderData data = dirProviderData.get( directoryProvider );
- if ( data == null ) {
- data = new DirectoryProviderData();
- dirProviderData.put( directoryProvider, data );
+ public void addClassToDirectoryProvider(Class<?> entity,
DirectoryProvider<?> directoryProvider, boolean exclusiveIndexUsage) {
+ DirectoryProviderData data = dirProviderData.get( directoryProvider );
+ if ( data == null ) {
+ data = new DirectoryProviderData();
+ dirProviderData.put( directoryProvider, data );
+ }
+ data.getClasses().add( entity );
+ data.setExclusiveIndexUsage( exclusiveIndexUsage );
}
- data.getClasses().add( entity );
- data.setExclusiveIndexUsage( exclusiveIndexUsage );
- }
- public SearchFactoryImplementor getUninitializedSearchFactory() {
- return rootFactory;
- }
+ public SearchFactoryImplementor getUninitializedSearchFactory() {
+ return rootFactory;
+ }
- public String getIndexingStrategy() {
- return indexingStrategy;
- }
+ public String getIndexingStrategy() {
+ return indexingStrategy;
+ }
- public Set<DirectoryProvider<?>> getDirectoryProviders() {
- return this.dirProviderData.keySet();
- }
+ public Set<DirectoryProvider<?>> getDirectoryProviders() {
+ return SearchFactoryBuilder.this.dirProviderData.keySet();
+ }
- public void setBackendQueueProcessorFactory(BackendQueueProcessorFactory
backendQueueProcessorFactory) {
- this.backendQueueProcessorFactory = backendQueueProcessorFactory;
- }
+ public void setBackendQueueProcessorFactory(BackendQueueProcessorFactory
backendQueueProcessorFactory) {
+ SearchFactoryBuilder.this.backendQueueProcessorFactory =
backendQueueProcessorFactory;
+ }
- public OptimizerStrategy getOptimizerStrategy(DirectoryProvider<?> provider) {
- return dirProviderData.get( provider ).getOptimizerStrategy();
- }
+ public OptimizerStrategy getOptimizerStrategy(DirectoryProvider<?> provider) {
+ return dirProviderData.get( provider ).getOptimizerStrategy();
+ }
- public Set<Class<?>>
getClassesInDirectoryProvider(DirectoryProvider<?> directoryProvider) {
- return Collections.unmodifiableSet( dirProviderData.get( directoryProvider
).getClasses() );
- }
+ public Set<Class<?>>
getClassesInDirectoryProvider(DirectoryProvider<?> directoryProvider) {
+ return Collections.unmodifiableSet( dirProviderData.get( directoryProvider
).getClasses() );
+ }
- public LuceneIndexingParameters getIndexingParameters(DirectoryProvider<?>
provider) {
- return dirProviderIndexingParams.get( provider );
- }
+ public LuceneIndexingParameters getIndexingParameters(DirectoryProvider<?>
provider) {
+ return dirProviderIndexingParams.get( provider );
+ }
- public ReentrantLock getDirectoryProviderLock(DirectoryProvider<?> dp) {
- return this.dirProviderData.get( dp ).getDirLock();
- }
+ public ReentrantLock getDirectoryProviderLock(DirectoryProvider<?> dp) {
+ return SearchFactoryBuilder.this.dirProviderData.get( dp ).getDirLock();
+ }
- public Similarity getSimilarity(DirectoryProvider<?> provider) {
- Similarity similarity = dirProviderData.get( provider ).getSimilarity();
- if ( similarity == null ) throw new SearchException( "Assertion error: a
similarity should be defined for each provider" );
- return similarity;
- }
+ public Similarity getSimilarity(DirectoryProvider<?> provider) {
+ Similarity similarity = dirProviderData.get( provider ).getSimilarity();
+ if ( similarity == null ) throw new SearchException( "Assertion error: a
similarity should be defined for each provider" );
+ return similarity;
+ }
- public boolean isExclusiveIndexUsageEnabled(DirectoryProvider<?> provider) {
- return dirProviderData.get( provider ).isExclusiveIndexUsage();
- }
+ public boolean isExclusiveIndexUsageEnabled(DirectoryProvider<?> provider) {
+ return dirProviderData.get( provider ).isExclusiveIndexUsage();
+ }
- public ErrorHandler getErrorHandler() {
- return errorHandler;
- }
+ public ErrorHandler getErrorHandler() {
+ return errorHandler;
+ }
- @SuppressWarnings("unchecked")
- public <T> DocumentBuilderIndexedEntity<T>
getDocumentBuilderIndexedEntity(Class<T> entityType) {
- return ( DocumentBuilderIndexedEntity<T> ) documentBuildersIndexedEntities.get(
entityType );
+ @SuppressWarnings("unchecked")
+ public <T> DocumentBuilderIndexedEntity<T>
getDocumentBuilderIndexedEntity(Class<T> entityType) {
+ return ( DocumentBuilderIndexedEntity<T> ) documentBuildersIndexedEntities.get(
entityType );
+ }
+
}
}