Package org.hibernate.search.test.envers

Source Code of org.hibernate.search.test.envers.SearchAndEnversIntegrationTest

/*
* 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.envers;

import java.util.List;

import org.apache.lucene.analysis.core.StopAnalyzer;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;

import org.hibernate.Transaction;

import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.hibernate.envers.query.AuditEntity;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.test.SearchTestBase;
import org.hibernate.search.testsupport.TestConstants;
import org.hibernate.search.testsupport.TestForIssue;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

/**
* Unit test covering proper behavior and integration between Hibernate Search and Envers.
* As well as it verifies that the index is in sync with the latest transaction state.
*
* @author Davide Di Somma <davide.disomma@gmail.com>
*/
public class SearchAndEnversIntegrationTest extends SearchTestBase {

  private Person harryPotter;
  private Person hermioneGranger;
  private Address privetDrive;
  private Address grimmauldPlace;

  /**
   * This test case aims to verify that insertion, updating and deleting operations work correctly
   * for both Hibernate Search and Hibernate Envers
   */
  @TestForIssue(jiraKey = "HSEARCH-1293")
  @Test
  public void testHibernateSearchAndEnversIntegration() {
    atRevision1();
    atRevision2();
    atRevision3();
    atRevision4();
  }

  /**
   * It verifies that insertion operation works correctly
   */
  private void atRevision1() {
    // Objects creation
    privetDrive = new Address( "Privet Drive", 121 );
    privetDrive.setFlatNumber( 2 );
    harryPotter = new Person( "Harry", "Potter", privetDrive );
    grimmauldPlace = new Address( "Grimmauld Place", 12 );
    hermioneGranger = new Person( "Hermione", "Granger", grimmauldPlace );

    {
      FullTextSession session = Search.getFullTextSession( openSession() );
      try {
        Transaction tx = session.beginTransaction();
        session.save( privetDrive );
        session.save( grimmauldPlace );
        session.save( harryPotter );
        session.save( hermioneGranger );
        tx.commit();
      }
      finally {
        session.close();
      }
    }

    {
      FullTextSession session = Search.getFullTextSession( openSession() );
      try {
        Transaction tx = session.beginTransaction();

        //Let's assert that Hibernate Envers has audited correctly
        AuditReader auditReader = AuditReaderFactory.get( session );
        assertEquals( 1, findLastRevisionForEntity( auditReader, Person.class ) );
        assertEquals( 1, findLastRevisionForEntity( auditReader, Address.class ) );
        assertEquals( 2, howManyEntitiesChangedAtRevisionNumber( auditReader, Person.class, 1 ) );
        assertEquals( 2, howManyEntitiesChangedAtRevisionNumber( auditReader, Address.class, 1 ) );
        assertEquals( 2, howManyAuditedObjectsSoFar( auditReader, Person.class ) );
        assertEquals( 2, howManyAuditedObjectsSoFar( auditReader, Address.class ) );
        //Let's compares that entities from Hibernate Search and last revision entities from Hibernate Envers are equals
        Person hermioneFromHibSearch = findPersonFromIndexBySurname( session, "Granger" );
        Person hermioneAtRevision1 = findPersonFromAuditBySurname( auditReader, "Granger" );
        assertEquals( hermioneFromHibSearch, hermioneAtRevision1 );
        Person harryFromHibSearch = findPersonFromIndexBySurname( session, "Potter" );
        Person harryAtRevision1 = findPersonFromAuditBySurname( auditReader, "Potter" );
        assertEquals( harryFromHibSearch, harryAtRevision1 );

        tx.commit();
      }
      finally {
        session.close();
      }
    }
  }

