From 7718fe0cb4412fba6b26f8c764fd6c9231fa690b Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Thu, 4 Nov 2010 15:55:14 +0100 Subject: [PATCH] HSEARCH-115 Moving static DocumentBuilderIndexedEntity methods into DocumentBuilderHelper --- .../engine/AbstractDocumentBuilder.java | 11 +- .../search/engine/DocumentBuilderHelper.java | 206 +++++++++++++ .../engine/DocumentBuilderIndexedEntity.java | 279 +++++------------- .../search/engine/DocumentExtractor.java | 8 +- 4 files changed, 288 insertions(+), 216 deletions(-) create mode 100644 hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderHelper.java diff --git a/hibernate-search/src/main/java/org/hibernate/search/engine/AbstractDocumentBuilder.java b/hibernate-search/src/main/java/org/hibernate/search/engine/AbstractDocumentBuilder.java index 4823173877d..d6d707fedc7 100644 --- a/hibernate-search/src/main/java/org/hibernate/search/engine/AbstractDocumentBuilder.java +++ b/hibernate-search/src/main/java/org/hibernate/search/engine/AbstractDocumentBuilder.java @@ -96,11 +96,12 @@ public abstract class AbstractDocumentBuilder implements DocumentBuilder { private Analyzer passThroughAnalyzer = new PassThroughAnalyzer(); /** - * Constructor used on contained entities not annotated with @Indexed themselves. + * Constructor used on contained entities not annotated with {@code @Indexed} themselves. * - * @param xClass The class for which to build a DocumentBuilderContainedEntity. - * @param context Handle to default configuration settings. - * @param reflectionManager Reflection manager to use for processing the annotations. + * @param xClass The class for which to build a {@code}DocumentBuilderContainedEntity} + * @param context Handle to default configuration settings + * @param similarity The index level similarity + * @param reflectionManager Reflection manager to use for processing the annotations */ public AbstractDocumentBuilder(XClass xClass, ConfigContext context, Similarity similarity, ReflectionManager reflectionManager) { @@ -760,7 +761,7 @@ private void processSingleContainedInInstance(List queue, Search */ private void addWorkForEmbeddedValue(T value, List queue, Class valueClass, DocumentBuilderIndexedEntity builderIndexedEntity, SearchFactoryImplementor searchFactoryImplementor) { - Serializable id = (Serializable) ReflectionHelper.getMemberValue( value, builderIndexedEntity.idGetter ); + Serializable id = (Serializable) ReflectionHelper.getMemberValue( value, builderIndexedEntity.getIdGetter() ); if ( id != null ) { builderIndexedEntity.addWorkToQueue( valueClass, value, id, WorkType.UPDATE, queue, searchFactoryImplementor diff --git a/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderHelper.java b/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderHelper.java new file mode 100644 index 00000000000..8a99f2b837d --- /dev/null +++ b/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderHelper.java @@ -0,0 +1,206 @@ +/* + * 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 org.apache.lucene.document.Document; +import org.slf4j.Logger; + +import org.hibernate.annotations.common.reflection.XMember; +import org.hibernate.annotations.common.util.ReflectHelper; +import org.hibernate.search.SearchException; +import org.hibernate.search.annotations.Store; +import org.hibernate.search.bridge.FieldBridge; +import org.hibernate.search.bridge.TwoWayFieldBridge; +import org.hibernate.search.bridge.util.ContextualException2WayBridge; +import org.hibernate.search.util.LoggerFactory; + +/** + * @author Hardy Ferentschik + */ +public final class DocumentBuilderHelper { + private static final Logger log = LoggerFactory.make(); + + private DocumentBuilderHelper() { + } + + public static Class getDocumentClass(Document document) { + String className = document.get( DocumentBuilder.CLASS_FIELDNAME ); + try { + return ReflectHelper.classForName( className ); + } + catch ( ClassNotFoundException e ) { + throw new SearchException( "Unable to load indexed class: " + className, e ); + } + } + + public static Serializable getDocumentId(SearchFactoryImplementor searchFactoryImplementor, Class clazz, Document document) { + DocumentBuilderIndexedEntity builderIndexedEntity = searchFactoryImplementor.getDocumentBuilderIndexedEntity( + clazz + ); + if ( builderIndexedEntity == null ) { + throw new SearchException( "No Lucene configuration set up for: " + clazz.getName() ); + } + + + final TwoWayFieldBridge fieldBridge = builderIndexedEntity.getIdBridge(); + final String fieldName = builderIndexedEntity.getIdKeywordName(); + ContextualException2WayBridge contextualBridge = new ContextualException2WayBridge(); + contextualBridge + .setClass( clazz ) + .setFieldName( fieldName ) + .setFieldBridge( fieldBridge ) + .pushMethod( "identifier" ); + return (Serializable) contextualBridge.get( fieldName, document ); + } + + public static String getDocumentIdName(SearchFactoryImplementor searchFactoryImplementor, Class clazz) { + DocumentBuilderIndexedEntity builderIndexedEntity = searchFactoryImplementor.getDocumentBuilderIndexedEntity( + clazz + ); + if ( builderIndexedEntity == null ) { + throw new SearchException( "No Lucene configuration set up for: " + clazz.getName() ); + } + return builderIndexedEntity.getIdentifierName(); + } + + public static Object[] getDocumentFields(SearchFactoryImplementor searchFactoryImplementor, Class clazz, Document document, String[] fields) { + DocumentBuilderIndexedEntity builderIndexedEntity = searchFactoryImplementor.getDocumentBuilderIndexedEntity( + clazz + ); + if ( builderIndexedEntity == null ) { + throw new SearchException( "No Lucene configuration set up for: " + clazz.getName() ); + } + final int fieldNbr = fields.length; + Object[] result = new Object[fieldNbr]; + ContextualException2WayBridge contextualBridge = new ContextualException2WayBridge(); + contextualBridge.setClass( clazz ); + if ( builderIndexedEntity.getIdKeywordName() != null ) { + final XMember member = builderIndexedEntity.getIdGetter(); + if ( member != null ) { + contextualBridge.pushMethod( member.getName() ); + } + populateResult( + builderIndexedEntity.getIdKeywordName(), + builderIndexedEntity.getIdBridge(), + Store.YES, + fields, + result, + document, + contextualBridge + ); + if ( member != null ) { + contextualBridge.popMethod(); + } + } + + final AbstractDocumentBuilder.PropertiesMetadata metadata = builderIndexedEntity.metadata; + processFieldsForProjection( metadata, fields, result, document, contextualBridge ); + return result; + } + + public static void populateResult(String fieldName, FieldBridge fieldBridge, Store store, + String[] fields, Object[] result, Document document, ContextualException2WayBridge contextualBridge) { + int matchingPosition = getFieldPosition( fields, fieldName ); + if ( matchingPosition != -1 ) { + //TODO make use of an isTwoWay() method + if ( store != Store.NO && TwoWayFieldBridge.class.isAssignableFrom( fieldBridge.getClass() ) ) { + contextualBridge.setFieldName( fieldName ).setFieldBridge( (TwoWayFieldBridge) fieldBridge ); + result[matchingPosition] = contextualBridge.get( fieldName, document ); + if ( log.isTraceEnabled() ) { + log.trace( "Field {} projected as {}", fieldName, result[matchingPosition] ); + } + } + else { + if ( store == Store.NO ) { + throw new SearchException( "Projecting an unstored field: " + fieldName ); + } + else { + throw new SearchException( "FieldBridge is not a TwoWayFieldBridge: " + fieldBridge.getClass() ); + } + } + } + } + + public static void processFieldsForProjection(AbstractDocumentBuilder.PropertiesMetadata metadata, String[] fields, Object[] result, Document document, ContextualException2WayBridge contextualBridge) { + //process base fields + final int nbrFoEntityFields = metadata.fieldNames.size(); + for ( int index = 0; index < nbrFoEntityFields; index++ ) { + final String fieldName = metadata.fieldNames.get( index ); + contextualBridge.pushMethod( metadata.fieldGetters.get( index ).getName() ); + populateResult( + fieldName, + metadata.fieldBridges.get( index ), + metadata.fieldStore.get( index ), + fields, + result, + document, + contextualBridge + ); + contextualBridge.popMethod(); + } + + //process fields of embedded + final int nbrOfEmbeddedObjects = metadata.embeddedPropertiesMetadata.size(); + for ( int index = 0; index < nbrOfEmbeddedObjects; index++ ) { + //there is nothing we can do for collections + if ( metadata.embeddedContainers + .get( index ) == AbstractDocumentBuilder.PropertiesMetadata.Container.OBJECT ) { + contextualBridge.pushMethod( metadata.embeddedGetters.get( index ).getName() ); + processFieldsForProjection( + metadata.embeddedPropertiesMetadata.get( index ), fields, result, document, contextualBridge + ); + contextualBridge.popMethod(); + } + } + + //process class bridges + final int nbrOfClassBridges = metadata.classBridges.size(); + for ( int index = 0; index < nbrOfClassBridges; index++ ) { + populateResult( + metadata.classNames.get( index ), + metadata.classBridges.get( index ), + metadata.classStores.get( index ), + fields, + result, + document, + contextualBridge + ); + } + } + + public static int getFieldPosition(String[] fields, String fieldName) { + int fieldNbr = fields.length; + for ( int index = 0; index < fieldNbr; index++ ) { + if ( fieldName.equals( fields[index] ) ) { + return index; + } + } + return -1; + } +} + + diff --git a/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java b/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java index 261e672003d..da763195800 100644 --- a/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java +++ b/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java @@ -39,9 +39,6 @@ import org.apache.lucene.document.Field; import org.apache.lucene.document.Fieldable; import org.apache.lucene.index.Term; -import org.hibernate.search.annotations.NumericField; -import org.hibernate.search.bridge.util.ContextualException2WayBridge; -import org.hibernate.search.bridge.util.ContextualExceptionBridge; import org.slf4j.Logger; import org.hibernate.annotations.common.AssertionFailure; @@ -49,11 +46,11 @@ 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.ReflectHelper; import org.hibernate.search.SearchException; import org.hibernate.search.analyzer.Discriminator; import org.hibernate.search.annotations.DocumentId; import org.hibernate.search.annotations.Index; +import org.hibernate.search.annotations.NumericField; import org.hibernate.search.annotations.ProvidedId; import org.hibernate.search.annotations.Store; import org.hibernate.search.annotations.TermVector; @@ -69,6 +66,8 @@ import org.hibernate.search.bridge.TwoWayFieldBridge; import org.hibernate.search.bridge.TwoWayString2FieldBridgeAdaptor; import org.hibernate.search.bridge.TwoWayStringBridge; +import org.hibernate.search.bridge.util.ContextualException2WayBridge; +import org.hibernate.search.bridge.util.ContextualExceptionBridge; import org.hibernate.search.impl.ConfigContext; import org.hibernate.search.store.DirectoryProvider; import org.hibernate.search.store.DirectoryProviderFactory; @@ -114,12 +113,12 @@ public class DocumentBuilderIndexedEntity extends AbstractDocumentBuilder /** * The class member used as document id. */ - protected XMember idGetter; + private XMember idGetter; /** * Name of the document id field. */ - protected String idKeywordName; + private String idKeywordName; /** * Boost specified on the document id. @@ -140,11 +139,10 @@ public class DocumentBuilderIndexedEntity extends AbstractDocumentBuilder /** * Creates a document builder for entities annotated with @Indexed. * - * @param clazz The class for which to build a DocumentBuilderContainedEntity. - * @param context Handle to default configuration settings. - * @param directoryProviders Arrays of directory providers for the underlying Lucene indexes of the indexed entity. - * @param shardingStrategy The sharding strategy used for the indexed entity. - * @param reflectionManager Reflection manager to use for processing the annotations. + * @param clazz The class for which to build a DocumentBuilderContainedEntity + * @param context Handle to default configuration settings + * @param providerWrapper wrapper for access to directory providers for the underlying Lucene indexes + * @param reflectionManager Reflection manager to use for processing the annotations */ public DocumentBuilderIndexedEntity( XClass clazz, ConfigContext context, DirectoryProviderFactory.DirectoryProviders providerWrapper, ReflectionManager reflectionManager) { @@ -156,6 +154,10 @@ public DocumentBuilderIndexedEntity( this.shardingStrategy = providerWrapper.getSelectionStrategy(); } + public XMember getIdGetter() { + return idGetter; + } + protected void initSubClass(XClass clazz, ConfigContext context) { // special case @ProvidedId ProvidedId provided = findProvidedId( clazz, reflectionManager ); @@ -184,7 +186,7 @@ protected void subClassSpecificCheck(XProperty member, PropertiesMetadata proper protected void checkDocumentId(XProperty member, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, ConfigContext context) { Annotation idAnnotation = getIdAnnotation( member, context ); - NumericField numericFieldAnn = member.getAnnotation(NumericField.class); + NumericField numericFieldAnn = member.getAnnotation( NumericField.class ); if ( idAnnotation != null ) { String attributeName = getIdAttributeName( member, idAnnotation ); if ( isRoot ) { @@ -198,7 +200,7 @@ protected void checkDocumentId(XProperty member, PropertiesMetadata propertiesMe FieldBridge fieldBridge = BridgeFactory.guessType( null, numericFieldAnn, member, reflectionManager ); if ( fieldBridge instanceof TwoWayFieldBridge ) { - idBridge = ( TwoWayFieldBridge ) fieldBridge; + idBridge = (TwoWayFieldBridge) fieldBridge; } else { throw new SearchException( @@ -339,23 +341,23 @@ else if ( luceneWork instanceof DeleteLuceneWork ) { } if ( workType == WorkType.ADD ) { - String idInString = objectToString(idBridge, idKeywordName, id); + String idInString = objectToString( idBridge, idKeywordName, id ); queue.add( createAddWork( entityClass, entity, id, idInString, false ) ); } else if ( workType == WorkType.DELETE || workType == WorkType.PURGE ) { - String idInString = objectToString(idBridge, idKeywordName, id); + String idInString = objectToString( idBridge, idKeywordName, id ); queue.add( new DeleteLuceneWork( id, idInString, entityClass ) ); } else if ( workType == WorkType.PURGE_ALL ) { queue.add( new PurgeAllLuceneWork( entityClass ) ); } else if ( workType == WorkType.UPDATE || workType == WorkType.COLLECTION ) { - String idInString = objectToString(idBridge, idKeywordName, id); + String idInString = objectToString( idBridge, idKeywordName, id ); queue.add( new DeleteLuceneWork( id, idInString, entityClass ) ); queue.add( createAddWork( entityClass, entity, id, idInString, false ) ); } else if ( workType == WorkType.INDEX ) { - String idInString = objectToString(idBridge, idKeywordName, id); + String idInString = objectToString( idBridge, idKeywordName, id ); queue.add( new DeleteLuceneWork( id, idInString, entityClass ) ); queue.add( createAddWork( entityClass, entity, id, idInString, true ) ); } @@ -370,18 +372,18 @@ else if ( workType == WorkType.INDEX ) { private String objectToString(TwoWayFieldBridge bridge, String fieldName, Object value) { ContextualException2WayBridge contextualBridge = new ContextualException2WayBridge() - .setClass(beanClass) - .setFieldBridge(bridge) - .setFieldName(fieldName); - return contextualBridge.objectToString(value); + .setClass( beanClass ) + .setFieldBridge( bridge ) + .setFieldName( fieldName ); + return contextualBridge.objectToString( value ); } private String objectToString(StringBridge bridge, String fieldName, Object value) { ContextualException2WayBridge contextualBridge = new ContextualException2WayBridge() - .setClass(beanClass) - .setStringBridge(bridge) - .setFieldName(fieldName); - return contextualBridge.objectToString(value); + .setClass( beanClass ) + .setStringBridge( bridge ) + .setFieldName( fieldName ); + return contextualBridge.objectToString( value ); } public AddLuceneWork createAddWork(Class entityClass, T entity, Serializable id, String idInString, boolean isBatch) { @@ -433,14 +435,14 @@ public Document getDocument(T instance, Serializable id, Map fie Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO, idBoost ); final ContextualExceptionBridge contextualBridge = new ContextualExceptionBridge() - .setFieldBridge(idBridge) - .setClass(entityType) - .setFieldName(idKeywordName); - if ( idGetter != null) { + .setFieldBridge( idBridge ) + .setClass( entityType ) + .setFieldName( idKeywordName ); + if ( idGetter != null ) { contextualBridge.pushMethod( idGetter.getName() ); } contextualBridge.set( idKeywordName, id, doc, luceneOptions ); - if ( idGetter != null) { + if ( idGetter != null ) { contextualBridge.popMethod(); } @@ -466,9 +468,9 @@ private void buildDocumentFields(Object instance, // process the class bridges for ( int i = 0; i < propertiesMetadata.classBridges.size(); i++ ) { FieldBridge fb = propertiesMetadata.classBridges.get( i ); - final String fieldName = propertiesMetadata.classNames.get(i); + final String fieldName = propertiesMetadata.classNames.get( i ); contextualBridge - .setFieldBridge(fb) + .setFieldBridge( fb ) .setFieldName( fieldName ) .set( fieldName, unproxiedInstance, @@ -481,15 +483,15 @@ private void buildDocumentFields(Object instance, XMember member = propertiesMetadata.fieldGetters.get( i ); Object value = ReflectionHelper.getMemberValue( unproxiedInstance, member ); - final FieldBridge fieldBridge = propertiesMetadata.fieldBridges.get(i); - final String fieldName = propertiesMetadata.fieldNames.get(i); + final FieldBridge fieldBridge = propertiesMetadata.fieldBridges.get( i ); + final String fieldName = propertiesMetadata.fieldNames.get( i ); contextualBridge - .setFieldBridge(fieldBridge) + .setFieldBridge( fieldBridge ) .pushMethod( member.getName() ) .setFieldName( fieldName ) .set( - fieldName, value, doc, - propertiesMetadata.getFieldLuceneOptions( i, value ) + fieldName, value, doc, + propertiesMetadata.getFieldLuceneOptions( i, value ) ); contextualBridge.popMethod(); } @@ -512,28 +514,45 @@ private void buildDocumentFields(Object instance, PropertiesMetadata embeddedMetadata = propertiesMetadata.embeddedPropertiesMetadata.get( i ); switch ( propertiesMetadata.embeddedContainers.get( i ) ) { case ARRAY: - for ( Object arrayValue : ( Object[] ) value ) { + for ( Object arrayValue : (Object[]) value ) { buildDocumentFields( - arrayValue, doc, embeddedMetadata, fieldToAnalyzerMap, processedFieldNames, contextualBridge + arrayValue, + doc, + embeddedMetadata, + fieldToAnalyzerMap, + processedFieldNames, + contextualBridge ); } break; case COLLECTION: - for ( Object collectionValue : ( Collection ) value ) { + for ( Object collectionValue : (Collection) value ) { buildDocumentFields( - collectionValue, doc, embeddedMetadata, fieldToAnalyzerMap, processedFieldNames, contextualBridge + collectionValue, + doc, + embeddedMetadata, + fieldToAnalyzerMap, + processedFieldNames, + contextualBridge ); } break; case MAP: - for ( Object collectionValue : ( ( Map ) value ).values() ) { + for ( Object collectionValue : ( (Map) value ).values() ) { buildDocumentFields( - collectionValue, doc, embeddedMetadata, fieldToAnalyzerMap, processedFieldNames, contextualBridge + collectionValue, + doc, + embeddedMetadata, + fieldToAnalyzerMap, + processedFieldNames, + contextualBridge ); } break; case OBJECT: - buildDocumentFields( value, doc, embeddedMetadata, fieldToAnalyzerMap, processedFieldNames, contextualBridge ); + buildDocumentFields( + value, doc, embeddedMetadata, fieldToAnalyzerMap, processedFieldNames, contextualBridge + ); break; default: throw new AssertionFailure( @@ -568,7 +587,7 @@ private void allowAnalyzerDiscriminatorOverride(Document doc, PropertiesMetadata // now we give the discriminator the opportunity to specify a analyzer per field level for ( Object o : doc.getFields() ) { - Fieldable field = ( Fieldable ) o; + Fieldable field = (Fieldable) o; if ( !processedFieldNames.contains( field.name() ) ) { String analyzerName = discriminator.getAnalyzerDefinitionName( value, unproxiedInstance, field.name() ); if ( analyzerName != null ) { @@ -605,26 +624,16 @@ public boolean allowFieldSelectionInProjection() { public Term getTerm(Serializable id) { if ( idProvided ) { - return new Term( idKeywordName, ( String ) id ); + return new Term( idKeywordName, (String) id ); } - return new Term( idKeywordName, objectToString(idBridge, idKeywordName, id)); + return new Term( idKeywordName, objectToString( idBridge, idKeywordName, id ) ); } public TwoWayFieldBridge getIdBridge() { return idBridge; } - public static Class getDocumentClass(Document document) { - String className = document.get( CLASS_FIELDNAME ); - try { - return ReflectHelper.classForName( className ); - } - catch ( ClassNotFoundException e ) { - throw new SearchException( "Unable to load indexed class: " + className, e ); - } - } - public String getIdKeywordName() { return idKeywordName; } @@ -643,151 +652,7 @@ public Serializable getId(Object entity) { if ( entity == null || idGetter == null ) { throw new IllegalStateException( "Cannot guess id form entity" ); } - return ( Serializable ) ReflectionHelper.getMemberValue( entity, idGetter ); - } - - public static Serializable getDocumentId(SearchFactoryImplementor searchFactoryImplementor, Class clazz, Document document) { - DocumentBuilderIndexedEntity builderIndexedEntity = searchFactoryImplementor.getDocumentBuilderIndexedEntity( - clazz - ); - if ( builderIndexedEntity == null ) { - throw new SearchException( "No Lucene configuration set up for: " + clazz.getName() ); - } - - - final TwoWayFieldBridge fieldBridge = builderIndexedEntity.getIdBridge(); - final String fieldName = builderIndexedEntity.getIdKeywordName(); - ContextualException2WayBridge contextualBridge = new ContextualException2WayBridge(); - contextualBridge - .setClass(clazz) - .setFieldName(fieldName) - .setFieldBridge(fieldBridge) - .pushMethod( "identifier" ); - return ( Serializable ) contextualBridge.get(fieldName, document ); - } - - public static String getDocumentIdName(SearchFactoryImplementor searchFactoryImplementor, Class clazz) { - DocumentBuilderIndexedEntity builderIndexedEntity = searchFactoryImplementor.getDocumentBuilderIndexedEntity( - clazz - ); - if ( builderIndexedEntity == null ) { - throw new SearchException( "No Lucene configuration set up for: " + clazz.getName() ); - } - return builderIndexedEntity.getIdentifierName(); - } - - public static Object[] getDocumentFields(SearchFactoryImplementor searchFactoryImplementor, Class clazz, Document document, String[] fields) { - DocumentBuilderIndexedEntity builderIndexedEntity = searchFactoryImplementor.getDocumentBuilderIndexedEntity( - clazz - ); - if ( builderIndexedEntity == null ) { - throw new SearchException( "No Lucene configuration set up for: " + clazz.getName() ); - } - final int fieldNbr = fields.length; - Object[] result = new Object[fieldNbr]; - ContextualException2WayBridge contextualBridge = new ContextualException2WayBridge(); - contextualBridge.setClass(clazz); - if ( builderIndexedEntity.idKeywordName != null ) { - final XMember member = builderIndexedEntity.idGetter; - if ( member != null) { - contextualBridge.pushMethod( member.getName() ); - } - populateResult( - builderIndexedEntity.idKeywordName, - builderIndexedEntity.idBridge, - Store.YES, - fields, - result, - document, - contextualBridge - ); - if ( member != null) { - contextualBridge.popMethod(); - } - } - - final PropertiesMetadata metadata = builderIndexedEntity.metadata; - processFieldsForProjection( metadata, fields, result, document, contextualBridge ); - return result; - } - - private static void populateResult(String fieldName, FieldBridge fieldBridge, Store store, - String[] fields, Object[] result, Document document, ContextualException2WayBridge contextualBridge) { - int matchingPosition = getFieldPosition( fields, fieldName ); - if ( matchingPosition != -1 ) { - //TODO make use of an isTwoWay() method - if ( store != Store.NO && TwoWayFieldBridge.class.isAssignableFrom( fieldBridge.getClass() ) ) { - contextualBridge.setFieldName(fieldName).setFieldBridge( ( TwoWayFieldBridge ) fieldBridge ); - result[matchingPosition] = contextualBridge.get( fieldName, document ); - if ( log.isTraceEnabled() ) { - log.trace( "Field {} projected as {}", fieldName, result[matchingPosition] ); - } - } - else { - if ( store == Store.NO ) { - throw new SearchException( "Projecting an unstored field: " + fieldName ); - } - else { - throw new SearchException( "FieldBridge is not a TwoWayFieldBridge: " + fieldBridge.getClass() ); - } - } - } - } - - private static void processFieldsForProjection(PropertiesMetadata metadata, String[] fields, Object[] result, Document document, ContextualException2WayBridge contextualBridge) { - //process base fields - final int nbrFoEntityFields = metadata.fieldNames.size(); - for ( int index = 0; index < nbrFoEntityFields; index++ ) { - final String fieldName = metadata.fieldNames.get(index); - contextualBridge.pushMethod( metadata.fieldGetters.get(index).getName() ); - populateResult( - fieldName, - metadata.fieldBridges.get( index ), - metadata.fieldStore.get( index ), - fields, - result, - document, - contextualBridge - ); - contextualBridge.popMethod(); - } - - //process fields of embedded - final int nbrOfEmbeddedObjects = metadata.embeddedPropertiesMetadata.size(); - for ( int index = 0; index < nbrOfEmbeddedObjects; index++ ) { - //there is nothing we can do for collections - if ( metadata.embeddedContainers.get( index ) == PropertiesMetadata.Container.OBJECT ) { - contextualBridge.pushMethod( metadata.embeddedGetters.get( index ).getName() ); - processFieldsForProjection( - metadata.embeddedPropertiesMetadata.get( index ), fields, result, document, contextualBridge - ); - contextualBridge.popMethod(); - } - } - - //process class bridges - final int nbrOfClassBridges = metadata.classBridges.size(); - for ( int index = 0; index < nbrOfClassBridges; index++ ) { - populateResult( - metadata.classNames.get( index ), - metadata.classBridges.get( index ), - metadata.classStores.get( index ), - fields, - result, - document, - contextualBridge - ); - } - } - - private static int getFieldPosition(String[] fields, String fieldName) { - int fieldNbr = fields.length; - for ( int index = 0; index < fieldNbr; index++ ) { - if ( fieldName.equals( fields[index] ) ) { - return index; - } - } - return -1; + return (Serializable) ReflectionHelper.getMemberValue( entity, idGetter ); } public String objectToString(String fieldName, Object value) { @@ -795,17 +660,17 @@ public String objectToString(String fieldName, Object value) { throw new AssertionFailure( "Field name should not be null" ); } if ( fieldName.equals( idKeywordName ) ) { - return objectToString(idBridge, idKeywordName, value); + return objectToString( idBridge, idKeywordName, value ); } else { FieldBridge bridge = getBridge( metadata, fieldName ); if ( bridge != null ) { final Class bridgeClass = bridge.getClass(); if ( TwoWayFieldBridge.class.isAssignableFrom( bridgeClass ) ) { - return objectToString( ( TwoWayFieldBridge ) bridge, fieldName, value ); + return objectToString( (TwoWayFieldBridge) bridge, fieldName, value ); } else if ( StringBridge.class.isAssignableFrom( bridgeClass ) ) { - return objectToString(( StringBridge ) bridge, fieldName, value ); + return objectToString( (StringBridge) bridge, fieldName, value ); } throw new SearchException( "FieldBridge " + bridgeClass + "does not have a objectToString method: field " @@ -827,7 +692,7 @@ private FieldBridge getBridge(List names, List bridges, Str } public FieldBridge getBridge(String fieldName) { - return getBridge(metadata,fieldName); + return getBridge( metadata, fieldName ); } private FieldBridge getBridge(PropertiesMetadata metadata, String fieldName) { @@ -891,7 +756,7 @@ private String getIdAttributeName(XProperty member, Annotation idAnnotation) { String name = null; try { Method m = idAnnotation.getClass().getMethod( "name" ); - name = ( String ) m.invoke( idAnnotation ); + name = (String) m.invoke( idAnnotation ); } catch ( Exception e ) { // ignore diff --git a/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentExtractor.java b/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentExtractor.java index c11d7e8f989..ca2421c749d 100644 --- a/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentExtractor.java +++ b/hibernate-search/src/main/java/org/hibernate/search/engine/DocumentExtractor.java @@ -91,12 +91,12 @@ private void initFieldSelection(String[] projection, Set idFieldNames) { } private EntityInfo extract(Document document) { - Class clazz = DocumentBuilderIndexedEntity.getDocumentClass( document ); - String idName = DocumentBuilderIndexedEntity.getDocumentIdName( searchFactoryImplementor, clazz ); - Serializable id = DocumentBuilderIndexedEntity.getDocumentId( searchFactoryImplementor, clazz, document ); + Class clazz = DocumentBuilderHelper.getDocumentClass( document ); + String idName = DocumentBuilderHelper.getDocumentIdName( searchFactoryImplementor, clazz ); + Serializable id = DocumentBuilderHelper.getDocumentId( searchFactoryImplementor, clazz, document ); Object[] projected = null; if ( projection != null && projection.length > 0 ) { - projected = DocumentBuilderIndexedEntity.getDocumentFields( + projected = DocumentBuilderHelper.getDocumentFields( searchFactoryImplementor, clazz, document, projection ); }