/*
* 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.bridge;
import java.util.List;
import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Query;
import org.apache.lucene.document.Document;
import org.hibernate.Transaction;
import org.hibernate.ScrollableResults;
import org.hibernate.cfg.Configuration;
import org.hibernate.search.Environment;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.test.SearchTestCase;
import org.hibernate.search.test.TestConstants;
/**
* @author John Griffin
*/
public class ClassBridgeTest extends SearchTestCase {
/**
* This tests that a field created by a user-supplied
* EquipmentType class has been created and is a translation
* from an identifier to a manufacturer name.
*
* @throws Exception
*/
public void testClassBridges() throws Exception {
org.hibernate.Session s = openSession();
Transaction tx = s.beginTransaction();
s.persist( getDepts1() );
s.persist( getDepts2() );
s.persist( getDepts3() );
s.persist( getDepts4() );
s.flush();
tx.commit();
tx = s.beginTransaction();
FullTextSession session = Search.getFullTextSession( s );
// The equipment field is the manufacturer field in the
// Departments entity after being massaged by passing it
// through the EquipmentType class. This field is in
// the Lucene document but not in the Department entity itself.
QueryParser parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "equipment", TestConstants.simpleAnalyzer );
// Check the second ClassBridge annotation
Query query = parser.parse( "equiptype:Cisco" );
org.hibernate.search.FullTextQuery hibQuery = session.createFullTextQuery( query, Departments.class );
List<Departments> result = hibQuery.list();
assertNotNull( result );
assertEquals( "incorrect number of results returned", 2, result.size() );
for (Departments d : result) {
assertEquals("incorrect manufacturer", "C", d.getManufacturer());
}
// No data cross-ups.
query = parser.parse( "branchnetwork:Kent Lewin" );
hibQuery = session.createFullTextQuery( query, Departments.class );
result = hibQuery.list();
assertNotNull( result );
assertTrue( "problem with field cross-ups", result.size() == 0 );
// Non-ClassBridge field.
parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "branchHead", TestConstants.simpleAnalyzer );
query = parser.parse( "branchHead:Kent Lewin" );
hibQuery = session.createFullTextQuery( query, Departments.class );
result = hibQuery.list();
assertNotNull( result );
assertTrue( "incorrect entity returned, wrong branch head", result.size() == 1 );
assertEquals("incorrect entity returned", "Kent Lewin", ( result.get( 0 ) ).getBranchHead());
// Check other ClassBridge annotation.
parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "branchnetwork", TestConstants.simpleAnalyzer );
query = parser.parse( "branchnetwork:st. george 1D" );
hibQuery = session.createFullTextQuery( query, Departments.class );
result = hibQuery.list();
assertNotNull( result );
assertEquals( "incorrect entity returned, wrong network", "1D", ( result.get( 0 ) ).getNetwork() );
assertEquals( "incorrect entity returned, wrong branch", "St. George", ( result.get( 0 ) ).getBranch() );
assertEquals( "incorrect number of results returned", 1, result.size() );
//cleanup
for (Object element : s.createQuery( "from " + Departments.class.getName() ).list()) s.delete( element );
tx.commit();
s.close();
}
/**
* This is the same test as above with a projection query
* to show the presence of the ClassBridge impl built fields
* just in case you don't believe us.
*
* @throws Exception
*/
public void testClassBridgesWithProjection() throws Exception {
org.hibernate.Session s = openSession();
Transaction tx = s.beginTransaction();
s.persist( getDepts1() );
s.persist( getDepts2() );
s.persist( getDepts3() );
s.persist( getDepts4() );
s.flush();
tx.commit();
tx = s.beginTransaction();
FullTextSession session = Search.getFullTextSession( s );
// The equipment field is the manufacturer field in the
// Departments entity after being massaged by passing it
// through the EquipmentType class. This field is in
// the Lucene document but not in the Department entity itself.
QueryParser parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "equipment", TestConstants.simpleAnalyzer );
// Check the second ClassBridge annotation
Query query = parser.parse( "equiptype:Cisco" );
org.hibernate.search.FullTextQuery hibQuery = session.createFullTextQuery( query, Departments.class );
hibQuery.setProjection( FullTextQuery.THIS, FullTextQuery.DOCUMENT );
ScrollableResults projections = hibQuery.scroll();
assertNotNull( projections );
projections.beforeFirst();
projections.next();
Object[] projection = projections.get();
assertTrue( "DOCUMENT incorrect", projection[0] instanceof Departments );
assertEquals( "id incorrect", 1, ((Departments)projection[0]).getId() );
assertTrue( "DOCUMENT incorrect", projection[1] instanceof Document );
assertEquals( "DOCUMENT size incorrect", 8, ( (Document) projection[1] ).getFields().size() );
assertNotNull( "equiptype is null", ( (Document) projection[1] ).getFieldable("equiptype") );
assertEquals( "equiptype incorrect", "Cisco", ( (Document) projection[1] ).getFieldable("equiptype" ).stringValue() );
assertNotNull( "branchnetwork is null", ( (Document) projection[1] ).getFieldable("branchnetwork") );
assertEquals( "branchnetwork incorrect", "Salt Lake City 1A", ( (Document) projection[1] ).getFieldable("branchnetwork" ).stringValue() );
projections.next();
projection = projections.get();
assertTrue( "DOCUMENT incorrect", projection[0] instanceof Departments );
assertEquals( "id incorrect", 4, ((Departments)projection[0]).getId() );
assertTrue( "DOCUMENT incorrect", projection[1] instanceof Document );
assertEquals( "DOCUMENT size incorrect", 8, ( (Document) projection[1] ).getFields().size() );
assertNotNull( "equiptype is null", ( (Document) projection[1] ).getFieldable("equiptype") );
assertEquals( "equiptype incorrect", "Cisco", ( (Document) projection[1] ).getFieldable("equiptype" ).stringValue() );
assertNotNull( "branchnetwork is null", ( (Document) projection[1] ).getFieldable("branchnetwork") );
assertEquals( "branchnetwork incorrect", "St. George 1D", ( (Document) projection[1] ).getFieldable("branchnetwork" ).stringValue() );
assertTrue("incorrect result count returned", projections.isLast());
//cleanup
for (Object element : s.createQuery( "from " + Departments.class.getName() ).list()) s.delete( element );
tx.commit();
s.close();
}
/**
* This test checks for two fields being concatentated by the user-supplied
* CatFieldsClassBridge class which is specified as the implementation class
* in the ClassBridge annotation of the Department class.
*
* @throws Exception
*/
public void testClassBridge() throws Exception {
org.hibernate.Session s = openSession();
Transaction tx = s.beginTransaction();
s.persist( getDept1() );
s.persist( getDept2() );
s.persist( getDept3() );
s.flush();
tx.commit();
tx = s.beginTransaction();
FullTextSession session = Search.getFullTextSession( s );
// The branchnetwork field is the concatenation of both
// the branch field and the network field of the Department
// class. This is in the Lucene document but not in the
// Department entity itself.
QueryParser parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "branchnetwork", TestConstants.simpleAnalyzer );
Query query = parser.parse( "branchnetwork:layton 2B" );
org.hibernate.search.FullTextQuery hibQuery = session.createFullTextQuery( query, Department.class );
List result = hibQuery.list();
assertNotNull( result );
assertEquals( "incorrect entity returned, wrong network", "2B", ( (Department) result.get( 0 ) ).getNetwork() );
assertEquals( "incorrect entity returned, wrong branch", "Layton", ( (Department) result.get( 0 ) ).getBranch() );
assertEquals( "incorrect number of results returned", 1, result.size() );
// Partial match.
query = parser.parse( "branchnetwork:3c" );
hibQuery = session.createFullTextQuery( query, Department.class );
result = hibQuery.list();
assertNotNull( result );
assertEquals( "incorrect entity returned, wrong network", "3C", ( (Department) result.get( 0 ) ).getNetwork() );
assertEquals( "incorrect entity returned, wrong branch", "West Valley", ( (Department) result.get( 0 ) ).getBranch() );
assertEquals( "incorrect number of results returned", 1, result.size() );
// No data cross-ups .
query = parser.parse( "branchnetwork:Kent Lewin" );
hibQuery = session.createFullTextQuery( query, Department.class );
result = hibQuery.list();
assertNotNull( result );
assertTrue( "problem with field cross-ups", result.size() == 0 );
// Non-ClassBridge field.
parser = new QueryParser( TestConstants.getTargetLuceneVersion(), "branchHead", TestConstants.simpleAnalyzer );
query = parser.parse( "branchHead:Kent Lewin" );
hibQuery = session.createFullTextQuery( query, Department.class );
result = hibQuery.list();
assertNotNull( result );
assertTrue( "incorrect entity returned, wrong branch head", result.size() == 1 );
assertEquals("incorrect entity returned", "Kent Lewin", ( (Department) result.get( 0 ) ).getBranchHead());
//cleanup
for (Object element : s.createQuery( "from " + Department.class.getName() ).list()) s.delete( element );
tx.commit();
s.close();
}
private Department getDept1() {
Department dept = new Department();
dept.setBranch( "Salt Lake City" );
dept.setBranchHead( "Kent Lewin" );
dept.setMaxEmployees( 100 );
dept.setNetwork( "1A" );
return dept;
}
private Department getDept2() {
Department dept = new Department();
dept.setBranch( "Layton" );
dept.setBranchHead( "Terry Poperszky" );
dept.setMaxEmployees( 20 );
dept.setNetwork( "2B" );
return dept;
}
private Department getDept3() {
Department dept = new Department();
dept.setBranch( "West Valley" );
dept.setBranchHead( "Pat Kelley" );
dept.setMaxEmployees( 15 );
dept.setNetwork( "3C" );
return dept;
}
private Departments getDepts1() {
Departments depts = new Departments();
depts.setBranch( "Salt Lake City" );
depts.setBranchHead( "Kent Lewin" );
depts.setMaxEmployees( 100 );
depts.setNetwork( "1A" );
depts.setManufacturer( "C" );
return depts;
}
private Departments getDepts2() {
Departments depts = new Departments();
depts.setBranch( "Layton" );
depts.setBranchHead( "Terry Poperszky" );
depts.setMaxEmployees( 20 );
depts.setNetwork( "2B" );
depts.setManufacturer( "3" );
return depts;
}
private Departments getDepts3() {
Departments depts = new Departments();
depts.setBranch( "West Valley" );
depts.setBranchHead( "Pat Kelley" );
depts.setMaxEmployees( 15 );
depts.setNetwork( "3C" );
depts.setManufacturer( "D" );
return depts;
}
private Departments getDepts4() {
Departments depts = new Departments();
depts.setBranch( "St. George" );
depts.setBranchHead( "Spencer Stajskal" );
depts.setMaxEmployees( 10 );
depts.setNetwork( "1D" );
depts.setManufacturer( "C" );
return depts;
}
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {
Department.class,
Departments.class
};
}
protected void configure(Configuration cfg) {
super.configure( cfg );
cfg.setProperty( Environment.ANALYZER_CLASS, SimpleAnalyzer.class.getName() );
}
}