[hibernate-commits] Hibernate SVN: r11279 - in branches/Branch_3_2/HibernateExt/search: src/java/org/hibernate/search/annotations and 12 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Mar 14 16:57:53 EDT 2007


Author: epbernard
Date: 2007-03-14 16:57:53 -0400 (Wed, 14 Mar 2007)
New Revision: 11279

Added:
   branches/Branch_3_2/HibernateExt/search/lib/lucene-core-2.1.0.jar
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/annotations/ContainedIn.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/AddLuceneWork.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteLuceneWork.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/LuceneWork.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Work.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/WorkType.java
Removed:
   branches/Branch_3_2/HibernateExt/search/lib/lucene-core-2.0.0.jar
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/AddWork.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteWork.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/UpdateWork.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Work.java
Modified:
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/BackendQueueProcessorFactory.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/QueueingProcessor.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Worker.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/PostTransactionWorkQueueSynchronization.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/AbstractJMSHibernateSearchController.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/JMSBackendQueueProcessor.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/JMSBackendQueueProcessorFactory.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessorFactory.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/event/FullTextIndexEventListener.java
   branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/impl/FullTextSessionImpl.java
   branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/FSDirectoryTest.java
   branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/directoryProvider/FSSlaveAndMasterDPTest.java
   branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Address.java
   branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java
   branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/jms/master/JMSMasterTest.java
   branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/jms/slave/SearchQueueChecker.java
Log:
HSEARCH-27 add @ContainedIn
HSEARCH-31 move to Lucene 2.1

Deleted: branches/Branch_3_2/HibernateExt/search/lib/lucene-core-2.0.0.jar
===================================================================
(Binary files differ)

Added: branches/Branch_3_2/HibernateExt/search/lib/lucene-core-2.1.0.jar
===================================================================
(Binary files differ)