  /**
   * It verifies that updating operation on Address entity works correctly
   */
  private void atRevision2() {
    // Changing the address's house number and flat number
    {
      FullTextSession session = Search.getFullTextSession( openSession() );
      try {
        Transaction tx = session.beginTransaction();

        privetDrive = (Address) session.merge( privetDrive );
        privetDrive.setHouseNumber( 5 );
        privetDrive.setFlatNumber( null );

        tx.commit();
      }
      finally {
        session.close();
      }
    }

    {
      FullTextSession session = Search.getFullTextSession( openSession() );
      try {
        Transaction tx = session.beginTransaction();
        AuditReader auditReader = AuditReaderFactory.get( session );

        //Let's assert that Hibernate Envers has audited everything correctly
        assertEquals( 1, findLastRevisionForEntity( auditReader, Person.class ) );
        assertEquals( 2, findLastRevisionForEntity( auditReader, Address.class ) );
        assertEquals( 0, howManyEntitiesChangedAtRevisionNumber( auditReader, Person.class, 2 ) );
        assertEquals( 1, howManyEntitiesChangedAtRevisionNumber( auditReader, Address.class, 2 ) );
        assertEquals( 2, howManyAuditedObjectsSoFar( auditReader, Person.class ) );
        assertEquals( 3, howManyAuditedObjectsSoFar( auditReader, Address.class ) );
        @SuppressWarnings("unchecked")
        List<Address> houseNumberAddressChangedAtRevision2 = auditReader.createQuery()
            .forEntitiesModifiedAtRevision( Address.class, 2 )
            .add( AuditEntity.property( "houseNumber" ).hasChanged() )
            .add( AuditEntity.property( "flatNumber" ).hasChanged() )
            .add( AuditEntity.property( "streetName" ).hasNotChanged() ).getResultList();
        assertEquals( 1, houseNumberAddressChangedAtRevision2.size() );

        //Let's assert that Hibernate Search has indexed everything correctly
        List<Person> peopleLivingInPrivetDriveFromHibSearch = findPeopleFromIndexByStreetName( session, "Privet" );
        assertEquals( 1, peopleLivingInPrivetDriveFromHibSearch.size() );
        //Let's compare that entities from Hibernate Search and last revision entities from Hibernate Envers are equals
        Person harryFromHibSearch = peopleLivingInPrivetDriveFromHibSearch.get( 0 );
        Person harryAtRevision2 = findPersonFromAuditBySurname( auditReader, "Potter" );
        assertEquals( harryFromHibSearch, harryAtRevision2 );

        tx.commit();
      }
      finally {
        session.close();
      }
    }
  }

  /**
   * It verifies that updating operation on Person entity works correctly
   */
  private void atRevision3() {
    // Moving Hermione to Harry
    {
      FullTextSession session = Search.getFullTextSession( openSession() );
      try {
        Transaction tx = session.beginTransaction();

        hermioneGranger = (Person) session.merge( hermioneGranger );
        hermioneGranger.setAddress( privetDrive );

        tx.commit();
      }
      finally {
        session.close();
      }
    }

    {
      FullTextSession session = Search.getFullTextSession( openSession() );
      try {
        Transaction tx = session.beginTransaction();
        AuditReader auditReader = AuditReaderFactory.get( session );

        //Let's assert that Hibernate Envers has audited everything correctly
        @SuppressWarnings("unchecked")
        List<Person> peopleWhoHasMovedHouseAtRevision3 = auditReader.createQuery()
            .forEntitiesModifiedAtRevision( Person.class, 3 ).add( AuditEntity.property( "address" ).hasChanged() )
            .getResultList();
        assertEquals( 1, peopleWhoHasMovedHouseAtRevision3.size() );
        assertEquals( 3, findLastRevisionForEntity( auditReader, Person.class ) );
        assertEquals( 3, findLastRevisionForEntity( auditReader, Address.class ) );
        assertEquals( 1, howManyEntitiesChangedAtRevisionNumber( auditReader, Person.class, 3 ) );
        assertEquals( 2, howManyEntitiesChangedAtRevisionNumber( auditReader, Address.class, 3 ) );
        assertEquals( 3, howManyAuditedObjectsSoFar( auditReader, Person.class ) );
        assertEquals( 5, howManyAuditedObjectsSoFar( auditReader, Address.class ) );
        //Let's assert that Hibernate Search has indexed everything correctly
        List<Person> peopleLivingInPrivetDriveFromHibSearch = findPeopleFromIndexByStreetName( session, "Privet" );
        assertEquals( 2, peopleLivingInPrivetDriveFromHibSearch.size() );

        tx.commit();
      }
      finally {
        session.close();
      }
    }
  }

