[hibernate-commits] Hibernate SVN: r16207 - in search/trunk: src/java/org/hibernate/search/annotations and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Sun Mar 22 22:11:37 EDT 2009


Author: epbernard
Date: 2009-03-22 22:11:36 -0400 (Sun, 22 Mar 2009)
New Revision: 16207

Added:
   search/trunk/src/java/org/hibernate/search/cfg/AnalyzerDefMapping.java
   search/trunk/src/java/org/hibernate/search/cfg/EntityDescriptor.java
   search/trunk/src/java/org/hibernate/search/cfg/EntityMapping.java
   search/trunk/src/java/org/hibernate/search/cfg/FieldMapping.java
   search/trunk/src/java/org/hibernate/search/cfg/PropertyDescriptor.java
   search/trunk/src/java/org/hibernate/search/cfg/PropertyMapping.java
   search/trunk/src/java/org/hibernate/search/cfg/SearchMapping.java
   search/trunk/src/java/org/hibernate/search/cfg/TokenFilterDefMapping.java
   search/trunk/src/java/org/hibernate/search/impl/MappingModelMetadataProvider.java
   search/trunk/src/test/org/hibernate/search/test/configuration/Address.java
   search/trunk/src/test/org/hibernate/search/test/configuration/Country.java
   search/trunk/src/test/org/hibernate/search/test/configuration/ProgrammaticMappingTest.java
   search/trunk/src/test/org/hibernate/search/test/configuration/User.java
Modified:
   search/trunk/pom.xml
   search/trunk/src/java/org/hibernate/search/annotations/Analyzer.java
   search/trunk/src/java/org/hibernate/search/cfg/SearchConfiguration.java
   search/trunk/src/java/org/hibernate/search/cfg/SearchConfigurationFromHibernateCore.java
   search/trunk/src/java/org/hibernate/search/impl/FullTextSessionImpl.java
   search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java
Log:
HSEARCH-352 inital commit for the programmatic mapping API

Modified: search/trunk/pom.xml
===================================================================
--- search/trunk/pom.xml	2009-03-23 01:53:05 UTC (rev 16206)
+++ search/trunk/pom.xml	2009-03-23 02:11:36 UTC (rev 16207)
@@ -4,7 +4,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-search</artifactId>
-    <version>3.1.0.GA</version>
+    <version>3.2.0-SNAPSHOT</version>
     <name>Hibernate Search</name>
     <description>Hibernate Search</description>
     <url>http://search.hibernate.org</url>
@@ -32,12 +32,12 @@
         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-core</artifactId>
-            <version>3.3.1.GA</version>
+            <version>3.5.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-commons-annotations</artifactId>
-            <version>3.1.0.GA</version>
+            <version>3.5.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.hibernate</groupId>
@@ -198,13 +198,13 @@
                 <dependency>
                     <groupId>org.hibernate</groupId>
                     <artifactId>hibernate-annotations</artifactId>
-                    <version>3.4.0.GA</version>
+                    <version>3.5.0-SNAPSHOT</version>
                     <optional>true</optional>
                 </dependency>
                 <dependency>
                     <groupId>org.hibernate</groupId>
                     <artifactId>hibernate-entitymanager</artifactId>
-                    <version>3.4.0.GA</version>
+                    <version>3.5.0-SNAPSHOT</version>
                     <optional>true</optional>
                 </dependency>
                 <dependency>

Modified: search/trunk/src/java/org/hibernate/search/annotations/Analyzer.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/annotations/Analyzer.java	2009-03-23 01:53:05 UTC (rev 16206)
+++ search/trunk/src/java/org/hibernate/search/annotations/Analyzer.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -23,8 +23,7 @@
 @Retention( RetentionPolicy.RUNTIME )
 @Target( { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD} )
 @Documented
-
 public @interface Analyzer {
-	Class impl() default void.class;
+	Class<?> impl() default void.class;
 	String definition() default "";
 }

