Max Rydahl Andersen wrote:


Sidequestion:
How transactional is the index update in it self ? If you are indexing 10 objects after tx.commit() and the 7th object fails to index does the 6 previous indexed objects go to the index or are the "rolled" back ?

No the file system changes are not transactional nor logged


/max

> What I expect to add is a better implementation of what's currently > happening. Especially, I want to batch all operations for a single > transaction using the same DirectoryProvider I/O (there are several > currently). But this is a speed improvement, not a behavioral change. > I'm also considering adding an asynchronous batch mode. but that's mode > a mid term work.
>
> WDYT?
>
> Richard Hallier wrote:
>>
>> Oui oui j'avais bien compris, je plaisantais :-)
>> J'avais une autre question tant que j'y étais, par rapport à la gestion
>> transactionnelle des opérations Lucene, y a t il quelque chose de prévu >> ?
>>
>> > -----Message d'origine-----
>> > De : Emmanuel Bernard [mailto:[EMAIL PROTECTED]
>> > Envoyé : vendredi 13 octobre 2006 16:00
>> > À : Richard Hallier
>> > Objet : Re: Hibernate Lucene & fields
>> >
>> > je parlais des Bridges pour toutes les propriétés
>> >
>> > Richard Hallier wrote:
>> > >
>> > > Développé dans l'avion? J'espère que tu as fait un vol long
>> > courrier
>> > > ;-) Tiens moi au courant pour le patch.
>> > > Richard
>> > >
>> > > > -----Message d'origine-----
>> > > > De : Emmanuel Bernard [mailto:[EMAIL PROTECTED]
>> > > > Envoyé : vendredi 13 octobre 2006 01:36 À : Richard
>> > Hallier Objet :
>> > > > Re: Hibernate Lucene & fields
>> > > >
>> > > > Si, je viens de le développer dans l'avion aujourd'hui ;-) Merci
>> > > > pour le patch je vais regarder ca demain
>> > > >
>> > > > Richard Hallier wrote:
>> > > > >
>> > > > > Salut Emmanuel,
>> > > > > Tu trouveras le patch en question en pièce jointe.
>> > > > > J'ai rajouté une classe de test plutot sommaire, cela
>> > > > peut-etre amélioré.
>> > > > >
>> > > > > J'ai une question. J'ai vu que la conversion (hors identifiant)
>> > > > > des properties des entités en valeur lucene se fait par
>> > une simple
>> > > > > conversion texte, alors que tu as mis en place pour la
>> > gestion de
>> > > > > l'identifiant un bridge. Ce concept de "converter" ne
>> > > > pourrait il pas
>> > > > > etre appliqué à toute conversion (pas seulement l'id) en
>> > > > valeur Lucene?
>> > > > >
>> > > > > Richard.
>> > > > >
>> > > > > > -----Message d'origine-----
>> > > > > > De : Emmanuel Bernard [mailto:[EMAIL PROTECTED] Envoyé :
>> > > > > > mercredi 11 octobre 2006 05:24 À :
>> > > > [EMAIL PROTECTED] Objet
>> > > > > > : Hibernate Lucene & fields
>> > > > > >
>> > > > > > Hi,
>> > > > > > I bet you're French so I'll switch to it.
>> > > > > >
>> > > > > > J'ai pensé au code qui permettrait d'annoter les attributs.
>> > > > > > En fait je voudrais utiliser une abstraction que l'on a
>> > > > écrit pour
>> > > > > > Hibernate Annotations. Cela abstrait le code de la résolution
>> > > > > > Generics de Java 5 et des propriétés vs attributs.
>> > > > > >
>> > > > > > Quand tu commences le patch, regarde
>> > > > > > org.hibernate.validator.ClassValidator, les accès aux
>> > > > annotations se
>> > > > > > font via  ReflectionManager reflectionManager = new
>> > > > JavaXFactory();
>> > > > > > dans la methode
>> > > > > > ClassValidator.initValidator(...)
>> > > > > >
>> > > > > > Si tu as des questions, n'hésites pas à me demander.
>> > > > > >
>> > > > > > Emmanuel
>> > > > > >
>> > > > >
>> > > > >
>> > > >
>> > --------------------------------------------------------------------
>> > > > --
>> > > > > --
>> > > > >
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/test/org/hibern
>> > > > at
>> > > > > e/lucene/test/FieldMappingTest.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/test/org/
>> > > > hibernate/lucene/test/FieldMappingTest.java   (revision 0)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/test/org/
>> > > > hibernate/lucene/test/FieldMappingTest.java   (revision 0)
>> > > > > @@ -0,0 +1,191 @@
>> > > > > +//$Id: LuceneTest.java 10014 2006-06-12 09:56:27 -0700
>> > > > (lun., 12 juin
>> > > > > +2006) epbernard $ package org.hibernate.lucene.test;
>> > > > > +
>> > > > > +import java.io.File;
>> > > > > +import java.util.List;
>> > > > > +
>> > > > > +import org.apache.lucene.analysis.StopAnalyzer;
>> > > > > +import org.apache.lucene.analysis.standard.StandardAnalyzer;
>> > > > > +import org.apache.lucene.index.IndexReader;
>> > > > > +import org.apache.lucene.index.Term; import
>> > > > > +org.apache.lucene.index.TermDocs; import
>> > > > > +org.apache.lucene.queryParser.QueryParser;
>> > > > > +import org.apache.lucene.search.Hits; import
>> > > > > +org.apache.lucene.search.IndexSearcher;
>> > > > > +import org.apache.lucene.search.Query; import
>> > > > org.hibernate.Session;
>> > > > > +import org.hibernate.event.PostDeleteEventListener;
>> > > > > +import org.hibernate.event.PostInsertEventListener;
>> > > > > +import org.hibernate.event.PostUpdateEventListener;
>> > > > > +import org.hibernate.lucene.Environment; import
>> > > > > +org.hibernate.lucene.store.FSDirectoryProvider;
>> > > > > +import org.hibernate.lucene.event.LuceneEventListener;
>> > > > > +
>> > > > > +/**
>> > > > > + * @author Richard Hallier
>> > > > > + */
>> > > > > +public class FieldMappingTest extends TestCase {
>> > > > > +
>> > > > > +
>> > > > > +   protected void setUp() throws Exception {
>> > > > > +           File sub = getBaseIndexDir();
>> > > > > +           sub.mkdir();
>> > > > > +           File[] files = sub.listFiles();
>> > > > > +           for (File file : files) {
>> > > > > +                   if ( file.isDirectory() ) {
>> > > > > +                           delete( file );
>> > > > > +                   }
>> > > > > +           }
>> > > > > +           //super.setUp(); //we need a fresh session
>> > > > factory each time for index set up
>> > > > > +           buildSessionFactory( getMappings(),
>> > > > getAnnotatedPackages(), getXmlFiles() );
>> > > > > +   }
>> > > > > +
>> > > > > +   private File getBaseIndexDir() {
>> > > > > +           File current = new File( "." );
>> > > > > +           File sub = new File( current, "indextemp" );
>> > > > > +           return sub;
>> > > > > +   }
>> > > > > +
>> > > > > +   protected void tearDown() throws Exception {
>> > > > > +           super.tearDown();
>> > > > > +           File sub = getBaseIndexDir();
>> > > > > +           delete( sub );
>> > > > > +   }
>> > > > > +
>> > > > > +   private void delete(File sub) {
>> > > > > +           if ( sub.isDirectory() ) {
>> > > > > +                   for ( File file : sub.listFiles() ) {
>> > > > > +                           delete( file );
>> > > > > +                   }
>> > > > > +                   sub.delete();
>> > > > > +           }
>> > > > > +           else {
>> > > > > +                   sub.delete();
>> > > > > +           }
>> > > > > +   }
>> > > > > +
>> > > > > +   public void testEventIntegration() throws Exception {
>> > > > > +
>> > > > > +
>> > > > > +           Session s = getSessions().openSession();
>> > > > > +           s.getTransaction().begin();
>> > > > > +           s.persist(
>> > > > > +                           new Document2( "Hibernate in
>> > > > Action", "Object/relational mapping with Hibernate", "blah blah
>> > > > blah" )
>> > > > > +           );
>> > > > > +           s.getTransaction().commit();
>> > > > > +           s.close();
>> > > > > +           IndexReader reader = IndexReader.open( new
>> > > > File( getBaseIndexDir(), "Documents" ) );
>> > > > > +           try {
>> > > > > +                   int num = reader.numDocs();
>> > > > > +                   assertEquals( 1, num );
>> > > > > +                   TermDocs docs = reader.termDocs( new
>> > > > Term( "Abstract", "Hibernate" ) );
>> > > > > +                   org.apache.lucene.document.Document doc
>> > > > = reader.document( docs.doc() );
>> > > > > +                   assertFalse( docs.next() );
>> > > > > +                   docs = reader.termDocs( new Term(
>> > > > "Title", "Action" ) );
>> > > > > +                   doc = reader.document( docs.doc() );
>> > > > > +                   assertFalse( docs.next() );
>> > > > > +                   assertEquals( "1", doc.getField( "id"
>> > > ).stringValue() );
>> > > > > +           }
>> > > > > +           finally {
>> > > > > +                   reader.close();
>> > > > > +           }
>> > > > > +
>> > > > > +           s = getSessions().openSession();
>> > > > > +           s.getTransaction().begin();
>> > > > > +           Document2 entity = (Document2) s.get(
>> > > > Document2.class, new Long( 1 ) );
>> > > > > +           entity.setSummary( "Object/relational mapping
>> > > > with EJB3" );
>> > > > > +           s.persist( new Document2( "Seam in Action", "",
>> > > > "blah blah blah blah" ) );
>> > > > > +           s.getTransaction().commit();
>> > > > > +           s.close();
>> > > > > +
>> > > > > +           reader = IndexReader.open( new File(
>> > > > getBaseIndexDir(), "Documents" ) );
>> > > > > +           try {
>> > > > > +                   int num = reader.numDocs();
>> > > > > +                   assertEquals( 2, num );
>> > > > > +                   TermDocs docs = reader.termDocs( new
>> > > > Term( "Abstract", "EJB3" ) );
>> > > > > +                   org.apache.lucene.document.Document doc
>> > > > = reader.document( docs.doc() );
>> > > > > +                   assertFalse( docs.next() );
>> > > > > +           }
>> > > > > +           finally {
>> > > > > +                   reader.close();
>> > > > > +           }
>> > > > > +
>> > > > > +           s = getSessions().openSession();
>> > > > > +           s.getTransaction().begin();
>> > > > > +           s.delete( entity );
>> > > > > +           s.getTransaction().commit();
>> > > > > +           s.close();
>> > > > > +
>> > > > > +           reader = IndexReader.open( new File(
>> > > > getBaseIndexDir(), "Documents" ) );
>> > > > > +           try {
>> > > > > +                   int num = reader.numDocs();
>> > > > > +                   assertEquals( 1, num );
>> > > > > +                   TermDocs docs = reader.termDocs( new
>> > > > Term( "Title", "Seam" ) );
>> > > > > +                   org.apache.lucene.document.Document doc
>> > > > = reader.document( docs.doc() );
>> > > > > +                   assertFalse( docs.next() );
>> > > > > +                   assertEquals( "2", doc.getField( "id"
>> > > ).stringValue() );
>> > > > > +           }
>> > > > > +           finally {
>> > > > > +                   reader.close();
>> > > > > +           }
>> > > > > +
>> > > > > +           s = getSessions().openSession();
>> > > > > +           s.getTransaction().begin();
>> > > > > +           s.delete( s.createCriteria( Document2.class
>> > > > ).uniqueResult() );
>> > > > > +           s.getTransaction().commit();
>> > > > > +           s.close();
>> > > > > +   }
>> > > > > +
>> > > > > +   public void testBoost() throws Exception {
>> > > > > +           Session s = getSessions().openSession();
>> > > > > +           s.getTransaction().begin();
>> > > > > +           s.persist(
>> > > > > +                           new Document2( "Hibernate in
>> > > > Action", "Object and Relational", "blah blah blah" )
>> > > > > +           );
>> > > > > +           s.persist(
>> > > > > +                           new Document2( "Object and
>> > > > Relational", "Hibernate in Action", "blah blah blah" )
>> > > > > +           );
>> > > > > +           s.getTransaction().commit();
>> > > > > +           s.close();
>> > > > > +
>> > > > > +           IndexSearcher searcher = new IndexSearcher( new
>> > > > File( getBaseIndexDir(), "Documents" ).getCanonicalPath() );
>> > > > > +           try {
>> > > > > +                   QueryParser qp = new QueryParser( "id",
>> > > > new StandardAnalyzer() );
>> > > > > +                   Query query = qp.parse( "title:Action
>> > > > OR Abstract:Action" );
>> > > > > +                   Hits hits = searcher.search( query );
>> > > > > +                   assertEquals( 2, hits.length() );
>> > > > > +                   assertTrue( hits.score( 0 ) == 2 *
>> > > > hits.score( 1 ) );
>> > > > > +                   assertEquals( "Hibernate in Action",
>> > > > hits.doc( 0 ).get( "title" ) );
>> > > > > +           }
>> > > > > +           finally {
>> > > > > +                   if ( searcher != null ) searcher.close();
>> > > > > +           }
>> > > > > +
>> > > > > +
>> > > > > +           s = getSessions().openSession();
>> > > > > +           s.getTransaction().begin();
>> > > > > +           List list = s.createQuery( "from Document2"
>> > ).list();
>> > > > > +           for ( Document2 document :
>> > (List<Document2>) list ) {
>> > > > > +                   s.delete( document );
>> > > > > +           }
>> > > > > +           s.getTransaction().commit();
>> > > > > +           s.close();
>> > > > > +   }
>> > > > > +
>> > > > > +   protected Class[] getMappings() {
>> > > > > +           return new Class[]{Document2.class};
>> > > > > +   }
>> > > > > +
>> > > > > +   protected void
>> > configure(org.hibernate.cfg.Configuration cfg) {
>> > > > > +           File sub = getBaseIndexDir();
>> > > > > +           cfg.setProperty(
>> > > > "hibernate.lucene.default.indexBase", sub.getAbsolutePath() );
>> > > > > +           cfg.setProperty(
>> > > > "hibernate.lucene.Clock.directory_provider",
>> > > > FSDirectoryProvider.class.getName() );
>> > > > > +           cfg.setProperty( Environment.ANALYZER_CLASS,
>> > > > StopAnalyzer.class.getName() );
>> > > > > + LuceneEventListener del = new LuceneEventListener(); >> > > > > + > > > >> cfg.getEventListeners().setPostCommitDeleteEventListeners(
>> > > > new PostDeleteEventListener[]{del} );
>> > > > > + > > > >> cfg.getEventListeners().setPostCommitUpdateEventListeners(
>> > > > new PostUpdateEventListener[]{del} );
>> > > > > + > > > >> cfg.getEventListeners().setPostCommitInsertEventListeners(
>> > > > new PostInsertEventListener[]{del} );
>> > > > > +   }
>> > > > > +
>> > > > > +}
>> > > > > +
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/test/org/hibern
>> > > > at
>> > > > > e/lucene/test/Document2.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/test/org/
>> > > > hibernate/lucene/test/Document2.java  (revision 0)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/test/org/
>> > > > hibernate/lucene/test/Document2.java  (revision 0)
>> > > > > @@ -0,0 +1,75 @@
>> > > > > +//$Id: Document.java 10566 2006-10-11 04:01:11Z epbernard
>> > > > $ package
>> > > > > +org.hibernate.lucene.test;
>> > > > > +
>> > > > > +import javax.persistence.Entity;
>> > > > > +import javax.persistence.GeneratedValue; import
>> > > > javax.persistence.Id;
>> > > > > +import javax.persistence.Lob;
>> > > > > +
>> > > > > +import org.hibernate.lucene.Indexed; import
>> > > > > +org.hibernate.lucene.Keyword; import
>> > org.hibernate.lucene.Text;
>> > > > > +import org.hibernate.lucene.Unstored; import
>> > > > > +org.hibernate.lucene.Boost;
>> > > > > +
>> > > > > [EMAIL PROTECTED]
>> > > > > [EMAIL PROTECTED](index = "Documents")
>> > > > > +public class Document2 {
>> > > > > +   @Id
>> > > > > +   @GeneratedValue
>> > > > > +   @Keyword(id = true)
>> > > > > +   private Long id;
>> > > > > +
>> > > > > +   @Text
>> > > > > +   @Boost(2)
>> > > > > +   private String title;
>> > > > > + > > > > +   @Unstored(name = "Abstract")
>> > > > > +   private String summary;
>> > > > > +
>> > > > > +   @Lob
>> > > > > +   @Unstored
>> > > > > +   private String text;
>> > > > > +
>> > > > > +   Document2() {
>> > > > > +   }
>> > > > > +
>> > > > > +   public Document2(String title, String summary,
>> > String text) {
>> > > > > +           super();
>> > > > > +           this.summary = summary;
>> > > > > +           this.text = text;
>> > > > > +           this.title = title;
>> > > > > +   }
>> > > > > +
>> > > > > +   public Long getId() {
>> > > > > +           return id;
>> > > > > +   }
>> > > > > +
>> > > > > +   public void setId(Long id) {
>> > > > > +           this.id = id;
>> > > > > +   }
>> > > > > +
>> > > > > +   public String getTitle() {
>> > > > > +           return title;
>> > > > > +   }
>> > > > > +
>> > > > > +   public void setTitle(String title) {
>> > > > > +           this.title = title;
>> > > > > +   }
>> > > > > +
>> > > > > +   public String getSummary() {
>> > > > > +           return summary;
>> > > > > +   }
>> > > > > +
>> > > > > +   public void setSummary(String summary) {
>> > > > > +           this.summary = summary;
>> > > > > +   }
>> > > > > +
>> > > > > +   public String getText() {
>> > > > > +           return text;
>> > > > > +   }
>> > > > > +
>> > > > > +   public void setText(String text) {
>> > > > > +           this.text = text;
>> > > > > +   }
>> > > > > +}
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/hibern
>> > > > at
>> > > > > e/lucene/event/LuceneEventListener.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/event/LuceneEventListener.java > (revision >> 10571)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/event/LuceneEventListener.java > (working >> copy)
>> > > > > @@ -99,13 +99,10 @@
>> > > > >              PersistentClass clazz = (PersistentClass)
>> > iter.next();
>> > > > >              Class<?> mappedClass = clazz.getMappedClass();
>> > > > >              if (mappedClass != null) {
>> > > > > -                if
>> > > > (mappedClass.isAnnotationPresent(Indexed.class)) {
>> > > > > -                    DirectoryProvider provider =
>> > > > factory.createDirectoryProvider(mappedClass, cfg);
>> > > > > -                    final DocumentBuilder<Object>
>> > > > documentBuilder = new DocumentBuilder<Object>(
>> > > > > -                            (Class<Object>) mappedClass,
>> > > > analyzer, provider
>> > > > > -                    );
>> > > > > -                    if (!indexLock.containsKey(provider)) {
>> > > > > -                        indexLock.put(provider, new
>> > > > ReentrantLock());
>> > > > > +                   final DocumentBuilder documentBuilder =
>> > > > DocumentBuilder.createDocumentBuilder(mappedClass, analyzer,
>> > > > factory, cfg);
>> > > > > +                if(documentBuilder!=null) {
>> > > > > +                    if
>> > > > (!indexLock.containsKey(documentBuilder.getDirectoryProvider())) { >> > > > > + > > > > >> + indexLock.put(documentBuilder.getDirectoryProvider(), new
>> > > > > + ReentrantLock());
>> > > > >                      }
>> > > > >                      documentBuilders.put(mappedClass,
>> > > > documentBuilder);
>> > > > >                  }
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/hibern
>> > > > at
>> > > > > e/lucene/Unstored.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/Unstored.java        (revision 10571)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/Unstored.java        (working copy)
>> > > > > @@ -8,7 +8,7 @@
>> > > > >  import java.lang.annotation.Target;
>> > > > >
>> > > > >  @Retention(RetentionPolicy.RUNTIME)
>> > > > > [EMAIL PROTECTED](ElementType.METHOD)
>> > > > > [EMAIL PROTECTED]({ElementType.METHOD, ElementType.FIELD})
>> > > > >  @Documented
>> > > > >  /**
>> > > > >   * Specifies that a property of an entity is a Lucene
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/hibern
>> > > > at
>> > > > > e/lucene/Keyword.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/Keyword.java (revision 10571)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/Keyword.java (working copy)
>> > > > > @@ -8,7 +8,7 @@
>> > > > >  import java.lang.annotation.Target;
>> > > > >
>> > > > >  @Retention(RetentionPolicy.RUNTIME)
>> > > > > [EMAIL PROTECTED](ElementType.METHOD)
>> > > > > [EMAIL PROTECTED]({ElementType.METHOD, ElementType.FIELD})
>> > > > >  @Documented
>> > > > >  /**
>> > > > >   * Specifies that a property of an entity is a Lucene
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/hibern
>> > > > at
>> > > > > e/lucene/Text.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/Text.java    (revision 10571)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/Text.java    (working copy)
>> > > > > @@ -8,7 +8,7 @@
>> > > > >  import java.lang.annotation.Target;
>> > > > >
>> > > > >  @Retention(RetentionPolicy.RUNTIME)
>> > > > > [EMAIL PROTECTED](ElementType.METHOD)
>> > > > > [EMAIL PROTECTED]({ElementType.METHOD, ElementType.FIELD})
>> > > > >  @Documented
>> > > > >  /**
>> > > > >   * Specifies that a property of an entity is a Lucene
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/hibern
>> > > > at
>> > > > > e/lucene/DocumentBuilder.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/DocumentBuilder.java (revision 10571)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/DocumentBuilder.java (working copy)
>> > > > > @@ -2,10 +2,6 @@
>> > > > >  package org.hibernate.lucene;
>> > > > >
>> > > > >  import java.io.Serializable;
>> > > > > -import java.lang.reflect.AccessibleObject;
>> > > > > -import java.lang.reflect.AnnotatedElement;
>> > > > > -import java.lang.reflect.Member;
>> > > > > -import java.lang.reflect.Method;
>> > > > >  import java.lang.reflect.Modifier;  import
>> > java.util.ArrayList; > > > > import java.util.Collections; @@ -17,31 >> +13,46 @@ import
>> > > > > org.apache.lucene.document.Document;
>> > > > >  import org.apache.lucene.document.Field;  import
>> > > > > org.apache.lucene.index.Term; -import
>> > > > org.hibernate.AssertionFailure;
>> > > > > import org.hibernate.HibernateException;
>> > > > > +import org.hibernate.cfg.Configuration;
>> > > > >  import org.hibernate.cfg.annotations.Version;
>> > > > >  import org.hibernate.lucene.bridge.BridgeFactory;
>> > > > >  import org.hibernate.lucene.bridge.FieldBridge;
>> > > > >  import org.hibernate.lucene.event.LuceneEventListener;
>> > > > >  import org.hibernate.lucene.store.DirectoryProvider;
>> > > > > +import org.hibernate.lucene.store.DirectoryProviderFactory;
>> > > > >  import org.hibernate.lucene.util.BinderHelper;
>> > > > > +import org.hibernate.reflection.ReflectionManager;
>> > > > > +import org.hibernate.reflection.XAnnotatedElement;
>> > > > > +import org.hibernate.reflection.XClass; import
>> > > > > +org.hibernate.reflection.XMember;
>> > > > > +import org.hibernate.reflection.XMethod; import
>> > > > > +org.hibernate.reflection.XProperty;
>> > > > > +import org.hibernate.reflection.java.JavaXFactory;
>> > > > >  import org.hibernate.util.ReflectHelper;
>> > > > >
>> > > > > -//TODO handle attribute (only getters are handled currently)
>> > > > > +/**
>> > > > > + * Set up and provide a manager for indexes classes
>> > > > > + *
>> > > > > + * @author Gavin King
>> > > > > + * @author Emmanuel Bernard
>> > > > > + * @author Sylvain Vieujot
>> > > > > + */
>> > > > >  public class DocumentBuilder<T> {
>> > > > >
>> > > > >      static {
>> > > > >          Version.touch(); //touch version
>> > > > >      }
>> > > > >
>> > > > > -    private final List<Member> keywordGetters = new
>> > > > ArrayList<Member>();
>> > > > > +    private final List<XMember> keywordGetters = new
>> > > > > + ArrayList<XMember>();
>> > > > >      private final List<String> keywordNames = new
>> > > > ArrayList<String>();
>> > > > > -    private final List<Member> unstoredGetters = new
>> > > > ArrayList<Member>();
>> > > > > +    private final List<XMember> unstoredGetters = new
>> > > > > + ArrayList<XMember>();
>> > > > >      private final List<String> unstoredNames = new
>> > > > ArrayList<String>();
>> > > > > -    private final List<Member> textGetters = new
>> > > > ArrayList<Member>();
>> > > > > +    private final List<XMember> textGetters = new
>> > > > > + ArrayList<XMember>();
>> > > > >      private final List<String> textNames = new
>> > > > > ArrayList<String>();
>> > > > >
>> > > > >      private final Class<T> beanClass;
>> > > > > + > > > > private final DirectoryProvider >> directoryProvider;
>> > > > >      private String idKeywordName;
>> > > > >      private final Analyzer analyzer; @@ -50,40 +61,30 @@
>> > > > >      private FieldBridge idBridge;
>> > > > > private Set<Class> mappedSubclasses = new HashSet<Class>();
>> > > > >
>> > > > > -    public DocumentBuilder(Class<T> clazz, Analyzer
>> > > > analyzer, DirectoryProvider directory) {
>> > > > > -        this.beanClass = clazz;
>> > > > > +   private ReflectionManager reflectionManager = new
>> > > > JavaXFactory();
>> > > > > +
>> > > > > +   private DocumentBuilder(Class<T> clazz, Analyzer analyzer,
>> > > > > +DirectoryProvider directory) {
>> > > > > +
>> > > > > +           XClass beanXClass =
>> > reflectionManager.toXClass( clazz );
>> > > > > +           if( !beanXClass.isAnnotationPresent(Indexed.class))
>> > > > > +                   throw new IllegalArgumentException();
>> > > > > +                 > > > > +           this.beanClass = clazz;
>> > > > >          this.analyzer = analyzer;
>> > > > >          this.directoryProvider = directory;
>> > > > >
>> > > > > -        for (Class currClass = clazz; currClass != null;
>> > > > currClass = currClass.getSuperclass()) {
>> > > > > -            Method[] methods = currClass.getDeclaredMethods();
>> > > > > -            for (int i = 0; i < methods.length; i++) {
>> > > > > -                Method method = methods[i];
>> > > > > -                Keyword keywordAnn =
>> > > > method.getAnnotation(Keyword.class);
>> > > > > -                if (keywordAnn != null) {
>> > > > > -                    String name =
>> > > > BinderHelper.getAttributeName(method, keywordAnn.name());
>> > > > > -                    if (keywordAnn.id()) {
>> > > > > -                        idKeywordName = name;
>> > > > > -                        idBoost = getBoost(method);
>> > > > > -                        idBridge =
>> > BridgeFactory.guessType(method);
>> > > > > -                    } else {
>> > > > > -                        setAccessible(method);
>> > > > > -                        keywordGetters.add(method);
>> > > > > -                        keywordNames.add(name);
>> > > > > -                    }
>> > > > > -                }
>> > > > > -                Unstored unstoredAnn =
>> > > > method.getAnnotation(Unstored.class);
>> > > > > -                if (unstoredAnn != null) {
>> > > > > -                    setAccessible(method);
>> > > > > -                    unstoredGetters.add(method);
>> > > > > - > > > >> unstoredNames.add(BinderHelper.getAttributeName(method,
>> > > > unstoredAnn.name()));
>> > > > > -                }
>> > > > > -                Text textAnn =
>> > method.getAnnotation(Text.class);
>> > > > > -                if (textAnn != null) {
>> > > > > -                    textGetters.add(method);
>> > > > > - > > > >> textNames.add(BinderHelper.getAttributeName(method,
>> > > > textAnn.name()));
>> > > > > -                }
>> > > > > -            }
>> > > > > +
>> > > > > +        for (XClass currClass = beanXClass; currClass !=
>> > > > null; currClass = currClass.getSuperclass()) {
>> > > > > +                   List<XMethod> methods =
>> > > > currClass.getDeclaredMethods();
>> > > > > +                   for ( XMethod method : methods ) {
>> > > > > + > >> createMemberLuceneAttribute( method );
>> > > > > +                   }
>> > > > > +
>> > > > > +                   // No filter applied = default filter (
>> > > > no transient, no static fields)
>> > > > > +                   List<XProperty> fields =
>> > > > currClass.getDeclaredProperties("field");
>> > > > > +                   for ( XProperty field : fields ) {
>> > > > > + > createMemberLuceneAttribute( field >> );
>> > > > > +                   }
>> > > > >          }
>> > > > >
>> > > > >          if (idKeywordName == null) { @@ -91,42 +92,84 @@
>> > > > >          }
>> > > > >      }
>> > > > >
>> > > > > +   public static <S> DocumentBuilder<S>
>> > > > createDocumentBuilder(Class<S> clazz, Analyzer analyzer,
>> > > > DirectoryProviderFactory factory, Configuration cfg)
>> > > > > +   {
>> > > > > +           DocumentBuilder<S> result = null;
>> > > > > +         > > > > +           try {
>> > > > > +                   result = new DocumentBuilder<S>(clazz,
>> > > > analyzer, factory.createDirectoryProvider(clazz, cfg));
>> > > > > +           }
>> > > > > +           catch (Exception e) {
>> > > > > +           }
>> > > > > +         > > > > +           return result;
>> > > > > +   }                     > > > >
>> > > > > -    private Float getBoost(AnnotatedElement element) {
>> > > > > +   private void createMemberLuceneAttribute(XMember member) {
>> > > > > +           Keyword keywordAnn =
>> > > > member.getAnnotation(Keyword.class);
>> > > > > +        if (keywordAnn != null) {
>> > > > > +            String name =
>> > > > BinderHelper.getAttributeName(member, keywordAnn.name());
>> > > > > +            if (keywordAnn.id()) {
>> > > > > +                idKeywordName = name;
>> > > > > +                idBoost = getBoost(member);
>> > > > > +                idBridge = BridgeFactory.guessType(member);
>> > > > > +            } else {
>> > > > > +                setAccessible(member);
>> > > > > +                keywordGetters.add(member);
>> > > > > +                keywordNames.add(name);
>> > > > > +            }
>> > > > > +        }
>> > > > > +
>> > > > > +        Unstored unstoredAnn =
>> > > > member.getAnnotation(Unstored.class);
>> > > > > +        if (unstoredAnn != null) {
>> > > > > +            setAccessible(member);
>> > > > > +            unstoredGetters.add(member);
>> > > > > + > > > >> unstoredNames.add(BinderHelper.getAttributeName(member,
>> > > > unstoredAnn.name()));
>> > > > > +        }
>> > > > > +
>> > > > > +        Text textAnn = member.getAnnotation(Text.class);
>> > > > > +        if (textAnn != null) {
>> > > > > +            setAccessible(member);
>> > > > > +            textGetters.add(member);
>> > > > > + > > > >> textNames.add(BinderHelper.getAttributeName(member,
>> > > > textAnn.name()));
>> > > > > +        }
>> > > > > +   }
>> > > > > +
>> > > > > +   private Float getBoost(XAnnotatedElement element) {
>> > > > >          if (element == null) return null;
>> > > > >          Boost boost = element.getAnnotation(Boost.class);
>> > > > >          return boost != null ?
>> > Float.valueOf(boost.value()) : null;
>> > > > >      }
>> > > > >
>> > > > > -    private Object getValue(Member member, T bean) {
>> > > > > -        try {
>> > > > > -            if (member instanceof java.lang.reflect.Field) {
>> > > > > -                return ((java.lang.reflect.Field)
>> > > > member).get(bean);
>> > > > > -            } else if (member instanceof Method) {
>> > > > > -                return ((Method) member).invoke(bean);
>> > > > > -            } else {
>> > > > > -                throw new AssertionFailure("Unexpected
>> > > > member: " + member.getClass().getName());
>> > > > > -            }
>> > > > > -        }
>> > > > > -        catch (Exception e) {
>> > > > > -            throw new IllegalStateException("Could not get
>> > > > property value", e);
>> > > > > -        }
>> > > > > +    private Object getMemberValue(XMember member, T bean) {
>> > > > > +           Object value;
>> > > > > +           try {
>> > > > > +                   value = member.invoke( bean );
>> > > > > +           }
>> > > > > +           catch (Exception e) {
>> > > > > +                   throw new IllegalStateException( "Could
>> > > > not get property value", e );
>> > > > > +           }
>> > > > > +           return value;
>> > > > >      }
>> > > > >
>> > > > >      public Document getDocument(T instance, Serializable id) {
>> > > > > +           XClass xClazz =
>> > > > reflectionManager.toXClass(instance.getClass());
>> > > > > +         > > > >          Document doc = new Document();
>> > > > > -        Float boost = getBoost(instance.getClass());
>> > > > > +        Float boost = getBoost(xClazz);
>> > > > >          if (boost != null) {
>> > > > >              doc.setBoost(boost.floatValue());
>> > > > >          }
>> > > > > +
>> > > > >          {
>> > > > > -            Field classField = new Field(CLASS_FIELDNAME,
>> > > > instance.getClass().getName(), Field.Store.YES, Field.Index.NO);
>> > > > > +            Field classField = new Field(CLASS_FIELDNAME,
>> > > > > + xClazz.getName(), Field.Store.YES, Field.Index.NO);
>> > > > >              doc.add(classField);
>> > > > >              idBridge.set(idKeywordName, id, doc,
>> > > > Field.Store.YES, Field.Index.UN_TOKENIZED, idBoost);
>> > > > >          }
>> > > > > + > > > > for (int i = 0; i < >> keywordNames.size(); i++) {
>> > > > > -            Member member = keywordGetters.get(i);
>> > > > > -            Object value = getValue(member, instance);
>> > > > > +            XMember member = keywordGetters.get(i);
>> > > > > +            Object value = getMemberValue(member, instance);
>> > > > >              if (value != null) {
>> > > > >                  Field field = new
>> > > > Field(keywordNames.get(i), toString(value), Field.Store.YES,
>> > > > Field.Index.UN_TOKENIZED);
>> > > > >                  boostField(field, member); @@ -134,8 +177,8 @@
>> > > > >              }
>> > > > >          }
>> > > > >          for (int i = 0; i < textNames.size(); i++) {
>> > > > > -            Member member = textGetters.get(i);
>> > > > > -            Object value = getValue(member, instance);
>> > > > > +            XMember member = textGetters.get(i);
>> > > > > +            Object value = getMemberValue(member, instance);
>> > > > >              if (value != null) {
>> > > > >                  Field field = new Field(textNames.get(i),
>> > > > toString(value), Field.Store.YES, Field.Index.TOKENIZED);
>> > > > >                  boostField(field, member); @@ -143,8 +186,8 @@
>> > > > >              }
>> > > > >          }
>> > > > >          for (int i = 0; i < unstoredNames.size(); i++) {
>> > > > > -            Member member = unstoredGetters.get(i);
>> > > > > -            Object value = getValue(member, instance);
>> > > > > +            XMember member = unstoredGetters.get(i);
>> > > > > +            Object value = getMemberValue(member, instance);
>> > > > >              if (value != null) {
>> > > > >                  Field field = new
>> > > > Field(unstoredNames.get(i), toString(value), Field.Store.NO,
>> > > > Field.Index.TOKENIZED);
>> > > > >                  boostField(field, member); @@ -155,8 +198,8 @@
>> > > > >          return doc;
>> > > > >      }
>> > > > >
>> > > > > -    private void boostField(Field field, Member member) {
>> > > > > -        Float boost = getBoost((AnnotatedElement) member);
>> > > > > +    private void boostField(Field field, XMember member) {
>> > > > > +        Float boost = getBoost(member);
>> > > > >          if (boost != null) field.setBoost(boost.floatValue());
>> > > > >      }
>> > > > >
>> > > > > @@ -176,11 +219,11 @@
>> > > > >          return analyzer;
>> > > > >      }
>> > > > >
>> > > > > -    private static void setAccessible(Member member) {
>> > > > > -        if (!Modifier.isPublic(member.getModifiers())) {
>> > > > > -            ((AccessibleObject) member).setAccessible(true);
>> > > > > -        }
>> > > > > -    }
>> > > > > +   private static void setAccessible(XMember member) {
>> > > > > + if ( !Modifier.isPublic( member.getModifiers() ) ) {
>> > > > > +                   member.setAccessible( true );
>> > > > > +           }
>> > > > > +   }
>> > > > >
>> > > > >      public FieldBridge getIdBridge() {
>> > > > >          return idBridge;
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/hibern
>> > > > at
>> > > > > e/lucene/Boost.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/Boost.java   (revision 10571)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/Boost.java   (working copy)
>> > > > > @@ -13,7 +13,7 @@
>> > > > >   * @author Emmanuel Bernard
>> > > > >   */
>> > > > >  @Retention(RetentionPolicy.RUNTIME)
>> > > > > [EMAIL PROTECTED]({ElementType.TYPE, ElementType.METHOD})
>> > > > > [EMAIL PROTECTED]({ElementType.TYPE, ElementType.METHOD,
>> > > > > +ElementType.FIELD})
>> > > > >  @Documented
>> > > > >  public @interface Boost {
>> > > > >     float value();
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/hibern
>> > > > at
>> > > > > e/lucene/bridge/BridgeFactory.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/bridge/BridgeFactory.java    (revision 10571)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/bridge/BridgeFactory.java    (working copy)
>> > > > > @@ -1,8 +1,6 @@
>> > > > >  //$Id: $
>> > > > >  package org.hibernate.lucene.bridge;
>> > > > >
>> > > > > -import java.lang.reflect.AnnotatedElement;
>> > > > > -import java.lang.reflect.Member;
>> > > > >  import java.util.Date;
>> > > > >  import java.util.HashMap;
>> > > > >  import java.util.Map;
>> > > > > @@ -10,6 +8,8 @@
>> > > > >  import org.hibernate.HibernateException;  import
>> > > > > org.hibernate.annotations.Parameter;
>> > > > >  import org.hibernate.lucene.util.BinderHelper;
>> > > > > +import org.hibernate.reflection.XClass; import
>> > > > > +org.hibernate.reflection.XMember;
>> > > > >
>> > > > >  /**
>> > > > >   * @author Emmanuel Bernard
>> > > > > @@ -62,9 +62,9 @@
>> > > > >             return new String2FieldBridgeAdaptor( date );
>> > > > >     }
>> > > > >
>> > > > > -   public static FieldBridge guessType(Member member) {
>> > > > > +   public static FieldBridge guessType(XMember member) {
>> > > > >             FieldBridge bridge = null;
>> > > > > -           org.hibernate.lucene.FieldBridge bridgeAnn = (
>> > > > (AnnotatedElement) member ).getAnnotation(
>> > > > org.hibernate.lucene.FieldBridge.class );
>> > > > > +           org.hibernate.lucene.FieldBridge bridgeAnn =
>> > > > member.getAnnotation(
>> > > > > +org.hibernate.lucene.FieldBridge.class );
>> > > > >             if (bridgeAnn != null) {
>> > > > >                     Class impl = bridgeAnn.impl();
>> > > > >                     try {
>> > > > > @@ -89,7 +89,7 @@
>> > > > >             }
>> > > > >             else {
>> > > > >                     //find in built-ins
>> > > > > -                   Class<?> returnType =
>> > > > BinderHelper.getReturnType( member );
>> > > > > +                   XClass returnType =
>> > > > BinderHelper.getReturnType( member );
>> > > > >                     bridge = builtInBridges.get(
>> > > > returnType.getName() );
>> > > > >             }
>> > > > >             if (bridge == null) throw new
>> > > > HibernateException("Unable to guess
>> > > > > FieldBridge for " + BinderHelper.getAttributeName(member) );
>> > > > > Index:
>> > > > >
>> > > >
>> > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/hibern
>> > > > at
>> > > > > e/lucene/util/BinderHelper.java
>> > > > >
>> > ==================================================================
>> > > > > =
>> > > > > ---
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/util/BinderHelper.java       (revision 10571)
>> > > > > +++
>> > > > C:/dev/source/workspace1.5/HibernateExt/metadata/src/java/org/
>> > > > hibernate/lucene/util/BinderHelper.java       (working copy)
>> > > > > @@ -1,11 +1,13 @@
>> > > > >  //$Id: $
>> > > > >  package org.hibernate.lucene.util;
>> > > > >
>> > > > > -import java.lang.reflect.Method;
>> > > > > -import java.lang.reflect.Member;
>> > > > > -import java.lang.reflect.Field;
>> > > > >  import java.beans.Introspector;
>> > > > >
>> > > > > +import org.hibernate.AssertionFailure; import
>> > > > > +org.hibernate.reflection.XClass; import
>> > > > > +org.hibernate.reflection.XMember;
>> > > > > +import org.hibernate.reflection.XMethod; import
>> > > > > +org.hibernate.reflection.XProperty;
>> > > > >  import org.hibernate.util.StringHelper;
>> > > > >
>> > > > >  /**
>> > > > > @@ -15,37 +17,41 @@
>> > > > >
>> > > > >     private BinderHelper() {}
>> > > > >
>> > > > > -   public static String getAttributeName(Member member) {
>> > > > > +   public static String getAttributeName(XMember member) {
>> > > > >             return getAttributeName( member, null );
>> > > > >     }
>> > > > >     /**
>> > > > >      * Get attribute name out of member unless overriden by
>> > > > <code>name</code>
>> > > > >      */
>> > > > > -   //TODO move to reflection layer
>> > > > > -   public static String getAttributeName(Member member,
>> > > > String name) {
>> > > > > -           if( StringHelper.isNotEmpty( name ) ) return
>> > > > name; //explicit field name
>> > > > > -           if (member instanceof Field ) {
>> > > > > -                   return ( (Field) member ).getName();
>> > > > > +   public static String getAttributeName(XMember member,
>> > > > String name) {
>> > > > > +           return StringHelper.isNotEmpty( name ) ? name :
>> > > > getPropertyName(member);
>> > > > > +   }
>> > > > > +
>> > > > > +   public static XClass getReturnType(XMember member) {
>> > > > > +           return member.getType();
>> > > > > +   }
>> > > > > + > > > > + // Could be located in a better place, shared >> method
>> > > > with ClassValidator
>> > > > > +   public static String getPropertyName(XMember member) {
>> > > > > +           //Do no try to cache the result in a map, it's
>> > > > actually much slower (2.x time)
>> > > > > +           String propertyName;
>> > > > > +           if ( XProperty.class.isAssignableFrom(
>> > > > member.getClass() ) ) {
>> > > > > +                   propertyName = member.getName();
>> > > > >             }
>> > > > > -           else {
>> > > > > -                   //decapitalize
>> > > > > -                   String methodName = ( (Method)
>> > > > member).getName();
>> > > > > -                   //FIXME we probably should exclude
>> > > > methods not starting with "get" nor "is"
>> > > > > -                   int startIndex = 3;
>> > > > > -                   if( methodName.startsWith("is") ) {
>> > > > > -                           startIndex = 2;
>> > > > > +           else if ( XMethod.class.isAssignableFrom(
>> > > > member.getClass() ) ) {
>> > > > > +                   propertyName = member.getName();
>> > > > > +                   if ( propertyName.startsWith( "is" ) ) {
>> > > > > +                           propertyName =
>> > > > Introspector.decapitalize( propertyName.substring(
>> > > > > +2 ) );
>> > > > >                     }
>> > > > > -                   return Introspector.decapitalize(
>> > > > methodName.substring( startIndex ) );
>> > > > > +                   else if ( propertyName.startsWith(
>> > "get" ) ) {
>> > > > > +                           propertyName =
>> > > > Introspector.decapitalize( propertyName.substring( 3 ) );
>> > > > > +                   }
>> > > > > +                   //do nothing for non getter method, in
>> > > > case someone want to
>> > > > > +validate a PO Method
>> > > > >             }
>> > > > > -   }
>> > > > > -
>> > > > > -   //TODO move to reflection layer
>> > > > > -   public static Class<?> getReturnType(Member member) {
>> > > > > -           if (member instanceof Field) {
>> > > > > -                   return ( (Field) member ).getType();
>> > > > > -           }
>> > > > >             else {
>> > > > > -                   return ( (Method) member ).getReturnType();
>> > > > > +                   throw new AssertionFailure( "Unexpected
>> > > > member: " +
>> > > > > +member.getClass().getName() );
>> > > > >             }
>> > > > > +           return propertyName;
>> > > > >     }
>> > > > > +
>> > > > >  }
>> > > > > > > >
>> > >
>> >
>>
> _______________________________________________
> hibernate-dev mailing list
> [email protected]
> https://lists.jboss.org/mailman/listinfo/hibernate-dev



--
--
Max Rydahl Andersen
callto://max.rydahl.andersen

Hibernate
[EMAIL PROTECTED]
http://hibernate.org

JBoss a division of Red Hat
[EMAIL PROTECTED]

_______________________________________________
hibernate-dev mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/hibernate-dev

Reply via email to