Hibernate SVN: r20700 - core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/lock.
by hibernate-commits@lists.jboss.org
Author: stliu
Date: 2010-09-25 05:22:27 -0400 (Sat, 25 Sep 2010)
New Revision: 20700
Modified:
core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/lock/JPALockTest.java
Log:
HHH-5594 org.hibernate.test.jpa.lock.JPALockTest fails on hsqldb
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/lock/JPALockTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/lock/JPALockTest.java 2010-09-25 07:57:56 UTC (rev 20699)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/lock/JPALockTest.java 2010-09-25 09:22:27 UTC (rev 20700)
@@ -5,10 +5,12 @@
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.hibernate.dialect.HSQLDialect;
import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.test.jpa.AbstractJPATest;
import org.hibernate.test.jpa.Item;
import org.hibernate.test.jpa.MyEntity;
+import org.hibernate.util.ReflectHelper;
/**
* Tests specifically relating to section 3.3.5.3 [Lock Modes] of the
@@ -61,7 +63,24 @@
reportSkip( "deadlock", "jpa read locking" );
return;
}
+ if ( getDialect() instanceof HSQLDialect ) {
+ int hsqldbVersion = 18;
+ try {
+ Class props = ReflectHelper
+ .classForName( "org.hsqldb.persist.HsqlDatabaseProperties" );
+ String versionString = (String) props.getDeclaredField(
+ "THIS_VERSION").get(null);
+ hsqldbVersion = Integer.parseInt( versionString.substring( 0, 1 ) ) * 10;
+ hsqldbVersion += Integer
+ .parseInt( versionString.substring( 2, 3 ) );
+ } catch ( Throwable e ) {
+ // must be a very old version
+ }
+ if ( hsqldbVersion < 20 )
+ reportSkip( "hsqldb 1.8.x only supports read uncommitted", "lock doesn't work on hsqldb 1.8.x");
+ return;
+ }
final String initialName = "lock test";
// set up some test data
Session s1 = getSessions().openSession();
14 years, 5 months
Hibernate SVN: r20699 - core/trunk/testsuite/src/test/java/org/hibernate/test/legacy.
by hibernate-commits@lists.jboss.org
Author: stliu
Date: 2010-09-25 03:57:56 -0400 (Sat, 25 Sep 2010)
New Revision: 20699
Modified:
core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/Baz.hbm.xml
core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/FooBarTest.java
Log:
HHH-5593 org.hibernate.test.legacy.FooBarTest.testCollectionWhere fails on hsqldb
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/Baz.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/Baz.hbm.xml 2010-09-25 06:07:07 UTC (rev 20698)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/Baz.hbm.xml 2010-09-25 07:57:56 UTC (rev 20699)
@@ -104,7 +104,7 @@
<element column="map_value" type="date"/>
</map>
- <array name="fooArray" element-class="org.hibernate.test.legacy.FooProxy" where="i<8" check="i>=0">
+ <array name="fooArray" table="FOO_ARRAY" element-class="org.hibernate.test.legacy.FooProxy" where="i<8" check="i>=0">
<!--cache-->
<key column="id_"/>
<index column="i"/>
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/FooBarTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/FooBarTest.java 2010-09-25 06:07:07 UTC (rev 20698)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/legacy/FooBarTest.java 2010-09-25 07:57:56 UTC (rev 20699)
@@ -2038,7 +2038,7 @@
String bazid = baz.getCode();
s.delete(baz);
int rows=s.connection().createStatement().executeUpdate(
- "delete from fooArray where id_='" + bazid + "' and i>=8"
+ "delete from FOO_ARRAY where id_='" + bazid + "' and i>=8"
);
assertTrue(rows==1);
s.getTransaction().commit();
14 years, 5 months
Hibernate SVN: r20698 - core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/mutable.
by hibernate-commits@lists.jboss.org
Author: stliu
Date: 2010-09-25 02:07:07 -0400 (Sat, 25 Sep 2010)
New Revision: 20698
Modified:
core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/mutable/MutableNaturalIdTest.java
Log:
HHH-5592 org.hibernate.test.naturalid.mutable.MutableNaturalIdTest hangs on postgresql
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/mutable/MutableNaturalIdTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/mutable/MutableNaturalIdTest.java 2010-09-25 05:53:53 UTC (rev 20697)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/mutable/MutableNaturalIdTest.java 2010-09-25 06:07:07 UTC (rev 20698)
@@ -333,7 +333,9 @@
assertEquals( getSessions().getStatistics().getQueryCachePutCount(), 1 );
getSessions().getStatistics().clear();
-
+ s.getTransaction().commit();
+ s.close();
+
s = openSession();
s.beginTransaction();
u = ( User ) s.createCriteria( User.class )
14 years, 5 months
Hibernate SVN: r20697 - core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/immutable.
by hibernate-commits@lists.jboss.org
Author: stliu
Date: 2010-09-25 01:53:53 -0400 (Sat, 25 Sep 2010)
New Revision: 20697
Modified:
core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/immutable/ImmutableNaturalIdTest.java
Log:
HHH-5592 org.hibernate.test.naturalid.immutable.ImmutableNaturalIdTest hangs on postgresql
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/immutable/ImmutableNaturalIdTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/immutable/ImmutableNaturalIdTest.java 2010-09-25 05:29:17 UTC (rev 20696)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/naturalid/immutable/ImmutableNaturalIdTest.java 2010-09-25 05:53:53 UTC (rev 20697)
@@ -233,7 +233,7 @@
assertEquals( getSessions().getStatistics().getQueryCachePutCount(), 1 );
getSessions().getStatistics().clear();
-
+ s.getTransaction().commit();
s = openSession();
s.beginTransaction();
u = ( User ) s.createCriteria( User.class )
14 years, 5 months
Hibernate SVN: r20696 - core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/naturalid.
by hibernate-commits@lists.jboss.org
Author: stliu
Date: 2010-09-25 01:29:17 -0400 (Sat, 25 Sep 2010)
New Revision: 20696
Modified:
core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/naturalid/ImmutableNaturalIdTest.java
Log:
HHH-5592 org.hibernate.test.jpa.naturalid.ImmutableNaturalIdTest hangs on postgresql
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/naturalid/ImmutableNaturalIdTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/naturalid/ImmutableNaturalIdTest.java 2010-09-25 02:47:05 UTC (rev 20695)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/jpa/naturalid/ImmutableNaturalIdTest.java 2010-09-25 05:29:17 UTC (rev 20696)
@@ -244,7 +244,8 @@
assertEquals( getSessions().getStatistics().getQueryCachePutCount(), 1 );
getSessions().getStatistics().clear();
-
+ s.getTransaction().commit();
+ s.close();
s = openSession();
s.beginTransaction();
u = ( User ) s.createCriteria( User.class )
14 years, 5 months
Hibernate SVN: r20695 - core/trunk/testsuite/src/test/java/org/hibernate/test/hql.
by hibernate-commits@lists.jboss.org
Author: stliu
Date: 2010-09-24 22:47:05 -0400 (Fri, 24 Sep 2010)
New Revision: 20695
Modified:
core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingOrderByTest.java
Log:
HHH-5592 org.hibernate.test.hql.ASTParserLoadingOrderByTest hangs on postgresql
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingOrderByTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingOrderByTest.java 2010-09-24 15:39:44 UTC (rev 20694)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingOrderByTest.java 2010-09-25 02:47:05 UTC (rev 20695)
@@ -694,6 +694,8 @@
assertEquals( Long.valueOf( 1 ), ( ( Object[] ) list.get( 1 ) )[ 1 ] );
assertEquals( zoo4.getName(), ( ( Object[] ) list.get( 2 ) )[ 0 ] );
assertEquals( Long.valueOf( 1 ), ( ( Object[] ) list.get( 2 ) )[ 1 ] );
+ t.commit();
+ s.close();
cleanupData();
}
14 years, 5 months
Hibernate SVN: r20694 - core/trunk/core/src/main/java/org/hibernate/dialect.
by hibernate-commits@lists.jboss.org
Author: stliu
Date: 2010-09-24 11:39:44 -0400 (Fri, 24 Sep 2010)
New Revision: 20694
Modified:
core/trunk/core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java
Log:
HHH-5589 mysql does not support column check
Modified: core/trunk/core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java 2010-09-24 14:04:23 UTC (rev 20693)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java 2010-09-24 15:39:44 UTC (rev 20694)
@@ -37,4 +37,14 @@
registerColumnType( Types.VARCHAR, 65535, "varchar($l)" );
registerColumnType( Types.LONGVARCHAR, "longtext" );
}
+
+ /**
+ * Does this dialect support column-level check constraints?
+ *
+ * @return True if column-level CHECK constraints are supported; false
+ * otherwise.
+ */
+ public boolean supportsColumnCheck() {
+ return false;
+ }
}
14 years, 5 months
Hibernate SVN: r20693 - jpamodelgen/trunk.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-09-24 10:04:23 -0400 (Fri, 24 Sep 2010)
New Revision: 20693
Modified:
jpamodelgen/trunk/pom.xml
Log:
METAGEN-39 - Cleanup of pom
Modified: jpamodelgen/trunk/pom.xml
===================================================================
--- jpamodelgen/trunk/pom.xml 2010-09-24 13:53:55 UTC (rev 20692)
+++ jpamodelgen/trunk/pom.xml 2010-09-24 14:04:23 UTC (rev 20693)
@@ -127,7 +127,7 @@
<configuration>
<bytecodeInjections>
<bytecodeInjection>
- <expression>${pom.version}</expression>
+ <expression>${project.version}</expression>
<targetMembers>
<methodBodyReturn>
<className>org.hibernate.jpamodelgen.Version</className>
@@ -226,9 +226,9 @@
<archive>
<manifestEntries>
<Created-By>${java.version} (${java.vendor})</Created-By>
- <Implementation-Title>${pom.name}</Implementation-Title>
+ <Implementation-Title>${project.name}</Implementation-Title>
<Implementation-URL>http://www.jboss.org/</Implementation-URL>
- <Implementation-Version>${pom.version}</Implementation-Version>
+ <Implementation-Version>${project.version}</Implementation-Version>
<Implementation-Vendor>JBoss by Red Hat, Inc.</Implementation-Vendor>
<Implementation-Vendor-Id>http://www.jboss.org/</Implementation-Vendor-Id>
</manifestEntries>
@@ -237,19 +237,6 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- <version>2.0.4</version>
- <executions>
- <execution>
- <id>attach-sources</id>
- <goals>
- <goal>jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
<configuration>
@@ -369,63 +356,4 @@
<url>https://repository.jboss.org/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
-
- <reporting>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-project-info-reports-plugin</artifactId>
- <version>2.0.1</version>
- </plugin>
- <plugin>
- <artifactId>maven-javadoc-plugin</artifactId>
- <reportSets>
- <reportSet>
- <id>html</id>
- <configuration>
- <tags>
- <tag>
- <name>todo</name>
- <placement>a</placement>
- <head>ToDo:</head>
- </tag>
- </tags>
- </configuration>
- <reports>
- <report>javadoc</report>
- </reports>
- </reportSet>
- </reportSets>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>jxr-maven-plugin</artifactId>
- </plugin>
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- </plugin>
- <plugin>
- <artifactId>maven-clover-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-pmd-plugin</artifactId>
- <configuration>
- <targetJdk>1.5</targetJdk>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>taglist-maven-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>changelog-maven-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>changes-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </reporting>
</project>
14 years, 5 months
Hibernate SVN: r20692 - in search/trunk/hibernate-search/src/main/java/org/hibernate/search: util and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-09-24 09:53:55 -0400 (Fri, 24 Sep 2010)
New Revision: 20692
Added:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/AbstractDocumentBuilder.java
Modified:
search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderContainedEntity.java
search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java
search/trunk/hibernate-search/src/main/java/org/hibernate/search/util/HibernateHelper.java
Log:
HSEARCH-371 - added abstract base class
Copied: search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/AbstractDocumentBuilder.java (from rev 20691, search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderContainedEntity.java)
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/AbstractDocumentBuilder.java (rev 0)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/AbstractDocumentBuilder.java 2010-09-24 13:53:55 UTC (rev 20692)
@@ -0,0 +1,810 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.search.engine;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.search.Similarity;
+import org.slf4j.Logger;
+
+import org.hibernate.annotations.common.AssertionFailure;
+import org.hibernate.annotations.common.reflection.ReflectionManager;
+import org.hibernate.annotations.common.reflection.XAnnotatedElement;
+import org.hibernate.annotations.common.reflection.XClass;
+import org.hibernate.annotations.common.reflection.XMember;
+import org.hibernate.annotations.common.reflection.XProperty;
+import org.hibernate.annotations.common.util.StringHelper;
+import org.hibernate.search.SearchException;
+import org.hibernate.search.analyzer.Discriminator;
+import org.hibernate.search.annotations.AnalyzerDef;
+import org.hibernate.search.annotations.AnalyzerDefs;
+import org.hibernate.search.annotations.AnalyzerDiscriminator;
+import org.hibernate.search.annotations.Boost;
+import org.hibernate.search.annotations.ClassBridge;
+import org.hibernate.search.annotations.ClassBridges;
+import org.hibernate.search.annotations.ContainedIn;
+import org.hibernate.search.annotations.DynamicBoost;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.IndexedEmbedded;
+import org.hibernate.search.annotations.Store;
+import org.hibernate.search.annotations.TermVector;
+import org.hibernate.search.backend.LuceneWork;
+import org.hibernate.search.backend.WorkType;
+import org.hibernate.search.bridge.BridgeFactory;
+import org.hibernate.search.bridge.FieldBridge;
+import org.hibernate.search.bridge.LuceneOptions;
+import org.hibernate.search.impl.ConfigContext;
+import org.hibernate.search.util.ClassLoaderHelper;
+import org.hibernate.search.util.HibernateHelper;
+import org.hibernate.search.util.LoggerFactory;
+import org.hibernate.search.util.PassThroughAnalyzer;
+import org.hibernate.search.util.ReflectionHelper;
+import org.hibernate.search.util.ScopedAnalyzer;
+
+/**
+ * Abstract base class for the document builders.
+ *
+ * @author Hardy Ferentschik
+ */
+public abstract class AbstractDocumentBuilder<T> implements DocumentBuilder {
+ private static final Logger log = LoggerFactory.make();
+
+ protected final PropertiesMetadata metadata = new PropertiesMetadata();
+ protected final XClass beanXClass;
+ protected final Class<?> beanClass;
+ protected Set<Class<?>> mappedSubclasses = new HashSet<Class<?>>();
+ protected ReflectionManager reflectionManager; //available only during initialization and post-initialization
+ protected int level = 0;
+ protected int maxLevel = Integer.MAX_VALUE;
+ protected final ScopedAnalyzer analyzer = new ScopedAnalyzer();
+ protected Similarity similarity; //there is only 1 similarity per class hierarchy, and only 1 per index
+ protected boolean isRoot;
+ protected EntityState entityState;
+ private Analyzer passThroughAnalyzer = new PassThroughAnalyzer();
+
+ /**
+ * Constructor used on contained entities not annotated with <code>@Indexed</code> themselves.
+ *
+ * @param xClass The class for which to build a <code>DocumentBuilderContainedEntity</code>.
+ * @param context Handle to default configuration settings.
+ * @param reflectionManager Reflection manager to use for processing the annotations.
+ */
+ public AbstractDocumentBuilder(XClass xClass, ConfigContext context, ReflectionManager reflectionManager) {
+
+ if ( xClass == null ) {
+ throw new AssertionFailure( "Unable to build a DocumentBuilderContainedEntity with a null class" );
+ }
+
+ this.entityState = EntityState.CONTAINED_IN_ONLY;
+ this.beanXClass = xClass;
+ this.reflectionManager = reflectionManager;
+ this.beanClass = reflectionManager.toClass( xClass );
+ init( xClass, context );
+
+ if ( metadata.containedInGetters.size() == 0 ) {
+ this.entityState = EntityState.NON_INDEXABLE;
+ }
+ }
+
+ abstract public void addWorkToQueue(Class<T> entityClass, T entity, Serializable id, WorkType workType, List<LuceneWork> queue, SearchFactoryImplementor searchFactoryImplementor);
+
+ abstract protected void subClassSpecificCheck(XProperty member, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, ConfigContext context);
+
+ abstract protected void initSubClass(XClass clazz, ConfigContext context);
+
+ public boolean isRoot() {
+ return isRoot;
+ }
+
+ public Similarity getSimilarity() {
+ return similarity;
+ }
+
+ public Analyzer getAnalyzer() {
+ return analyzer;
+ }
+
+ public EntityState getEntityState() {
+ return entityState;
+ }
+
+ public Set<Class<?>> getMappedSubclasses() {
+ return mappedSubclasses;
+ }
+
+ public void postInitialize(Set<Class<?>> indexedClasses) {
+ //we initialize only once because we no longer have a reference to the reflectionManager
+ //in theory
+ Class<?> plainClass = beanClass;
+ if ( entityState == EntityState.NON_INDEXABLE ) {
+ throw new AssertionFailure( "A non indexed entity is post processed" );
+ }
+ Set<Class<?>> tempMappedSubclasses = new HashSet<Class<?>>();
+ //together with the caller this creates a o(2), but I think it's still faster than create the up hierarchy for each class
+ for ( Class<?> currentClass : indexedClasses ) {
+ if ( plainClass != currentClass && plainClass.isAssignableFrom( currentClass ) ) {
+ tempMappedSubclasses.add( currentClass );
+ }
+ }
+ this.mappedSubclasses = Collections.unmodifiableSet( tempMappedSubclasses );
+ Class<?> superClass = plainClass.getSuperclass();
+ this.isRoot = true;
+ while ( superClass != null ) {
+ if ( indexedClasses.contains( superClass ) ) {
+ this.isRoot = false;
+ break;
+ }
+ superClass = superClass.getSuperclass();
+ }
+ this.reflectionManager = null;
+ }
+
+ protected Analyzer getAnalyzer(XAnnotatedElement annotatedElement, ConfigContext context) {
+ org.hibernate.search.annotations.Analyzer analyzerAnn =
+ annotatedElement.getAnnotation( org.hibernate.search.annotations.Analyzer.class );
+ return getAnalyzer( analyzerAnn, context );
+ }
+
+ protected void addToScopedAnalyzer(String fieldName, Analyzer analyzer, Index index) {
+ if ( index == Index.TOKENIZED ) {
+ if ( analyzer != null ) {
+ this.analyzer.addScopedAnalyzer( fieldName, analyzer );
+ }
+ }
+ else {
+ //no analyzer is used, add a fake one for queries
+ this.analyzer.addScopedAnalyzer( fieldName, passThroughAnalyzer );
+ }
+ }
+
+ protected Float getBoost(XProperty member, org.hibernate.search.annotations.Field fieldAnn) {
+ float computedBoost = 1.0f;
+ Boost boostAnn = member.getAnnotation( Boost.class );
+ if ( boostAnn != null ) {
+ computedBoost = boostAnn.value();
+ }
+ if ( fieldAnn != null ) {
+ computedBoost *= fieldAnn.boost().value();
+ }
+ return computedBoost;
+ }
+
+ protected BoostStrategy getDynamicBoost(XProperty member) {
+ DynamicBoost boostAnnotation = member.getAnnotation( DynamicBoost.class );
+ if ( boostAnnotation == null ) {
+ return new DefaultBoostStrategy();
+ }
+
+ Class<? extends BoostStrategy> boostStrategyClass = boostAnnotation.impl();
+ BoostStrategy strategy;
+ try {
+ strategy = boostStrategyClass.newInstance();
+ }
+ catch ( Exception e ) {
+ throw new SearchException(
+ "Unable to instantiate boost strategy implementation: " + boostStrategyClass.getName()
+ );
+ }
+ return strategy;
+ }
+
+ protected Field.TermVector getTermVector(TermVector vector) {
+ switch ( vector ) {
+ case NO:
+ return Field.TermVector.NO;
+ case YES:
+ return Field.TermVector.YES;
+ case WITH_OFFSETS:
+ return Field.TermVector.WITH_OFFSETS;
+ case WITH_POSITIONS:
+ return Field.TermVector.WITH_POSITIONS;
+ case WITH_POSITION_OFFSETS:
+ return Field.TermVector.WITH_POSITIONS_OFFSETS;
+ default:
+ throw new AssertionFailure( "Unexpected TermVector: " + vector );
+ }
+ }
+
+ protected Field.Index getIndex(Index index) {
+ switch ( index ) {
+ case NO:
+ return Field.Index.NO;
+ case NO_NORMS:
+ return Field.Index.NOT_ANALYZED_NO_NORMS;
+ case TOKENIZED:
+ return Field.Index.ANALYZED;
+ case UN_TOKENIZED:
+ return Field.Index.NOT_ANALYZED;
+ default:
+ throw new AssertionFailure( "Unexpected Index: " + index );
+ }
+ }
+
+ /**
+ * If we have a work instance we have to check whether the instance to be indexed is contained in any other indexed entities.
+ *
+ * @param instance The instance to be indexed
+ * @param queue the current work queue
+ * @param metadata metadata
+ * @param searchFactoryImplementor the current session
+ */
+ protected <T> void processContainedInInstances(Object instance, List<LuceneWork> queue, PropertiesMetadata metadata, SearchFactoryImplementor searchFactoryImplementor) {
+ for ( int i = 0; i < metadata.containedInGetters.size(); i++ ) {
+ XMember member = metadata.containedInGetters.get( i );
+ Object value = ReflectionHelper.getMemberValue( instance, member );
+
+ if ( value == null ) {
+ continue;
+ }
+
+ if ( member.isArray() ) {
+ @SuppressWarnings("unchecked")
+ T[] array = ( T[] ) value;
+ for ( T arrayValue : array ) {
+ processSingleContainedInInstance( queue, searchFactoryImplementor, arrayValue );
+ }
+ }
+ else if ( member.isCollection() ) {
+ Collection<T> collection = null;
+ try {
+ collection = getActualCollection( member, value );
+ collection.size(); //load it
+ }
+ catch ( Exception e ) {
+ if ( e.getClass().getName().contains( "org.hibernate.LazyInitializationException" ) ) {
+ /* A deleted entity not having its collection initialized
+ * leads to a LIE because the colleciton is no longer attached to the session
+ *
+ * But that's ok as the collection update event has been processed before
+ * or the fk would have been cleared and thus triggering the cleaning
+ */
+ collection = null;
+ }
+ }
+ if ( collection != null ) {
+ for ( T collectionValue : collection ) {
+ processSingleContainedInInstance( queue, searchFactoryImplementor, collectionValue );
+ }
+ }
+ }
+ else {
+ processSingleContainedInInstance( queue, searchFactoryImplementor, value );
+ }
+ }
+ }
+
+ private void init(XClass clazz, ConfigContext context) {
+ metadata.boost = getBoost( clazz );
+ metadata.classBoostStrategy = getDynamicBoost( clazz );
+ metadata.analyzer = context.getDefaultAnalyzer();
+
+ Set<XClass> processedClasses = new HashSet<XClass>();
+ processedClasses.add( clazz );
+ initializeClass( clazz, metadata, true, "", processedClasses, context );
+
+ this.analyzer.setGlobalAnalyzer( metadata.analyzer );
+
+ // set the default similarity in case that after processing all classes there is still no similarity set
+ if ( this.similarity == null ) {
+ this.similarity = context.getDefaultSimilarity();
+ }
+
+ initSubClass( clazz, context );
+ }
+
+ private void initializeClass(XClass clazz, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix,
+ Set<XClass> processedClasses, ConfigContext context) {
+ List<XClass> hierarchy = new ArrayList<XClass>();
+ for ( XClass currentClass = clazz; currentClass != null; currentClass = currentClass.getSuperclass() ) {
+ hierarchy.add( currentClass );
+ }
+
+ /*
+ * Iterate the class hierarchy top down. This allows to override the default analyzer for the properties if the class holds one
+ */
+ for ( int index = hierarchy.size() - 1; index >= 0; index-- ) {
+ XClass currentClass = hierarchy.get( index );
+
+ initializeClassLevelAnnotations( currentClass, propertiesMetadata, isRoot, prefix, context );
+
+ // rejecting non properties (ie regular methods) because the object is loaded from Hibernate,
+ // so indexing a non property does not make sense
+ List<XProperty> methods = currentClass.getDeclaredProperties( XClass.ACCESS_PROPERTY );
+ for ( XProperty method : methods ) {
+ initializeMemberLevelAnnotations(
+ method, propertiesMetadata, isRoot, prefix, processedClasses, context
+ );
+ }
+
+ List<XProperty> fields = currentClass.getDeclaredProperties( XClass.ACCESS_FIELD );
+ for ( XProperty field : fields ) {
+ initializeMemberLevelAnnotations(
+ field, propertiesMetadata, isRoot, prefix, processedClasses, context
+ );
+ }
+ }
+ }
+
+ /**
+ * Check and initialize class level annotations.
+ *
+ * @param clazz The class to process.
+ * @param propertiesMetadata The meta data holder.
+ * @param isRoot Flag indicating if the specified class is a root entity, meaning the start of a chain of indexed
+ * entities.
+ * @param prefix The current prefix used for the <code>Document</code> field names.
+ * @param context Handle to default configuration settings.
+ */
+ private void initializeClassLevelAnnotations(XClass clazz, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, ConfigContext context) {
+
+ // check for a class level specified analyzer
+ Analyzer analyzer = getAnalyzer( clazz, context );
+ if ( analyzer != null ) {
+ propertiesMetadata.analyzer = analyzer;
+ }
+
+ // check for AnalyzerDefs annotations
+ checkForAnalyzerDefs( clazz, context );
+
+ // Check for any ClassBridges annotation.
+ ClassBridges classBridgesAnn = clazz.getAnnotation( ClassBridges.class );
+ if ( classBridgesAnn != null ) {
+ ClassBridge[] classBridges = classBridgesAnn.value();
+ for ( ClassBridge cb : classBridges ) {
+ bindClassBridgeAnnotation( prefix, propertiesMetadata, cb, context );
+ }
+ }
+
+ // Check for any ClassBridge style of annotations.
+ ClassBridge classBridgeAnn = clazz.getAnnotation( ClassBridge.class );
+ if ( classBridgeAnn != null ) {
+ bindClassBridgeAnnotation( prefix, propertiesMetadata, classBridgeAnn, context );
+ }
+
+ checkForAnalyzerDiscriminator( clazz, propertiesMetadata );
+
+ // Get similarity
+ if ( isRoot ) {
+ checkForSimilarity( clazz );
+ }
+ }
+
+ private void initializeMemberLevelAnnotations(XProperty member, PropertiesMetadata propertiesMetadata, boolean isRoot,
+ String prefix, Set<XClass> processedClasses, ConfigContext context) {
+ checkForField( member, propertiesMetadata, prefix, context );
+ checkForFields( member, propertiesMetadata, prefix, context );
+ checkForAnalyzerDefs( member, context );
+ checkForAnalyzerDiscriminator( member, propertiesMetadata );
+ checkForIndexedEmbedded( member, propertiesMetadata, prefix, processedClasses, context );
+ checkForContainedIn( member, propertiesMetadata );
+ subClassSpecificCheck( member, propertiesMetadata, isRoot, prefix, context );
+ }
+
+ private Analyzer getAnalyzer(org.hibernate.search.annotations.Analyzer analyzerAnn, ConfigContext context) {
+ Class<?> analyzerClass = analyzerAnn == null ? void.class : analyzerAnn.impl();
+ if ( analyzerClass == void.class ) {
+ String definition = analyzerAnn == null ? "" : analyzerAnn.definition();
+ if ( StringHelper.isEmpty( definition ) ) {
+ return null;
+ }
+ else {
+ return context.buildLazyAnalyzer( definition );
+ }
+ }
+ else {
+ try {
+ return ClassLoaderHelper.analyzerInstanceFromClass( analyzerClass, context.getLuceneMatchVersion() );
+ }
+ catch ( ClassCastException e ) {
+ throw new SearchException(
+ "Lucene analyzer does not implement " + Analyzer.class.getName() + ": " + analyzerClass.getName(),
+ e
+ );
+ }
+ catch ( Exception e ) {
+ throw new SearchException(
+ "Failed to instantiate lucene analyzer with type " + analyzerClass.getName(), e
+ );
+ }
+ }
+ }
+
+ private void checkForAnalyzerDefs(XAnnotatedElement annotatedElement, ConfigContext context) {
+ AnalyzerDefs defs = annotatedElement.getAnnotation( AnalyzerDefs.class );
+ if ( defs != null ) {
+ for ( AnalyzerDef def : defs.value() ) {
+ context.addAnalyzerDef( def );
+ }
+ }
+ AnalyzerDef def = annotatedElement.getAnnotation( AnalyzerDef.class );
+ context.addAnalyzerDef( def );
+ }
+
+ private void checkForAnalyzerDiscriminator(XAnnotatedElement annotatedElement, PropertiesMetadata propertiesMetadata) {
+ AnalyzerDiscriminator discriminatorAnn = annotatedElement.getAnnotation( AnalyzerDiscriminator.class );
+ if ( discriminatorAnn != null ) {
+ if ( propertiesMetadata.discriminator != null ) {
+ throw new SearchException(
+ "Multiple AnalyzerDiscriminator defined in the same class hierarchy: " + beanXClass.getName()
+ );
+ }
+
+ Class<? extends Discriminator> discriminatorClass = discriminatorAnn.impl();
+ try {
+ propertiesMetadata.discriminator = discriminatorClass.newInstance();
+ }
+ catch ( Exception e ) {
+ throw new SearchException(
+ "Unable to instantiate analyzer discriminator implementation: " + discriminatorClass.getName()
+ );
+ }
+
+ if ( annotatedElement instanceof XMember ) {
+ propertiesMetadata.discriminatorGetter = ( XMember ) annotatedElement;
+ }
+ }
+ }
+
+ private void checkForFields(XProperty member, PropertiesMetadata propertiesMetadata, String prefix, ConfigContext context) {
+ org.hibernate.search.annotations.Fields fieldsAnn =
+ member.getAnnotation( org.hibernate.search.annotations.Fields.class );
+ if ( fieldsAnn != null ) {
+ for ( org.hibernate.search.annotations.Field fieldAnn : fieldsAnn.value() ) {
+ bindFieldAnnotation( member, propertiesMetadata, prefix, fieldAnn, context );
+ }
+ }
+ }
+
+ private void checkForSimilarity(XClass currClass) {
+ org.hibernate.search.annotations.Similarity similarityAnn = currClass.getAnnotation( org.hibernate.search.annotations.Similarity.class );
+ if ( similarityAnn != null ) {
+ if ( similarity != null ) {
+ throw new SearchException(
+ "Multiple Similarities defined in the same class hierarchy: " + beanXClass.getName()
+ );
+ }
+ Class<?> similarityClass = similarityAnn.impl();
+ try {
+ similarity = ( Similarity ) similarityClass.newInstance();
+ }
+ catch ( Exception e ) {
+ log.error(
+ "Exception attempting to instantiate Similarity '{}' set for {}",
+ similarityClass.getName(), beanXClass.getName()
+ );
+ }
+ }
+ }
+
+ private void checkForField(XProperty member, PropertiesMetadata propertiesMetadata, String prefix, ConfigContext context) {
+ org.hibernate.search.annotations.Field fieldAnn =
+ member.getAnnotation( org.hibernate.search.annotations.Field.class );
+ if ( fieldAnn != null ) {
+ bindFieldAnnotation( member, propertiesMetadata, prefix, fieldAnn, context );
+ }
+ }
+
+ private void checkForContainedIn(XProperty member, PropertiesMetadata propertiesMetadata) {
+ ContainedIn containedAnn = member.getAnnotation( ContainedIn.class );
+ if ( containedAnn != null ) {
+ ReflectionHelper.setAccessible( member );
+ propertiesMetadata.containedInGetters.add( member );
+ }
+ }
+
+ private void checkForIndexedEmbedded(XProperty member, PropertiesMetadata propertiesMetadata, String prefix, Set<XClass> processedClasses, ConfigContext context) {
+ IndexedEmbedded embeddedAnn = member.getAnnotation( IndexedEmbedded.class );
+ if ( embeddedAnn != null ) {
+ int oldMaxLevel = maxLevel;
+ int potentialLevel = embeddedAnn.depth() + level;
+ if ( potentialLevel < 0 ) {
+ potentialLevel = Integer.MAX_VALUE;
+ }
+ maxLevel = potentialLevel > maxLevel ? maxLevel : potentialLevel;
+ level++;
+
+ XClass elementClass;
+ if ( void.class == embeddedAnn.targetElement() ) {
+ elementClass = member.getElementClass();
+ }
+ else {
+ elementClass = reflectionManager.toXClass( embeddedAnn.targetElement() );
+ }
+ if ( maxLevel == Integer.MAX_VALUE //infinite
+ && processedClasses.contains( elementClass ) ) {
+ throw new SearchException(
+ "Circular reference. Duplicate use of "
+ + elementClass.getName()
+ + " in root entity " + beanXClass.getName()
+ + "#" + buildEmbeddedPrefix( prefix, embeddedAnn, member )
+ );
+ }
+ if ( level <= maxLevel ) {
+ processedClasses.add( elementClass ); //push
+
+ ReflectionHelper.setAccessible( member );
+ propertiesMetadata.embeddedGetters.add( member );
+ PropertiesMetadata metadata = new PropertiesMetadata();
+ propertiesMetadata.embeddedPropertiesMetadata.add( metadata );
+ metadata.boost = getBoost( member, null );
+ //property > entity analyzer
+ Analyzer analyzer = getAnalyzer( member, context );
+ metadata.analyzer = analyzer != null ? analyzer : propertiesMetadata.analyzer;
+ String localPrefix = buildEmbeddedPrefix( prefix, embeddedAnn, member );
+ initializeClass( elementClass, metadata, false, localPrefix, processedClasses, context );
+ /**
+ * We will only index the "expected" type but that's OK, HQL cannot do down-casting either
+ */
+ if ( member.isArray() ) {
+ propertiesMetadata.embeddedContainers.add( PropertiesMetadata.Container.ARRAY );
+ }
+ else if ( member.isCollection() ) {
+ if ( Map.class.equals( member.getCollectionClass() ) ) {
+ //hum subclasses etc etc??
+ propertiesMetadata.embeddedContainers.add( PropertiesMetadata.Container.MAP );
+ }
+ else {
+ propertiesMetadata.embeddedContainers.add( PropertiesMetadata.Container.COLLECTION );
+ }
+ }
+ else {
+ propertiesMetadata.embeddedContainers.add( PropertiesMetadata.Container.OBJECT );
+ }
+
+ processedClasses.remove( elementClass ); //pop
+ }
+ else if ( log.isTraceEnabled() ) {
+ String localPrefix = buildEmbeddedPrefix( prefix, embeddedAnn, member );
+ log.trace( "depth reached, ignoring {}", localPrefix );
+ }
+
+ level--;
+ maxLevel = oldMaxLevel; //set back the the old max level
+ }
+ }
+
+ private void bindClassBridgeAnnotation(String prefix, PropertiesMetadata propertiesMetadata, ClassBridge ann, ConfigContext context) {
+ String fieldName = prefix + ann.name();
+ propertiesMetadata.classNames.add( fieldName );
+ propertiesMetadata.classStores.add( ann.store() );
+ propertiesMetadata.classIndexes.add( getIndex( ann.index() ) );
+ propertiesMetadata.classTermVectors.add( getTermVector( ann.termVector() ) );
+ propertiesMetadata.classBridges.add( BridgeFactory.extractType( ann ) );
+ propertiesMetadata.classBoosts.add( ann.boost().value() );
+
+ Analyzer analyzer = getAnalyzer( ann.analyzer(), context );
+ if ( analyzer == null ) {
+ analyzer = propertiesMetadata.analyzer;
+ }
+ if ( analyzer == null ) {
+ throw new AssertionFailure( "Analyzer should not be undefined" );
+ }
+ addToScopedAnalyzer( fieldName, analyzer, ann.index() );
+ }
+
+ private void bindFieldAnnotation(XProperty member, PropertiesMetadata propertiesMetadata, String prefix, org.hibernate.search.annotations.Field fieldAnn, ConfigContext context) {
+ ReflectionHelper.setAccessible( member );
+ propertiesMetadata.fieldGetters.add( member );
+ String fieldName = prefix + ReflectionHelper.getAttributeName( member, fieldAnn.name() );
+ propertiesMetadata.fieldNames.add( fieldName );
+ propertiesMetadata.fieldStore.add( fieldAnn.store() );
+ propertiesMetadata.fieldIndex.add( getIndex( fieldAnn.index() ) );
+ propertiesMetadata.fieldBoosts.add( getBoost( member, fieldAnn ) );
+ propertiesMetadata.dynamicFieldBoosts.add( getDynamicBoost( member ) );
+ propertiesMetadata.fieldTermVectors.add( getTermVector( fieldAnn.termVector() ) );
+ propertiesMetadata.fieldBridges.add( BridgeFactory.guessType( fieldAnn, member, reflectionManager ) );
+
+ // Field > property > entity analyzer
+ Analyzer analyzer = getAnalyzer( fieldAnn.analyzer(), context );
+ if ( analyzer == null ) {
+ analyzer = getAnalyzer( member, context );
+ }
+ addToScopedAnalyzer( fieldName, analyzer, fieldAnn.index() );
+ }
+
+ private String buildEmbeddedPrefix(String prefix, IndexedEmbedded embeddedAnn, XProperty member) {
+ String localPrefix = prefix;
+ if ( ".".equals( embeddedAnn.prefix() ) ) {
+ //default to property name
+ localPrefix += member.getName() + '.';
+ }
+ else {
+ localPrefix += embeddedAnn.prefix();
+ }
+ return localPrefix;
+ }
+
+ private float getBoost(XClass element) {
+ float boost = 1.0f;
+ if ( element == null ) {
+ return boost;
+ }
+ Boost boostAnnotation = element.getAnnotation( Boost.class );
+ if ( boostAnnotation != null ) {
+ boost = boostAnnotation.value();
+ }
+ return boost;
+ }
+
+ private BoostStrategy getDynamicBoost(XClass element) {
+ if ( element == null ) {
+ return null;
+ }
+ DynamicBoost boostAnnotation = element.getAnnotation( DynamicBoost.class );
+ if ( boostAnnotation == null ) {
+ return new DefaultBoostStrategy();
+ }
+
+ Class<? extends BoostStrategy> boostStrategyClass = boostAnnotation.impl();
+ BoostStrategy strategy;
+ try {
+ strategy = boostStrategyClass.newInstance();
+ }
+ catch ( Exception e ) {
+ throw new SearchException(
+ "Unable to instantiate boost strategy implementation: " + boostStrategyClass.getName()
+ );
+ }
+ return strategy;
+ }
+
+ /**
+ * A {@code XMember } instance treats a map as a collection as well in which case the map values are returned as
+ * collection.
+ *
+ * @param member The member instance
+ * @param value The value
+ *
+ * @return The {@code value} casted to collection or in case of {@code value} being a map the map values as collection.
+ */
+ private <T> Collection<T> getActualCollection(XMember member, Object value) {
+ Collection<T> collection;
+ if ( Map.class.equals( member.getCollectionClass() ) ) {
+ //hum
+ @SuppressWarnings("unchecked")
+ Collection<T> tmpCollection = ( ( Map<?, T> ) value ).values();
+ collection = tmpCollection;
+ }
+ else {
+ @SuppressWarnings("unchecked")
+ Collection<T> tmpCollection = ( Collection<T> ) value;
+ collection = tmpCollection;
+ }
+ return collection;
+ }
+
+ private <T> void processSingleContainedInInstance(List<LuceneWork> queue, SearchFactoryImplementor searchFactoryImplementor, T value) {
+ Class<T> valueClass = HibernateHelper.getClass( value );
+ DocumentBuilderIndexedEntity<T> builderIndexedEntity =
+ searchFactoryImplementor.getDocumentBuilderIndexedEntity( valueClass );
+
+ // it could be we have a nested @IndexedEmbedded chain in which case we have to find the top level @Indexed entities
+ if ( builderIndexedEntity == null ) {
+ DocumentBuilderContainedEntity<T> builderContainedEntity =
+ searchFactoryImplementor.getDocumentBuilderContainedEntity( valueClass );
+ if ( builderContainedEntity != null ) {
+ processContainedInInstances( value, queue, builderContainedEntity.metadata, searchFactoryImplementor );
+ }
+ }
+ else {
+ addWorkForEmbeddedValue( value, queue, valueClass, builderIndexedEntity, searchFactoryImplementor );
+ }
+ }
+
+ /**
+ * Create a {@code LuceneWork} instance of the entity which needs updating due to the embedded instance change.
+ *
+ * @param value The value to index
+ * @param queue The current (Lucene) work queue
+ * @param valueClass The class of the value
+ * @param builderIndexedEntity the document builder for the entity which needs updating due to a update event of the embedded instance
+ * @param searchFactoryImplementor the search factory.
+ */
+ private <T> void addWorkForEmbeddedValue(T value, List<LuceneWork> queue, Class<T> valueClass,
+ DocumentBuilderIndexedEntity<T> builderIndexedEntity, SearchFactoryImplementor searchFactoryImplementor) {
+ Serializable id = ( Serializable ) ReflectionHelper.getMemberValue( value, builderIndexedEntity.idGetter );
+ if ( id != null ) {
+ builderIndexedEntity.addWorkToQueue(
+ valueClass, value, id, WorkType.UPDATE, queue, searchFactoryImplementor
+ );
+ }
+ else {
+ //this is an indexed entity that is not yet persisted but should be reached by cascade
+ // and thus raise an Hibernate Core event leading to its indexing by Hibernate Search
+ // => no need to do anything here
+ }
+ }
+
+ /**
+ * Wrapper class containing all the meta data extracted out of a single entity.
+ * All field/property related properties are kept in lists. Retrieving all metadata for a given
+ * property/field means accessing all the lists with the same index.
+ */
+ protected static class PropertiesMetadata {
+ public float boost;
+ public Analyzer analyzer;
+ public Discriminator discriminator;
+ public XMember discriminatorGetter;
+ public BoostStrategy classBoostStrategy;
+
+ public final List<String> fieldNames = new ArrayList<String>();
+ public final List<XMember> fieldGetters = new ArrayList<XMember>();
+ public final List<FieldBridge> fieldBridges = new ArrayList<FieldBridge>();
+ public final List<Store> fieldStore = new ArrayList<Store>();
+ public final List<Field.Index> fieldIndex = new ArrayList<Field.Index>();
+ public final List<Float> fieldBoosts = new ArrayList<Float>();
+ public final List<BoostStrategy> dynamicFieldBoosts = new ArrayList<BoostStrategy>();
+
+ public final List<Field.TermVector> fieldTermVectors = new ArrayList<Field.TermVector>();
+ public final List<XMember> embeddedGetters = new ArrayList<XMember>();
+ public final List<PropertiesMetadata> embeddedPropertiesMetadata = new ArrayList<PropertiesMetadata>();
+ public final List<Container> embeddedContainers = new ArrayList<Container>();
+ public final List<XMember> containedInGetters = new ArrayList<XMember>();
+
+ public final List<String> classNames = new ArrayList<String>();
+ public final List<Store> classStores = new ArrayList<Store>();
+ public final List<Field.Index> classIndexes = new ArrayList<Field.Index>();
+ public final List<FieldBridge> classBridges = new ArrayList<FieldBridge>();
+ public final List<Field.TermVector> classTermVectors = new ArrayList<Field.TermVector>();
+ public final List<Float> classBoosts = new ArrayList<Float>();
+
+ public enum Container {
+ OBJECT,
+ COLLECTION,
+ MAP,
+ ARRAY
+ }
+
+ protected LuceneOptions getClassLuceneOptions(int i) {
+ return new LuceneOptionsImpl(
+ classStores.get( i ),
+ classIndexes.get( i ), classTermVectors.get( i ), classBoosts.get( i )
+ );
+ }
+
+ protected LuceneOptions getFieldLuceneOptions(int i, Object value) {
+ LuceneOptions options;
+ options = new LuceneOptionsImpl(
+ fieldStore.get( i ),
+ fieldIndex.get( i ),
+ fieldTermVectors.get( i ),
+ fieldBoosts.get( i ) * dynamicFieldBoosts.get( i ).defineBoost( value )
+ );
+ return options;
+ }
+
+ protected float getClassBoost(Object value) {
+ return boost * classBoostStrategy.defineBoost( value );
+ }
+ }
+}
Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderContainedEntity.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderContainedEntity.java 2010-09-23 14:54:28 UTC (rev 20691)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderContainedEntity.java 2010-09-24 13:53:55 UTC (rev 20692)
@@ -24,54 +24,14 @@
package org.hibernate.search.engine;
import java.io.Serializable;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.search.Similarity;
-import org.slf4j.Logger;
-
-import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.annotations.common.reflection.ReflectionManager;
-import org.hibernate.annotations.common.reflection.XAnnotatedElement;
import org.hibernate.annotations.common.reflection.XClass;
-import org.hibernate.annotations.common.reflection.XMember;
import org.hibernate.annotations.common.reflection.XProperty;
-import org.hibernate.annotations.common.util.StringHelper;
-import org.hibernate.search.SearchException;
-import org.hibernate.search.analyzer.Discriminator;
-import org.hibernate.search.annotations.AnalyzerDef;
-import org.hibernate.search.annotations.AnalyzerDefs;
-import org.hibernate.search.annotations.AnalyzerDiscriminator;
-import org.hibernate.search.annotations.Boost;
-import org.hibernate.search.annotations.ClassBridge;
-import org.hibernate.search.annotations.ClassBridges;
-import org.hibernate.search.annotations.ContainedIn;
-import org.hibernate.search.annotations.DynamicBoost;
-import org.hibernate.search.annotations.Index;
-import org.hibernate.search.annotations.IndexedEmbedded;
-import org.hibernate.search.annotations.Store;
-import org.hibernate.search.annotations.TermVector;
import org.hibernate.search.backend.LuceneWork;
import org.hibernate.search.backend.WorkType;
-import org.hibernate.search.bridge.BridgeFactory;
-import org.hibernate.search.bridge.FieldBridge;
-import org.hibernate.search.bridge.LuceneOptions;
import org.hibernate.search.impl.ConfigContext;
-import org.hibernate.search.util.HibernateHelper;
-import org.hibernate.search.util.LoggerFactory;
-import org.hibernate.search.util.PassThroughAnalyzer;
-import org.hibernate.search.util.ClassLoaderHelper;
-import org.hibernate.search.util.ReflectionHelper;
-import org.hibernate.search.util.ScopedAnalyzer;
/**
* Set up and provide a manager for classes which are indexed via <code>@IndexedEmbedded</code>, but themselves do not
@@ -83,23 +43,7 @@
* @author Richard Hallier
* @author Hardy Ferentschik
*/
-public class DocumentBuilderContainedEntity<T> implements DocumentBuilder {
- private static final Logger log = LoggerFactory.make();
-
- protected final PropertiesMetadata metadata = new PropertiesMetadata();
- protected final XClass beanXClass;
- protected final Class<?> beanClass;
- protected Set<Class<?>> mappedSubclasses = new HashSet<Class<?>>();
- protected ReflectionManager reflectionManager; //available only during initialization and post-initialization
- protected int level = 0;
- protected int maxLevel = Integer.MAX_VALUE;
- protected final ScopedAnalyzer analyzer = new ScopedAnalyzer();
- protected Similarity similarity; //there is only 1 similarity per class hierarchy, and only 1 per index
- protected boolean isRoot;
- protected EntityState entityState;
- private Analyzer passThroughAnalyzer = new PassThroughAnalyzer();
- private boolean initialized;
-
+public class DocumentBuilderContainedEntity<T> extends AbstractDocumentBuilder<T> implements DocumentBuilder {
/**
* Constructor used on contained entities not annotated with <code>@Indexed</code> themselves.
*
@@ -108,512 +52,15 @@
* @param reflectionManager Reflection manager to use for processing the annotations.
*/
public DocumentBuilderContainedEntity(XClass xClass, ConfigContext context, ReflectionManager reflectionManager) {
-
- if ( xClass == null ) {
- throw new AssertionFailure( "Unable to build a DocumentBuilderContainedEntity with a null class" );
- }
-
- this.entityState = EntityState.CONTAINED_IN_ONLY;
- this.beanXClass = xClass;
- this.reflectionManager = reflectionManager;
- this.beanClass = reflectionManager.toClass( xClass );
- init( xClass, context );
-
- if ( metadata.containedInGetters.size() == 0 ) {
- this.entityState = EntityState.NON_INDEXABLE;
- }
+ super( xClass, context, reflectionManager );
}
- protected void init(XClass clazz, ConfigContext context) {
- metadata.boost = getBoost( clazz );
- metadata.classBoostStrategy = getDynamicBoost( clazz );
- metadata.analyzer = context.getDefaultAnalyzer();
-
- Set<XClass> processedClasses = new HashSet<XClass>();
- processedClasses.add( clazz );
- initializeClass( clazz, metadata, true, "", processedClasses, context );
-
- this.analyzer.setGlobalAnalyzer( metadata.analyzer );
-
- // set the default similarity in case that after processing all classes there is still no similarity set
- if ( this.similarity == null ) {
- this.similarity = context.getDefaultSimilarity();
- }
+ protected void initSubClass(XClass clazz, ConfigContext context) {
}
- public boolean isRoot() {
- return isRoot;
+ protected void subClassSpecificCheck(XProperty member, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, ConfigContext context) {
}
- private void initializeClass(XClass clazz, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix,
- Set<XClass> processedClasses, ConfigContext context) {
- List<XClass> hierarchy = new ArrayList<XClass>();
- for ( XClass currentClass = clazz; currentClass != null; currentClass = currentClass.getSuperclass() ) {
- hierarchy.add( currentClass );
- }
-
- /*
- * Iterate the class hierarchy top down. This allows to override the default analyzer for the properties if the class holds one
- */
- for ( int index = hierarchy.size() - 1; index >= 0; index-- ) {
- XClass currentClass = hierarchy.get( index );
-
- initializeClassLevelAnnotations( currentClass, propertiesMetadata, isRoot, prefix, context );
-
- // rejecting non properties (ie regular methods) because the object is loaded from Hibernate,
- // so indexing a non property does not make sense
- List<XProperty> methods = currentClass.getDeclaredProperties( XClass.ACCESS_PROPERTY );
- for ( XProperty method : methods ) {
- initializeMemberLevelAnnotations(
- method, propertiesMetadata, isRoot, prefix, processedClasses, context
- );
- }
-
- List<XProperty> fields = currentClass.getDeclaredProperties( XClass.ACCESS_FIELD );
- for ( XProperty field : fields ) {
- initializeMemberLevelAnnotations(
- field, propertiesMetadata, isRoot, prefix, processedClasses, context
- );
- }
- }
- }
-
- /**
- * Check and initialize class level annotations.
- *
- * @param clazz The class to process.
- * @param propertiesMetadata The meta data holder.
- * @param isRoot Flag indicating if the specified class is a root entity, meaning the start of a chain of indexed
- * entities.
- * @param prefix The current prefix used for the <code>Document</code> field names.
- * @param context Handle to default configuration settings.
- */
- private void initializeClassLevelAnnotations(XClass clazz, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, ConfigContext context) {
-
- // check for a class level specified analyzer
- Analyzer analyzer = getAnalyzer( clazz, context );
- if ( analyzer != null ) {
- propertiesMetadata.analyzer = analyzer;
- }
-
- // check for AnalyzerDefs annotations
- checkForAnalyzerDefs( clazz, context );
-
- // Check for any ClassBridges annotation.
- ClassBridges classBridgesAnn = clazz.getAnnotation( ClassBridges.class );
- if ( classBridgesAnn != null ) {
- ClassBridge[] classBridges = classBridgesAnn.value();
- for ( ClassBridge cb : classBridges ) {
- bindClassBridgeAnnotation( prefix, propertiesMetadata, cb, context );
- }
- }
-
- // Check for any ClassBridge style of annotations.
- ClassBridge classBridgeAnn = clazz.getAnnotation( ClassBridge.class );
- if ( classBridgeAnn != null ) {
- bindClassBridgeAnnotation( prefix, propertiesMetadata, classBridgeAnn, context );
- }
-
- checkForAnalyzerDiscriminator( clazz, propertiesMetadata );
-
- // Get similarity
- if ( isRoot ) {
- checkForSimilarity( clazz );
- }
- }
-
- protected void initializeMemberLevelAnnotations(XProperty member, PropertiesMetadata propertiesMetadata, boolean isRoot,
- String prefix, Set<XClass> processedClasses, ConfigContext context) {
- checkDocumentId( member, propertiesMetadata, isRoot, prefix, context );
- checkForField( member, propertiesMetadata, prefix, context );
- checkForFields( member, propertiesMetadata, prefix, context );
- checkForAnalyzerDefs( member, context );
- checkForAnalyzerDiscriminator( member, propertiesMetadata );
- checkForIndexedEmbedded( member, propertiesMetadata, prefix, processedClasses, context );
- checkForContainedIn( member, propertiesMetadata );
- }
-
- protected Analyzer getAnalyzer(XAnnotatedElement annotatedElement, ConfigContext context) {
- org.hibernate.search.annotations.Analyzer analyzerAnn =
- annotatedElement.getAnnotation( org.hibernate.search.annotations.Analyzer.class );
- return getAnalyzer( analyzerAnn, context );
- }
-
- protected Analyzer getAnalyzer(org.hibernate.search.annotations.Analyzer analyzerAnn, ConfigContext context) {
- Class<?> analyzerClass = analyzerAnn == null ? void.class : analyzerAnn.impl();
- if ( analyzerClass == void.class ) {
- String definition = analyzerAnn == null ? "" : analyzerAnn.definition();
- if ( StringHelper.isEmpty( definition ) ) {
- return null;
- }
- else {
- return context.buildLazyAnalyzer( definition );
- }
- }
- else {
- try {
- return ClassLoaderHelper.analyzerInstanceFromClass( analyzerClass, context.getLuceneMatchVersion() );
- }
- catch ( ClassCastException e ) {
- throw new SearchException(
- "Lucene analyzer does not implement " + Analyzer.class.getName() + ": " + analyzerClass.getName(),
- e
- );
- }
- catch ( Exception e ) {
- throw new SearchException(
- "Failed to instantiate lucene analyzer with type " + analyzerClass.getName(), e
- );
- }
- }
- }
-
- private void checkForAnalyzerDefs(XAnnotatedElement annotatedElement, ConfigContext context) {
- AnalyzerDefs defs = annotatedElement.getAnnotation( AnalyzerDefs.class );
- if ( defs != null ) {
- for ( AnalyzerDef def : defs.value() ) {
- context.addAnalyzerDef( def );
- }
- }
- AnalyzerDef def = annotatedElement.getAnnotation( AnalyzerDef.class );
- context.addAnalyzerDef( def );
- }
-
- private void checkForAnalyzerDiscriminator(XAnnotatedElement annotatedElement, PropertiesMetadata propertiesMetadata) {
- AnalyzerDiscriminator discriminatorAnn = annotatedElement.getAnnotation( AnalyzerDiscriminator.class );
- if ( discriminatorAnn != null ) {
- if ( propertiesMetadata.discriminator != null ) {
- throw new SearchException(
- "Multiple AnalyzerDiscriminator defined in the same class hierarchy: " + beanXClass.getName()
- );
- }
-
- Class<? extends Discriminator> discriminatorClass = discriminatorAnn.impl();
- try {
- propertiesMetadata.discriminator = discriminatorClass.newInstance();
- }
- catch ( Exception e ) {
- throw new SearchException(
- "Unable to instantiate analyzer discriminator implementation: " + discriminatorClass.getName()
- );
- }
-
- if ( annotatedElement instanceof XMember ) {
- propertiesMetadata.discriminatorGetter = ( XMember ) annotatedElement;
- }
- }
- }
-
- public Similarity getSimilarity() {
- return similarity;
- }
-
- private void checkForFields(XProperty member, PropertiesMetadata propertiesMetadata, String prefix, ConfigContext context) {
- org.hibernate.search.annotations.Fields fieldsAnn =
- member.getAnnotation( org.hibernate.search.annotations.Fields.class );
- if ( fieldsAnn != null ) {
- for ( org.hibernate.search.annotations.Field fieldAnn : fieldsAnn.value() ) {
- bindFieldAnnotation( member, propertiesMetadata, prefix, fieldAnn, context );
- }
- }
- }
-
- private void checkForSimilarity(XClass currClass) {
- org.hibernate.search.annotations.Similarity similarityAnn = currClass.getAnnotation( org.hibernate.search.annotations.Similarity.class );
- if ( similarityAnn != null ) {
- if ( similarity != null ) {
- throw new SearchException(
- "Multiple Similarities defined in the same class hierarchy: " + beanXClass.getName()
- );
- }
- Class<?> similarityClass = similarityAnn.impl();
- try {
- similarity = ( Similarity ) similarityClass.newInstance();
- }
- catch ( Exception e ) {
- log.error(
- "Exception attempting to instantiate Similarity '{}' set for {}",
- similarityClass.getName(), beanXClass.getName()
- );
- }
- }
- }
-
- private void checkForField(XProperty member, PropertiesMetadata propertiesMetadata, String prefix, ConfigContext context) {
- org.hibernate.search.annotations.Field fieldAnn =
- member.getAnnotation( org.hibernate.search.annotations.Field.class );
- if ( fieldAnn != null ) {
- bindFieldAnnotation( member, propertiesMetadata, prefix, fieldAnn, context );
- }
- }
-
- private void checkForContainedIn(XProperty member, PropertiesMetadata propertiesMetadata) {
- ContainedIn containedAnn = member.getAnnotation( ContainedIn.class );
- if ( containedAnn != null ) {
- ReflectionHelper.setAccessible( member );
- propertiesMetadata.containedInGetters.add( member );
- }
- }
-
- private void checkForIndexedEmbedded(XProperty member, PropertiesMetadata propertiesMetadata, String prefix, Set<XClass> processedClasses, ConfigContext context) {
- IndexedEmbedded embeddedAnn = member.getAnnotation( IndexedEmbedded.class );
- if ( embeddedAnn != null ) {
- int oldMaxLevel = maxLevel;
- int potentialLevel = embeddedAnn.depth() + level;
- if ( potentialLevel < 0 ) {
- potentialLevel = Integer.MAX_VALUE;
- }
- maxLevel = potentialLevel > maxLevel ? maxLevel : potentialLevel;
- level++;
-
- XClass elementClass;
- if ( void.class == embeddedAnn.targetElement() ) {
- elementClass = member.getElementClass();
- }
- else {
- elementClass = reflectionManager.toXClass( embeddedAnn.targetElement() );
- }
- if ( maxLevel == Integer.MAX_VALUE //infinite
- && processedClasses.contains( elementClass ) ) {
- throw new SearchException(
- "Circular reference. Duplicate use of "
- + elementClass.getName()
- + " in root entity " + beanXClass.getName()
- + "#" + buildEmbeddedPrefix( prefix, embeddedAnn, member )
- );
- }
- if ( level <= maxLevel ) {
- processedClasses.add( elementClass ); //push
-
- ReflectionHelper.setAccessible( member );
- propertiesMetadata.embeddedGetters.add( member );
- PropertiesMetadata metadata = new PropertiesMetadata();
- propertiesMetadata.embeddedPropertiesMetadata.add( metadata );
- metadata.boost = getBoost( member, null );
- //property > entity analyzer
- Analyzer analyzer = getAnalyzer( member, context );
- metadata.analyzer = analyzer != null ? analyzer : propertiesMetadata.analyzer;
- String localPrefix = buildEmbeddedPrefix( prefix, embeddedAnn, member );
- initializeClass( elementClass, metadata, false, localPrefix, processedClasses, context );
- /**
- * We will only index the "expected" type but that's OK, HQL cannot do down-casting either
- */
- if ( member.isArray() ) {
- propertiesMetadata.embeddedContainers.add( PropertiesMetadata.Container.ARRAY );
- }
- else if ( member.isCollection() ) {
- if ( Map.class.equals( member.getCollectionClass() ) ) {
- //hum subclasses etc etc??
- propertiesMetadata.embeddedContainers.add( PropertiesMetadata.Container.MAP );
- }
- else {
- propertiesMetadata.embeddedContainers.add( PropertiesMetadata.Container.COLLECTION );
- }
- }
- else {
- propertiesMetadata.embeddedContainers.add( PropertiesMetadata.Container.OBJECT );
- }
-
- processedClasses.remove( elementClass ); //pop
- }
- else if ( log.isTraceEnabled() ) {
- String localPrefix = buildEmbeddedPrefix( prefix, embeddedAnn, member );
- log.trace( "depth reached, ignoring {}", localPrefix );
- }
-
- level--;
- maxLevel = oldMaxLevel; //set back the the old max level
- }
- }
-
- protected void checkDocumentId(XProperty member, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, ConfigContext context) {
- // TODO - HSEARCH-333
- // for a contained entity there is nothing to do here. This is really bad design since this protected method is called by the constructor and
- // overridden by DocumentBuilderIndexedEntity
- }
-
- /**
- * Determines the property name for the document id. It is either the name of the property itself or the
- * value of the name attribute of the <code>idAnnotation</code>.
- *
- * @param member the property used as id property.
- * @param idAnnotation the id annotation
- *
- * @return property name to be used as document id.
- */
- protected String getIdAttributeName(XProperty member, Annotation idAnnotation) {
- String name = null;
- try {
- Method m = idAnnotation.getClass().getMethod( "name" );
- name = ( String ) m.invoke( idAnnotation );
- }
- catch ( Exception e ) {
- // ignore
- }
-
- return ReflectionHelper.getAttributeName( member, name );
- }
-
- private void bindClassBridgeAnnotation(String prefix, PropertiesMetadata propertiesMetadata, ClassBridge ann, ConfigContext context) {
- String fieldName = prefix + ann.name();
- propertiesMetadata.classNames.add( fieldName );
- propertiesMetadata.classStores.add( ann.store() );
- propertiesMetadata.classIndexes.add( getIndex( ann.index() ) );
- propertiesMetadata.classTermVectors.add( getTermVector( ann.termVector() ) );
- propertiesMetadata.classBridges.add( BridgeFactory.extractType( ann ) );
- propertiesMetadata.classBoosts.add( ann.boost().value() );
-
- Analyzer analyzer = getAnalyzer( ann.analyzer(), context );
- if ( analyzer == null ) {
- analyzer = propertiesMetadata.analyzer;
- }
- if ( analyzer == null ) {
- throw new AssertionFailure( "Analyzer should not be undefined" );
- }
- addToScopedAnalyzer( fieldName, analyzer, ann.index() );
- }
-
- private void bindFieldAnnotation(XProperty member, PropertiesMetadata propertiesMetadata, String prefix, org.hibernate.search.annotations.Field fieldAnn, ConfigContext context) {
- ReflectionHelper.setAccessible( member );
- propertiesMetadata.fieldGetters.add( member );
- String fieldName = prefix + ReflectionHelper.getAttributeName( member, fieldAnn.name() );
- propertiesMetadata.fieldNames.add( fieldName );
- propertiesMetadata.fieldStore.add( fieldAnn.store() );
- propertiesMetadata.fieldIndex.add( getIndex( fieldAnn.index() ) );
- propertiesMetadata.fieldBoosts.add( getBoost( member, fieldAnn ) );
- propertiesMetadata.dynamicFieldBoosts.add( getDynamicBoost( member ) );
- propertiesMetadata.fieldTermVectors.add( getTermVector( fieldAnn.termVector() ) );
- propertiesMetadata.fieldBridges.add( BridgeFactory.guessType( fieldAnn, member, reflectionManager ) );
-
- // Field > property > entity analyzer
- Analyzer analyzer = getAnalyzer( fieldAnn.analyzer(), context );
- if ( analyzer == null ) {
- analyzer = getAnalyzer( member, context );
- }
- addToScopedAnalyzer( fieldName, analyzer, fieldAnn.index() );
- }
-
- protected void addToScopedAnalyzer(String fieldName, Analyzer analyzer, Index index) {
- if ( index == Index.TOKENIZED) {
- if ( analyzer != null ) {
- this.analyzer.addScopedAnalyzer( fieldName, analyzer );
- }
- }
- else {
- //no analyzer is used, add a fake one for queries
- this.analyzer.addScopedAnalyzer( fieldName, passThroughAnalyzer );
- }
- }
-
- protected Float getBoost(XProperty member, org.hibernate.search.annotations.Field fieldAnn) {
- float computedBoost = 1.0f;
- Boost boostAnn = member.getAnnotation( Boost.class );
- if ( boostAnn != null ) {
- computedBoost = boostAnn.value();
- }
- if ( fieldAnn != null ) {
- computedBoost *= fieldAnn.boost().value();
- }
- return computedBoost;
- }
-
- protected BoostStrategy getDynamicBoost(XProperty member) {
- DynamicBoost boostAnnotation = member.getAnnotation( DynamicBoost.class );
- if ( boostAnnotation == null ) {
- return new DefaultBoostStrategy();
- }
-
- Class<? extends BoostStrategy> boostStrategyClass = boostAnnotation.impl();
- BoostStrategy strategy;
- try {
- strategy = boostStrategyClass.newInstance();
- }
- catch ( Exception e ) {
- throw new SearchException(
- "Unable to instantiate boost strategy implementation: " + boostStrategyClass.getName()
- );
- }
- return strategy;
- }
-
- private String buildEmbeddedPrefix(String prefix, IndexedEmbedded embeddedAnn, XProperty member) {
- String localPrefix = prefix;
- if ( ".".equals( embeddedAnn.prefix() ) ) {
- //default to property name
- localPrefix += member.getName() + '.';
- }
- else {
- localPrefix += embeddedAnn.prefix();
- }
- return localPrefix;
- }
-
- protected Field.TermVector getTermVector(TermVector vector) {
- switch ( vector ) {
- case NO:
- return Field.TermVector.NO;
- case YES:
- return Field.TermVector.YES;
- case WITH_OFFSETS:
- return Field.TermVector.WITH_OFFSETS;
- case WITH_POSITIONS:
- return Field.TermVector.WITH_POSITIONS;
- case WITH_POSITION_OFFSETS:
- return Field.TermVector.WITH_POSITIONS_OFFSETS;
- default:
- throw new AssertionFailure( "Unexpected TermVector: " + vector );
- }
- }
-
- protected Field.Index getIndex(Index index) {
- switch ( index ) {
- case NO:
- return Field.Index.NO;
- case NO_NORMS:
- return Field.Index.NOT_ANALYZED_NO_NORMS;
- case TOKENIZED:
- return Field.Index.ANALYZED;
- case UN_TOKENIZED:
- return Field.Index.NOT_ANALYZED;
- default:
- throw new AssertionFailure( "Unexpected Index: " + index );
- }
- }
-
- protected float getBoost(XClass element) {
- float boost = 1.0f;
- if ( element == null ) {
- return boost;
- }
- Boost boostAnnotation = element.getAnnotation( Boost.class );
- if ( boostAnnotation != null ) {
- boost = boostAnnotation.value();
- }
- return boost;
- }
-
- protected BoostStrategy getDynamicBoost(XClass element) {
- if ( element == null ) {
- return null;
- }
- DynamicBoost boostAnnotation = element.getAnnotation( DynamicBoost.class );
- if ( boostAnnotation == null ) {
- return new DefaultBoostStrategy();
- }
-
- Class<? extends BoostStrategy> boostStrategyClass = boostAnnotation.impl();
- BoostStrategy strategy;
- try {
- strategy = boostStrategyClass.newInstance();
- }
- catch ( Exception e ) {
- throw new SearchException(
- "Unable to instantiate boost strategy implementation: " + boostStrategyClass.getName()
- );
- }
- return strategy;
- }
-
public void addWorkToQueue(Class<T> entityClass, T entity, Serializable id, WorkType workType, List<LuceneWork> queue, SearchFactoryImplementor searchFactoryImplementor) {
/**
* When references are changed, either null or another one, we expect dirty checking to be triggered (both sides
@@ -624,224 +71,4 @@
processContainedInInstances( entity, queue, metadata, searchFactoryImplementor );
}
}
-
- /**
- * If we have a work instance we have to check whether the instance to be indexed is contained in any other indexed entities.
- *
- * @param instance The instance to be indexed
- * @param queue the current work queue
- * @param metadata metadata
- * @param searchFactoryImplementor the current session
- */
- private <T> void processContainedInInstances(Object instance, List<LuceneWork> queue, PropertiesMetadata metadata, SearchFactoryImplementor searchFactoryImplementor) {
- for ( int i = 0; i < metadata.containedInGetters.size(); i++ ) {
- XMember member = metadata.containedInGetters.get( i );
- Object value = ReflectionHelper.getMemberValue( instance, member );
-
- if ( value == null ) {
- continue;
- }
-
- if ( member.isArray() ) {
- @SuppressWarnings("unchecked")
- T[] array = ( T[] ) value;
- for ( T arrayValue : array ) {
- processSingleContainedInInstance( queue, searchFactoryImplementor, arrayValue );
- }
- }
- else if ( member.isCollection() ) {
- Collection<T> collection = null;
- try {
- collection = getActualCollection( member, value );
- collection.size(); //load it
- }
- catch ( Exception e ) {
- if ( e.getClass().getName().contains( "org.hibernate.LazyInitializationException" ) ) {
- /* A deleted entity not having its collection initialized
- * leads to a LIE because the colleciton is no longer attached to the session
- *
- * But that's ok as the collection update event has been processed before
- * or the fk would have been cleared and thus triggering the cleaning
- */
- collection = null;
- }
- }
- if ( collection != null ) {
- for ( T collectionValue : collection ) {
- processSingleContainedInInstance( queue, searchFactoryImplementor, collectionValue );
- }
- }
- }
- else {
- processSingleContainedInInstance( queue, searchFactoryImplementor, value );
- }
- }
- }
-
- /**
- * A {@code XMember } instance treats a map as a collection as well in which case the map values are returned as
- * collection.
- *
- * @param member The member instance
- * @param value The value
- *
- * @return The {@code value} casted to collection or in case of {@code value} being a map the map values as collection.
- */
- private <T> Collection<T> getActualCollection(XMember member, Object value) {
- Collection<T> collection;
- if ( Map.class.equals( member.getCollectionClass() ) ) {
- //hum
- @SuppressWarnings("unchecked")
- Collection<T> tmpCollection = ( ( Map<?, T> ) value ).values();
- collection = tmpCollection;
- }
- else {
- @SuppressWarnings("unchecked")
- Collection<T> tmpCollection = ( Collection<T> ) value;
- collection = tmpCollection;
- }
- return collection;
- }
-
- private <T> void processSingleContainedInInstance(List<LuceneWork> queue, SearchFactoryImplementor searchFactoryImplementor, T value) {
- Class<T> valueClass = HibernateHelper.getClass( value );
- DocumentBuilderIndexedEntity<T> builderIndexedEntity =
- searchFactoryImplementor.getDocumentBuilderIndexedEntity( valueClass );
-
- // it could be we have a nested @IndexedEmbedded chain in which case we have to find the top level @Indexed entities
- if ( builderIndexedEntity == null ) {
- DocumentBuilderContainedEntity<T> builderContainedEntity =
- searchFactoryImplementor.getDocumentBuilderContainedEntity( valueClass );
- if ( builderContainedEntity != null ) {
- processContainedInInstances( value, queue, builderContainedEntity.metadata, searchFactoryImplementor );
- }
- }
- else {
- addWorkForEmbeddedValue( value, queue, valueClass, builderIndexedEntity, searchFactoryImplementor );
- }
- }
-
- /**
- * Create a {@code LuceneWork} instance of the entity which needs updating due to the embedded instance change.
- *
- * @param value The value to index
- * @param queue The current (Lucene) work queue
- * @param valueClass The class of the value
- * @param builderIndexedEntity the document builder for the entity which needs updating due to a update event of the embedded instance
- * @param searchFactoryImplementor the search factory.
- */
- private <T> void addWorkForEmbeddedValue(T value, List<LuceneWork> queue, Class<T> valueClass,
- DocumentBuilderIndexedEntity<T> builderIndexedEntity, SearchFactoryImplementor searchFactoryImplementor) {
- Serializable id = ( Serializable ) ReflectionHelper.getMemberValue( value, builderIndexedEntity.idGetter );
- if ( id != null) {
- builderIndexedEntity.addWorkToQueue( valueClass, value, id, WorkType.UPDATE, queue, searchFactoryImplementor );
- }
- else {
- //this is an indexed entity that is not yet persisted but should be reached by cascade
- // and thus raise an Hibernate Core event leading to its indexing by Hibernate Search
- // => no need to do anything here
- }
- }
-
- public Analyzer getAnalyzer() {
- return analyzer;
- }
-
- public void postInitialize(Set<Class<?>> indexedClasses) {
- //we initialize only once because we no longer have a reference to the reflectionManager
- //in theory
- Class<?> plainClass = beanClass;
- if ( entityState == EntityState.NON_INDEXABLE ) {
- throw new AssertionFailure( "A non indexed entity is post processed" );
- }
- Set<Class<?>> tempMappedSubclasses = new HashSet<Class<?>>();
- //together with the caller this creates a o(2), but I think it's still faster than create the up hierarchy for each class
- for ( Class<?> currentClass : indexedClasses ) {
- if ( plainClass != currentClass && plainClass.isAssignableFrom( currentClass ) ) {
- tempMappedSubclasses.add( currentClass );
- }
- }
- this.mappedSubclasses = Collections.unmodifiableSet( tempMappedSubclasses );
- Class<?> superClass = plainClass.getSuperclass();
- this.isRoot = true;
- while ( superClass != null ) {
- if ( indexedClasses.contains( superClass ) ) {
- this.isRoot = false;
- break;
- }
- superClass = superClass.getSuperclass();
- }
- this.reflectionManager = null;
- }
-
- public EntityState getEntityState() {
- return entityState;
- }
-
- public Set<Class<?>> getMappedSubclasses() {
- return mappedSubclasses;
- }
-
- /**
- * Wrapper class containing all the meta data extracted out of a single entity.
- * All field/property related properties are kept in lists. Retrieving all metadata for a given
- * property/field means accessing all the lists with the same index.
- */
- protected static class PropertiesMetadata {
- public float boost;
- public Analyzer analyzer;
- public Discriminator discriminator;
- public XMember discriminatorGetter;
- public BoostStrategy classBoostStrategy;
-
- public final List<String> fieldNames = new ArrayList<String>();
- public final List<XMember> fieldGetters = new ArrayList<XMember>();
- public final List<FieldBridge> fieldBridges = new ArrayList<FieldBridge>();
- public final List<Store> fieldStore = new ArrayList<Store>();
- public final List<Field.Index> fieldIndex = new ArrayList<Field.Index>();
- public final List<Float> fieldBoosts = new ArrayList<Float>();
- public final List<BoostStrategy> dynamicFieldBoosts = new ArrayList<BoostStrategy>();
-
- public final List<Field.TermVector> fieldTermVectors = new ArrayList<Field.TermVector>();
- public final List<XMember> embeddedGetters = new ArrayList<XMember>();
- public final List<PropertiesMetadata> embeddedPropertiesMetadata = new ArrayList<PropertiesMetadata>();
- public final List<Container> embeddedContainers = new ArrayList<Container>();
- public final List<XMember> containedInGetters = new ArrayList<XMember>();
-
- public final List<String> classNames = new ArrayList<String>();
- public final List<Store> classStores = new ArrayList<Store>();
- public final List<Field.Index> classIndexes = new ArrayList<Field.Index>();
- public final List<FieldBridge> classBridges = new ArrayList<FieldBridge>();
- public final List<Field.TermVector> classTermVectors = new ArrayList<Field.TermVector>();
- public final List<Float> classBoosts = new ArrayList<Float>();
-
- public enum Container {
- OBJECT,
- COLLECTION,
- MAP,
- ARRAY
- }
-
- protected LuceneOptions getClassLuceneOptions(int i) {
- return new LuceneOptionsImpl(
- classStores.get( i ),
- classIndexes.get( i ), classTermVectors.get( i ), classBoosts.get( i )
- );
- }
-
- protected LuceneOptions getFieldLuceneOptions(int i, Object value) {
- LuceneOptions options;
- options = new LuceneOptionsImpl(
- fieldStore.get( i ),
- fieldIndex.get( i ),
- fieldTermVectors.get( i ),
- fieldBoosts.get( i ) * dynamicFieldBoosts.get( i ).defineBoost( value )
- );
- return options;
- }
-
- protected float getClassBoost(Object value) {
- return boost * classBoostStrategy.defineBoost( value );
- }
- }
}
Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java 2010-09-23 14:54:28 UTC (rev 20691)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java 2010-09-24 13:53:55 UTC (rev 20692)
@@ -26,6 +26,7 @@
import java.io.Serializable;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -47,7 +48,6 @@
import org.hibernate.annotations.common.reflection.XMember;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.annotations.common.util.ReflectHelper;
-import org.hibernate.proxy.HibernateProxy;
import org.hibernate.search.SearchException;
import org.hibernate.search.analyzer.Discriminator;
import org.hibernate.search.annotations.DocumentId;
@@ -83,7 +83,7 @@
* @author Richard Hallier
* @author Hardy Ferentschik
*/
-public class DocumentBuilderIndexedEntity<T> extends DocumentBuilderContainedEntity<T> {
+public class DocumentBuilderIndexedEntity<T> extends AbstractDocumentBuilder<T> {
private static final Logger log = LoggerFactory.make();
/**
@@ -153,9 +153,7 @@
this.shardingStrategy = shardingStrategy;
}
- protected void init(XClass clazz, ConfigContext context) {
- super.init( clazz, context );
-
+ protected void initSubClass(XClass clazz, ConfigContext context) {
// special case @ProvidedId
ProvidedId provided = findProvidedId( clazz, reflectionManager );
if ( provided != null ) {
@@ -177,6 +175,10 @@
}
}
+ protected void subClassSpecificCheck(XProperty member, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, ConfigContext context) {
+ checkDocumentId( member, propertiesMetadata, isRoot, prefix, context );
+ }
+
protected void checkDocumentId(XProperty member, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, ConfigContext context) {
Annotation idAnnotation = getIdAnnotation( member, context );
if ( idAnnotation != null ) {
@@ -278,8 +280,6 @@
return id;
}
- //TODO could we use T instead of EntityClass?
-
public void addWorkToQueue(Class<T> entityClass, T entity, Serializable id, WorkType workType, List<LuceneWork> queue, SearchFactoryImplementor searchFactoryImplementor) {
//TODO with the caller loop we are in a n^2: optimize it using a HashMap for work recognition
@@ -358,7 +358,9 @@
throw new AssertionFailure( "Unknown WorkType: " + workType );
}
- super.addWorkToQueue( entityClass, entity, id, workType, queue, searchFactoryImplementor );
+ if ( workType.searchForContainers() ) {
+ processContainedInInstances( entity, queue, metadata, searchFactoryImplementor );
+ }
}
public AddLuceneWork createAddWork(Class<T> entityClass, T entity, Serializable id, String idInString, boolean isBatch) {
@@ -424,7 +426,7 @@
}
// needed for field access: I cannot work in the proxied version
- Object unproxiedInstance = unproxy( instance );
+ Object unproxiedInstance = HibernateHelper.unproxy( instance );
// process the class bridges
for ( int i = 0; i < propertiesMetadata.classBridges.size(); i++ ) {
@@ -528,16 +530,6 @@
}
}
- private Object unproxy(Object value) {
- //FIXME this service should be part of Core?
- if ( value instanceof HibernateProxy ) {
- // .getImplementation() initializes the data by side effect
- value = ( ( HibernateProxy ) value ).getHibernateLazyInitializer()
- .getImplementation();
- }
- return value;
- }
-
public String getIdentifierName() {
return idGetter.getName();
}
@@ -594,6 +586,8 @@
* <p/>
* If the id is provided, we can't extract it from the entity
*
+ * @param entity The entity for which to return the id. Cannot be {@code null}.
+ *
* @return entity id
*/
public Serializable getId(Object entity) {
@@ -804,4 +798,26 @@
}
}
}
+
+ /**
+ * Determines the property name for the document id. It is either the name of the property itself or the
+ * value of the name attribute of the <code>idAnnotation</code>.
+ *
+ * @param member the property used as id property.
+ * @param idAnnotation the id annotation
+ *
+ * @return property name to be used as document id.
+ */
+ private String getIdAttributeName(XProperty member, Annotation idAnnotation) {
+ String name = null;
+ try {
+ Method m = idAnnotation.getClass().getMethod( "name" );
+ name = ( String ) m.invoke( idAnnotation );
+ }
+ catch ( Exception e ) {
+ // ignore
+ }
+
+ return ReflectionHelper.getAttributeName( member, name );
+ }
}
Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/util/HibernateHelper.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/util/HibernateHelper.java 2010-09-23 14:54:28 UTC (rev 20691)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/util/HibernateHelper.java 2010-09-24 13:53:55 UTC (rev 20692)
@@ -25,6 +25,7 @@
package org.hibernate.search.util;
import org.hibernate.Hibernate;
+import org.hibernate.proxy.HibernateProxy;
import org.hibernate.search.backend.Work;
/**
@@ -39,9 +40,7 @@
* In case of Hibernate proxies, return the entity type rather than the proxy's
*/
public static <T> Class<T> getClass(T entity) {
- @SuppressWarnings("unchecked")
- final Class<T> type = Hibernate.getClass( entity );
- return type;
+ return ( Class<T> ) Hibernate.getClass( entity );
}
public static void initialize(Object entity) {
@@ -57,4 +56,11 @@
work.getEntityClass() :
getClass( work.getEntity() );
}
+
+ public static Object unproxy(Object value) {
+ if ( value instanceof HibernateProxy ) {
+ value = ( ( HibernateProxy ) value ).getHibernateLazyInitializer().getImplementation();
+ }
+ return value;
+ }
}
14 years, 5 months
Hibernate SVN: r20691 - search/trunk/hibernate-search/src/main/docbook/en-US/modules.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-09-23 10:54:28 -0400 (Thu, 23 Sep 2010)
New Revision: 20691
Modified:
search/trunk/hibernate-search/src/main/docbook/en-US/modules/advanced-features.xml
Log:
HSEARCH-586 made the JMX chapter a monitoring one
Modified: search/trunk/hibernate-search/src/main/docbook/en-US/modules/advanced-features.xml
===================================================================
--- search/trunk/hibernate-search/src/main/docbook/en-US/modules/advanced-features.xml 2010-09-23 14:53:58 UTC (rev 20690)
+++ search/trunk/hibernate-search/src/main/docbook/en-US/modules/advanced-features.xml 2010-09-23 14:54:28 UTC (rev 20691)
@@ -33,13 +33,13 @@
<para>The <classname>SearchFactory</classname> object keeps track of the
underlying Lucene resources for Hibernate Search, it's also a convenient
way to access Lucene natively. The <classname>SearchFactory</classname>
- can be accessed from a <classname>FullTextSession</classname>:</para>
+ can be accessed from a<classname>FullTextSession</classname>:</para>
<example>
<title>Accessing the <classname>SearchFactory</classname></title>
<programlisting>FullTextSession fullTextSession = Search.getFullTextSession(regularSession);
-SearchFactory searchFactory = fullTextSession.getSearchFactory();</programlisting>
+SearchFactory searchFactory = fullTextSession.getSearchFactory(); </programlisting>
</example>
</section>
@@ -53,15 +53,15 @@
<classname>DirectoryProvider</classname>s per indexed class. One directory
provider can be shared amongst several indexed classes if the classes
share the same underlying index directory. While usually not the case, a
- given entity can have several <classname>DirectoryProvider</classname>s if
- the index is sharded (see <xref
+ given entity can have several<classname>DirectoryProvider</classname>s if
+ the index is sharded (see<xref
linkend="search-configuration-directory-sharding" />).</para>
<example>
<title>Accessing the Lucene <classname>Directory</classname></title>
<programlisting>DirectoryProvider[] provider = searchFactory.getDirectoryProviders(Order.class);
-org.apache.lucene.store.Directory directory = provider[0].getDirectory();</programlisting>
+org.apache.lucene.store.Directory directory = provider[0].getDirectory(); </programlisting>
</example>
<para>In this example, directory points to the lucene index storing
@@ -73,7 +73,7 @@
<section>
<title>Using an IndexReader</title>
- <para>Queries in Lucene are executed on an <literal>IndexReader</literal>.
+ <para>Queries in Lucene are executed on an<literal>IndexReader</literal>.
Hibernate Search caches all index readers to maximize performance. Your
code can access this cached resources, but you have to follow some "good
citizen" rules.</para>
@@ -88,14 +88,14 @@
IndexReader reader = readerProvider.openReader(orderProvider, clientProvider);
try {
- //do read-only operations on the reader
+ //do read-only operations on the reader
}
finally {
- readerProvider.closeReader(reader);
-}</programlisting>
+ readerProvider.closeReader(reader);
+} </programlisting>
</example>
- <para>The ReaderProvider (described in <xref
+ <para>The ReaderProvider (described in<xref
linkend="search-architecture-readerstrategy" />), will open an IndexReader
on top of the index(es) referenced by the directory providers. Because
this <classname>IndexReader</classname> is shared amongst several clients,
@@ -130,10 +130,10 @@
methods defined in this class match the factors of the following formula
calculating the score of query q for document d:</para>
- <para><emphasis role="bold">score(q,d) = coord(q,d) · queryNorm(q) ·
- ∑<subscript>t in q</subscript> ( tf(t in d) ·
- idf(t)<superscript>2</superscript> · t.getBoost() · norm(t,d)
- )</emphasis></para>
+ <para><emphasis role="bold">score(q,d) = coord(q,d) · queryNorm(q) · ∑
+ <subscript>t in q</subscript> ( tf(t in d) · idf(t)
+ <superscript>2</superscript> · t.getBoost() · norm(t,d) )
+ </emphasis></para>
<para><informaltable align="left" width="">
<tgroup cols="2">
@@ -187,7 +187,7 @@
</row>
</tbody>
</tgroup>
- </informaltable>It is beyond the scope of this manual to explain this
+ </informaltable> It is beyond the scope of this manual to explain this
formula in more detail. Please refer to
<classname>Similarity</classname>'s Javadocs for more information.</para>
@@ -198,76 +198,86 @@
<constant>hibernate.search.similarity</constant>. The default value is
<classname>org.apache.lucene.search.DefaultSimilarity</classname>.
Additionally you can override the default similarity on class level using
- the <literal>@Similarity</literal> annotation.<programlisting>@Entity
+ the <literal>@Similarity</literal> annotation. <programlisting>@Entity
@Indexed
<emphasis role="bold">@Similarity(impl = DummySimilarity.class)</emphasis>
public class Book {
- ...
-}</programlisting>As an example, let's assume it is not important how often a
- term appears in a document. Documents with a single occurrence of the term
- should be scored the same as documents with multiple occurrences. In this
- case your custom implementation of the method <methodname>tf(float
- freq)</methodname> should return 1.0.</para>
-
- <warning><para>When two entities share the same index they must declare the
- same <classname>Similarity</classname> implementation. Classes in the same
- class hierarchy always share the index, so it's not allowed to override the
- <classname>Similarity</classname> implementation in a subtype.</para></warning>
-
+...
+} </programlisting> As an example, let's assume it is not important
+ how often a term appears in a document. Documents with a single occurrence
+ of the term should be scored the same as documents with multiple
+ occurrences. In this case your custom implementation of the method
+ <methodname>tf(float freq) </methodname> should return 1.0.</para>
+
+ <warning>
+ <para>When two entities share the same index they must declare the same
+ <classname>Similarity</classname> implementation. Classes in the same
+ class hierarchy always share the index, so it's not allowed to override
+ the <classname>Similarity</classname> implementation in a
+ subtype.</para>
+ </warning>
</section>
- <section id="search-jmx">
- <title>JMX integration</title>
+ <section id="section-monitoring">
+ <title>Monitoring</title>
- <para>Hibernate Search offers, similar to Hibernate Core, the ability to
- manage several aspects of Search via JMX. In order to use this functionality
- you have to set the <literal>hibernate.search.jmx_enabled</literal> property
- in your configuration. Setting this property will give you access to the
- Mbeans <classname>StatisticsInfoMBean</classname>,
- <classname>IndexControlMBean</classname> and
- <classname>IndexingProgressMonitorMBean</classname>. Depending on the
- configuration and state of Search not all beans are available at all times.
- Lets have a closer look at the different MBeans.</para>
+ <para>Hibernate Search offers access to a
+ <classname>Statistics</classname> object via
+ <methodname>SearchFactory.getStatistics()</methodname>. It allows you for
+ example to determine which classes are indexed and how many entities are
+ in the index. This information is always available. However, by specifying
+ the <literal>hibernate.search.generate_statistics</literal> property in
+ your configuration you can also collect total and average Lucene query and
+ object loading timings. </para>
- <section>
- <title>StatisticsInfoMBean</title>
+ <section>
+ <title>JMX</title>
- <para>This MBean gives you access to information like the total number of
- indexed entities as well as total and average Lucene query and object
- loading times. Setting the property
- <literal>hibernate.search.jmx_enabled</literal> will automatically
- register the MBean, however query and object loading timings will not be
- taken unless you also specify
- <literal>hibernate.search.generate_statistics</literal> in your
- configuration. The statistics offered by
- <classname>StatisticsInfoMBean</classname> are also available
- programmatically via <code>SearchFactory.getStatistics()</code>.</para>
- </section>
+ <para>You can also enable access to the statistics via JMX. Setting the
+ property <literal>hibernate.search.jmx_enabled</literal> will
+ automatically register the <classname>StatisticsInfoMBean</classname>.
+ Depending on your the configuration the
+ <classname>IndexControlMBean</classname> and
+ <classname>IndexingProgressMonitorMBean</classname> will also be
+ registered. Lets have a closer look at the different MBeans.<tip>
+ <para>If you want to access your JMX beans remotely via JConsole
+ make sure to set the system property
+ <varname>com.sun.management.jmxremote</varname> to
+ <constant>true</constant>.</para>
+ </tip></para>
- <section>
- <title>IndexControlMBean</title>
+ <section>
+ <title>StatisticsInfoMBean</title>
- <para>This MBean allows to build, optimize and purge the index for a given
- entity. Indexing occurs via the mass indexing API (see <xref
- linkend="search-batchindex-massindexer" />). A requirement for this bean
- to be registered in JMX is, that the Hibernate
- <classname>SessionFactory</classname> is bound to JNDI via the
- <literal>hibernate.session_factory_name</literal> property. Refer to the
- Hibernate Core manual for more information on how to configure JNDI. The
- <classname>IndexControlMBean</classname> and its API have to be considered
- experimental.</para>
- </section>
+ <para>This MBean gives you access to <classname>Statistics</classname>
+ object as desribed in the previous section.</para>
+ </section>
- <section>
- <title>IndexingProgressMonitorMBean</title>
+ <section>
+ <title>IndexControlMBean</title>
- <para>This MBean is an implementation
- <classname>MassIndexerProgressMonitor</classname> interface. If
- <literal>hibernate.search.jmx_enabled</literal> is enabled and the mass
- indexer API is used the indexing progress can be followed via this bean.
- The bean will only be bound to JMX while indexing is in progress. Once
- indexing is completed the MBean is not longer available.</para>
+ <para>This MBean allows to build, optimize and purge the index for a
+ given entity. Indexing occurs via the mass indexing API (see<xref
+ linkend="search-batchindex-massindexer" />). A requirement for this
+ bean to be registered in JMX is, that the Hibernate
+ <classname>SessionFactory</classname> is bound to JNDI via the
+ <literal>hibernate.session_factory_name</literal> property. Refer to
+ the Hibernate Core manual for more information on how to configure
+ JNDI. The <classname>IndexControlMBean</classname> and its API are for
+ now experimental.</para>
+ </section>
+
+ <section>
+ <title>IndexingProgressMonitorMBean</title>
+
+ <para>This MBean is an implementation
+ <classname>MassIndexerProgressMonitor</classname> interface. If
+ <literal>hibernate.search.jmx_enabled</literal> is enabled and the
+ mass indexer API is used the indexing progress can be followed via
+ this bean. The bean will only be bound to JMX while indexing is in
+ progress. Once indexing is completed the MBean is not longer
+ available.</para>
+ </section>
+ </section>
</section>
-</section>
-
</chapter>
14 years, 5 months