Added: search/trunk/src/java/org/hibernate/search/cfg/AnalyzerDefMapping.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/AnalyzerDefMapping.java	                        (rev 0)
+++ search/trunk/src/java/org/hibernate/search/cfg/AnalyzerDefMapping.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,55 @@
+package org.hibernate.search.cfg;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.analysis.TokenizerFactory;
+import org.apache.solr.analysis.TokenFilterFactory;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class AnalyzerDefMapping {
+	private SearchMapping mapping;
+	private Map<String, Object> analyzerDef;
+	private Map<String, Object> tokenizer;
+
+	AnalyzerDefMapping(String name, Class<? extends TokenizerFactory> tokenizerFactory, SearchMapping mapping) {
+		this.mapping = mapping;
+		this.analyzerDef = new HashMap<String, Object>();
+		mapping.addAnalyzerDef(analyzerDef);
+		analyzerDef.put( "name", name );
+		tokenizer = new HashMap<String, Object>();
+		tokenizer.put( "factory", tokenizerFactory );
+		analyzerDef.put( "tokenizer", tokenizer );
+	}
+
+	/**
+	 * @TokenizerDef(, ... params={@Parameter(name="name", value="value"), ...})
+	 */
+	public AnalyzerDefMapping tokenizerParam(String name, String value) {
+		Map<String, Object> param = SearchMapping.addElementToAnnotationArray(tokenizer, "params");
+		param.put("name", name);
+		param.put("value", value);
+		return this;
+	}
+
+	/**
+	 * @TokenFilterDef(factory=factory)
+	 */
+	public TokenFilterDefMapping filter(Class<? extends TokenFilterFactory> factory) {
+		return new TokenFilterDefMapping(factory, analyzerDef, mapping);
+	}
+
+	public AnalyzerDefMapping analyzerDef(String name, Class<? extends TokenizerFactory> tokenizerFactory) {
+		return new AnalyzerDefMapping(name, tokenizerFactory, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType) {
+		return new EntityMapping(entityType, null, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType, String indexName) {
+		return new EntityMapping(entityType, indexName,  mapping);
+	}
+}

Added: search/trunk/src/java/org/hibernate/search/cfg/EntityDescriptor.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/EntityDescriptor.java	                        (rev 0)
+++ search/trunk/src/java/org/hibernate/search/cfg/EntityDescriptor.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,79 @@
+package org.hibernate.search.cfg;
+
+import java.lang.annotation.ElementType;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class EntityDescriptor {
+	private Class<?> entityType;
+	private Map<String, Object> indexed;
+	private Map<PropertyKey, PropertyDescriptor> properties = new HashMap<PropertyKey, PropertyDescriptor>();
+
+	public Map<String, Object> getIndexed() {
+		return indexed;
+	}
+
+	public EntityDescriptor(Class<?> entityType) {
+		this.entityType = entityType;
+	}
+
+	public void setIndexed(Map<String, Object> indexed) {
+		this.indexed = indexed;
+	}
+
+	PropertyDescriptor getProperty(String name, ElementType type) {
+		PropertyKey propertyKey = new PropertyKey( name, type );
+		PropertyDescriptor descriptor = properties.get( propertyKey );
+		if (descriptor == null) {
+			descriptor = new PropertyDescriptor(name, type);
+			properties.put(propertyKey, descriptor);
+		}
+		return descriptor;
+	}
+
+	public PropertyDescriptor getPropertyDescriptor(String name, ElementType type) {
+		return properties.get( new PropertyKey( name, type ) );
+	}
+
+
+	private static class PropertyKey {
+		private String name;
+		private ElementType type;
+
+		PropertyKey(String name, ElementType type) {
+			this.name = name;
+			this.type = type;
+		}
+
+		@Override
+		public boolean equals(Object o) {
+			if ( this == o ) {
+				return true;
+			}
+			if ( o == null || getClass() != o.getClass() ) {
+				return false;
+			}
+
+			PropertyKey property = ( PropertyKey ) o;
+
+			if ( name != null ? !name.equals( property.name ) : property.name != null ) {
+				return false;
+			}
+			if ( type != property.type ) {
+				return false;
+			}
+
+			return true;
+		}
+
+		@Override
+		public int hashCode() {
+			int result = name != null ? name.hashCode() : 0;
+			result = 31 * result + ( type != null ? type.hashCode() : 0 );
+			return result;
+		}
+	}
+}

Added: search/trunk/src/java/org/hibernate/search/cfg/EntityMapping.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/EntityMapping.java	                        (rev 0)
+++ search/trunk/src/java/org/hibernate/search/cfg/EntityMapping.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,41 @@
+package org.hibernate.search.cfg;
+
+import java.lang.annotation.ElementType;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.analysis.TokenizerFactory;
+
+import org.hibernate.search.annotations.Indexed;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class EntityMapping {
+	private SearchMapping mapping;
+	private EntityDescriptor entity;
+
+	public EntityMapping(Class<?> entityType, String name, SearchMapping mapping) {
+		this.mapping = mapping;
+		entity = mapping.getEntity(entityType);
+		Map<String, Object> indexed = new HashMap<String, Object>();
+		if (name != null) indexed.put( "index", name );
+		entity.setIndexed(indexed);
+	}
+
+	public PropertyMapping property(String name, ElementType type) {
+		return new PropertyMapping(name, type, entity, mapping);
+	}
+
+	public AnalyzerDefMapping analyzerDef(String name, Class<? extends TokenizerFactory> tokenizerFactory) {
+		return new AnalyzerDefMapping(name, tokenizerFactory, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType) {
+		return new EntityMapping(entityType, null, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType, String indexName) {
+		return new EntityMapping(entityType, indexName,  mapping);
+	}
+}

Added: search/trunk/src/java/org/hibernate/search/cfg/FieldMapping.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/FieldMapping.java	                        (rev 0)
+++ search/trunk/src/java/org/hibernate/search/cfg/FieldMapping.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,78 @@
+package org.hibernate.search.cfg;
+
+import java.lang.annotation.ElementType;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.analysis.TokenizerFactory;
+
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.Store;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class FieldMapping {
+	private SearchMapping mapping;
+	private EntityDescriptor entity;
+	private PropertyDescriptor property;
+	private Map<String, Object> field = new HashMap<String, Object>();
+
+	public FieldMapping(PropertyDescriptor property, EntityDescriptor entity, SearchMapping mapping) {
+		this.mapping = mapping;
+		this.entity = entity;
+		this.mapping = mapping;
+		this.property = property;
+		property.addField(field);
+	}
+
+	public FieldMapping name(String fieldName) {
+		field.put( "name", fieldName );
+		return this;
+	}
+
+	public FieldMapping store(Store store) {
+		field.put( "store", store );
+		return this;
+	}
+
+	public FieldMapping index(Index index) {
+		field.put( "index", index );
+		return this;
+	}
+
+	public FieldMapping analyzer(Class<?> analyzerClass) {
+		final Map<String, Object> analyzer = new HashMap<String, Object>();
+		analyzer.put( "impl", analyzerClass );
+		field.put( "analyzer", analyzer );
+		return this;
+	}
+
+	public FieldMapping analyzer(String analyzerDef) {
+		final Map<String, Object> analyzer = new HashMap<String, Object>();
+		analyzer.put( "definition", analyzerDef );
+		field.put( "analyzer", analyzer );
+		return this;
+	}
+
+	public FieldMapping field() {
+		return new FieldMapping(property, entity, mapping);
+	}
+
+	public PropertyMapping property(String name, ElementType type) {
+		return new PropertyMapping(name, type, entity, mapping);
+	}
+
+	public AnalyzerDefMapping analyzerDef(String name, Class<? extends TokenizerFactory> tokenizerFactory) {
+		return new AnalyzerDefMapping(name, tokenizerFactory, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType) {
+		return new EntityMapping(entityType, null, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType, String indexName) {
+		return new EntityMapping(entityType, indexName,  mapping);
+	}
+
+}

Added: search/trunk/src/java/org/hibernate/search/cfg/PropertyDescriptor.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/PropertyDescriptor.java	                        (rev 0)
+++ search/trunk/src/java/org/hibernate/search/cfg/PropertyDescriptor.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,28 @@
+package org.hibernate.search.cfg;
+
+import java.lang.annotation.ElementType;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class PropertyDescriptor {
+	private ElementType type;
+	private String name;
+	private Set<Map<String, Object>> fields = new HashSet<Map<String, Object>>();
+
+	public PropertyDescriptor(String name, ElementType type) {
+		this.name = name;
+		this.type = type;
+	}
+
+	public void addField(Map<String, Object> field) {
+		fields.add( field );
+	}
+
+	public Set<Map<String, Object>> getFields() {
+		return fields;
+	}
+}

Added: search/trunk/src/java/org/hibernate/search/cfg/PropertyMapping.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/PropertyMapping.java	                        (rev 0)
+++ search/trunk/src/java/org/hibernate/search/cfg/PropertyMapping.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,40 @@
+package org.hibernate.search.cfg;
+
+import java.lang.annotation.ElementType;
+
+import org.apache.solr.analysis.TokenizerFactory;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class PropertyMapping {
+	private SearchMapping mapping;
+	private EntityDescriptor entity;
+	private PropertyDescriptor property;
+
+	public PropertyMapping(String name, ElementType type, EntityDescriptor entity, SearchMapping mapping) {
+		this.mapping = mapping;
+		this.entity = entity;
+		property = entity.getProperty(name, type);
+	}
+
+	public FieldMapping field() {
+		return new FieldMapping(property, entity, mapping);
+	}
+
+	public PropertyMapping property(String name, ElementType type) {
+		return new PropertyMapping(name, type, entity, mapping);
+	}
+
+	public AnalyzerDefMapping analyzerDef(String name, Class<? extends TokenizerFactory> tokenizerFactory) {
+		return new AnalyzerDefMapping(name, tokenizerFactory, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType) {
+		return new EntityMapping(entityType, null, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType, String indexName) {
+		return new EntityMapping(entityType, indexName,  mapping);
+	}
+}

Modified: search/trunk/src/java/org/hibernate/search/cfg/SearchConfiguration.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/SearchConfiguration.java	2009-03-23 01:53:05 UTC (rev 16206)
+++ search/trunk/src/java/org/hibernate/search/cfg/SearchConfiguration.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -52,5 +52,9 @@
 	 */
 	ReflectionManager getReflectionManager();
 
-
+	/**
+	 * returns the programmatic configuration or null
+	 * //TODO remove hard dep with solr classes
+	 */
+	SearchMapping getProgrammaticMapping();
 }

Modified: search/trunk/src/java/org/hibernate/search/cfg/SearchConfigurationFromHibernateCore.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/SearchConfigurationFromHibernateCore.java	2009-03-23 01:53:05 UTC (rev 16206)
+++ search/trunk/src/java/org/hibernate/search/cfg/SearchConfigurationFromHibernateCore.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -2,8 +2,8 @@
 package org.hibernate.search.cfg;
 
 import java.util.Iterator;
+import java.util.NoSuchElementException;
 import java.util.Properties;
-import java.util.NoSuchElementException;
 
 import org.hibernate.annotations.common.reflection.ReflectionManager;
 import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
@@ -56,6 +56,10 @@
 		return reflectionManager;
 	}
 
+	public SearchMapping getProgrammaticMapping() {
+		return ( SearchMapping ) getProperties().get( "hibernate.search.mapping_model" );
+	}
+
 	private static class ClassIterator implements Iterator<Class<?>> {
 		private Iterator hibernatePersistentClassIterator;
 		private Class<?> future;

Added: search/trunk/src/java/org/hibernate/search/cfg/SearchMapping.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/SearchMapping.java	                        (rev 0)
+++ search/trunk/src/java/org/hibernate/search/cfg/SearchMapping.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,67 @@
+package org.hibernate.search.cfg;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.solr.analysis.TokenizerFactory;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class SearchMapping {
+	private Set<Map<String, Object>> analyzerDefs = new HashSet<Map<String, Object>>();
+	private Map<Class<?>, EntityDescriptor> entities = new HashMap<Class<?>, EntityDescriptor>();
+
+	public Set<Map<String, Object>> getAnalyzerDefs() {
+		return analyzerDefs;
+	}
+
+	public EntityDescriptor getEntityDescriptor(Class<?> entityType) {
+		return entities.get( entityType );
+	}
+
+	public AnalyzerDefMapping analyzerDef(String name, Class<? extends TokenizerFactory> tokenizerFactory) {
+		return new AnalyzerDefMapping(name, tokenizerFactory, this);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType) {
+		return new EntityMapping(entityType, null, this);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType, String indexName) {
+		return new EntityMapping(entityType, indexName,  this);
+	}
+
+	/**
+	 * eg @Containing(things={@Thing(...), @Thing(...)}
+	 * Map<String, Object> addedThing = addElementToAnnotationArray(containing, "things");
+	 */
+	static Map<String, Object> addElementToAnnotationArray(Map<String, Object> containingAnnotation,
+													  String attributeName) {
+		List<Map<String, Object>> array = (List<Map<String, Object>>) containingAnnotation.get( attributeName );
+		if ( array == null) {
+			array = new ArrayList<Map<String, Object>>();
+			containingAnnotation.put( attributeName, array );
+		}
+		Map<String, Object> param = new HashMap<String, Object>();
+		array.add( param );
+		return param;
+	}
+
+	void addAnalyzerDef(Map<String, Object> analyzerDef) {
+		analyzerDefs.add( analyzerDef );
+	}
+
+	EntityDescriptor getEntity(Class<?> entityType) {
+		EntityDescriptor entity = entities.get( entityType );
+		if (entity == null) {
+			entity = new EntityDescriptor(entityType);
+			entities.put( entityType, entity );
+		}
+		return entity;
+	}
+}

Added: search/trunk/src/java/org/hibernate/search/cfg/TokenFilterDefMapping.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/cfg/TokenFilterDefMapping.java	                        (rev 0)
+++ search/trunk/src/java/org/hibernate/search/cfg/TokenFilterDefMapping.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,52 @@
+package org.hibernate.search.cfg;
+
+import java.util.Map;
+
+import org.apache.solr.analysis.TokenFilterFactory;
+import org.apache.solr.analysis.TokenizerFactory;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class TokenFilterDefMapping {
+	private Map<String, Object> filter;
+	private Map<String, Object> analyzerDef;
+	private SearchMapping mapping;
+
+	TokenFilterDefMapping(Class<? extends TokenFilterFactory> factory, Map<String, Object> analyzerDef, SearchMapping mapping) {
+		this.mapping = mapping;
+		this.analyzerDef = analyzerDef;
+		this.filter = SearchMapping.addElementToAnnotationArray( analyzerDef, "filters" );
+		filter.put( "factory", factory );
+	}
+
+	/**
+	 * @TokenFilterDef(, ... params={@Parameter(name="name", value="value"), ...})
+	 */
+	public TokenFilterDefMapping param(String name, String value) {
+		Map<String, Object> param = SearchMapping.addElementToAnnotationArray(filter, "params");
+		param.put("name", name);
+		param.put("value", value);
+		return this;
+	}
+
+	/**
+	 * @TokenFilterDef(factory=factory)
+	 */
+	public TokenFilterDefMapping filter(Class<? extends TokenFilterFactory> factory) {
+		return new TokenFilterDefMapping(factory, analyzerDef, mapping );
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType) {
+		return new EntityMapping(entityType, null,  mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType, String indexName) {
+		return new EntityMapping(entityType, indexName,  mapping);
+	}
+
+	public AnalyzerDefMapping analyzerDef(String name, Class<? extends TokenizerFactory> tokenizerFactory) {
+		return new AnalyzerDefMapping(name, tokenizerFactory, mapping);
+	}
+
+}

Modified: search/trunk/src/java/org/hibernate/search/impl/FullTextSessionImpl.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/impl/FullTextSessionImpl.java	2009-03-23 01:53:05 UTC (rev 16206)
+++ search/trunk/src/java/org/hibernate/search/impl/FullTextSessionImpl.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -25,6 +25,7 @@
 import org.hibernate.ScrollableResults;
 import org.hibernate.SessionFactory;
 import org.hibernate.Transaction;
+import org.hibernate.UnknownProfileException;
 import org.hibernate.classic.Session;
 import org.hibernate.collection.PersistentCollection;
 import org.hibernate.engine.EntityKey;
@@ -32,6 +33,7 @@
 import org.hibernate.engine.QueryParameters;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
 import org.hibernate.engine.query.ParameterMetadata;
 import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
 import org.hibernate.event.EventListeners;
@@ -571,6 +573,10 @@
 		return sessionImplementor.isClosed();
 	}
 
+	public LoadQueryInfluencers getLoadQueryInfluencers() {
+		return sessionImplementor.getLoadQueryInfluencers();
+	}
+
 	public org.hibernate.Session getSession(EntityMode entityMode) {
 		return session.getSession( entityMode );
 	}
@@ -706,4 +712,16 @@
 	public void update(Object object) throws HibernateException {
 		session.update( object );
 	}
+
+	public boolean isFetchProfileEnabled(String name) throws UnknownProfileException {
+		return session.isFetchProfileEnabled( name );
+	}
+
+	public void enableFetchProfile(String name) throws UnknownProfileException {
+		session.enableFetchProfile( name );
+	}
+
+	public void disableFetchProfile(String name) throws UnknownProfileException {
+		session.disableFetchProfile( name );
+	}
 }

Added: search/trunk/src/java/org/hibernate/search/impl/MappingModelMetadataProvider.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/impl/MappingModelMetadataProvider.java	                        (rev 0)
+++ search/trunk/src/java/org/hibernate/search/impl/MappingModelMetadataProvider.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,220 @@
+package org.hibernate.search.impl;
+
+import java.util.Map;
+import java.util.List;
+import java.util.Set;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.beans.Introspector;
+
+import org.hibernate.annotations.common.reflection.MetadataProvider;
+import org.hibernate.annotations.common.reflection.AnnotationReader;
+import org.hibernate.annotations.common.reflection.ReflectionUtil;
+import org.hibernate.annotations.common.reflection.Filter;
+import org.hibernate.annotations.common.annotationfactory.AnnotationFactory;
+import org.hibernate.annotations.common.annotationfactory.AnnotationDescriptor;
+import org.hibernate.search.cfg.SearchMapping;
+import org.hibernate.search.cfg.EntityDescriptor;
+import org.hibernate.search.cfg.PropertyDescriptor;
+import org.hibernate.search.SearchException;
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.Analyzer;
+import org.hibernate.search.annotations.Fields;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class MappingModelMetadataProvider implements MetadataProvider {
+
+	private static final Filter FILTER = new Filter() {
+		public boolean returnStatic() {
+			return false;
+		}
+
+		public boolean returnTransient() {
+			return true;
+		}
+	};
+
+	private final MetadataProvider delegate;
+	private final SearchMapping mapping;
+	private final Map<AnnotatedElement, AnnotationReader> cache = new HashMap<AnnotatedElement, AnnotationReader>(100);
+
+	public MappingModelMetadataProvider(MetadataProvider delegate, SearchMapping mapping) {
+		this.delegate = delegate;
+		this.mapping = mapping;
+	}
+	public Map<Object, Object> getDefaults() {
+		return delegate.getDefaults();
+	}
+
+	public AnnotationReader getAnnotationReader(AnnotatedElement annotatedElement) {
+		AnnotationReader reader = cache.get(annotatedElement);
+		if (reader == null) {
+			reader = new MappingModelAnnotationReader( mapping, delegate, annotatedElement);
+			cache.put( annotatedElement, reader );
+		}
+		return reader;
+	}
+
+	private static class MappingModelAnnotationReader implements AnnotationReader {
+		private AnnotationReader delegate;
+		private SearchMapping mapping;
+		private transient Annotation[] annotationsArray;
+		private transient Map<Class<? extends Annotation>, Annotation> annotations;
+		private Class<?> entityType;
+		private ElementType elementType;
+		private String propertyName;
+
+		public MappingModelAnnotationReader(SearchMapping mapping, MetadataProvider delegate, AnnotatedElement el) {
+			this.delegate = delegate.getAnnotationReader( el );
+			this.mapping = mapping;
+			if ( el instanceof Class ) {
+				entityType = (Class) el;
+			}
+			else if ( el instanceof Field ) {
+				Field field = (Field) el;
+				entityType = field.getDeclaringClass();
+				propertyName = field.getName();
+				elementType = ElementType.FIELD;
+			}
+			else if ( el instanceof Method ) {
+				Method method = (Method) el;
+				entityType = method.getDeclaringClass();
+				propertyName = method.getName();
+				if ( ReflectionUtil.isProperty(
+						method,
+						null, //this is yukky!! we'd rather get the TypeEnvironment()
+						FILTER
+				) ) {
+					if ( propertyName.startsWith( "get" ) ) {
+						propertyName = Introspector.decapitalize( propertyName.substring( "get".length() ) );
+					}
+					else if ( propertyName.startsWith( "is" ) ) {
+						propertyName = Introspector.decapitalize( propertyName.substring( "is".length() ) );
+					}
+					else {
+						throw new RuntimeException( "Method " + propertyName + " is not a property getter" );
+					}
+					elementType = ElementType.METHOD;
+				}
+				else {
+					throw new SearchException( "Error in programmatic mapping. Method " + propertyName + " is not a property getter" );
+				}
+			}
+			else {
+				entityType = null;
+				propertyName = null;
+			}
+		}
+
+		/**
+		 * Consider the class to be free of Hibernate Search annotations. Does nto attempt to merge
+		 * data.
+		 * TODO do merge data? or safe-guard against errors
+		 */
+		private void initAnnotations() {
+			if ( annotationsArray == null ) {
+				annotations = new HashMap<Class<? extends Annotation>, Annotation>();
+				delegatesAnnotationReading();
+				if (entityType != null) {
+					final EntityDescriptor entity = mapping.getEntityDescriptor( entityType );
+					if (entity != null) {
+						if (propertyName == null) {
+							//entityType overriding
+							createIndexed( entity );
+						}
+						else {
+							final PropertyDescriptor property = entity.getPropertyDescriptor( propertyName, elementType );
+							if (property != null) {
+								// property name overriding
+								createFields( property );
+							}
+						}
+					}
+				}
+				else {
+					delegatesAnnotationReading();
+				}
+
+				populateAnnotationArray();
+			}
+		}
+
+		private void createFields(PropertyDescriptor property) {
+			final Set<Map<String,Object>> fields = property.getFields();
+			List<org.hibernate.search.annotations.Field> fieldAnnotations =
+					new ArrayList<org.hibernate.search.annotations.Field>( fields.size() );
+			for(Map<String, Object> field : fields) {
+				AnnotationDescriptor fieldAnnotation = new AnnotationDescriptor( org.hibernate.search.annotations.Field.class );
+				for ( Map.Entry<String, Object> entry : field.entrySet() ) {
+					if ( entry.getKey().equals( "analyzer" ) ) {
+						AnnotationDescriptor analyzerAnnotation = new AnnotationDescriptor( Analyzer.class );
+						@SuppressWarnings( "unchecked" )
+						Map<String, Object> analyzer = (Map<String, Object>) entry.getValue();
+						for( Map.Entry<String, Object> analyzerEntry : analyzer.entrySet() ) {
+							analyzerAnnotation.setValue( analyzerEntry.getKey(), analyzerEntry.getValue() );
+						}
+						fieldAnnotation.setValue( "analyzer", AnnotationFactory.create( analyzerAnnotation ) );
+					}
+					else {
+						fieldAnnotation.setValue( entry.getKey(), entry.getValue() );
+					}
+				}
+				fieldAnnotations.add( (org.hibernate.search.annotations.Field) AnnotationFactory.create( fieldAnnotation ) );
+			}
+			AnnotationDescriptor fieldsAnnotation = new AnnotationDescriptor( Fields.class );
+
+			final org.hibernate.search.annotations.Field[] fieldArray =
+					new org.hibernate.search.annotations.Field[fieldAnnotations.size()];
+			fieldsAnnotation.setValue( "value", fieldAnnotations.toArray( fieldArray ));
+			annotations.put( Fields.class, AnnotationFactory.create( fieldsAnnotation ) );
+		}
+
+		private void createIndexed(EntityDescriptor entity) {
+			Class<? extends Annotation> annotationType = Indexed.class;
+			AnnotationDescriptor annotation = new AnnotationDescriptor( annotationType );
+			for ( Map.Entry<String, Object> entry : entity.getIndexed().entrySet() ) {
+				annotation.setValue( entry.getKey(), entry.getValue() );
+			}
+			annotations.put( annotationType, AnnotationFactory.create( annotation ) );
+		}
+
+		private void populateAnnotationArray() {
+			annotationsArray = new Annotation[ annotations.size() ];
+			int index = 0;
+			for( Annotation ann: annotations.values() ) {
+				annotationsArray[index] = ann;
+				index++;
+			}
+		}
+
+		private void delegatesAnnotationReading() {
+			for ( Annotation a : delegate.getAnnotations() ) {
+				annotations.put( a.annotationType(), a );
+			}
+		}
+
+		@SuppressWarnings( "unchecked" )
+		public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
+			initAnnotations();
+			return (T) annotations.get( annotationType );
+		}
+
+		@SuppressWarnings( "unchecked" )
+		public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationType) {
+			initAnnotations();
+			return (T) annotations.get( annotationType ) != null;
+		}
+
+		public Annotation[] getAnnotations() {
+			initAnnotations();
+			return new Annotation[0];  //To change body of implemented methods use File | Settings | File Templates.
+		}
+	}
+}

Modified: search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java	2009-03-23 01:53:05 UTC (rev 16206)
+++ search/trunk/src/java/org/hibernate/search/impl/SearchFactoryImpl.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -21,6 +21,8 @@
 
 import org.hibernate.annotations.common.reflection.ReflectionManager;
 import org.hibernate.annotations.common.reflection.XClass;
+import org.hibernate.annotations.common.reflection.MetadataProvider;
+import org.hibernate.annotations.common.reflection.MetadataProviderInjector;
 import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
 import org.hibernate.annotations.common.util.StringHelper;
 import org.hibernate.search.Environment;
@@ -39,6 +41,7 @@
 import org.hibernate.search.backend.WorkerFactory;
 import org.hibernate.search.backend.configuration.ConfigurationParseHelper;
 import org.hibernate.search.cfg.SearchConfiguration;
+import org.hibernate.search.cfg.SearchMapping;
 import org.hibernate.search.engine.DocumentBuilderIndexedEntity;
 import org.hibernate.search.engine.FilterDef;
 import org.hibernate.search.engine.SearchFactoryImplementor;
@@ -111,10 +114,8 @@
 	}
 
 	public SearchFactoryImpl(SearchConfiguration cfg) {
-		ReflectionManager reflectionManager = cfg.getReflectionManager();
-		if ( reflectionManager == null ) {
-			reflectionManager = new JavaReflectionManager();
-		}
+		ReflectionManager reflectionManager = getReflectionManager(cfg);
+
 		this.indexingStrategy = defineIndexingStrategy( cfg ); //need to be done before the document builds
 		initDocumentBuilders( cfg, reflectionManager );
 
@@ -135,6 +136,25 @@
 		this.barrier = 1; //write barrier
 	}
 
+	private ReflectionManager getReflectionManager(SearchConfiguration cfg) {
+		ReflectionManager reflectionManager = cfg.getReflectionManager();
+		if ( reflectionManager == null ) {
+			reflectionManager = new JavaReflectionManager();
+		}
+		final SearchMapping mapping = cfg.getProgrammaticMapping();
+		if ( mapping != null) {
+			if ( ! ( reflectionManager instanceof MetadataProviderInjector)) {
+				throw new SearchException("Programmatic mapping model used but ReflectionManager does not implement "
+						+ MetadataProviderInjector.class.getName() );
+			}
+			MetadataProviderInjector injector = (MetadataProviderInjector) reflectionManager;
+			MetadataProvider original = injector.getMetadataProvider();
+			injector.setMetadataProvider( new MappingModelMetadataProvider( original, mapping ) );
+			
+		}
+		return reflectionManager;
+	}
+
 	private static String defineIndexingStrategy(SearchConfiguration cfg) {
 		String indexingStrategy = cfg.getProperties().getProperty( Environment.INDEXING_STRATEGY, "event" );
 		if ( !( "event".equals( indexingStrategy ) || "manual".equals( indexingStrategy ) ) ) {

Added: search/trunk/src/test/org/hibernate/search/test/configuration/Address.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/configuration/Address.java	                        (rev 0)
+++ search/trunk/src/test/org/hibernate/search/test/configuration/Address.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,44 @@
+package org.hibernate.search.test.configuration;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Address {
+	@Id
+	@GeneratedValue
+	private Long id;
+	private String street1;
+	private String street2;
+	@ManyToOne
+	private Country country;
+
+	public String getStreet1() {
+		return street1;
+	}
+
+	public void setStreet1(String street1) {
+		this.street1 = street1;
+	}
+
+	public Country getCountry() {
+		return country;
+	}
+
+	public void setCountry(Country country) {
+		this.country = country;
+	}
+
+	public String getStreet2() {
+		return street2;
+	}
+
+	public void setStreet2(String street2) {
+		this.street2 = street2;
+	}
+}

Added: search/trunk/src/test/org/hibernate/search/test/configuration/Country.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/configuration/Country.java	                        (rev 0)
+++ search/trunk/src/test/org/hibernate/search/test/configuration/Country.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,24 @@
+package org.hibernate.search.test.configuration;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Country {
+	@Id
+	@GeneratedValue
+	private Long id;
+	private String name;
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+}

Added: search/trunk/src/test/org/hibernate/search/test/configuration/ProgrammaticMappingTest.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/configuration/ProgrammaticMappingTest.java	                        (rev 0)
+++ search/trunk/src/test/org/hibernate/search/test/configuration/ProgrammaticMappingTest.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,107 @@
+package org.hibernate.search.test.configuration;
+
+import java.lang.annotation.ElementType;
+
+import org.apache.solr.analysis.StandardTokenizerFactory;
+import org.apache.solr.analysis.SnowballPorterFilterFactory;
+import org.apache.solr.analysis.LowerCaseFilterFactory;
+import org.apache.solr.analysis.NGramFilterFactory;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+
+import org.hibernate.search.cfg.SearchMapping;
+import org.hibernate.search.annotations.Store;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.test.analyzer.inheritance.ISOLatin1Analyzer;
+import org.hibernate.search.test.SearchTestCase;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.FullTextQuery;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.Transaction;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class ProgrammaticMappingTest extends SearchTestCase {
+
+	public void testMapping() throws Exception{
+		Address address = new Address();
+		address.setStreet1( "3340 Peachtree Rd NE" );
+		address.setStreet2( "JBoss" );
+
+		FullTextSession s = Search.getFullTextSession( openSession() );
+		Transaction tx = s.beginTransaction();
+		s.persist( address );
+		tx.commit();
+
+		s.clear();
+
+		tx = s.beginTransaction();
+
+		QueryParser parser = new QueryParser( "id", new StandardAnalyzer() );
+		org.apache.lucene.search.Query luceneQuery = parser.parse( "street1:peachtree" );
+		FullTextQuery query = s.createFullTextQuery( luceneQuery ).setProjection( "idx_street2", FullTextQuery.THIS );
+		assertEquals( "Not properly indexed", 1, query.getResultSize() );
+		Object[] firstResult = (Object[]) query.list().get( 0 );
+		assertEquals( "@Field.store not respected", "JBoss", firstResult[0] );
+
+		s.delete( firstResult[1] );
+		tx.commit();
+		s.close();
+
+	}
+
+	@Override
+	protected void configure(Configuration cfg) {
+		super.configure( cfg );
+		SearchMapping mapping = new SearchMapping();
+		mapping.indexedClass( Address.class )
+				.property( "street1", ElementType.FIELD )
+					.field()
+				.property( "street2", ElementType.METHOD )
+					.field().name( "idx_street2" )
+							.store( Store.YES );
+		cfg.getProperties().put( "hibernate.search.mapping_model", mapping );
+	}
+
+	public void NotUseddefineMapping() {
+		SearchMapping mapping = new SearchMapping();
+		mapping.analyzerDef( "stem", StandardTokenizerFactory.class )
+					.tokenizerParam( "name", "value" )
+					.tokenizerParam(  "name2", "value2" )
+					.filter( LowerCaseFilterFactory.class )
+					.filter( SnowballPorterFilterFactory.class)
+						.param("language", "English")
+				.analyzerDef( "ngram", StandardTokenizerFactory.class )
+					.tokenizerParam( "name", "value" )
+					.tokenizerParam(  "name2", "value2" )
+					.filter( LowerCaseFilterFactory.class )
+					.filter( NGramFilterFactory.class)
+						.param("minGramSize", "3")
+						.param("maxGramSize", "3")
+				.indexedClass(Address.class, "Address_Index")
+					.property("street1", ElementType.FIELD)
+						.field()
+						.field()
+							.name("street1_iso")
+							.store( Store.YES )
+							.index( Index.TOKENIZED )
+							.analyzer( ISOLatin1Analyzer.class)
+						.field()
+							.name("street1_ngram")
+							.analyzer("ngram")
+				.indexedClass(User.class)
+					.property("name", ElementType.METHOD)
+						.field()
+				.analyzerDef( "minimal", StandardTokenizerFactory.class  );
+
+	}
+
+	protected Class[] getMappings() {
+		return new Class[] {
+				Address.class,
+				Country.class
+		};
+	}
+}
\ No newline at end of file

Added: search/trunk/src/test/org/hibernate/search/test/configuration/User.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/configuration/User.java	                        (rev 0)
+++ search/trunk/src/test/org/hibernate/search/test/configuration/User.java	2009-03-23 02:11:36 UTC (rev 16207)
@@ -0,0 +1,16 @@
+package org.hibernate.search.test.configuration;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class User {
+	private String name;
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+}




More information about the hibernate-commits mailing list