[hibernate-commits] Hibernate SVN: r17533 - in search/trunk/src: test/java/org/hibernate/search/test/embedded and 1 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Wed Sep 23 12:12:50 EDT 2009
Author: hardy.ferentschik
Date: 2009-09-23 12:12:46 -0400 (Wed, 23 Sep 2009)
New Revision: 17533
Added:
search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/
search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Address.java
search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Attribute.java
search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/AttributeValue.java
search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/NestedEmbeddedTest.java
search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Person.java
search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Place.java
search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Product.java
Modified:
search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderContainedEntity.java
Log:
HSEARCH-391 - HSEARCH-391 - made sure the top level indexed entity gets found by recusively calling processContainedInInstances.
Refactored the code by splitting out more methods
Modified: search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderContainedEntity.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderContainedEntity.java 2009-09-23 10:21:55 UTC (rev 17532)
+++ search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderContainedEntity.java 2009-09-23 16:12:46 UTC (rev 17533)
@@ -66,7 +66,7 @@
protected final PropertiesMetadata metadata = new PropertiesMetadata();
protected final XClass beanClass;
protected Set<Class<?>> mappedSubclasses = new HashSet<Class<?>>();
- protected ReflectionManager reflectionManager; //available only during initializationa and post-initialization
+ 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();
@@ -122,28 +122,28 @@
private void initializeClass(XClass clazz, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix,
Set<XClass> processedClasses, InitContext context) {
List<XClass> hierarchy = new ArrayList<XClass>();
- for ( XClass currClass = clazz; currClass != null; currClass = currClass.getSuperclass() ) {
- hierarchy.add( currClass );
+ 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 currClass = hierarchy.get( index );
+ XClass currentClass = hierarchy.get( index );
- initalizeClassLevelAnnotations( currClass, propertiesMetadata, isRoot, prefix, context );
+ 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 = currClass.getDeclaredProperties( XClass.ACCESS_PROPERTY );
+ List<XProperty> methods = currentClass.getDeclaredProperties( XClass.ACCESS_PROPERTY );
for ( XProperty method : methods ) {
initializeMemberLevelAnnotations(
method, propertiesMetadata, isRoot, prefix, processedClasses, context
);
}
- List<XProperty> fields = currClass.getDeclaredProperties( XClass.ACCESS_FIELD );
+ List<XProperty> fields = currentClass.getDeclaredProperties( XClass.ACCESS_FIELD );
for ( XProperty field : fields ) {
initializeMemberLevelAnnotations(
field, propertiesMetadata, isRoot, prefix, processedClasses, context
@@ -162,7 +162,7 @@
* @param prefix The current prefix used for the <code>Document</code> field names.
* @param context Handle to default configuration settings.
*/
- private void initalizeClassLevelAnnotations(XClass clazz, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, InitContext context) {
+ private void initializeClassLevelAnnotations(XClass clazz, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix, InitContext context) {
// check for a class level specified analyzer
Analyzer analyzer = getAnalyzer( clazz, context );
@@ -176,8 +176,8 @@
// Check for any ClassBridges annotation.
ClassBridges classBridgesAnn = clazz.getAnnotation( ClassBridges.class );
if ( classBridgesAnn != null ) {
- ClassBridge[] cbs = classBridgesAnn.value();
- for ( ClassBridge cb : cbs ) {
+ ClassBridge[] classBridges = classBridgesAnn.value();
+ for ( ClassBridge cb : classBridges ) {
bindClassBridgeAnnotation( prefix, propertiesMetadata, cb, context );
}
}
@@ -256,15 +256,15 @@
}
private void checkForAnalyzerDiscriminator(XAnnotatedElement annotatedElement, PropertiesMetadata propertiesMetadata) {
- AnalyzerDiscriminator discriminiatorAnn = annotatedElement.getAnnotation( AnalyzerDiscriminator.class );
- if ( discriminiatorAnn != null ) {
+ AnalyzerDiscriminator discriminatorAnn = annotatedElement.getAnnotation( AnalyzerDiscriminator.class );
+ if ( discriminatorAnn != null ) {
if ( propertiesMetadata.discriminator != null ) {
throw new SearchException(
"Multiple AnalyzerDiscriminator defined in the same class hierarchy: " + beanClass.getName()
);
}
- Class<? extends Discriminator> discriminatorClass = discriminiatorAnn.impl();
+ Class<? extends Discriminator> discriminatorClass = discriminatorAnn.impl();
try {
propertiesMetadata.discriminator = discriminatorClass.newInstance();
}
@@ -372,7 +372,7 @@
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 downcasting either
+ * 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 );
@@ -596,8 +596,6 @@
return strategy;
}
-
- //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) {
/**
* When references are changed, either null or another one, we expect dirty checking to be triggered (both sides
@@ -605,75 +603,101 @@
* When the internal object is changed, we apply the {Add|Update}Work on containedIns
*/
if ( workType.searchForContainers() ) {
- processContainedIn( entity, queue, metadata, searchFactoryImplementor );
+ processContainedInInstances( entity, queue, metadata, searchFactoryImplementor );
}
}
- private void processContainedIn(Object instance, List<LuceneWork> queue, PropertiesMetadata metadata, SearchFactoryImplementor searchFactoryImplementor) {
+ /**
+ * If we have a work instance we have to check whether the intance 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() ) {
- for ( Object arrayValue : ( Object[] ) value ) {
- //highly inneficient but safe wrt the actual targeted class
- Class<?> valueClass = Hibernate.getClass( arrayValue );
- DocumentBuilderIndexedEntity<?> builderIndexedEntity = searchFactoryImplementor.getDocumentBuilderIndexedEntity(
- valueClass
- );
- if ( builderIndexedEntity == null ) {
- continue;
- }
- processContainedInValue(
- arrayValue, queue, valueClass,
- builderIndexedEntity, searchFactoryImplementor
- );
+ @SuppressWarnings("unchecked")
+ T[] array = ( T[] ) value;
+ for ( T arrayValue : array ) {
+ processSingleContainedInInstance( queue, searchFactoryImplementor, arrayValue );
}
}
else if ( member.isCollection() ) {
- Collection collection;
- if ( Map.class.equals( member.getCollectionClass() ) ) {
- //hum
- collection = ( ( Map ) value ).values();
+ Collection<T> collection = getActualCollection( member, value );
+ for ( T collectionValue : collection ) {
+ processSingleContainedInInstance( queue, searchFactoryImplementor, collectionValue );
}
- else {
- collection = ( Collection ) value;
- }
- for ( Object collectionValue : collection ) {
- //highly inneficient but safe wrt the actual targeted class
- Class<?> valueClass = Hibernate.getClass( collectionValue );
- DocumentBuilderIndexedEntity<?> builderIndexedEntity = searchFactoryImplementor.getDocumentBuilderIndexedEntity(
- valueClass
- );
- if ( builderIndexedEntity == null ) {
- continue;
- }
- processContainedInValue(
- collectionValue, queue, valueClass,
- builderIndexedEntity, searchFactoryImplementor
- );
- }
}
else {
- Class<?> valueClass = Hibernate.getClass( value );
- DocumentBuilderIndexedEntity<?> builderIndexedEntity = searchFactoryImplementor.getDocumentBuilderIndexedEntity(
- valueClass
- );
- if ( builderIndexedEntity == null ) {
- continue;
- }
- processContainedInValue( value, queue, valueClass, builderIndexedEntity, searchFactoryImplementor );
+ processSingleContainedInInstance( queue, searchFactoryImplementor, value );
}
}
- //an embedded cannot have a useful @ContainedIn (no shared reference)
- //do not walk through them
}
- private void processContainedInValue(Object value, List<LuceneWork> queue, Class<?> valueClass,
- DocumentBuilderIndexedEntity builderIndexedEntity, SearchFactoryImplementor searchFactoryImplementor) {
+ /**
+ * 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) {
+ @SuppressWarnings("unchecked")
+ Class<T> valueClass = Hibernate.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 );
builderIndexedEntity.addWorkToQueue( valueClass, value, id, WorkType.UPDATE, queue, searchFactoryImplementor );
}
@@ -727,7 +751,7 @@
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>();
Added: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Address.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Address.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Address.java 2009-09-23 16:12:46 UTC (rev 17533)
@@ -0,0 +1,87 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.search.test.embedded.nested;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+
+import org.hibernate.search.annotations.ContainedIn;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Index;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Entity
+public class Address {
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @Field(index = Index.TOKENIZED)
+ private String street;
+
+ @Field(index = Index.TOKENIZED)
+ private String city;
+
+ @ContainedIn
+ @OneToMany(mappedBy = "address")
+ private Set<Place> places;
+
+ public Address(String street, String city) {
+ this();
+ this.street = street;
+ this.city = city;
+ }
+
+ private Address() {
+ places = new HashSet<Place>();
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public Set<Place> getPlaces() {
+ return places;
+ }
+
+ public void addPlace(Place place) {
+ places.add( place );
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+}
Property changes on: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Address.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Attribute.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Attribute.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Attribute.java 2009-09-23 16:12:46 UTC (rev 17533)
@@ -0,0 +1,79 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.search.test.embedded.nested;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+
+import org.hibernate.search.annotations.ContainedIn;
+import org.hibernate.search.annotations.IndexedEmbedded;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Entity
+public class Attribute {
+
+ @Id
+ @GeneratedValue
+ private long id;
+
+ @ManyToOne
+ @ContainedIn
+ private Product product;
+
+ @OneToMany(mappedBy = "attribute", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
+ @IndexedEmbedded
+ private List<AttributeValue> values;
+
+ private Attribute() {
+ values = new ArrayList<AttributeValue>();
+ }
+
+ public Attribute(Product product) {
+ this.product = product;
+ values = new ArrayList<AttributeValue>();
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+
+ public List<AttributeValue> getValues() {
+ return values;
+ }
+
+ public void setValue(AttributeValue value) {
+ values.add( value );
+ }
+}
Property changes on: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Attribute.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/AttributeValue.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/AttributeValue.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/AttributeValue.java 2009-09-23 16:12:46 UTC (rev 17533)
@@ -0,0 +1,77 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.search.test.embedded.nested;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+
+import org.hibernate.search.annotations.ContainedIn;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.Store;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Entity
+public class AttributeValue {
+
+ @Id
+ @GeneratedValue
+ private long id;
+
+ @ManyToOne(targetEntity = Attribute.class, fetch = FetchType.EAGER)
+ @ContainedIn
+ private Attribute attribute;
+
+ @Column(name = "_value")
+ @Field(index = Index.TOKENIZED, store = Store.YES)
+ private String value;
+
+ private AttributeValue() {
+ }
+
+ public AttributeValue(Attribute attribute, String value) {
+ this.attribute = attribute;
+ this.value = value;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public Attribute getAttribute() {
+ return attribute;
+ }
+
+ public void setAttribute(Attribute attribute) {
+ this.attribute = attribute;
+ }
+}
\ No newline at end of file
Property changes on: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/AttributeValue.java
___________________________________________________________________
Name: svn:keywords
+ Id
Copied: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/NestedEmbeddedTest.java (from rev 17482, search/trunk/src/test/java/org/hibernate/search/test/embedded/EmbeddedTest.java)
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/NestedEmbeddedTest.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/NestedEmbeddedTest.java 2009-09-23 16:12:46 UTC (rev 17533)
@@ -0,0 +1,138 @@
+//$Id$
+package org.hibernate.search.test.embedded.nested;
+
+import java.util.List;
+
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.Query;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.test.SearchTestCase;
+
+
+/**
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class NestedEmbeddedTest extends SearchTestCase {
+
+ /**
+ * HSEARCH-391
+ *
+ * @throws Exception in case the tests fails
+ */
+ public void testNestedEmbeddedIndexing() throws Exception {
+ Product product = new Product();
+ Attribute attribute = new Attribute( product );
+ product.setAttribute( attribute );
+ AttributeValue value = new AttributeValue( attribute, "foo" );
+ attribute.setValue( value );
+
+ Session s = openSession();
+ Transaction tx = s.beginTransaction();
+ s.persist( product );
+ tx.commit();
+
+ FullTextSession session = Search.getFullTextSession( s );
+ QueryParser parser = new QueryParser( "attributes.values.value", new StandardAnalyzer() );
+ Query query;
+ List<?> result;
+
+
+ query = parser.parse( "foo" );
+ result = session.createFullTextQuery( query ).list();
+ assertEquals( "unable to find property in attribute value", 1, result.size() );
+
+
+ s.clear();
+ tx = s.beginTransaction();
+
+ product = ( Product ) s.get( Product.class, product.getId() );
+ product.getAttributes().get( 0 ).getValues().get( 0 ).setValue( "bar" );
+ tx.commit();
+
+ s.clear();
+
+ session = Search.getFullTextSession( s );
+
+ query = parser.parse( "foo" );
+ result = session.createFullTextQuery( query, Product.class ).list();
+ assertEquals( "change in embedded not reflected in root index", 0, result.size() );
+
+ query = parser.parse( "bar" );
+ result = session.createFullTextQuery( query, Product.class ).list();
+ assertEquals( "change in embedded not reflected in root index", 1, result.size() );
+
+ s.close();
+ }
+
+
+ /**
+ * HSEARCH-391
+ *
+ * @throws Exception in case the tests fails
+ */
+ public void testNestedEmbeddedIndexingWithContainedInOnCollection() throws Exception {
+ Person john = new Person( "John Doe" );
+ Place eiffelTower = new Place( "Eiffel Tower" );
+ Address addressEiffel = new Address( "Avenue Gustave Eiffel", "London" );
+ addressEiffel.addPlace( eiffelTower );
+ eiffelTower.setAddress( addressEiffel );
+ john.addPlaceVisited( eiffelTower );
+ eiffelTower.visitedBy( john );
+
+
+ Session s = openSession();
+ Transaction tx = s.beginTransaction();
+ s.persist( john );
+ tx.commit();
+
+ FullTextSession session = Search.getFullTextSession( s );
+ QueryParser parser = new QueryParser( "placesVisited.address.city", new StandardAnalyzer() );
+ Query query;
+ List<?> result;
+
+
+ query = parser.parse( "London" );
+ result = session.createFullTextQuery( query ).list();
+ assertEquals( "unable to find nested indexed value", 1, result.size() );
+
+
+ s.clear();
+ tx = s.beginTransaction();
+
+ john = ( Person ) s.get( Person.class, john.getId() );
+ john.getPlacesVisited().get( 0 ).getAddress().setCity( "Paris" );
+ tx.commit();
+
+ s.clear();
+
+ john = ( Person ) s.get( Person.class, john.getId() );
+
+ session = Search.getFullTextSession( s );
+
+ query = parser.parse( "London" );
+ result = session.createFullTextQuery( query, Person.class ).list();
+ assertEquals( "change in embedded not reflected in root index", 0, result.size() );
+
+ query = parser.parse( "Paris" );
+ result = session.createFullTextQuery( query, Person.class ).list();
+ assertEquals( "change in embedded not reflected in root index", 1, result.size() );
+
+ s.close();
+ }
+
+ protected void configure(org.hibernate.cfg.Configuration cfg) {
+ super.configure( cfg );
+ }
+
+ protected Class<?>[] getMappings() {
+ return new Class[] {
+ Product.class, Attribute.class, AttributeValue.class, Person.class, Place.class, Address.class
+ };
+ }
+}
\ No newline at end of file
Added: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Person.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Person.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Person.java 2009-09-23 16:12:46 UTC (rev 17533)
@@ -0,0 +1,71 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.search.test.embedded.nested;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.IndexedEmbedded;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Entity
+ at Indexed
+public class Person {
+ @Id
+ @GeneratedValue
+ private long id;
+
+ String name;
+
+ @IndexedEmbedded
+ @ManyToMany(cascade = { CascadeType.ALL })
+ private List<Place> placesVisited;
+
+ private Person() {
+ placesVisited = new ArrayList<Place>( 0 );
+ }
+
+ public Person(String name) {
+ this();
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List<Place> getPlacesVisited() {
+ return placesVisited;
+ }
+
+ public void addPlaceVisited(Place place) {
+ placesVisited.add( place );
+ }
+
+ public long getId() {
+ return id;
+ }
+}
Property changes on: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Person.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Place.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Place.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Place.java 2009-09-23 16:12:46 UTC (rev 17533)
@@ -0,0 +1,87 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.search.test.embedded.nested;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToOne;
+
+import org.hibernate.search.annotations.ContainedIn;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.IndexedEmbedded;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Entity
+public class Place {
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @Field(index = Index.TOKENIZED)
+ private String name;
+
+ @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
+ @IndexedEmbedded
+ private Address address;
+
+ @ContainedIn
+ @ManyToMany(cascade = { CascadeType.ALL }, mappedBy = "placesVisited")
+ private Set<Person> visitedBy;
+
+ private Place() {
+ this.visitedBy = new HashSet<Person>();
+ }
+
+ public Place(String name) {
+ this();
+ this.name = name;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public String getName() {
+
+ return name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ public void visitedBy(Person person) {
+ visitedBy.add( person );
+ }
+
+ public Set<Person> getVisitedBy() {
+ return visitedBy;
+ }
+}
Property changes on: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Place.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Product.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Product.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Product.java 2009-09-23 16:12:46 UTC (rev 17533)
@@ -0,0 +1,61 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.search.test.embedded.nested;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.IndexedEmbedded;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Entity
+ at Indexed
+public class Product {
+ @Id
+ @GeneratedValue
+ private long id;
+
+ @OneToMany(mappedBy = "product", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
+ @IndexedEmbedded
+ private List<Attribute> attributes;
+
+ public Product() {
+ attributes = new ArrayList<Attribute>();
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public List<Attribute> getAttributes() {
+ return attributes;
+ }
+
+ public void setAttribute(Attribute attribute) {
+ attributes.add( attribute );
+ }
+}
Property changes on: search/trunk/src/test/java/org/hibernate/search/test/embedded/nested/Product.java
___________________________________________________________________
Name: svn:keywords
+ Id
More information about the hibernate-commits
mailing list