Author: epbernard
Date: 2006-10-18 18:09:34 -0400 (Wed, 18 Oct 2006)
New Revision: 10611
Added:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentId.java
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Field.java
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Index.java
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Store.java
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/IdFieldBridge.java
Modified:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Keyword.java
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Text.java
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Unstored.java
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FieldBridge.java
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/String2FieldBridgeAdaptor.java
branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/Document.java
Log:
ANN-383 adjust to the Lucene 2 APIs (deprecate the old annotations)
Use of idBridge to remove an element from the index
ANN-468 IdFieldBridge (but the String2FieldBridgeAdaptor is broken
Modified:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -18,6 +18,7 @@
import org.hibernate.cfg.annotations.Version;
import org.hibernate.lucene.bridge.BridgeFactory;
import org.hibernate.lucene.bridge.FieldBridge;
+import org.hibernate.lucene.bridge.IdFieldBridge;
import org.hibernate.lucene.event.LuceneEventListener;
import org.hibernate.lucene.store.DirectoryProvider;
import org.hibernate.lucene.util.BinderHelper;
@@ -51,6 +52,11 @@
private final List<XMember> textGetters = new ArrayList<XMember>();
private final List<String> textNames = new ArrayList<String>();
private final List<FieldBridge> textBridges = new
ArrayList<FieldBridge>();
+ private final List<String> fieldNames = new ArrayList<String>();
+ private final List<XMember> fieldGetters = new ArrayList<XMember>();
+ private final List<FieldBridge> fieldBridges = new
ArrayList<FieldBridge>();
+ private final List<Field.Store> fieldStore = new
ArrayList<Field.Store>();
+ private final List<Field.Index> fieldIndex = new
ArrayList<Field.Index>();
private final XClass beanClass;
private final DirectoryProvider directoryProvider;
@@ -58,10 +64,11 @@
private final Analyzer analyzer;
private Float idBoost;
public static final String CLASS_FIELDNAME = "_hibernate_class";
- private FieldBridge idBridge;
+ private IdFieldBridge idBridge;
private Set<Class> mappedSubclasses = new HashSet<Class>();
private ReflectionManager reflectionManager;
+
public DocumentBuilder(XClass clazz, Analyzer analyzer, DirectoryProvider directory,
ReflectionManager reflectionManager) {
this.beanClass = clazz;
this.analyzer = analyzer;
@@ -85,7 +92,7 @@
}
if ( idKeywordName == null ) {
- throw new HibernateException( "No id Keyword for: " +
clazz.getName() );
+ throw new HibernateException( "No document id for: " +
clazz.getName() );
}
}
@@ -96,7 +103,13 @@
if ( keywordAnn.id() ) {
idKeywordName = name;
idBoost = getBoost( member );
- idBridge = BridgeFactory.guessType( member );
+ FieldBridge fieldBridge = BridgeFactory.guessType( member );
+ if ( fieldBridge instanceof IdFieldBridge ) {
+ idBridge = (IdFieldBridge) fieldBridge;
+ }
+ else {
+ throw new HibernateException( "Bridge for document id does not
implement IdFieldBridge: " + member.getName() );
+ }
}
else {
setAccessible( member );
@@ -121,9 +134,63 @@
textNames.add( BinderHelper.getAttributeName( member, textAnn.name() ) );
textBridges.add( BridgeFactory.guessType( member ) );
}
+
+ DocumentId documentIdAnn = member.getAnnotation( DocumentId.class );
+ if ( documentIdAnn != null ) {
+ if ( idKeywordName != null ) {
+ throw new AssertionFailure( "Two document id assigned: "
+ + idKeywordName + " and " + BinderHelper.getAttributeName(
member, documentIdAnn.name() ) );
+ }
+ idKeywordName = BinderHelper.getAttributeName( member, documentIdAnn.name()
);
+ FieldBridge fieldBridge = BridgeFactory.guessType( member );
+ if ( fieldBridge instanceof IdFieldBridge ) {
+ idBridge = (IdFieldBridge) fieldBridge;
+ }
+ else {
+ throw new HibernateException( "Bridge for document id does not
implement IdFieldBridge: " + member.getName() );
+ }
+ idBoost = getBoost( member );
+ }
+
+ org.hibernate.lucene.Field fieldAnn = member.getAnnotation(
org.hibernate.lucene.Field.class );
+ if ( fieldAnn != null ) {
+ setAccessible( member );
+ fieldGetters.add( member );
+ fieldNames.add( BinderHelper.getAttributeName( member, fieldAnn.name() ) );
+ fieldStore.add( getStore( fieldAnn.store() ) );
+ fieldIndex.add( getIndex( fieldAnn.index() ) );
+ fieldBridges.add( BridgeFactory.guessType( member ) );
+ }
}
+ private Field.Store getStore(Store store) {
+ switch( store ) {
+ case NO:
+ return Field.Store.NO;
+ case YES:
+ return Field.Store.YES;
+ case COMPRESS:
+ return Field.Store.COMPRESS;
+ default:
+ throw new AssertionFailure( "Unexpected Store: " + store );
+ }
+ }
+ private Field.Index getIndex(Index index) {
+ switch( index ) {
+ case NO:
+ return Field.Index.NO;
+ case NO_NORMS:
+ return Field.Index.NO_NORMS;
+ case TOKENIZED:
+ return Field.Index.TOKENIZED;
+ case UN_TOKENISED:
+ return Field.Index.UN_TOKENIZED;
+ default:
+ throw new AssertionFailure( "Unexpected Index: " + index );
+ }
+ }
+
private Float getBoost(XAnnotatedElement element) {
if ( element == null ) return null;
Boost boost = element.getAnnotation( Boost.class );
@@ -180,11 +247,19 @@
Field.Index.TOKENIZED, getBoost( member )
);
}
+ for ( int i = 0; i < fieldNames.size(); i++ ) {
+ XMember member = fieldGetters.get( i );
+ Object value = getMemberValue( instance, member );
+ fieldBridges.get( i ).set(
+ fieldNames.get( i ), value, doc, fieldStore.get( i ),
+ fieldIndex.get( i ), getBoost( member )
+ );
+ }
return doc;
}
public Term getTerm(Serializable id) {
- return new Term( idKeywordName, id.toString() );
+ return new Term( idKeywordName, idBridge.objectToString( id ) );
}
public DirectoryProvider getDirectoryProvider() {
@@ -201,7 +276,7 @@
}
}
- public FieldBridge getIdBridge() {
+ public IdFieldBridge getIdBridge() {
return idBridge;
}
Added:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentId.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentId.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentId.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -0,0 +1,22 @@
+//$Id: $
+package org.hibernate.lucene;
+
+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;
+
+/**
+ * Declare a field as the document id. If set to a property, the property will be used
+ * TODO: If set to a class, the class itself will be passed to the FieldBridge
+ * Note that @{link org.hibernate.lucene.bridge.FieldBridge#get} must return the Entity
id
+ *
+ * @author Emmanuel Bernard
+ */
+@Retention( RetentionPolicy.RUNTIME)
+(a)Target({ElementType.METHOD, ElementType.FIELD})
+@Documented
+public @interface DocumentId {
+ String name() default "";
+}
Added:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Field.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Field.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Field.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -0,0 +1,38 @@
+//$Id: $
+/**
+ * JavaDoc copy/pastle from the Apache Lucene project
+ * Available under the ASL 2.0
http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.hibernate.lucene;
+
+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;
+
+/**
+ * Mark a property as indexable
+ *
+ * @author Emmanuel Bernard
+ */
+@Retention( RetentionPolicy.RUNTIME)
+(a)Target({ElementType.METHOD, ElementType.FIELD})
+@Documented
+public @interface Field {
+ /**
+ * Field name, default to the JavaBean property name
+ */
+ String name() default "";
+
+ /**
+ * Should the value be stored in the document
+ */
+ Store store() default Store.NO;
+
+ /**
+ * Defines how the Field should be indexed
+ */
+ Index index();
+
+}
Added:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Index.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Index.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Index.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -0,0 +1,29 @@
+//$Id: $
+package org.hibernate.lucene;
+
+/**
+ * Defines how an Field should be indexed
+ */
+public enum Index {
+ /** Do not index the field value. This field can thus not be searched,
+ * but one can still access its contents provided it is
+ * {@link Store stored}. */
+ NO,
+ /** Index the field's value so it can be searched. An Analyzer will be used
+ * to tokenize and possibly further normalize the text before its
+ * terms will be stored in the index. This is useful for common text.
+ */
+ TOKENIZED,
+ /** Index the field's value without using an Analyzer, so it can be searched.
+ * As no analyzer is used the value will be stored as a single term. This is
+ * useful for unique Ids like product numbers.
+ */
+ UN_TOKENISED,
+ /** Index the field's value without an Analyzer, and disable
+ * the storing of norms. No norms means that index-time boosting
+ * and field length normalization will be disabled. The benefit is
+ * less memory usage as norms take up one byte per indexed field
+ * for every document in the index.
+ */
+ NO_NORMS
+}
Modified:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Keyword.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Keyword.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Keyword.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -13,7 +13,9 @@
/**
* Specifies that a property of an entity is a Lucene
* keyword field
+ * @deprecated use @Field(index=Index.UN_TOKENIZED, store=Store.YES) or @DocumentId when
id=true was used
*/
+@Deprecated
public @interface Keyword {
/**
* The field name
Added:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Store.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Store.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Store.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -0,0 +1,13 @@
+//$Id: $
+package org.hibernate.lucene;
+
+/**
+ * Whether or not the value is stored in the document
+ *
+ * @author Emmanuel Bernard
+ */
+public enum Store {
+ NO,
+ YES,
+ COMPRESS
+}
Modified:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Text.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Text.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Text.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -13,7 +13,9 @@
/**
* Specifies that a property of an entity is a Lucene
* text field
+ * @deprecated use @Field(index=Index.TOKENIZED, store=Store.YES)
*/
+@Deprecated
public @interface Text {
/**
* The field name
Modified:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Unstored.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Unstored.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/Unstored.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -13,7 +13,9 @@
/**
* Specifies that a property of an entity is a Lucene
* unstored field
+ * @deprecated use @Field(index=Index.TOKENIZED, store=Store.NO)
*/
+@Deprecated
public @interface Unstored {
/**
* The field name
Modified:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FieldBridge.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FieldBridge.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FieldBridge.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -13,6 +13,11 @@
//TODO should show Field or document?
//document is nice since I can save an object into several fields
public interface FieldBridge {
- Object get(String name, Document document);
- void set(String name, Object value, Document document, Field.Store store, Field.Index
index, Float boost);
+ /**
+ * Manipulate the document to index the given value.
+ * A common implementation is to add a Field <code>name</code> to the
given document following
+ * the parameters (<code>store</code>, <code>index</code>,
<code>boost</code>) if the
+ * <code>value></code> is not null
+ */
+ void set(String name, Object value, Document document, Field.Store store, Field.Index
index, Float boost);
}
Added:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/IdFieldBridge.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/IdFieldBridge.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/IdFieldBridge.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -0,0 +1,29 @@
+//$Id: $
+package org.hibernate.lucene.bridge;
+
+import org.apache.lucene.document.Document;
+
+/**
+ * Any bridge expected to process a document id should implement this interface
+ *
+ * @author Emmanuel Bernard
+ */
+//FIXME rework the interface inheritance there are some common concepts with
StringBridge
+public interface IdFieldBridge extends FieldBridge {
+ /**
+ * build the element from the Document
+ * This method is called when the bridge is used on a document id, If the Bridge is
not expected to
+ * support document id, this method should raise an exception
+ * The return value is the Entity id
+ *
+ * @param name field name
+ * @param document document
+ */
+ Object get(String name, Document document);
+
+ /**
+ * convert the object representation to a String
+ * The return String must not be null, it can be empty though
+ */
+ String objectToString(Object object);
+}
Modified:
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/String2FieldBridgeAdaptor.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/String2FieldBridgeAdaptor.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/String2FieldBridgeAdaptor.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -10,7 +10,8 @@
*
* @author Emmanuel Bernard
*/
-public class String2FieldBridgeAdaptor implements FieldBridge {
+//FIXME all String2FieldBridgeAdaptor are not IdFieldBridge
+public class String2FieldBridgeAdaptor implements FieldBridge, IdFieldBridge {
private StringBridge stringBridge;
@@ -22,7 +23,11 @@
return stringBridge.stringToObject( field.stringValue() );
}
- public void set(String name, Object value, Document document, Field.Store store,
Field.Index index, Float boost) {
+ public String objectToString(Object object) {
+ return stringBridge.objectToString( object );
+ }
+
+ public void set(String name, Object value, Document document, Field.Store store,
Field.Index index, Float boost) {
String indexedString = stringBridge.objectToString(value);
//Do not add fields on empty strings, seems a sensible default in most
situations
if ( StringHelper.isNotEmpty( indexedString ) ) {
Modified:
branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/Document.java
===================================================================
---
branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/Document.java 2006-10-18
16:14:49 UTC (rev 10610)
+++
branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/Document.java 2006-10-18
22:09:34 UTC (rev 10611)
@@ -11,6 +11,10 @@
import org.hibernate.lucene.Text;
import org.hibernate.lucene.Unstored;
import org.hibernate.lucene.Boost;
+import org.hibernate.lucene.Field;
+import org.hibernate.lucene.Index;
+import org.hibernate.lucene.DocumentId;
+import org.hibernate.lucene.Store;
@Entity
@Indexed(index = "Documents")
@@ -32,8 +36,9 @@
@Id
@GeneratedValue
- @Keyword(id = true)
- public Long getId() {
+ //@Keyword(id = true)
+ @DocumentId
+ public Long getId() {
return id;
}
@@ -41,8 +46,9 @@
this.id = id;
}
- @Text
- @Boost(2)
+ //@Text
+ @Field( store = Store.YES, index = Index.TOKENIZED )
+ @Boost(2)
public String getTitle() {
return title;
}
@@ -51,8 +57,9 @@
this.title = title;
}
- @Unstored(name = "Abstract")
- public String getSummary() {
+ //@Unstored(name = "Abstract")
+ @Field( name="Abstract", store = Store.NO, index = Index.TOKENIZED )
+ public String getSummary() {
return summary;
}
@@ -61,8 +68,9 @@
}
@Lob
- @Unstored
- public String getText() {
+ //@Unstored
+ @Field( store = Store.NO, index = Index.TOKENIZED )
+ public String getText() {
return text;
}