Property changes on: branches/Branch_3_2/HibernateExt/search/lib/lucene-core-2.1.0.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/annotations/ContainedIn.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/annotations/ContainedIn.java	                        (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/annotations/ContainedIn.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -0,0 +1,40 @@
+//$Id: $
+package org.hibernate.search.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Documented;
+
+/**
+ * Describe the owning entity as being part of the target entity's
+ * index (to be more accurate, being part of the indexed object graph)
+ *
+ * Only necessary when an @Indexed class is used as a @IndexedEmbedded
+ * target class. @ContainedIn must mark the property pointing back
+ * to the @IndexedEmbedded owning Entity
+ *
+ * Not necessary if the class is an @Embeddable class.
+ *
+ * <code>
+ * @Indexed
+ * public class OrderLine {
+ *     @IndexedEmbedded
+ *     private Order order;
+ * }
+ *
+ * @Indexed
+ * public class Order {
+ *     @ContainedBy
+ *     Set<OrderLine> lines;
+ * }
+ * </code>
+ *
+ * @author Emmanuel Bernard
+ */
+ at Retention( RetentionPolicy.RUNTIME )
+ at Target( {ElementType.FIELD, ElementType.METHOD} )
+ at Documented
+public @interface ContainedIn {
+}

Copied: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/AddLuceneWork.java (from rev 11171, branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/AddWork.java)
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/AddLuceneWork.java	                        (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/AddLuceneWork.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -0,0 +1,15 @@
+//$Id: $
+package org.hibernate.search.backend;
+
+import java.io.Serializable;
+
+import org.apache.lucene.document.Document;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class AddLuceneWork extends LuceneWork {
+	public AddLuceneWork(Serializable id, Class entity, Document document) {
+		super( id, entity, document );
+	}
+}

Deleted: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/AddWork.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/AddWork.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/AddWork.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -1,15 +0,0 @@
-//$Id: $
-package org.hibernate.search.backend;
-
-import java.io.Serializable;
-
-import org.apache.lucene.document.Document;
-
-/**
- * @author Emmanuel Bernard
- */
-public class AddWork extends Work {
-	public AddWork(Serializable id, Class entity, Document document) {
-		super( id, entity, document );
-	}
-}

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/BackendQueueProcessorFactory.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/BackendQueueProcessorFactory.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/BackendQueueProcessorFactory.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -20,5 +20,5 @@
 	 * Return a runnable implementation responsible for processing the queue to a given backend
 	 */
 
-	Runnable getProcessor(List<Work> queue);
+	Runnable getProcessor(List<LuceneWork> queue);
 }

Copied: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteLuceneWork.java (from rev 11171, branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteWork.java)
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteLuceneWork.java	                        (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteLuceneWork.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -0,0 +1,13 @@
+//$Id: $
+package org.hibernate.search.backend;
+
+import java.io.Serializable;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class DeleteLuceneWork extends LuceneWork {
+	public DeleteLuceneWork(Serializable id, Class entity) {
+		super( id, entity );
+	}
+}

Deleted: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteWork.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteWork.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteWork.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -1,13 +0,0 @@
-//$Id: $
-package org.hibernate.search.backend;
-
-import java.io.Serializable;
-
-/**
- * @author Emmanuel Bernard
- */
-public class DeleteWork extends Work {
-	public DeleteWork(Serializable id, Class entity) {
-		super( id, entity );
-	}
-}

Copied: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/LuceneWork.java (from rev 11171, branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Work.java)
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/LuceneWork.java	                        (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/LuceneWork.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -0,0 +1,40 @@
+//$Id: $
+package org.hibernate.search.backend;
+
+import java.io.Serializable;
+
+import org.apache.lucene.document.Document;
+
+/**
+ * Represent a Serializable Lucene unit work
+ *
+ * @author Emmanuel Bernard
+ */
+public abstract class LuceneWork implements Serializable {
+	private Document document;
+	private Class entityClass;
+	private Serializable id;
+
+	public LuceneWork(Serializable id, Class entity) {
+		this( id, entity, null );
+	}
+
+	public LuceneWork(Serializable id, Class entity, Document document) {
+		this.id = id;
+		this.entityClass = entity;
+		this.document = document;
+	}
+
+
+	public Document getDocument() {
+		return document;
+	}
+
+	public Class getEntityClass() {
+		return entityClass;
+	}
+
+	public Serializable getId() {
+		return id;
+	}
+}

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/QueueingProcessor.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/QueueingProcessor.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/QueueingProcessor.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -2,8 +2,9 @@
 package org.hibernate.search.backend;
 
 import java.util.List;
+import java.io.Serializable;
 
-import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.LuceneWork;
 
 /**
  * Pile work operations
@@ -15,8 +16,9 @@
 public interface QueueingProcessor {
 	/**
 	 * Add a work
+	 * TODO move that womewhere else, it does not really fit here
 	 */
-	void add(Work work, List<Work> queue);
+	void add(Object entity, Serializable id, WorkType workType, List<Work> queue);
 
 	/**
 	 * Execute works

Deleted: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/UpdateWork.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/UpdateWork.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/UpdateWork.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -1,15 +0,0 @@
-//$Id: $
-package org.hibernate.search.backend;
-
-import java.io.Serializable;
-
-import org.apache.lucene.document.Document;
-
-/**
- * @author Emmanuel Bernard
- */
-public class UpdateWork extends Work {
-	public UpdateWork(Serializable id, Class entity, Document document) {
-		super( id, entity, document );
-	}
-}

Deleted: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Work.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Work.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Work.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -1,40 +0,0 @@
-//$Id: $
-package org.hibernate.search.backend;
-
-import java.io.Serializable;
-
-import org.apache.lucene.document.Document;
-
-/**
- * Represent a Lucene unit work
- *
- * @author Emmanuel Bernard
- */
-public abstract class Work implements Serializable {
-	private Document document;
-	private Class entity;
-	private Serializable id;
-
-	public Work(Serializable id, Class entity) {
-		this( id, entity, null );
-	}
-
-	public Work(Serializable id, Class entity, Document document) {
-		this.id = id;
-		this.entity = entity;
-		this.document = document;
-	}
-
-
-	public Document getDocument() {
-		return document;
-	}
-
-	public Class getEntity() {
-		return entity;
-	}
-
-	public Serializable getId() {
-		return id;
-	}
-}

Added: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Work.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Work.java	                        (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Work.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -0,0 +1,48 @@
+//$Id: $
+package org.hibernate.search.backend;
+
+import java.io.Serializable;
+
+import org.hibernate.annotations.common.reflection.XMember;
+
+/**
+ * work unit. Only make sense inside the same session since it uses the scope principle
+ *
+ * @author Emmanuel Bernard
+ */
+public class Work {
+	private Object entity;
+	private Serializable id;
+	private XMember idGetter;
+	private WorkType type;
+
+
+	public Work(Object entity, Serializable id, WorkType type) {
+		this.entity = entity;
+		this.id = id;
+		this.type = type;
+	}
+
+
+	public Work(Object entity, XMember idGetter, WorkType type) {
+		this.entity = entity;
+		this.idGetter = idGetter;
+		this.type = type;
+	}
+
+	public Object getEntity() {
+		return entity;
+	}
+
+	public Serializable getId() {
+		return id;
+	}
+
+	public XMember getIdGetter() {
+		return idGetter;
+	}
+
+	public WorkType getType() {
+		return type;
+	}
+}

Added: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/WorkType.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/WorkType.java	                        (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/WorkType.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -0,0 +1,12 @@
+//$Id: $
+package org.hibernate.search.backend;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public enum WorkType {
+	ADD,
+	UPDATE,
+	DELETE
+	//add INDEX at some point to behave differently during the queue process?
+}

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Worker.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Worker.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/Worker.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -2,6 +2,7 @@
 package org.hibernate.search.backend;
 
 import java.util.Properties;
+import java.io.Serializable;
 
 import org.hibernate.event.EventSource;
 import org.hibernate.search.SearchFactory;
@@ -11,7 +12,7 @@
  * @author Emmanuel Bernard
  */
 public interface Worker {
-	void performWork(Work work, EventSource session);
+	void performWork(Object entity, Serializable id, WorkType workType, EventSource session);
 
 	void initialize(Properties props, SearchFactory searchFactory);
 }

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/BatchedQueueingProcessor.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -1,6 +1,8 @@
 //$Id: $
 package org.hibernate.search.backend.impl;
 
+import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 import java.util.concurrent.ExecutorService;
@@ -8,18 +10,19 @@
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import org.hibernate.Hibernate;
 import org.hibernate.annotations.common.util.StringHelper;
 import org.hibernate.search.Environment;
 import org.hibernate.search.SearchException;
 import org.hibernate.search.SearchFactory;
-import org.hibernate.search.backend.AddWork;
 import org.hibernate.search.backend.BackendQueueProcessorFactory;
-import org.hibernate.search.backend.DeleteWork;
+import org.hibernate.search.backend.LuceneWork;
 import org.hibernate.search.backend.QueueingProcessor;
-import org.hibernate.search.backend.UpdateWork;
 import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.WorkType;
 import org.hibernate.search.backend.impl.jms.JMSBackendQueueProcessorFactory;
 import org.hibernate.search.backend.impl.lucene.LuceneBackendQueueProcessorFactory;
+import org.hibernate.search.engine.DocumentBuilder;
 import org.hibernate.util.ReflectHelper;
 
 /**
@@ -32,9 +35,11 @@
 	private boolean sync;
 	private ExecutorService executorService;
 	private BackendQueueProcessorFactory backendQueueProcessorFactory;
+	private SearchFactory searchFactory;
 
 	public BatchedQueueingProcessor(SearchFactory searchFactory,
 									Properties properties) {
+		this.searchFactory = searchFactory;
 		//default to sync if none defined
 		this.sync = !"async".equalsIgnoreCase( properties.getProperty( Environment.WORKER_EXECUTION ) );
 
@@ -86,28 +91,27 @@
 		searchFactory.setBackendQueueProcessorFactory( backendQueueProcessorFactory );
 	}
 
-	public void add(Work work, List<Work> queue) {
-		//TODO optimize by getting rid of dupe works
-		if ( work instanceof UpdateWork ) {
-			//split in 2 to optimize the process (reader first, writer next)
-			/**
-			 * even with Lucene 2.1, use of indexWriter to update is not an option
-			 * We can only delete by term, and the index doesn't have a term that
-			 * uniquely identify the entry.
-			 * But essentially the optimization we are doing is the same Lucene is doing, the only extra cost is the
-			 * double file opening.
-			 */
-			queue.add( new DeleteWork( work.getId(), work.getEntity() ) );
-			queue.add( new AddWork( work.getId(), work.getEntity(), work.getDocument() ) );
-		}
-		else {
-			queue.add( work );
-		}
+	public void add(Object entity, Serializable id, WorkType workType, List<Work> queue) {
+		//don't check for builder it's done in performWork
+		Work work = new Work(entity, id, workType);
+		queue.add( work );
 	}
 
 	//TODO implements parallel batchWorkers (one per Directory)
 	public void performWork(List<Work> queue) {
-		Runnable processor = backendQueueProcessorFactory.getProcessor( queue );
+		int initialSize = queue.size();
+		List<LuceneWork> luceneQueue = new ArrayList<LuceneWork>( initialSize ); //TODO load factor for containedIn
+
+		for ( int i = 0 ; i < initialSize ; i++ ) {
+			Work work = queue.get( i );
+			queue.set( i, null ); // help GC and avoid 2 loaded queues in memory
+			Class entityClass = Hibernate.getClass( work.getEntity() );
+			DocumentBuilder<Object> builder = searchFactory.getDocumentBuilders().get( entityClass );
+			if ( builder == null ) return; //or exception?
+			builder.addWorkToQueue(work.getEntity(), work.getId(), work.getType(), luceneQueue, searchFactory);
+		}
+
+		Runnable processor = backendQueueProcessorFactory.getProcessor( luceneQueue );
 		if ( sync ) {
 			processor.run();
 		}

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/PostTransactionWorkQueueSynchronization.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/PostTransactionWorkQueueSynchronization.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/PostTransactionWorkQueueSynchronization.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -3,10 +3,13 @@
 
 import java.util.List;
 import java.util.ArrayList;
+import java.io.Serializable;
 import javax.transaction.Status;
 import javax.transaction.Synchronization;
 
 import org.hibernate.search.backend.QueueingProcessor;
+import org.hibernate.search.backend.LuceneWork;
+import org.hibernate.search.backend.WorkType;
 import org.hibernate.search.backend.Work;
 import org.hibernate.search.util.WeakIdentityHashMap;
 
@@ -29,8 +32,8 @@
 		this.queuePerTransaction = queuePerTransaction;
 	}
 
-	public void add(Work work) {
-		queueingProcessor.add( work, queue );
+	public void add(Object entity, Serializable id, WorkType workType) {
+		queueingProcessor.add( entity, id, workType, queue );
 	}
 
 	public boolean isConsumed() {

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -4,10 +4,13 @@
 import java.util.Properties;
 import java.util.List;
 import java.util.ArrayList;
+import java.io.Serializable;
 
 import org.hibernate.search.backend.Worker;
+import org.hibernate.search.backend.LuceneWork;
+import org.hibernate.search.backend.QueueingProcessor;
+import org.hibernate.search.backend.WorkType;
 import org.hibernate.search.backend.Work;
-import org.hibernate.search.backend.QueueingProcessor;
 import org.hibernate.search.backend.impl.BatchedQueueingProcessor;
 import org.hibernate.search.util.WeakIdentityHashMap;
 import org.hibernate.search.SearchFactory;
@@ -28,7 +31,7 @@
 	protected WeakIdentityHashMap synchronizationPerTransaction = new WeakIdentityHashMap();
 	private QueueingProcessor queueingProcessor;
 
-	public void performWork(Work work, EventSource session) {
+	public void performWork(Object entity, Serializable id, WorkType workType, EventSource session) {
 		if ( session.isTransactionInProgress() ) {
 			Transaction transaction = session.getTransaction();
 			PostTransactionWorkQueueSynchronization txSync = (PostTransactionWorkQueueSynchronization)
@@ -38,11 +41,11 @@
 				transaction.registerSynchronization( txSync );
 				synchronizationPerTransaction.put(transaction, txSync);
 			}
-			txSync.add( work );
+			txSync.add( entity, id, workType );
 		}
 		else {
 			List<Work> queue = new ArrayList<Work>(2); //one work can be split
-			queueingProcessor.add( work, queue );
+			queueingProcessor.add( entity, id, workType, queue );
 			queueingProcessor.performWork( queue );
 		}
 	}

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/AbstractJMSHibernateSearchController.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/AbstractJMSHibernateSearchController.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/AbstractJMSHibernateSearchController.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -13,7 +13,7 @@
 import org.apache.commons.logging.LogFactory;
 import org.hibernate.Session;
 import org.hibernate.search.SearchFactory;
-import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.LuceneWork;
 import org.hibernate.search.util.ContextHelper;
 
 /**
@@ -66,9 +66,9 @@
 			return;
 		}
 		ObjectMessage objectMessage = (ObjectMessage) message;
-		List<Work> queue;
+		List<LuceneWork> queue;
 		try {
-			queue = (List<Work>) objectMessage.getObject();
+			queue = (List<LuceneWork>) objectMessage.getObject();
 		}
 		catch (JMSException e) {
 			log.error( "Unable to retrieve object from message: " + message.getClass(), e );
@@ -82,7 +82,7 @@
 		worker.run();
 	}
 
-	private Runnable getWorker(List<Work> queue) {
+	private Runnable getWorker(List<LuceneWork> queue) {
 		//FIXME casting sucks becasue we do not control what get session from
 		Session session = getSession();
 		Runnable processor = null;

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/JMSBackendQueueProcessor.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/JMSBackendQueueProcessor.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/JMSBackendQueueProcessor.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -10,16 +10,16 @@
 import javax.jms.QueueSession;
 
 import org.hibernate.HibernateException;
-import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.LuceneWork;
 
 /**
  * @author Emmanuel Bernard
  */
 public class JMSBackendQueueProcessor implements Runnable {
-	private List<Work> queue;
+	private List<LuceneWork> queue;
 	private JMSBackendQueueProcessorFactory factory;
 
-	public JMSBackendQueueProcessor(List<Work> queue,
+	public JMSBackendQueueProcessor(List<LuceneWork> queue,
 									JMSBackendQueueProcessorFactory jmsBackendQueueProcessorFactory) {
 		this.queue = queue;
 		this.factory = jmsBackendQueueProcessorFactory;

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/JMSBackendQueueProcessorFactory.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/JMSBackendQueueProcessorFactory.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/jms/JMSBackendQueueProcessorFactory.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -15,7 +15,7 @@
 import org.hibernate.search.SearchException;
 import org.hibernate.search.SearchFactory;
 import org.hibernate.search.backend.BackendQueueProcessorFactory;
-import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.LuceneWork;
 
 /**
  * @author Emmanuel Bernard
@@ -38,7 +38,7 @@
 		prepareJMSTools();
 	}
 
-	public Runnable getProcessor(List<Work> queue) {
+	public Runnable getProcessor(List<LuceneWork> queue) {
 		return new JMSBackendQueueProcessor( queue, this );
 	}
 

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -6,8 +6,8 @@
 import java.util.List;
 
 import org.hibernate.search.SearchFactory;
-import org.hibernate.search.backend.AddWork;
-import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.AddLuceneWork;
+import org.hibernate.search.backend.LuceneWork;
 import org.hibernate.search.backend.Workspace;
 
 /**
@@ -17,10 +17,10 @@
  * @author Emmanuel Bernard
  */
 public class LuceneBackendQueueProcessor implements Runnable {
-	private List<Work> queue;
+	private List<LuceneWork> queue;
 	private SearchFactory searchFactory;
 
-	public LuceneBackendQueueProcessor(List<Work> queue, SearchFactory searchFactory) {
+	public LuceneBackendQueueProcessor(List<LuceneWork> queue, SearchFactory searchFactory) {
 		this.queue = queue;
 		this.searchFactory = searchFactory;
 	}
@@ -32,8 +32,8 @@
 		worker = new LuceneWorker( workspace );
 		try {
 			deadlockFreeQueue(queue, workspace);
-			for ( Work work : queue ) {
-				worker.performWork( work );
+			for ( LuceneWork luceneWork : queue ) {
+				worker.performWork( luceneWork );
 			}
 		}
 		finally {
@@ -47,9 +47,9 @@
 	 * dead lock between concurrent threads or processes
 	 * To achieve that, the work will be done per directory provider
 	 */
-	private void deadlockFreeQueue(List<Work> queue, final Workspace workspace) {
-		Collections.sort( queue, new Comparator<Work>() {
-			public int compare(Work o1, Work o2) {
+	private void deadlockFreeQueue(List<LuceneWork> queue, final Workspace workspace) {
+		Collections.sort( queue, new Comparator<LuceneWork>() {
+			public int compare(LuceneWork o1, LuceneWork o2) {
 				long h1 = getWorkHashCode( o1, workspace );
 				long h2 = getWorkHashCode( o2, workspace );
 				return h1 < h2 ?
@@ -61,9 +61,9 @@
 		} );
 	}
 
-	private long getWorkHashCode(Work work, Workspace workspace) {
-		long h = workspace.getDocumentBuilder( work.getEntity() ).hashCode() * 2;
-		if (work instanceof AddWork ) h+=1; //addwork after deleteWork
+	private long getWorkHashCode(LuceneWork luceneWork, Workspace workspace) {
+		long h = workspace.getDocumentBuilder( luceneWork.getEntityClass() ).hashCode() * 2;
+		if ( luceneWork instanceof AddLuceneWork ) h+=1; //addwork after deleteWork
 		return h;
 	}
 }

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessorFactory.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessorFactory.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessorFactory.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -6,7 +6,7 @@
 
 import org.hibernate.search.SearchFactory;
 import org.hibernate.search.backend.BackendQueueProcessorFactory;
-import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.LuceneWork;
 
 /**
  * @author Emmanuel Bernard
@@ -18,7 +18,7 @@
 		this.searchFactory = searchFactory;
 	}
 
-	public Runnable getProcessor(List<Work> queue) {
+	public Runnable getProcessor(List<LuceneWork> queue) {
 		return new LuceneBackendQueueProcessor( queue, searchFactory );
 	}
 }

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -12,13 +12,12 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermDocs;
 import org.hibernate.annotations.common.AssertionFailure;
-import org.hibernate.search.engine.DocumentBuilder;
-import org.hibernate.search.backend.Workspace;
-import org.hibernate.search.backend.DeleteWork;
-import org.hibernate.search.backend.AddWork;
-import org.hibernate.search.backend.UpdateWork;
-import org.hibernate.search.backend.Work;
 import org.hibernate.search.SearchException;
+import org.hibernate.search.backend.AddLuceneWork;
+import org.hibernate.search.backend.DeleteLuceneWork;
+import org.hibernate.search.backend.LuceneWork;
+import org.hibernate.search.backend.Workspace;
+import org.hibernate.search.engine.DocumentBuilder;
 
 /**
  * Stateless implementation that perform a work
@@ -33,23 +32,20 @@
 		this.workspace = workspace;
 	}
 
-	public void performWork(Work work) {
-		if ( AddWork.class.isAssignableFrom( work.getClass() ) ) {
-			performWork( (AddWork) work );
+	public void performWork(LuceneWork luceneWork) {
+		if ( AddLuceneWork.class.isAssignableFrom( luceneWork.getClass() ) ) {
+			performWork( (AddLuceneWork) luceneWork );
 		}
-		else if ( UpdateWork.class.isAssignableFrom( work.getClass() ) ) {
-			performWork( (UpdateWork) work );
+		else if ( DeleteLuceneWork.class.isAssignableFrom( luceneWork.getClass() ) ) {
+			performWork( (DeleteLuceneWork) luceneWork );
 		}
-		else if ( DeleteWork.class.isAssignableFrom( work.getClass() ) ) {
-			performWork( (DeleteWork) work );
-		}
 		else {
-			throw new AssertionFailure( "Unknown work type: " + work.getClass() );
+			throw new AssertionFailure( "Unknown work type: " + luceneWork.getClass() );
 		}
 	}
 
-	public void performWork(AddWork work) {
-		Class entity = work.getEntity();
+	public void performWork(AddLuceneWork work) {
+		Class entity = work.getEntityClass();
 		Serializable id = work.getId();
 		Document document = work.getDocument();
 		add( entity, id, document );
@@ -67,25 +63,12 @@
 		}
 	}
 
-	public void performWork(UpdateWork work) {
-		/**
-		 * even with Lucene 2.1, use of indexWriter to update is not an option
-		 * We can only delete by term, and the index doesn't have a term that
-		 * uniquely identify the entry.
-		 */
-		Class entity = work.getEntity();
+	public void performWork(DeleteLuceneWork work) {
+		Class entity = work.getEntityClass();
 		Serializable id = work.getId();
-		Document document = work.getDocument();
 		remove( entity, id );
-		add( entity, id, document );
 	}
 
-	public void performWork(DeleteWork work) {
-		Class entity = work.getEntity();
-		Serializable id = work.getId();
-		remove( entity, id );
-	}
-
 	private void remove(Class entity, Serializable id) {
 		/**
 		 * even with Lucene 2.1, use of indexWriter to delte is not an option

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -4,43 +4,47 @@
 import java.io.Serializable;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.HashMap;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.Term;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.hibernate.Hibernate;
+import org.hibernate.annotations.common.AssertionFailure;
 import org.hibernate.annotations.common.reflection.ReflectionManager;
 import org.hibernate.annotations.common.reflection.XAnnotatedElement;
 import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.annotations.common.reflection.XMember;
 import org.hibernate.annotations.common.reflection.XProperty;
-import org.hibernate.annotations.common.AssertionFailure;
+import org.hibernate.search.SearchException;
 import org.hibernate.search.SearchFactory;
-import org.hibernate.search.SearchException;
 import org.hibernate.search.annotations.Boost;
+import org.hibernate.search.annotations.ContainedIn;
 import org.hibernate.search.annotations.DocumentId;
 import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.IndexedEmbedded;
 import org.hibernate.search.annotations.Keyword;
 import org.hibernate.search.annotations.Store;
 import org.hibernate.search.annotations.Text;
 import org.hibernate.search.annotations.Unstored;
-import org.hibernate.search.annotations.IndexedEmbedded;
+import org.hibernate.search.backend.AddLuceneWork;
+import org.hibernate.search.backend.DeleteLuceneWork;
+import org.hibernate.search.backend.LuceneWork;
+import org.hibernate.search.backend.WorkType;
 import org.hibernate.search.bridge.BridgeFactory;
 import org.hibernate.search.bridge.FieldBridge;
 import org.hibernate.search.bridge.TwoWayFieldBridge;
 import org.hibernate.search.store.DirectoryProvider;
 import org.hibernate.search.util.BinderHelper;
 import org.hibernate.util.ReflectHelper;
-import org.hibernate.Hibernate;
 
 /**
  * Set up and provide a manager for indexes classes
@@ -57,6 +61,7 @@
 	private final XClass beanClass;
 	private final DirectoryProvider directoryProvider;
 	private String idKeywordName;
+	private XMember idGetter;
 	private final Analyzer analyzer;
 	private Float idBoost;
 	public static final String CLASS_FIELDNAME = "_hibernate_class";
@@ -120,6 +125,8 @@
 					throw new SearchException(
 							"Bridge for document id does not implement IdFieldBridge: " + member.getName() );
 				}
+				setAccessible( member );
+				idGetter = member;
 			}
 			else {
 				setAccessible( member );
@@ -161,6 +168,8 @@
 						"Bridge for document id does not implement IdFieldBridge: " + member.getName() );
 			}
 			idBoost = getBoost( member );
+			setAccessible( member );
+			idGetter = member;
 		}
 
 		org.hibernate.search.annotations.Field fieldAnn =
@@ -210,6 +219,12 @@
 			level--;
 			maxLevel = oldMaxLevel; //set back the the old max level
 		}
+
+		ContainedIn containedAnn = member.getAnnotation( ContainedIn.class );
+		if ( containedAnn != null ) {
+			setAccessible( member );
+			propertiesMetadata.containedInGetters.add( member );
+		}
 	}
 
 	private String buildEmbeddedPrefix(String prefix, IndexedEmbedded embeddedAnn, XProperty member) {
@@ -271,6 +286,93 @@
 		return value;
 	}
 
+	public void addWorkToQueue(T entity, Serializable id, WorkType workType, List<LuceneWork> queue, SearchFactory searchFactory) {
+		Class entityClass = Hibernate.getClass( entity );
+		//TODO with the caller loop we are in a n^2: optimize it using a HashMap for work recognition 
+		for ( LuceneWork luceneWork : queue) {
+			//whatever the actual work, we should ignore
+			if ( luceneWork.getEntityClass() == entityClass
+					&& luceneWork.getId().equals( id ) ) {//find a way to use Type.equals(x,y)
+				return;
+			}
+
+		}
+		boolean searchForContainers = false;
+		if ( workType == WorkType.ADD ) {
+			Document doc = getDocument( entity, id );
+			queue.add( new AddLuceneWork( id, entityClass, doc ) );
+			searchForContainers = true;
+		}
+		else if ( workType == WorkType.DELETE ) {
+			queue.add( new DeleteLuceneWork(id, entityClass) );
+		}
+		else if ( workType == WorkType.UPDATE ) {
+			Document doc = getDocument( entity, id );
+			/**
+			 * even with Lucene 2.1, use of indexWriter to update is not an option
+			 * We can only delete by term, and the index doesn't have a term that
+			 * uniquely identify the entry.
+			 * But essentially the optimization we are doing is the same Lucene is doing, the only extra cost is the
+			 * double file opening.
+			 */
+			queue.add( new DeleteLuceneWork(id, entityClass) );
+			queue.add( new AddLuceneWork( id, entityClass, doc ) );
+			searchForContainers = true;
+		}
+		else {
+			throw new AssertionFailure("Unknown WorkType: " + workType);
+		}
+
+		/**
+		 * When references are changed, either null or another one, we expect dirty checking to be triggered (both sides
+		 * have to be updated)
+		 * When the internal object is changed, we apply the {Add|Update}Work on containedIns
+		 */
+		if (searchForContainers) {
+			processContainedIn(entity, queue, rootPropertiesMetadata, searchFactory);
+		}
+	}
+
+	private void processContainedIn(Object instance, List<LuceneWork> queue, PropertiesMetadata metadata, SearchFactory searchFactory) {
+		for ( int i = 0; i < metadata.containedInGetters.size(); i++ ) {
+			XMember member = metadata.containedInGetters.get( i );
+			Object value = getMemberValue( instance, member );
+			if (value == null) continue;
+			Class valueClass = Hibernate.getClass( value );
+			DocumentBuilder builder = searchFactory.getDocumentBuilders().get( valueClass );
+			if (builder == null) continue;
+			if ( member.isArray() ) {
+				for ( Object arrayValue : (Object[]) value ) {
+					processContainedInValue( arrayValue, member, queue, valueClass, builder, searchFactory );
+				}
+			}
+			else if ( member.isCollection() ) {
+				Collection collection;
+				if ( Map.class.equals( member.getCollectionClass() ) ) {
+					//hum
+					collection = ( (Map) value ).values();
+				}
+				else {
+					collection = (Collection) value;
+				}
+				for ( Object collectionValue : collection ) {
+					processContainedInValue( collectionValue, member, queue, valueClass, builder, searchFactory );
+				}
+			}
+			else {
+				processContainedInValue( value, member, queue, valueClass, builder, searchFactory );
+			}
+		}
+		//an embedded cannot have a useful @ContainedIn (no shared reference)
+		//do not walk through them
+	}
+
+	private void processContainedInValue(Object value, XMember member, List<LuceneWork> queue, Class valueClass,
+										 DocumentBuilder builder, SearchFactory searchFactory) {
+		Serializable id = (Serializable) builder.getMemberValue( value, builder.idGetter );
+		builder.addWorkToQueue( value, id, WorkType.UPDATE, queue, searchFactory );
+	}
+
 	public Document getDocument(T instance, Serializable id) {
 		Document doc = new Document();
 		XClass instanceClass = reflectionManager.toXClass( instance.getClass() );
@@ -407,5 +509,6 @@
 		public final List<Field.Index> fieldIndex = new ArrayList<Field.Index>();
 		public final List<XMember> embeddedGetters = new ArrayList<XMember>();
 		public final List<PropertiesMetadata> embeddedPropertiesMetadata = new ArrayList<PropertiesMetadata>();
+		public final List<XMember> containedInGetters = new ArrayList<XMember>();
 	}
 }

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/event/FullTextIndexEventListener.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/event/FullTextIndexEventListener.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/event/FullTextIndexEventListener.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -5,7 +5,6 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.lucene.document.Document;
 import org.hibernate.cfg.Configuration;
 import org.hibernate.event.AbstractEvent;
 import org.hibernate.event.Initializable;
@@ -15,10 +14,7 @@
 import org.hibernate.event.PostInsertEventListener;
 import org.hibernate.event.PostUpdateEvent;
 import org.hibernate.event.PostUpdateEventListener;
-import org.hibernate.search.backend.AddWork;
-import org.hibernate.search.backend.DeleteWork;
-import org.hibernate.search.backend.UpdateWork;
-import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.WorkType;
 import org.hibernate.search.engine.DocumentBuilder;
 import org.hibernate.search.SearchFactory;
 
@@ -51,8 +47,7 @@
 
 	public void onPostDelete(PostDeleteEvent event) {
 		if ( used && searchFactory.getDocumentBuilders().containsKey( event.getEntity().getClass() ) ) {
-			DeleteWork work = new DeleteWork( event.getId(), event.getEntity().getClass() );
-			processWork( work, event );
+			processWork( event.getEntity(), event.getId(), WorkType.DELETE, event );
 		}
 	}
 
@@ -60,11 +55,10 @@
 		if (used) {
 			final Object entity = event.getEntity();
 			DocumentBuilder<Object> builder = searchFactory.getDocumentBuilders().get( entity.getClass() );
+			//not strictly necessary but a smal optimization
 			if ( builder != null ) {
 				Serializable id = event.getId();
-				Document doc = builder.getDocument( entity, id );
-				AddWork work = new AddWork( id, entity.getClass(), doc );
-				processWork( work, event );
+				processWork( entity, id, WorkType.ADD, event );
 			}
 		}
 	}
@@ -72,17 +66,16 @@
 	public void onPostUpdate(PostUpdateEvent event) {
 		if (used) {
 			final Object entity = event.getEntity();
+			//not strictly necessary but a smal optimization
 			DocumentBuilder<Object> builder = searchFactory.getDocumentBuilders().get( entity.getClass() );
 			if ( builder != null ) {
 				Serializable id = event.getId();
-				Document doc = builder.getDocument( entity, id );
-				UpdateWork work = new UpdateWork( id, entity.getClass(), doc );
-				processWork( work, event );
+				processWork( entity, id, WorkType.UPDATE, event );
 			}
 		}
 	}
 
-	private void processWork(Work work, AbstractEvent event) {
-		searchFactory.getWorker().performWork( work, event.getSession() );
+	private void processWork(Object entity, Serializable id, WorkType workType, AbstractEvent event) {
+		searchFactory.getWorker().performWork( entity, id, workType, event.getSession() );
 	}
 }

Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/impl/FullTextSessionImpl.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/impl/FullTextSessionImpl.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/impl/FullTextSessionImpl.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -8,7 +8,6 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.lucene.document.Document;
 import org.hibernate.CacheMode;
 import org.hibernate.Criteria;
 import org.hibernate.EntityMode;
@@ -43,7 +42,7 @@
 import org.hibernate.persister.entity.EntityPersister;
 import org.hibernate.search.FullTextSession;
 import org.hibernate.search.SearchFactory;
-import org.hibernate.search.backend.UpdateWork;
+import org.hibernate.search.backend.WorkType;
 import org.hibernate.search.engine.DocumentBuilder;
 import org.hibernate.search.query.FullTextQueryImpl;
 import org.hibernate.search.util.ContextHelper;
@@ -86,13 +85,13 @@
 	public void index(Object entity) {
 		if (entity == null) return;
 		Class clazz = Hibernate.getClass( entity );
+		//TODO cache that at the FTSession level
 		SearchFactory searchFactory = ContextHelper.getSearchFactory( session );
+		//not strictly necessary but a small optimization
 		DocumentBuilder<Object> builder = searchFactory.getDocumentBuilders().get( clazz );
 		if ( builder != null ) {
 			Serializable id = session.getIdentifier( entity );
-			Document doc = builder.getDocument( entity, id );
-			UpdateWork work = new UpdateWork( id, entity.getClass(), doc );
-			searchFactory.getWorker().performWork( work, eventSource );
+			searchFactory.getWorker().performWork( entity, id, WorkType.UPDATE, eventSource );
 		}
 		//TODO
 		//need to add elements in a queue kept at the Session level

Modified: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/FSDirectoryTest.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/FSDirectoryTest.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/FSDirectoryTest.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -102,7 +102,8 @@
 		try {
 			int num = reader.numDocs();
 			assertEquals( 2, num );
-			TermDocs docs = reader.termDocs( new Term( "Abstract", "EJB3" ) );
+			TermDocs docs = reader.termDocs( new Term( "Abstract", "ejb" ) );
+			assertTrue( docs.next() );
 			org.apache.lucene.document.Document doc = reader.document( docs.doc() );
 			assertFalse( docs.next() );
 		}
@@ -120,7 +121,8 @@
 		try {
 			int num = reader.numDocs();
 			assertEquals( 1, num );
-			TermDocs docs = reader.termDocs( new Term( "Title", "Seam" ) );
+			TermDocs docs = reader.termDocs( new Term( "title", "seam" ) );
+			assertTrue( docs.next() );
 			org.apache.lucene.document.Document doc = reader.document( docs.doc() );
 			assertFalse( docs.next() );
 			assertEquals( "2", doc.getField( "id" ).stringValue() );

Modified: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/directoryProvider/FSSlaveAndMasterDPTest.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/directoryProvider/FSSlaveAndMasterDPTest.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/directoryProvider/FSSlaveAndMasterDPTest.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -39,7 +39,8 @@
 		fts2.close();
 		s1.close();
 
-		Thread.sleep( 2 * 60 * 100 + 10); //wait a bit more than 2 refresh (one master / one slave)
+		int waitPeroid = 2 * 1 * 1000 + 10; //wait a bit more than 2 refresh (one master / one slave)
+		Thread.sleep( waitPeroid );
 
 		//temp test original
 		fts2 = Search.createFullTextSession( getSessionFactories()[0].openSession( ) );
@@ -61,7 +62,7 @@
 		fts2.close();
 		s1.close();
 
-		Thread.sleep( 2 * 60 * 100 + 10); //wait a bit more than 2 refresh (one master / one slave)
+		Thread.sleep( waitPeroid ); //wait a bit more than 2 refresh (one master / one slave)
 
 		fts2 = Search.createFullTextSession( getSessionFactories()[1].openSession( ) );
 		result = fts2.createFullTextQuery( parser.parse( "location:chennai" ) ).list();
@@ -78,7 +79,7 @@
 		fts2.close();
 		s1.close();
 
-		Thread.sleep( 2 * 60 * 100 + 10); //wait a bit more than 2 refresh (one master / one slave)
+		Thread.sleep( waitPeroid ); //wait a bit more than 2 refresh (one master / one slave)
 
 		fts2 = Search.createFullTextSession( getSessionFactories()[1].openSession( ) );
 		result = fts2.createFullTextQuery( parser.parse( "location:melbourne" ) ).list();

Modified: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Address.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Address.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Address.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -11,6 +11,7 @@
 import org.hibernate.search.annotations.Field;
 import org.hibernate.search.annotations.Index;
 import org.hibernate.search.annotations.IndexedEmbedded;
+import org.hibernate.search.annotations.ContainedIn;
 
 /**
  * @author Emmanuel Bernard
@@ -31,6 +32,7 @@
 	private Owner ownedBy;
 
 	@OneToOne(mappedBy = "address")
+	@ContainedIn
 	private Tower tower;
 
 

Modified: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -34,7 +34,7 @@
 		s.persist( tower );
 		tx.commit();
 
-		s.clear();
+
 		
 
 		FullTextSession session = Search.createFullTextSession(s);
@@ -50,7 +50,25 @@
 		result = session.createFullTextQuery(query, Tower.class).list();
 		assertEquals( "unable to find property in embedded", 1, result.size() );
 
+		s.clear();
+
 		tx = s.beginTransaction();
+		Address address = (Address) s.get(Address.class, a.getId() );
+		address.getOwnedBy().setName( "Buckhead community");
+		tx.commit();
+
+
+		s.clear();
+
+		session = Search.createFullTextSession(s);
+
+        query = parser.parse("address.ownedBy_name:buckhead");
+		result = session.createFullTextQuery(query, Tower.class).list();
+        assertEquals( "change in embedded not reflected in root index", 1, result.size() );
+
+		s.clear();
+
+		tx = s.beginTransaction();
 		s.delete( s.get(Tower.class, tower.getId() ) );
 		tx.commit();
 
@@ -58,6 +76,65 @@
 
 	}
 
+	public void testContainedIn() throws Exception {
+		Tower tower = new Tower();
+		tower.setName( "JBoss tower" );
+		Address a = new Address();
+		a.setStreet( "Tower place");
+		a.setTower( tower );
+		tower.setAddress( a );
+		Owner o = new Owner();
+		o.setName( "Atlanta Renting corp" );
+		a.setOwnedBy( o );
+		o.setAddress( a );
+
+		Session s = openSession( );
+		Transaction tx = s.beginTransaction();
+		s.persist( tower );
+		tx.commit();
+
+		s.clear();
+
+		tx = s.beginTransaction();
+		Address address = (Address) s.get(Address.class, a.getId() );
+		address.setStreet( "Peachtree Road NE" );
+		tx.commit();
+
+		s.clear();
+
+		FullTextSession session = Search.createFullTextSession(s);
+        QueryParser parser = new QueryParser("id", new StandardAnalyzer() );
+        Query query;
+        List result;
+
+        query = parser.parse("address.street:peachtree");
+		result = session.createFullTextQuery(query, Tower.class).list();
+        assertEquals( "change in embedded not reflected in root index", 1, result.size() );
+
+		s.clear();
+
+		tx = s.beginTransaction();
+		address = (Address) s.get(Address.class, a.getId() );
+		address.getTower().setAddress( null );
+		address.setTower( null );
+		tx.commit();
+
+		s.clear();
+
+		session = Search.createFullTextSession(s);
+
+        query = parser.parse("address.street:peachtree");
+		result = session.createFullTextQuery(query, Tower.class).list();
+        assertEquals( "breaking link fails", 0, result.size() );
+
+		tx = s.beginTransaction();
+		s.delete( s.get(Tower.class, tower.getId() ) );
+		tx.commit();
+
+		s.close();
+
+	}
+
 	protected Class[] getMappings() {
 		return new Class[] {
 				Tower.class,

Modified: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/jms/master/JMSMasterTest.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/jms/master/JMSMasterTest.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/jms/master/JMSMasterTest.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -23,8 +23,8 @@
 import org.hibernate.search.FullTextSession;
 import org.hibernate.search.Search;
 import org.hibernate.search.engine.DocumentBuilder;
-import org.hibernate.search.backend.AddWork;
-import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.AddLuceneWork;
+import org.hibernate.search.backend.LuceneWork;
 import org.hibernate.search.backend.impl.jms.JMSBackendQueueProcessorFactory;
 import org.hibernate.search.test.SearchTestCase;
 import org.jboss.deployers.spi.DeploymentException;
@@ -57,9 +57,9 @@
 		doc.add( field );
 		field = new Field("logo", ts.getLogo(), Field.Store.NO, Field.Index.TOKENIZED );
 		doc.add( field );
-		Work work = new AddWork(ts.getId(), ts.getClass(), doc );
-		List<Work> queue = new ArrayList<Work>();
-		queue.add( work );
+		LuceneWork luceneWork = new AddLuceneWork(ts.getId(), ts.getClass(), doc );
+		List<LuceneWork> queue = new ArrayList<LuceneWork>();
+		queue.add( luceneWork );
 
 		//send the queue
 		InitialContext context = new InitialContext();

Modified: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/jms/slave/SearchQueueChecker.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/jms/slave/SearchQueueChecker.java	2007-03-13 21:55:41 UTC (rev 11278)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/jms/slave/SearchQueueChecker.java	2007-03-14 20:57:53 UTC (rev 11279)
@@ -9,7 +9,7 @@
 import javax.ejb.MessageDriven;
 import javax.ejb.ActivationConfigProperty;
 
-import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.LuceneWork;
 
 /**
  * @author Emmanuel Bernard
@@ -33,9 +33,9 @@
 			return;
 		}
 		ObjectMessage objectMessage = (ObjectMessage) message;
-		List<Work> queue;
+		List<LuceneWork> queue;
 		try {
-			queue = (List<Work>) objectMessage.getObject();
+			queue = (List<LuceneWork>) objectMessage.getObject();
 		}
 		catch (JMSException e) {
 			return;




More information about the hibernate-commits mailing list