[hibernate-dev] Transactional Lucene index

Emmanuel Bernard emmanuel at hibernate.org
Mon Oct 16 08:30:22 EDT 2006



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:emmanuel.bernard at jboss.com]
> >> > 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:emmanuel.bernard at jboss.com]
> >> > > > 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:emmanuel at hibernate.org] 
> Envoyé :
> >> > > > > > mercredi 11 octobre 2006 05:24 À :
> >> > > > richard.hallier at freesbee.fr 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;
> >> > > > > +
> >> > > > > + at Entity
> >> > > > > + at Indexed(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)
> >> > > > > - at Target(ElementType.METHOD)
> >> > > > > + at Target({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)
> >> > > > > - at Target(ElementType.METHOD)
> >> > > > > + at Target({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)
> >> > > > > - at Target(ElementType.METHOD)
> >> > > > > + at Target({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)
> >> > > > > - at Target({ElementType.TYPE, ElementType.METHOD})
> >> > > > > + at Target({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
> > hibernate-dev at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
>
>
> --
> --
> Max Rydahl Andersen
> callto://max.rydahl.andersen
>
> Hibernate
> max at hibernate.org
> http://hibernate.org
>
> JBoss a division of Red Hat
> max.andersen at jboss.com
>



More information about the hibernate-dev mailing list