/* * Hibernate Search, full-text search for your domain model * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.search.test.embedded.depth; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.Serializable; import java.util.Arrays; import java.util.List; import java.util.Map; import org.apache.lucene.index.Term; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.search.FullTextQuery; import org.hibernate.search.FullTextSession; import org.hibernate.search.Search; import org.hibernate.search.annotations.IndexedEmbedded; import org.hibernate.search.backend.LuceneWork; import org.hibernate.search.test.SearchTestBase; import org.hibernate.search.testsupport.TestForIssue; import org.hibernate.search.testsupport.backend.LeakingLocalBackend; import org.junit.Test; /** * Verify the engine respects the includePaths parameter {@link IndexedEmbedded#includePaths()} without indexing larger * graphs than requested. */ public class RecursiveGraphIncludePathsTest extends SearchTestBase { @Test @TestForIssue(jiraKey = "HSEARCH-2074") public void testCorrectDepthIndexedWithIncludePath() { prepareSocialGraph(); verifyMatchExistsWithName( "name", "Ross", 0L ); verifyMatchExistsWithName( "name", "Rachel", 5L ); verifyMatchExistsWithName( "name", "Gunter", 6L ); verifyMatchExistsWithName( "friends.name", "Ross", 1L, 2L, 3L, 4L, 5L ); verifyMatchExistsWithName( "friends.name", "Rachel", 0L, 1L, 2L, 3L, 4L, 6L ); verifyNoMatchExists( "friends.name", "Gunter" ); LeakingLocalBackend.reset(); renamePerson( 5L, "Rachelita" ); // Rename Rachel, friend to anyone assertEquals( 1, countWorksDoneOnPerson( 0L ) ); assertEquals( 1, countWorksDoneOnPerson( 1L ) ); assertEquals( 1, countWorksDoneOnPerson( 2L ) ); assertEquals( 1, countWorksDoneOnPerson( 3L ) ); assertEquals( 1, countWorksDoneOnPerson( 4L ) ); assertEquals( 1, countWorksDoneOnPerson( 5L ) ); assertEquals( 1, countWorksDoneOnPerson( 6L ) ); LeakingLocalBackend.reset(); renamePerson( 0L, "Rossito" ); // Rename Ross, friend to anyone but Gunter assertEquals( 1, countWorksDoneOnPerson( 0L ) ); assertEquals( 1, countWorksDoneOnPerson( 1L ) ); assertEquals( 1, countWorksDoneOnPerson( 2L ) ); assertEquals( 1, countWorksDoneOnPerson( 3L ) ); assertEquals( 1, countWorksDoneOnPerson( 4L ) ); assertEquals( 1, countWorksDoneOnPerson( 5L ) ); // 6L (Gunter) does not embed any field from 0L (Ross/Rossito) // It should not be reindexed assertEquals( 0, countWorksDoneOnPerson( 6L ) ); } /** * rename a person having id to a new name */ private void renamePerson(Long id, String newName) { FullTextSession fullTextSession = Search.getFullTextSession( openSession() ); try { Transaction transaction = fullTextSession.beginTransaction(); SocialPerson person = fullTextSession.load( SocialPerson.class, id ); person.setName( newName ); transaction.commit(); } finally { fullTextSession.close(); } } /** * asserts no results are returned for fieldName having fieldValue */ void verifyNoMatchExists(String fieldName, String fieldValue) { FullTextSession fullTextSession = Search.getFullTextSession( openSession() ); try { Transaction transaction = fullTextSession.beginTransaction(); Query q = new TermQuery( new Term( fieldName, fieldValue ) ); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( q ); int resultSize = fullTextQuery.getResultSize(); assertEquals( 0, resultSize ); @SuppressWarnings("unchecked") List<SocialPerson> list = fullTextQuery.list(); assertEquals( 0, list.size() ); transaction.commit(); } finally { fullTextSession.close(); } } void verifyMatchExistsWithName(String fieldName, String fieldValue, Long... expectedIds) { FullTextSession fullTextSession = Search.getFullTextSession( openSession() ); try { Transaction transaction = fullTextSession.beginTransaction(); Query q = new TermQuery( new Term( fieldName, fieldValue ) ); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( q ); int resultSize = fullTextQuery.getResultSize(); assertEquals( expectedIds.length, resultSize ); @SuppressWarnings("unchecked") List<SocialPerson> list = fullTextQuery.list(); assertEquals( expectedIds.length, list.size() ); List<Long> expectIdsList = Arrays.asList( expectedIds ); for ( SocialPerson person : list ) { assertTrue( expectIdsList.contains( person.getId() ) ); } transaction.commit(); } finally { fullTextSession.close(); } } private void prepareSocialGraph() { Session session = openSession(); Transaction transaction = session.beginTransaction(); SocialPerson[] ps = new SocialPerson[7]; ps[0] = new SocialPerson( 0L, "Ross" ); ps[1] = new SocialPerson( 1L, "Chandler" ); ps[2] = new SocialPerson( 2L, "Joey" ); ps[3] = new SocialPerson( 3L, "Phoebe" ); ps[4] = new SocialPerson( 4L, "Monica" ); ps[5] = new SocialPerson( 5L, "Rachel" ); ps[6] = new SocialPerson( 6L, "Gunter" ); // Friends for ( int i = 0; i < 6; i++ ) { for ( int j = 0; j < 6; j++ ) { if ( i != j ) { ps[i].addFriends( ps[j] ); } } } // Lonely person ps[6].addFriends( ps[5] ); for ( int i = 0; i < ps.length; i++ ) { session.save( ps[i] ); } transaction.commit(); session.close(); for ( int i = 1; i < ps.length; i++ ) { assertEquals( 1, countWorksDoneOnPerson( Long.valueOf( i ) ) ); } } private int countWorksDoneOnPerson(Long pk) { List<LuceneWork> processedQueue = LeakingLocalBackend.getLastProcessedQueue(); int count = 0; for ( LuceneWork luceneWork : processedQueue ) { Serializable id = luceneWork.getId(); if ( pk.equals( id ) ) { count++; } } return count; } @Override public Class<?>[] getAnnotatedClasses() { return new Class[] { SocialPerson.class }; } @Override public void configure(Map<String, Object> cfg) { cfg.put( "hibernate.search.default.worker.backend", LeakingLocalBackend.class.getName() ); } }