You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by up...@apache.org on 2015/08/28 20:40:05 UTC
incubator-geode git commit: Implementing mapping objects to Lucene
documents
Repository: incubator-geode
Updated Branches:
refs/heads/feature/GEODE-11 07528954e -> e3ba6d9e9
Implementing mapping objects to Lucene documents
I've added an implementation of the code that converts and object to a
document. As part of this, I renamed a couple of interfaces
ObjectToDocumentMapper -> LuceneSerializer
SingleIndexRepository -> IndexRepository
The LuceneSerializer is an interface I hope maybe we can allow users
to implement if they want so they can customize how their object gets
converted to a Document - for example for spatial indexing.
I've implemented the LuceneSerializer and added unit tests. I also
implemented IndexRepository and added a unit test for that as well.
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/e3ba6d9e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/e3ba6d9e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/e3ba6d9e
Branch: refs/heads/feature/GEODE-11
Commit: e3ba6d9e959a7d996813c60e8be354d6ff452bb1
Parents: 0752895
Author: Dan Smith <up...@apache.org>
Authored: Thu Aug 27 16:38:59 2015 -0700
Committer: Dan Smith <up...@apache.org>
Committed: Fri Aug 28 11:24:39 2015 -0700
----------------------------------------------------------------------
.../lucene/internal/LuceneEventListener.java | 8 +-
.../internal/repository/IndexRepository.java | 33 +++++
.../repository/IndexRepositoryImpl.java | 52 ++++++++
.../repository/ObjectToDocumentMapper.java | 24 ----
.../internal/repository/RepositoryManager.java | 2 +-
.../repository/SingleIndexRepository.java | 33 -----
.../repository/SingleIndexRepositoryImpl.java | 40 ------
.../HeterogenousLuceneSerializer.java | 64 ++++++++++
.../repository/serializer/LuceneSerializer.java | 16 +++
.../serializer/PdxLuceneSerializer.java | 28 +++++
.../serializer/ReflectionLuceneSerializer.java | 55 ++++++++
.../repository/serializer/SerializerUtil.java | 126 +++++++++++++++++++
.../internal/LuceneEventListenerJUnitTest.java | 6 +-
.../SingleIndexRepositoryImplJUnitTest.java | 110 ++++++++++++++++
.../HeterogenousLuceneSerializerJUnitTest.java | 71 +++++++++++
.../serializer/PdxFieldMapperJUnitTest.java | 66 ++++++++++
.../ReflectionFieldMapperJUnitTest.java | 66 ++++++++++
.../internal/repository/serializer/Type1.java | 22 ++++
.../internal/repository/serializer/Type2.java | 15 +++
19 files changed, 732 insertions(+), 105 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListener.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListener.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListener.java
index 1eca80a..4c289bf 100644
--- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListener.java
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListener.java
@@ -13,7 +13,7 @@ import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEvent;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventListener;
import com.gemstone.gemfire.cache.lucene.internal.repository.RepositoryManager;
-import com.gemstone.gemfire.cache.lucene.internal.repository.SingleIndexRepository;
+import com.gemstone.gemfire.cache.lucene.internal.repository.IndexRepository;
import com.gemstone.gemfire.cache.query.internal.DefaultQuery;
import com.gemstone.gemfire.internal.logging.LogService;
@@ -39,14 +39,14 @@ public class LuceneEventListener implements AsyncEventListener {
// Try to get a PDX instance if possible, rather than a deserialized object
DefaultQuery.setPdxReadSerialized(true);
- Set<SingleIndexRepository> affectedRepos = new HashSet<SingleIndexRepository>();
+ Set<IndexRepository> affectedRepos = new HashSet<IndexRepository>();
try {
for (AsyncEvent event : events) {
Region region = event.getRegion();
Object key = event.getKey();
- SingleIndexRepository repository = repositoryManager.getRepository(region, key);
+ IndexRepository repository = repositoryManager.getRepository(region, key);
Operation op = event.getOperation();
@@ -64,7 +64,7 @@ public class LuceneEventListener implements AsyncEventListener {
affectedRepos.add(repository);
}
- for(SingleIndexRepository repo : affectedRepos) {
+ for(IndexRepository repo : affectedRepos) {
repo.commit();
}
return true;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepository.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepository.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepository.java
new file mode 100644
index 0000000..dac206d
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepository.java
@@ -0,0 +1,33 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository;
+
+import java.io.IOException;
+
+/**
+ * An Repository interface for the writing data to lucene.
+ */
+public interface IndexRepository {
+
+ /**
+ * Create a new entry in the lucene index
+ * @throws IOException
+ */
+ void create(Object key, Object value) throws IOException;
+
+ /**
+ * Update the entries in the lucene index
+ * @throws IOException
+ */
+ void update(Object key, Object value) throws IOException;
+
+ /**
+ * Delete the entries in the lucene index
+ * @throws IOException
+ */
+ void delete(Object key) throws IOException;
+
+ /**
+ * Commit the changes to all lucene index
+ * @throws IOException
+ */
+ void commit() throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepositoryImpl.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepositoryImpl.java
new file mode 100644
index 0000000..5fb7ae7
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/IndexRepositoryImpl.java
@@ -0,0 +1,52 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository;
+
+import java.io.IOException;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+
+import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.SerializerUtil;
+import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.LuceneSerializer;
+
+/**
+ * A repository that writes to a single lucene index writer
+ */
+public class IndexRepositoryImpl implements IndexRepository {
+
+ private final IndexWriter writer;
+ private final LuceneSerializer serializer;
+
+ public IndexRepositoryImpl(IndexWriter writer, LuceneSerializer serializer) {
+ this.writer = writer;
+ this.serializer = serializer;
+ }
+
+ @Override
+ public void create(Object key, Object value) throws IOException {
+ Document doc = new Document();
+ SerializerUtil.addKey(key, doc);
+ serializer.toDocument(value, doc);
+ writer.addDocument(doc);
+ }
+
+ @Override
+ public void update(Object key, Object value) throws IOException {
+ Document doc = new Document();
+ SerializerUtil.addKey(key, doc);
+ serializer.toDocument(value, doc);
+ writer.updateDocument(SerializerUtil.getKeyTerm(doc), doc);
+ }
+
+ @Override
+ public void delete(Object key) throws IOException {
+ Term keyTerm = SerializerUtil.toKeyTerm(key);
+ writer.deleteDocuments(keyTerm);
+ }
+
+ @Override
+ public void commit() throws IOException {
+ writer.commit();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/ObjectToDocumentMapper.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/ObjectToDocumentMapper.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/ObjectToDocumentMapper.java
deleted file mode 100644
index 24612ca..0000000
--- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/ObjectToDocumentMapper.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.gemstone.gemfire.cache.lucene.internal.repository;
-
-import org.apache.lucene.index.IndexableField;
-import org.apache.lucene.index.Term;
-
-/**
- * Interface for transforming a gemfire key and value into a lucene document
- */
-public interface ObjectToDocumentMapper {
-
- /**
- * Transform a gemfire key and value into a document suitable for adding
- * to a Lucene IndexWriter. The document is expected to have a unique
- * key which can later be used to delete or update the document
- */
- Iterable<? extends IndexableField> transform(Object key, Object value);
-
- /**
- * Convert a gemfire key into a key search term that can be used to
- * update or delete the document associated with this key.
- */
- Term keyTerm(Object key);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/RepositoryManager.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/RepositoryManager.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/RepositoryManager.java
index a6879a9..0d3e61f 100644
--- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/RepositoryManager.java
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/RepositoryManager.java
@@ -4,6 +4,6 @@ import com.gemstone.gemfire.cache.Region;
public interface RepositoryManager {
- SingleIndexRepository getRepository(Region region, Object key);
+ IndexRepository getRepository(Region region, Object key);
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepository.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepository.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepository.java
deleted file mode 100644
index f4cc4ef..0000000
--- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepository.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.gemstone.gemfire.cache.lucene.internal.repository;
-
-import java.io.IOException;
-
-/**
- * An Repository interface for the writing data to lucene.
- */
-public interface SingleIndexRepository {
-
- /**
- * Create a new entry in the lucene index
- * @throws IOException
- */
- void create(Object key, Object value) throws IOException;
-
- /**
- * Update the entries in the lucene index
- * @throws IOException
- */
- void update(Object key, Object value) throws IOException;
-
- /**
- * Delete the entries in the lucene index
- * @throws IOException
- */
- void delete(Object key) throws IOException;
-
- /**
- * Commit the changes to all lucene index
- * @throws IOException
- */
- void commit() throws IOException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepositoryImpl.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepositoryImpl.java
deleted file mode 100644
index 944cf41..0000000
--- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepositoryImpl.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.gemstone.gemfire.cache.lucene.internal.repository;
-
-import java.io.IOException;
-
-import org.apache.lucene.index.IndexWriter;
-
-/**
- * A repository that writes to a single lucene index writer
- */
-public class SingleIndexRepositoryImpl implements SingleIndexRepository {
-
- private final IndexWriter writer;
- private final ObjectToDocumentMapper mapper;
-
- public SingleIndexRepositoryImpl(IndexWriter writer, ObjectToDocumentMapper mapper) {
- this.writer = writer;
- this.mapper = mapper;
- }
-
- @Override
- public void create(Object key, Object value) throws IOException {
- writer.addDocument(mapper.transform(key, value));
- }
-
- @Override
- public void update(Object key, Object value) throws IOException {
- writer.updateDocument(mapper.keyTerm(key), mapper.transform(key, value));
- }
-
- @Override
- public void delete(Object key) throws IOException {
- writer.deleteDocuments(mapper.keyTerm(key));
- }
-
- @Override
- public void commit() throws IOException {
- writer.commit();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/HeterogenousLuceneSerializer.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/HeterogenousLuceneSerializer.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/HeterogenousLuceneSerializer.java
new file mode 100644
index 0000000..798f34e
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/HeterogenousLuceneSerializer.java
@@ -0,0 +1,64 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+import java.util.Map;
+
+import org.apache.lucene.document.Document;
+
+import com.gemstone.gemfire.internal.util.concurrent.CopyOnWriteWeakHashMap;
+import com.gemstone.gemfire.pdx.PdxInstance;
+
+/**
+ * An implementation of LuceneSerializer that reads the fields
+ * of a given object using reflection or from a PDX instance and
+ * writes them to a lucene document.
+ */
+public class HeterogenousLuceneSerializer implements LuceneSerializer {
+ /**
+ * The set of indexed fiels for this mapper
+ */
+ private String[] indexedFields;
+
+ /**
+ * A mapper for converting a PDX object into a document
+ */
+ private LuceneSerializer pdxMapper;
+
+ /**
+ * Mappers for each individual class type that this class has seen.
+ *
+ * Weak so that entry will be removed if a class is garbage collected.
+ */
+ private Map<Class<?>, LuceneSerializer> mappers = new CopyOnWriteWeakHashMap<Class<?>, LuceneSerializer>();
+
+ public HeterogenousLuceneSerializer(String[] indexedFields) {
+ this.indexedFields = indexedFields;
+ pdxMapper = new PdxLuceneSerializer(indexedFields);
+ }
+
+ @Override
+ public void toDocument(Object value, Document doc) {
+
+ LuceneSerializer mapper = getFieldMapper(value);
+
+ mapper.toDocument(value, doc);
+ }
+
+ /**
+ * Get the field mapper based on the type of the given object.
+ */
+ private LuceneSerializer getFieldMapper(Object value) {
+ if(value instanceof PdxInstance) {
+ return pdxMapper;
+ } else {
+ Class<?> clazz = value.getClass();
+ LuceneSerializer mapper = mappers.get(clazz);
+ if(mapper == null) {
+ mapper = new ReflectionLuceneSerializer(clazz, indexedFields);
+ mappers.put(clazz, mapper);
+ }
+ return mapper;
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/LuceneSerializer.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/LuceneSerializer.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/LuceneSerializer.java
new file mode 100644
index 0000000..a06617a
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/LuceneSerializer.java
@@ -0,0 +1,16 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+import org.apache.lucene.document.Document;
+
+/**
+ * An interface for writing the fields of an
+ * object into a lucene document
+ */
+public interface LuceneSerializer {
+
+ /**
+ * Add the fields of the given value to the document
+ */
+ void toDocument(Object value, Document doc);
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/PdxLuceneSerializer.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/PdxLuceneSerializer.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/PdxLuceneSerializer.java
new file mode 100644
index 0000000..338edb2
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/PdxLuceneSerializer.java
@@ -0,0 +1,28 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+import org.apache.lucene.document.Document;
+
+import com.gemstone.gemfire.pdx.PdxInstance;
+
+/**
+ * LuceneSerializer which can handle any PdxInstance
+ */
+class PdxLuceneSerializer implements LuceneSerializer {
+
+ private String[] indexedFields;
+
+ public PdxLuceneSerializer(String[] indexedFields) {
+ this.indexedFields = indexedFields;
+ }
+
+ @Override
+ public void toDocument(Object value, Document doc) {
+ PdxInstance pdx = (PdxInstance) value;
+ for(String field : indexedFields) {
+ if(pdx.hasField(field)) {
+ Object fieldValue = pdx.getField(field);
+ SerializerUtil.addField(doc, field, fieldValue);
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/ReflectionLuceneSerializer.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/ReflectionLuceneSerializer.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/ReflectionLuceneSerializer.java
new file mode 100644
index 0000000..0b54fdd
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/ReflectionLuceneSerializer.java
@@ -0,0 +1,55 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.lucene.document.Document;
+
+/**
+ * A lucene serializer that handles a single class and can
+ * map an instance of that class to a document using reflection.
+ */
+class ReflectionLuceneSerializer implements LuceneSerializer {
+
+ private Field[] fields;
+
+ public ReflectionLuceneSerializer(Class<? extends Object> clazz,
+ String[] indexedFields) {
+ Set<String> fieldSet = new HashSet<String>();
+ fieldSet.addAll(Arrays.asList(indexedFields));
+
+ //Iterate through all declared fields and save them
+ //in a list if they are an indexed field and have the correct
+ //type.
+ ArrayList<Field> foundFields = new ArrayList<Field>();
+ while(clazz != Object.class) {
+ for(Field field : clazz.getDeclaredFields()) {
+ Class<?> type = field.getType();
+ if(fieldSet.contains(field.getName())
+ && SerializerUtil.isSupported(type)) {
+ field.setAccessible(true);
+ foundFields.add(field);
+ }
+ }
+
+ clazz = clazz.getSuperclass();
+ }
+
+ this.fields = foundFields.toArray(new Field[foundFields.size()]);
+ }
+
+ @Override
+ public void toDocument(Object value, Document doc) {
+ for(Field field: fields) {
+ try {
+ Object fieldValue = field.get(value);
+ SerializerUtil.addField(doc, field.getName(), fieldValue);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ //TODO - what to do if we can't read a field?
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/SerializerUtil.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/SerializerUtil.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/SerializerUtil.java
new file mode 100644
index 0000000..07e89c9
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/SerializerUtil.java
@@ -0,0 +1,126 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+import java.io.IOException;
+
+import org.apache.lucene.document.BinaryDocValuesField;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.DoubleField;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FloatField;
+import org.apache.lucene.document.IntField;
+import org.apache.lucene.document.LongField;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.util.BytesRef;
+
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.InternalGemFireError;
+import com.gemstone.gemfire.internal.HeapDataOutputStream;
+import com.gemstone.gemfire.internal.Version;
+import com.gemstone.gemfire.internal.util.BlobHelper;
+
+/**
+ * Static utility functions for mapping objects to lucene documents
+ */
+public class SerializerUtil {
+ private static final String KEY_FIELD = "_STORED_KEY";
+ private static final String KEY_SEARCH_FIELD = "_SEARCH_KEY";
+
+ /**
+ * A small buffer for converting keys to byte[] arrays.
+ */
+ private static ThreadLocal<HeapDataOutputStream> buffer = new ThreadLocal<HeapDataOutputStream>() {
+ @Override
+ protected HeapDataOutputStream initialValue() {
+ return new HeapDataOutputStream(Version.CURRENT);
+ }
+ };
+
+ private SerializerUtil() {
+ }
+
+ /**
+ * Add a gemfire key to a document
+ */
+ public static void addKey(Object key, Document doc) {
+ BytesRef keyBytes = keyToBytes(key);
+ doc.add(new BinaryDocValuesField(KEY_SEARCH_FIELD, keyBytes));
+ doc.add(new StoredField(KEY_FIELD, keyBytes));
+ }
+
+ /**
+ * Add a field to the document.
+ *
+ * @return true if the field was successfully added
+ */
+ public static boolean addField(Document doc, String field, Object fieldValue) {
+ Class<?> clazz = fieldValue.getClass();
+ if(clazz == String.class) {
+ doc.add(new TextField(field, (String)fieldValue, Store.NO));
+ } else if (clazz == Long.class) {
+ doc.add(new LongField(field, (Long) fieldValue, Store.NO));
+ } else if (clazz == Integer.class) {
+ doc.add(new IntField(field, (Integer) fieldValue, Store.NO));
+ } else if (clazz == Float.class) {
+ doc.add(new FloatField(field, (Float) fieldValue, Store.NO));
+ } else if (clazz == Double.class) {
+ doc.add(new DoubleField(field, (Double) fieldValue, Store.NO));
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return true if a field type can be written to a lucene document.
+ */
+ public static boolean isSupported(Class<?> type) {
+ return type == String.class || type == long.class || type == int.class
+ || type == float.class || type == double.class
+ || type == Long.class || type == Integer.class
+ || type == Float.class || type == Double.class;
+ }
+
+ /**
+ * Extract the gemfire key from a lucene document
+ */
+ public static Object getKey(Document doc) {
+ try {
+ return BlobHelper.deserializeBlob(doc.getField(KEY_FIELD).binaryValue().bytes);
+ } catch (ClassNotFoundException | IOException e) {
+ throw new InternalGemFireError("Unable to deserialize key", e);
+ }
+ }
+
+ /**
+ * Extract the gemfire key term from a lucene document
+ */
+ public static Term getKeyTerm(Document doc) {
+ return new Term(KEY_SEARCH_FIELD, doc.getField(KEY_FIELD).binaryValue());
+ }
+
+ /**
+ * Convert a gemfire key into a key search term that can be used to
+ * update or delete the document associated with this key.
+ */
+ public static Term toKeyTerm(Object key) {
+ return new Term(KEY_SEARCH_FIELD, keyToBytes(key));
+ }
+
+ /**
+ * Convert a key to a byte array.
+ */
+ private static BytesRef keyToBytes(Object key) {
+ buffer.get().reset();
+ try {
+ DataSerializer.writeObject(key, buffer.get());
+ } catch (IOException e) {
+ throw new InternalGemFireError("Unable to serialize key", e);
+ }
+ return new BytesRef(buffer.get().toByteArray());
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListenerJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListenerJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListenerJUnitTest.java
index ca80db1..f296fd5 100644
--- a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListenerJUnitTest.java
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/LuceneEventListenerJUnitTest.java
@@ -20,7 +20,7 @@ import com.gemstone.gemfire.cache.Operation;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEvent;
import com.gemstone.gemfire.cache.lucene.internal.repository.RepositoryManager;
-import com.gemstone.gemfire.cache.lucene.internal.repository.SingleIndexRepository;
+import com.gemstone.gemfire.cache.lucene.internal.repository.IndexRepository;
import com.gemstone.gemfire.test.junit.categories.UnitTest;
/**
@@ -33,8 +33,8 @@ public class LuceneEventListenerJUnitTest {
@Test
public void testProcessBatch() throws IOException {
RepositoryManager manager = Mockito.mock(RepositoryManager.class);
- SingleIndexRepository repo1 = Mockito.mock(SingleIndexRepository.class);
- SingleIndexRepository repo2 = Mockito.mock(SingleIndexRepository.class);
+ IndexRepository repo1 = Mockito.mock(IndexRepository.class);
+ IndexRepository repo2 = Mockito.mock(IndexRepository.class);
Region region1 = Mockito.mock(Region.class);
Region region2 = Mockito.mock(Region.class);
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepositoryImplJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepositoryImplJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepositoryImplJUnitTest.java
new file mode 100644
index 0000000..bfae55a
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/SingleIndexRepositoryImplJUnitTest.java
@@ -0,0 +1,110 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.queryparser.classic.ParseException;
+import org.apache.lucene.queryparser.classic.QueryParser;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TopDocs;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.gemstone.gemfire.cache.lucene.internal.directory.RegionDirectory;
+import com.gemstone.gemfire.cache.lucene.internal.filesystem.ChunkKey;
+import com.gemstone.gemfire.cache.lucene.internal.filesystem.File;
+import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.HeterogenousLuceneSerializer;
+import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.SerializerUtil;
+import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.Type2;
+import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
+
+/**
+ * Test of the SingleIndexRepostory and everything below
+ * it. This tests that we can save gemfire objects or PDXInstance
+ * objects into a lucene index and search for those objects later.
+ */
+@Category(IntegrationTest.class)
+public class SingleIndexRepositoryImplJUnitTest {
+
+ private IndexRepositoryImpl repo;
+ private HeterogenousLuceneSerializer mapper;
+ private DirectoryReader reader;
+ private StandardAnalyzer analyzer = new StandardAnalyzer();
+
+ @Before
+ public void setUp() throws IOException {
+ ConcurrentHashMap<String, File> fileRegion = new ConcurrentHashMap<String, File>();
+ ConcurrentHashMap<ChunkKey, byte[]> chunkRegion = new ConcurrentHashMap<ChunkKey, byte[]>();
+ RegionDirectory dir = new RegionDirectory(fileRegion, chunkRegion);
+ IndexWriterConfig config = new IndexWriterConfig(analyzer);
+ IndexWriter writer = new IndexWriter(dir, config);
+ reader = DirectoryReader.open(writer, true);
+ String[] indexedFields= new String[] {"s", "i", "l", "d", "f", "s2", "missing"};
+ mapper = new HeterogenousLuceneSerializer(indexedFields);
+ repo = new IndexRepositoryImpl(writer, mapper);
+ }
+
+ @Test
+ public void testAddDocs() throws IOException, ParseException {
+ repo.create("key1", new Type2("bacon maple bar", 1, 2L, 3.0, 4.0f, "Grape Ape doughnut"));
+ repo.create("key2", new Type2("McMinnville Cream doughnut", 1, 2L, 3.0, 4.0f, "Captain my Captain doughnut"));
+ repo.create("key3", new Type2("Voodoo Doll doughnut", 1, 2L, 3.0, 4.0f, "Toasted coconut doughnut"));
+ repo.create("key4", new Type2("Portland Cream doughnut", 1, 2L, 3.0, 4.0f, "Captain my Captain doughnut"));
+ repo.commit();
+
+ checkQuery("Cream", "s", "key2", "key4");
+ }
+
+ @Test
+ @Ignore("This test is not yet working. The deletes aren't recognized")
+ public void testUpdateAndRemove() throws IOException, ParseException {
+ repo.create("key1", new Type2("bacon maple bar", 1, 2L, 3.0, 4.0f, "Grape Ape doughnut"));
+ repo.create("key2", new Type2("McMinnville Cream doughnut", 1, 2L, 3.0, 4.0f, "Captain my Captain doughnut"));
+ repo.create("key3", new Type2("Voodoo Doll doughnut", 1, 2L, 3.0, 4.0f, "Toasted coconut doughnut"));
+ repo.create("key4", new Type2("Portland Cream doughnut", 1, 2L, 3.0, 4.0f, "Captain my Captain doughnut"));
+ repo.commit();
+
+ repo.update("key3", new Type2("Boston Cream Pie", 1, 2L, 3.0, 4.0f, "Toasted coconut doughnut"));
+ repo.delete("key4");
+ repo.commit();
+
+
+ //Make sure the updates and deletes were applied
+ checkQuery("doughnut", "s", "key2");
+ checkQuery("Cream", "s", "key2", "key3");
+ }
+
+ private void checkQuery(String queryTerm, String queryField, String ... expectedKeys)
+ throws IOException, ParseException {
+ QueryParser parser = new QueryParser(queryField, analyzer);
+
+ reader = DirectoryReader.openIfChanged(reader);
+ IndexSearcher searcher = new IndexSearcher(reader);
+ TopDocs results = searcher.search(parser.parse(queryTerm), 100);
+// TopDocs results = searcher.search(new TermQuery(new Term("s", "Cream")), 100);
+
+ Set<String> expectedSet = new HashSet<String>();
+ expectedSet.addAll(Arrays.asList(expectedKeys));
+ Set<Object> actualKeys = new HashSet<Object>();
+ for(ScoreDoc scoreDoc: results.scoreDocs) {
+ Document doc = searcher.doc(scoreDoc.doc);
+ assertEquals(1, doc.getFields().size());
+ actualKeys.add(SerializerUtil.getKey(doc));
+ }
+ assertEquals(expectedSet, actualKeys);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/HeterogenousLuceneSerializerJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/HeterogenousLuceneSerializerJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/HeterogenousLuceneSerializerJUnitTest.java
new file mode 100644
index 0000000..7322311
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/HeterogenousLuceneSerializerJUnitTest.java
@@ -0,0 +1,71 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.Term;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.Mockito;
+
+import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.HeterogenousLuceneSerializer;
+import com.gemstone.gemfire.pdx.PdxInstance;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+/**
+ * Unit test of the ObjectToDocumentMapper.
+ */
+@Category(UnitTest.class)
+public class HeterogenousLuceneSerializerJUnitTest {
+
+ /**
+ * Test that the mapper can handle a mix of different
+ * object types.
+ */
+ @Test
+ public void testHetrogenousObjects() {
+ String[] fields = new String[] {"s", "i", "l", "d", "f", "s2", "missing"};
+ HeterogenousLuceneSerializer mapper = new HeterogenousLuceneSerializer(fields);
+
+ Type1 t1 = new Type1("a", 1, 2L, 3.0, 4.0f);
+
+ Document doc1 = new Document();
+ mapper.toDocument(t1, doc1);
+
+ assertEquals(5, doc1.getFields().size());
+ assertEquals("a", doc1.getField("s").stringValue());
+ assertEquals(1, doc1.getField("i").numericValue());
+ assertEquals(2L, doc1.getField("l").numericValue());
+ assertEquals(3.0, doc1.getField("d").numericValue());
+ assertEquals(4.0f, doc1.getField("f").numericValue());
+
+ Type2 t2 = new Type2("a", 1, 2L, 3.0, 4.0f, "b");
+
+ Document doc2 = new Document();
+ mapper.toDocument(t2, doc2);
+
+ assertEquals(6, doc2.getFields().size());
+ assertEquals("a", doc2.getField("s").stringValue());
+ assertEquals("b", doc2.getField("s2").stringValue());
+ assertEquals(1, doc2.getField("i").numericValue());
+ assertEquals(2L, doc2.getField("l").numericValue());
+ assertEquals(3.0, doc2.getField("d").numericValue());
+ assertEquals(4.0f, doc2.getField("f").numericValue());
+
+ PdxInstance i = Mockito.mock(PdxInstance.class);
+
+ Mockito.when(i.hasField("s")).thenReturn(true);
+ Mockito.when(i.hasField("i")).thenReturn(true);
+ Mockito.when(i.getField("s")).thenReturn("a");
+ Mockito.when(i.getField("i")).thenReturn(5);
+
+ Document doc3 = new Document();
+ mapper.toDocument(i, doc3);
+
+ assertEquals(2, doc3.getFields().size());
+ assertEquals("a", doc3.getField("s").stringValue());
+ assertEquals(5, doc3.getField("i").numericValue());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/PdxFieldMapperJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/PdxFieldMapperJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/PdxFieldMapperJUnitTest.java
new file mode 100644
index 0000000..e6e6b79
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/PdxFieldMapperJUnitTest.java
@@ -0,0 +1,66 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.lucene.document.Document;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.Mockito;
+
+import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.PdxLuceneSerializer;
+import com.gemstone.gemfire.pdx.PdxInstance;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+/**
+ * Unit test of the PdxFieldMapperJUnitTest. Tests that
+ * all field types are mapped correctly.
+ */
+@Category(UnitTest.class)
+public class PdxFieldMapperJUnitTest {
+
+ @Test
+ public void testWriteFields() {
+ String[] fields = new String[] {"s", "i"};
+ PdxLuceneSerializer mapper = new PdxLuceneSerializer(fields);
+
+ PdxInstance i = Mockito.mock(PdxInstance.class);
+
+ Mockito.when(i.hasField("s")).thenReturn(true);
+ Mockito.when(i.hasField("i")).thenReturn(true);
+ Mockito.when(i.getField("s")).thenReturn("a");
+ Mockito.when(i.getField("i")).thenReturn(5);
+
+
+ Document doc = new Document();
+ mapper.toDocument(i, doc);
+
+ assertEquals(2, doc.getFields().size());
+ assertEquals("a", doc.getField("s").stringValue());
+ assertEquals(5, doc.getField("i").numericValue());
+ }
+
+ @Test
+ public void testIgnoreMissing() {
+ String[] fields = new String[] {"s", "i", "s2", "o"};
+ PdxLuceneSerializer mapper = new PdxLuceneSerializer(fields);
+
+ PdxInstance i = Mockito.mock(PdxInstance.class);
+
+ Mockito.when(i.hasField("s")).thenReturn(true);
+ Mockito.when(i.hasField("i")).thenReturn(true);
+ Mockito.when(i.hasField("o")).thenReturn(true);
+ Mockito.when(i.hasField("o2")).thenReturn(true);
+ Mockito.when(i.getField("s")).thenReturn("a");
+ Mockito.when(i.getField("i")).thenReturn(5);
+ Mockito.when(i.getField("o")).thenReturn(new Object());
+ Mockito.when(i.getField("o2")).thenReturn(new Object());
+
+
+ Document doc = new Document();
+ mapper.toDocument(i, doc);
+
+ assertEquals(2, doc.getFields().size());
+ assertEquals("a", doc.getField("s").stringValue());
+ assertEquals(5, doc.getField("i").numericValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/ReflectionFieldMapperJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/ReflectionFieldMapperJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/ReflectionFieldMapperJUnitTest.java
new file mode 100644
index 0000000..5731ffc
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/ReflectionFieldMapperJUnitTest.java
@@ -0,0 +1,66 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.lucene.document.Document;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.ReflectionLuceneSerializer;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+/**
+ * Unit test of the ReflectionFieldMapperClass. Tests that
+ * all field types are mapped correctly.
+ */
+@Category(UnitTest.class)
+public class ReflectionFieldMapperJUnitTest {
+
+ @Test
+ public void testAllFields() {
+
+ String[] allFields = new String[] {"s", "i", "l", "d", "f", "s2"};
+ ReflectionLuceneSerializer mapper1 = new ReflectionLuceneSerializer(Type1.class, allFields);
+ ReflectionLuceneSerializer mapper2 = new ReflectionLuceneSerializer(Type2.class, allFields);
+
+ Type1 t1 = new Type1("a", 1, 2L, 3.0, 4.0f);
+ Type2 t2 = new Type2("a", 1, 2L, 3.0, 4.0f, "b");
+
+ Document doc1 = new Document();
+ mapper1.toDocument(t1, doc1);
+
+ assertEquals(5, doc1.getFields().size());
+ assertEquals("a", doc1.getField("s").stringValue());
+ assertEquals(1, doc1.getField("i").numericValue());
+ assertEquals(2L, doc1.getField("l").numericValue());
+ assertEquals(3.0, doc1.getField("d").numericValue());
+ assertEquals(4.0f, doc1.getField("f").numericValue());
+
+ Document doc2 = new Document();
+ mapper2.toDocument(t2, doc2);
+
+ assertEquals(6, doc2.getFields().size());
+ assertEquals("a", doc2.getField("s").stringValue());
+ assertEquals("b", doc2.getField("s2").stringValue());
+ assertEquals(1, doc2.getField("i").numericValue());
+ assertEquals(2L, doc2.getField("l").numericValue());
+ assertEquals(3.0, doc2.getField("d").numericValue());
+ assertEquals(4.0f, doc2.getField("f").numericValue());
+ }
+
+ @Test
+ public void testIgnoreInvalid() {
+
+ String[] fields = new String[] {"s", "o", "s2"};
+ ReflectionLuceneSerializer mapper = new ReflectionLuceneSerializer(Type2.class, fields);
+
+ Type2 t = new Type2("a", 1, 2L, 3.0, 4.0f, "b");
+
+ Document doc = new Document();
+ mapper.toDocument(t, doc);
+
+ assertEquals(2, doc.getFields().size());
+ assertEquals("a", doc.getField("s").stringValue());
+ assertEquals("b", doc.getField("s2").stringValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/Type1.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/Type1.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/Type1.java
new file mode 100644
index 0000000..c5d2a5b
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/Type1.java
@@ -0,0 +1,22 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+/**
+ * A test type to get mapped to a lucene document
+ */
+public class Type1 {
+ private String s;
+ private int i;
+ private long l;
+ private double d;
+ private float f;
+ private Object o = new Object();
+
+ public Type1(String s, int i, long l, double d, float f) {
+ super();
+ this.s = s;
+ this.i = i;
+ this.l = l;
+ this.d = d;
+ this.f = f;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e3ba6d9e/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/Type2.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/Type2.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/Type2.java
new file mode 100644
index 0000000..10cc11e
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/repository/serializer/Type2.java
@@ -0,0 +1,15 @@
+package com.gemstone.gemfire.cache.lucene.internal.repository.serializer;
+
+/**
+ * A test type to get mapped to a lucene document
+ */
+public class Type2 extends Type1 {
+ private String s2;
+
+ public Type2(String s, int i, long l, double d, float f, String s2) {
+ super(s, i, l, d, f);
+ this.s2=s2;
+ }
+
+
+}
\ No newline at end of file