/* * 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.test.embedded; import java.util.ArrayList; import java.util.List; import org.apache.lucene.index.Term; import org.apache.lucene.queryParser.MultiFieldQueryParser; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.search.FullTextSession; import org.hibernate.search.Search; import org.hibernate.search.test.SearchTestCase; import org.hibernate.search.test.TestConstants; /** * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class EmbeddedTest extends SearchTestCase { public void testEmbeddedIndexing() throws Exception { Tower tower = new Tower(); tower.setName( "JBoss tower" ); Address a = new Address(); a.setStreet( "Tower place" ); a.getTowers().add( tower ); tower.setAddress( a ); Person o = new Owner(); o.setName( "Atlanta Renting corp" ); a.setOwnedBy( o ); o.setAddress( a ); Country c = new Country(); c.setName( "France" ); a.setCountry( c ); Session s = openSession(); Transaction tx = s.beginTransaction(); s.persist( tower ); tx.commit(); FullTextSession session = Search.getFullTextSession( s ); QueryParser parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "id", TestConstants.standardAnalyzer ); Query query; List<?> result; query = parser.parse( "address.street:place" ); result = session.createFullTextQuery( query ).list(); assertEquals( "unable to find property in embedded", 1, result.size() ); query = parser.parse( "address.ownedBy_name:renting" ); result = session.createFullTextQuery( query, Tower.class ).list(); assertEquals( "unable to find property in embedded", 1, result.size() ); query = parser.parse( "address.id:" + a.getId().toString() ); result = session.createFullTextQuery( query, Tower.class ).list(); assertEquals( "unable to find property by id of embedded", 1, result.size() ); query = parser.parse( "address.country.name:" + a.getCountry().getName() ); result = session.createFullTextQuery( query, Tower.class ).list(); assertEquals( "unable to find property with 2 levels of embedded", 1, result.size() ); s.clear(); tx = s.beginTransaction(); Address address = (Address) s.get( Address.class, a.getId() ); address.getOwnedBy().setName( "Buckhead community" ); tx.commit(); s.clear(); session = Search.getFullTextSession( s ); query = parser.parse( "address.ownedBy_name:buckhead" ); result = session.createFullTextQuery( query, Tower.class ).list(); assertEquals( "change in embedded not reflected in root index", 1, result.size() ); s.clear(); tx = s.beginTransaction(); s.delete( s.get( Tower.class, tower.getId() ) ); tx.commit(); s.close(); } public void testEmbeddedIndexingOneToMany() throws Exception { Country country = new Country(); country.setName( "Germany" ); List<State> states = new ArrayList<State>(); State bayern = new State(); bayern.setName( "Bayern" ); State hessen = new State(); hessen.setName( "Hessen" ); State sachsen = new State(); sachsen.setName( "Sachsen" ); states.add( bayern ); states.add( hessen ); states.add( sachsen ); country.setStates( states ); Session s = openSession(); Transaction tx = s.beginTransaction(); s.persist( country ); tx.commit(); FullTextSession session = Search.getFullTextSession( s ); QueryParser parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "id", TestConstants.standardAnalyzer ); Query query; List<?> result; query = parser.parse( "states.name:Hessen" ); result = session.createFullTextQuery( query ).list(); assertEquals( "unable to find property in embedded", 1, result.size() ); s.close(); } public void testContainedIn() throws Exception { Tower tower = new Tower(); tower.setName( "JBoss tower" ); Address a = new Address(); a.setStreet( "Tower place" ); a.getTowers().add( tower ); tower.setAddress( a ); Person o = new Owner(); o.setName( "Atlanta Renting corp" ); a.setOwnedBy( o ); o.setAddress( a ); Session s = openSession(); Transaction tx = s.beginTransaction(); s.persist( tower ); tx.commit(); s.clear(); tx = s.beginTransaction(); Address address = (Address) s.get( Address.class, a.getId() ); address.setStreet( "Peachtree Road NE" ); tx.commit(); s.clear(); FullTextSession session = Search.getFullTextSession( s ); QueryParser parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "id", TestConstants.standardAnalyzer ); Query query; List<?> result; query = parser.parse( "address.street:peachtree" ); result = session.createFullTextQuery( query, Tower.class ).list(); assertEquals( "change in embedded not reflected in root index", 1, result.size() ); s.clear(); tx = s.beginTransaction(); address = (Address) s.get( Address.class, a.getId() ); Tower tower1 = address.getTowers().iterator().next(); tower1.setAddress( null ); address.getTowers().remove( tower1 ); tx.commit(); s.clear(); session = Search.getFullTextSession( s ); query = parser.parse( "address.street:peachtree" ); result = session.createFullTextQuery( query, Tower.class ).list(); assertEquals( "breaking link fails", 0, result.size() ); tx = s.beginTransaction(); s.delete( s.get( Tower.class, tower.getId() ) ); tx.commit(); s.close(); } public void testIndexedEmbeddedAndCollections() throws Exception { Author a = new Author(); a.setName( "Voltaire" ); Author a2 = new Author(); a2.setName( "Victor Hugo" ); Author a3 = new Author(); a3.setName( "Moliere" ); Author a4 = new Author(); a4.setName( "Proust" ); Order o = new Order(); o.setOrderNumber( "ACVBNM" ); Order o2 = new Order(); o2.setOrderNumber( "ZERTYD" ); Product p1 = new Product(); p1.setName( "Candide" ); p1.getAuthors().add( a ); p1.getAuthors().add( a2 ); // be creative Product p2 = new Product(); p2.setName( "Le malade imaginaire" ); p2.getAuthors().add( a3 ); p2.getOrders().put( "Emmanuel", o ); p2.getOrders().put( "Gavin", o2 ); Session s = openSession(); Transaction tx = s.beginTransaction(); s.persist( a ); s.persist( a2 ); s.persist( a3 ); s.persist( a4 ); s.persist( o ); s.persist( o2 ); s.persist( p1 ); s.persist( p2 ); tx.commit(); s.clear(); FullTextSession session = Search.getFullTextSession( s ); tx = session.beginTransaction(); QueryParser parser = new MultiFieldQueryParser( TestConstants.getTargetLuceneVersion(), new String[] { "name", "authors.name" }, TestConstants.standardAnalyzer ); Query query; List<?> result; query = parser.parse( "Hugo" ); result = session.createFullTextQuery( query, Product.class ).list(); assertEquals( "collection of embedded ignored", 1, result.size() ); // update the collection Product p = (Product) result.get( 0 ); p.getAuthors().add( a4 ); // PhraseQuery query = new TermQuery( new Term( "orders.orderNumber", "ZERTYD" ) ); result = session.createFullTextQuery( query, Product.class ).list(); assertEquals( "collection of untokenized ignored", 1, result.size() ); query = new TermQuery( new Term( "orders.orderNumber", "ACVBNM" ) ); result = session.createFullTextQuery( query, Product.class ).list(); assertEquals( "collection of untokenized ignored", 1, result.size() ); tx.commit(); s.clear(); tx = s.beginTransaction(); session = Search.getFullTextSession( s ); query = parser.parse( "Proust" ); result = session.createFullTextQuery( query, Product.class ).list(); // HSEARCH-56 assertEquals( "update of collection of embedded ignored", 1, result.size() ); s.delete( s.get( Product.class, p1.getId() ) ); s.delete( s.get( Product.class, p2.getId() ) ); tx.commit(); s.close(); } /** * Tests that updating an indexed embedded object updates the Lucene index as well. * * @throws Exception in case the test fails */ public void testEmbeddedObjectUpdate() throws Exception { State state = new State(); state.setName( "Bavaria" ); StateCandidate candiate = new StateCandidate(); candiate.setName( "Mueller" ); candiate.setState( state ); state.setCandidate( candiate ); Session s = openSession(); Transaction tx = s.beginTransaction(); s.persist( candiate ); tx.commit(); s.clear(); FullTextSession session = Search.getFullTextSession( s ); tx = session.beginTransaction(); QueryParser parser = new MultiFieldQueryParser( TestConstants.getTargetLuceneVersion(), new String[] { "name", "state.name" }, TestConstants.standardAnalyzer ); Query query; List<?> result; query = parser.parse( "Bavaria" ); result = session.createFullTextQuery( query, StateCandidate.class ).list(); assertEquals( "IndexEmbedded ignored.", 1, result.size() ); tx.commit(); s.clear(); tx = s.beginTransaction(); state.setName( "Hessen" ); s.merge( state ); tx.commit(); s.clear(); tx = s.beginTransaction(); session = Search.getFullTextSession( s ); query = parser.parse( "Hessen" ); result = session.createFullTextQuery( query, StateCandidate.class ).list(); assertEquals( "IndexEmbedded ignored.", 1, result.size() ); tx.commit(); s.clear(); s.close(); } public void testEmbeddedToManyInSuperclass() throws ParseException { ProductFeature featureA = new ProductFeature(); featureA.setName( "featureA" ); ProductFeature featureB = new ProductFeature(); featureB.setName( "featureB" ); AbstractProduct book = new Book(); book.setName( "A Book" ); featureA.setProduct( book ); book.getFeatures().add( featureA ); Session s = openSession(); Transaction tx = s.beginTransaction(); s.persist( book ); tx.commit(); s.clear(); FullTextSession session = Search.getFullTextSession( s ); tx = session.beginTransaction(); QueryParser parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "name", TestConstants.standardAnalyzer ); Query query; List<?> result; query = parser.parse( "features.name:featureA" ); result = session.createFullTextQuery( query, AbstractProduct.class ).list(); assertEquals( "Feature A should be indexed", 1, result.size() ); // Add product features - product should be re-indexed book = (AbstractProduct) result.get( 0 ); book.getFeatures().add( featureB ); tx.commit(); s.clear(); tx = s.beginTransaction(); tx.commit(); s.clear(); query = parser.parse( "features.name:featureB" ); result = session.createFullTextQuery( query, AbstractProduct.class ).list(); assertEquals( "Feature B should be indexed now as well", 1, result.size() ); s.close(); } protected void configure(org.hibernate.cfg.Configuration cfg) { super.configure( cfg ); } protected Class<?>[] getAnnotatedClasses() { return new Class[] { Tower.class, Address.class, Product.class, Order.class, Author.class, Country.class, State.class, StateCandidate.class, NonIndexedEntity.class, AbstractProduct.class, Book.class, ProductFeature.class }; } }