  /**
   * It verifies that deleting operation on Person entity works correctly
   */
  private void atRevision4() {
    // Now let's clean up everything
    {
      FullTextSession session = Search.getFullTextSession( openSession() );
      try {
        Transaction tx = session.beginTransaction();
        session.delete( harryPotter );
        session.delete( hermioneGranger );
        session.delete( grimmauldPlace );
        session.delete( privetDrive );
        tx.commit();
      }
      finally {
        session.close();
      }
    }

    {
      FullTextSession session = Search.getFullTextSession( openSession() );
      try {
        Transaction tx = session.beginTransaction();
        AuditReader auditReader = AuditReaderFactory.get( session );

        //Let's assert that Hibernate Envers has audited everything correctly
        assertEquals( 4, findLastRevisionForEntity( auditReader, Person.class ) );
        assertEquals( 4, findLastRevisionForEntity( auditReader, Address.class ) );
        assertEquals( 2, howManyEntitiesChangedAtRevisionNumber( auditReader, Person.class, 4 ) );
        assertEquals( 2, howManyEntitiesChangedAtRevisionNumber( auditReader, Address.class, 4 ) );
        assertEquals( 7, howManyAuditedObjectsSoFar( auditReader, Address.class ) );
        assertEquals( 5, howManyAuditedObjectsSoFar( auditReader, Person.class ) );
        //Let's assert that Hibernate Search has indexed everything correctly
        assertNull( findPersonFromIndexBySurname( session, "Potter" ) );
        assertNull( findPersonFromIndexBySurname( session, "Granger" ) );
        assertEquals( 0, findPeopleFromIndexByStreetName( session, "Privet" ).size() );
        assertEquals( 0, findPeopleFromIndexByStreetName( session, "Guillaume" ).size() );

        tx.commit();
      }
      finally {
        session.close();
      }
    }
  }

  /**
   * It returns how many entities are modified for a specific class and number revision.
   */
  private int howManyEntitiesChangedAtRevisionNumber(AuditReader auditReader, Class<?> clazz, Number revision) {
    return ( (Long) auditReader.createQuery().forEntitiesModifiedAtRevision( clazz, revision )
        .addProjection( AuditEntity.id().count() ).getSingleResult() ).intValue();
  }

  /**
   * It returns how many audited objects are there globally for a specific class.
   */
  private int howManyAuditedObjectsSoFar(AuditReader auditReader, Class<?> clazz) {
    return auditReader.createQuery().forRevisionsOfEntity( clazz, true, true ).getResultList().size();
  }

  /**
   * It returns the last revision for a specific class.
   */
  private Number findLastRevisionForEntity(AuditReader auditReader, Class<?> clazz) {
    return (Number) auditReader.createQuery().forRevisionsOfEntity( clazz, false, true )
        .addProjection( AuditEntity.revisionNumber().max() ).getSingleResult();
  }

  private Person findPersonFromAuditBySurname(AuditReader auditReader, String value) {
    return (Person) auditReader.createQuery().forEntitiesAtRevision( Person.class, 1 )
        .add( AuditEntity.property( "surname" ).eq( value ) ).getSingleResult();
  }

  @SuppressWarnings("unchecked")
  private List<Person> findPeopleFromIndex(FullTextSession session, String term, String value) {
    Query luceneQuery = createLuceneQuery( term, value );
    return session.createFullTextQuery( luceneQuery, Person.class )
        .setSort( new Sort( new SortField( "surname", SortField.Type.STRING ) ) ).list();
  }

  private Person findPersonFromIndexBySurname(FullTextSession session, String surname) {
    List<Person> people = findPeopleFromIndex( session, "surname", surname );
    if ( people.isEmpty() ) {
      return null;
    }
    else if ( people.size() > 1 ) {
      throw new RuntimeException( "I've found too many people!!!" );
    }
    return people.get( 0 );
  }

  private List<Person> findPeopleFromIndexByStreetName(FullTextSession session, String streetName) {
    return findPeopleFromIndex( session, "address.streetName", streetName );
  }

  private Query createLuceneQuery(String term, String value) {
    String searchQuery = term + ":" + value;
    QueryParser parser = new QueryParser(
        TestConstants.getTargetLuceneVersion(),
        term,
        new StopAnalyzer( TestConstants.getTargetLuceneVersion() )
    );
    Query luceneQuery;
    try {
      luceneQuery = parser.parse( searchQuery );
    }
    catch (ParseException e) {
      throw new RuntimeException( "Unable to parse query", e );
    }
    return luceneQuery;
  }

  @Override
  protected Class<?>[] getAnnotatedClasses() {
    return new Class[] { Person.class, Address.class };
  }
}
TOP

Related Classes of org.hibernate.search.test.envers.SearchAndEnversIntegrationTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.