[infinispan-commits] Infinispan SVN: r1209 - in trunk/query/src/main/java/org/infinispan/query: backend and 1 other directories.

infinispan-commits at lists.jboss.org infinispan-commits at lists.jboss.org
Tue Nov 24 06:43:35 EST 2009


Author: manik.surtani at jboss.com
Date: 2009-11-24 06:43:34 -0500 (Tue, 24 Nov 2009)
New Revision: 1209

Added:
   trunk/query/src/main/java/org/infinispan/query/KeyTransformationHandler.java
   trunk/query/src/main/java/org/infinispan/query/Transformable.java
   trunk/query/src/main/java/org/infinispan/query/Transformer.java
Modified:
   trunk/query/src/main/java/org/infinispan/query/backend/LocalQueryInterceptor.java
   trunk/query/src/main/java/org/infinispan/query/backend/QueryHelper.java
   trunk/query/src/main/java/org/infinispan/query/backend/QueryInterceptor.java
   trunk/query/src/main/java/org/infinispan/query/impl/CacheQueryImpl.java
Log:
Starting to implement multiple key types

Added: trunk/query/src/main/java/org/infinispan/query/KeyTransformationHandler.java
===================================================================
--- trunk/query/src/main/java/org/infinispan/query/KeyTransformationHandler.java	                        (rev 0)
+++ trunk/query/src/main/java/org/infinispan/query/KeyTransformationHandler.java	2009-11-24 11:43:34 UTC (rev 1209)
@@ -0,0 +1,75 @@
+package org.infinispan.query;
+
+import org.infinispan.util.Util;
+import org.infinispan.CacheException;
+
+/**
+ * // TODO: Manik: Document this
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class KeyTransformationHandler {
+   public static Object stringToKey(String s) {
+      char type = s.charAt(0);
+      switch (type) {
+         case 'S':
+            // this is a normal String
+            return s.substring(2);
+         case 'I':
+            // This is an Integer
+            return Integer.parseInt(s.substring(2));
+         case 'T':
+            // this is a custom transformable.
+            int indexOfSecondDelimiter = s.indexOf(":", 2);
+            String transformerClassName = s.substring(2, indexOfSecondDelimiter);
+            String keyAsString = s.substring(indexOfSecondDelimiter + 1);
+            Transformer t = null;
+            // try and locate class
+            try {
+               t = (Transformer) Util.getInstance(transformerClassName);
+            } catch (Exception e) {
+               // uh oh, cannot load this class!  What now?
+               throw new CacheException(e);
+            }
+
+            return t.fromString(keyAsString);
+      }
+      throw new CacheException("Unknown type metadata " + type);
+   }
+
+   public static String keyToString(Object key) {
+      if (validKey(key)) {
+         // this string should be in the format of
+         // "<TYPE>:(TRANSFORMER):<KEY>"
+         // e.g.:
+         //   "S:my string key"
+         //   "I:75"
+         //   "D:5.34"
+         //   "B:f"
+         //   "T:com.myorg.MyTransformer:STRING_GENERATED_BY_MY_TRANSFORMER"
+         return key.toString();
+      }
+      else
+         throw new IllegalArgumentException("Indexing only works with entries keyed on Strings!");
+   }
+
+   private static boolean validKey(Object key) {
+      // we support String and JDK primitives and their wrappers.
+      if (key instanceof String ||
+            key instanceof Integer ||
+            key instanceof Long ||
+            key instanceof Float ||
+            key instanceof Double ||
+            key instanceof Boolean ||
+            key instanceof Short ||
+            key instanceof Byte
+            )
+         return true;
+      if (key.getClass().isAnnotationPresent(Transformable.class))
+         return true;
+
+      return false;
+   }
+
+}


Property changes on: trunk/query/src/main/java/org/infinispan/query/KeyTransformationHandler.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/query/src/main/java/org/infinispan/query/Transformable.java
===================================================================
--- trunk/query/src/main/java/org/infinispan/query/Transformable.java	                        (rev 0)
+++ trunk/query/src/main/java/org/infinispan/query/Transformable.java	2009-11-24 11:43:34 UTC (rev 1209)
@@ -0,0 +1,18 @@
+package org.infinispan.query;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * If you annotate your object with this, it can be used as a valid key for Infinispan to index.
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+ at Target(ElementType.TYPE)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Transformable {
+   Class<? extends Transformer> transformer();
+}


Property changes on: trunk/query/src/main/java/org/infinispan/query/Transformable.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/query/src/main/java/org/infinispan/query/Transformer.java
===================================================================
--- trunk/query/src/main/java/org/infinispan/query/Transformer.java	                        (rev 0)
+++ trunk/query/src/main/java/org/infinispan/query/Transformer.java	2009-11-24 11:43:34 UTC (rev 1209)
@@ -0,0 +1,16 @@
+package org.infinispan.query;
+
+/**
+ * The task of this interface is to convert keys from their original types to a String representation (which can be
+ * used in Lucene) and vice versa.
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public interface Transformer {
+
+   Object fromString(String s);
+
+   String toString(Object customType);
+   
+}


Property changes on: trunk/query/src/main/java/org/infinispan/query/Transformer.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/query/src/main/java/org/infinispan/query/backend/LocalQueryInterceptor.java
===================================================================
--- trunk/query/src/main/java/org/infinispan/query/backend/LocalQueryInterceptor.java	2009-11-24 11:42:32 UTC (rev 1208)
+++ trunk/query/src/main/java/org/infinispan/query/backend/LocalQueryInterceptor.java	2009-11-24 11:43:34 UTC (rev 1209)
@@ -1,15 +1,10 @@
 package org.infinispan.query.backend;
 
 import org.hibernate.search.engine.SearchFactoryImplementor;
-import org.infinispan.commands.write.PutKeyValueCommand;
-import org.infinispan.commands.write.PutMapCommand;
-import org.infinispan.commands.write.RemoveCommand;
-import org.infinispan.commands.write.ReplaceCommand;
 import org.infinispan.context.InvocationContext;
 import org.infinispan.factories.annotations.Inject;
 
 import javax.transaction.TransactionManager;
-import java.util.Map;
 
 /**
  * <p/>
@@ -36,93 +31,8 @@
       this.transactionManager = transactionManager;
    }
 
-
    @Override
-   public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
-
-      // This method will get the put() calls on the cache and then send them into Lucene once it's successful.
-
-      if (log.isDebugEnabled()) log.debug("Entered the LocalQueryInterceptor visitPutKeyValueCommand()");
-
-      // do the actual put first.
-      Object toReturn = invokeNextInterceptor(ctx, command);
-
-      // Since this is going to index if local only, then we must first check to see if the
-      // context is local.
-
-      Object value = checkForMarshalledValue(command.getValue());
-
-      if (ctx.isOriginLocal()) {
-         if (log.isDebugEnabled()) log.debug("Origin is local");
-         addToIndexes(value, checkForMarshalledValue(command.getKey()).toString());
-      }
-
-      return toReturn;
+   protected boolean shouldModifyIndexes(InvocationContext ctx) {
+      return ctx.isOriginLocal();   
    }
-
-   @Override
-   public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
-
-      if (log.isDebugEnabled()) log.debug("Entered the LocalQueryInterceptor visitRemoveCommand()");
-
-      // remove the object out of the cache first.
-      Object valueRemoved = invokeNextInterceptor(ctx, command);
-
-
-      // Check to make sure that the context is local as well as successful.
-      if (command.isSuccessful() && ctx.isOriginLocal()) {
-         log.debug("Origin is local");
-         removeFromIndexes(checkForMarshalledValue(valueRemoved), checkForMarshalledValue(command.getKey()).toString());
-      }
-
-      return valueRemoved;
-
-   }
-
-
-   @Override
-   public Object visitReplaceCommand(InvocationContext ctx, ReplaceCommand command) throws Throwable {
-      if (log.isDebugEnabled()) log.debug("Entered the LocalQueryInterceptor visitReplaceCommand()");
-
-      Object valueReplaced = invokeNextInterceptor(ctx, command);
-
-      // Checking for local as well as making sure that the valueReplaced is not null.
-
-      if (valueReplaced != null && ctx.isOriginLocal()) {
-
-         if (log.isDebugEnabled()) log.debug("Origin is local");
-         Object[] parameters = command.getParameters();
-         String keyString = checkForMarshalledValue(command.getKey()).toString();
-
-         removeFromIndexes(checkForMarshalledValue(parameters[1]), keyString);
-         addToIndexes(checkForMarshalledValue(parameters[2]), keyString);
-      }
-
-      return valueReplaced;
-   }
-
-   @Override
-   public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
-
-      if (log.isDebugEnabled()) log.debug("Entered LocalQueryInterceptor visitPutMapCommand()");
-
-      Object mapPut = invokeNextInterceptor(ctx, command);
-
-      // Check to make sure the origin is local.
-
-      if (ctx.isOriginLocal()) {
-
-         if (log.isDebugEnabled()) log.debug("Origin is local");
-         Map<Object, Object> dataMap = command.getMap();
-
-         // Loop through all the keys and put those key, value pairings into lucene.
-
-         for (Map.Entry entry : dataMap.entrySet()) {
-            addToIndexes(entry.getValue(), entry.getKey().toString());
-         }
-      }
-
-      return mapPut;
-   }
-
 }

Modified: trunk/query/src/main/java/org/infinispan/query/backend/QueryHelper.java
===================================================================
--- trunk/query/src/main/java/org/infinispan/query/backend/QueryHelper.java	2009-11-24 11:42:32 UTC (rev 1208)
+++ trunk/query/src/main/java/org/infinispan/query/backend/QueryHelper.java	2009-11-24 11:43:34 UTC (rev 1209)
@@ -117,13 +117,13 @@
          try {
             if (indexLocal) {
                // Add a LocalQueryInterceptor to the chain
-               addInterceptor(LocalQueryInterceptor.class);
+               initComponents(LocalQueryInterceptor.class);
             }
             // We're indexing data even if it comes from other sources
 
             else {
                // Add in a QueryInterceptor to the chain
-               addInterceptor(QueryInterceptor.class);
+               initComponents(QueryInterceptor.class);
             }
          } catch (Exception e) {
             throw new CacheException("Unable to add interceptor", e);
@@ -166,7 +166,7 @@
    // Private method that adds the interceptor from the classname parameter.
 
 
-   private void addInterceptor(Class<? extends QueryInterceptor> interceptorClass)
+   private void initComponents(Class<? extends QueryInterceptor> interceptorClass)
          throws IllegalAccessException, InstantiationException {
 
       // get the component registry and then register the searchFactory.

Modified: trunk/query/src/main/java/org/infinispan/query/backend/QueryInterceptor.java
===================================================================
--- trunk/query/src/main/java/org/infinispan/query/backend/QueryInterceptor.java	2009-11-24 11:42:32 UTC (rev 1208)
+++ trunk/query/src/main/java/org/infinispan/query/backend/QueryInterceptor.java	2009-11-24 11:43:34 UTC (rev 1209)
@@ -12,6 +12,7 @@
 import org.infinispan.factories.annotations.Inject;
 import org.infinispan.interceptors.base.CommandInterceptor;
 import org.infinispan.marshall.MarshalledValue;
+import static org.infinispan.query.KeyTransformationHandler.keyToString;
 
 import javax.transaction.TransactionManager;
 import java.util.Map;
@@ -41,19 +42,22 @@
       this.transactionManager = transactionManager;
    }
 
+   protected boolean shouldModifyIndexes(InvocationContext ctx) {
+      return true;
+   }
 
    @Override
    public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
 
       // This method will get the put() calls on the cache and then send them into Lucene once it's successful.
-
-      if (log.isDebugEnabled()) log.debug("Entered the searchable core interceptor visitPutKeyValueCommand()");
-
       // do the actual put first.
       Object toReturn = invokeNextInterceptor(ctx, command);
 
-      addToIndexes(checkForMarshalledValue(command.getValue()), checkForMarshalledValue(command.getKey()).toString());
+      if (shouldModifyIndexes(ctx)) {         
+         addToIndexes(extractValue(command.getKey()), extractValue(command.getValue()));
+      }
 
+
       return toReturn;
    }
 
@@ -67,8 +71,8 @@
 
       if (log.isDebugEnabled()) log.debug("Transaction Manager is " + transactionManager);
 
-      if (command.isSuccessful()) {
-         removeFromIndexes(checkForMarshalledValue(valueRemoved), checkForMarshalledValue(command.getKey()).toString());
+      if (command.isSuccessful() && shouldModifyIndexes(ctx)) {
+         removeFromIndexes(extractValue(valueRemoved), extractValue(command.getKey()));
       }
 
       return valueRemoved;
@@ -82,13 +86,13 @@
       if (log.isDebugEnabled()) log.debug("Entered the searchable core interceptor visitReplaceCommand()");
 
       Object valueReplaced = invokeNextInterceptor(ctx, command);
-      if (valueReplaced != null) {
+      if (valueReplaced != null && shouldModifyIndexes(ctx)) {
 
          Object[] parameters = command.getParameters();
-         String keyString = checkForMarshalledValue(command.getKey()).toString();
+         Object key = extractValue(command.getKey());
 
-         removeFromIndexes(checkForMarshalledValue(parameters[1]), keyString);
-         addToIndexes(checkForMarshalledValue(parameters[2]), keyString);
+         removeFromIndexes(extractValue(parameters[1]), key);
+         addToIndexes(extractValue(parameters[2]), key);
       }
 
       return valueReplaced;
@@ -101,48 +105,47 @@
 
       Object mapPut = invokeNextInterceptor(ctx, command);
 
+      if (shouldModifyIndexes(ctx)) {
+         Map<Object, Object> dataMap = command.getMap();
 
-      Map<Object, Object> dataMap = command.getMap();
+         // Loop through all the keys and put those key, value pairings into lucene.
 
-      // Loop through all the keys and put those key, value pairings into lucene.
-
-      for (Map.Entry entry : dataMap.entrySet()) {
-         addToIndexes(checkForMarshalledValue(entry.getValue()), checkForMarshalledValue(entry.getKey()).toString());
+         for (Map.Entry entry : dataMap.entrySet()) {
+            addToIndexes(extractValue(entry.getValue()), extractValue(entry.getKey()));
+         }
       }
       return mapPut;
    }
 
 
    // Method that will be called when data needs to be added into Lucene.
-   protected void addToIndexes(Object value, String key) {
+   protected void addToIndexes(Object value, Object key) {
+      if (log.isDebugEnabled()) log.debug("Adding to indexes for key [{0}] and value [{0}]", key, value);
 
       // The key here is the String representation of the key that is stored in the cache.
       // The key is going to be the documentID for Lucene.
       // The object parameter is the actual value that needs to be put into lucene.
 
       TransactionContext transactionContext = new TransactionalEventTransactionContext(transactionManager);
-      searchFactory.getWorker().performWork(new Work(value, key, WorkType.ADD), transactionContext);
+      searchFactory.getWorker().performWork(new Work<Object>(value, keyToString(key), WorkType.ADD), transactionContext);
    }
 
 
    // Method that will be called when data needs to be removed from Lucene.
-   protected void removeFromIndexes(Object value, String key) {
+   protected void removeFromIndexes(Object value, Object key) {
 
       // The key here is the String representation of the key that is stored in the cache.
       // The key is going to be the documentID for Lucene.
       // The object parameter is the actual value that needs to be removed from lucene.
 
       TransactionContext transactionContext = new TransactionalEventTransactionContext(transactionManager);
-      searchFactory.getWorker().performWork(new Work(value, key, WorkType.DELETE), transactionContext);
+      searchFactory.getWorker().performWork(new Work<Object>(value, keyToString(key), WorkType.DELETE), transactionContext);
    }
 
-   // Check to see if a given object is a marshalled value or not.
-   protected Object checkForMarshalledValue(Object o) {
-      if (o instanceof MarshalledValue) {
-         return ((MarshalledValue) o).get();
-      } else {
-         return o;
-      }
+   private Object extractValue(Object wrappedValue) {
+      if (wrappedValue instanceof MarshalledValue)
+         return ((MarshalledValue) wrappedValue).get();
+      else
+         return wrappedValue;
    }
-
 }

Modified: trunk/query/src/main/java/org/infinispan/query/impl/CacheQueryImpl.java
===================================================================
--- trunk/query/src/main/java/org/infinispan/query/impl/CacheQueryImpl.java	2009-11-24 11:42:32 UTC (rev 1208)
+++ trunk/query/src/main/java/org/infinispan/query/impl/CacheQueryImpl.java	2009-11-24 11:43:34 UTC (rev 1209)
@@ -47,6 +47,7 @@
 import org.infinispan.Cache;
 import org.infinispan.query.CacheQuery;
 import org.infinispan.query.QueryIterator;
+import org.infinispan.query.KeyTransformationHandler;
 import org.infinispan.query.backend.IndexSearcherCloser;
 
 import java.io.IOException;
@@ -290,21 +291,21 @@
 
          DocumentExtractor extractor = new DocumentExtractor(queryHits, searchFactory, indexProjection, idFieldNames, allowFieldSelectionInProjection);
 
-         List<Object> keysForCache = new ArrayList<Object>(size);
+         List<String> keysForCache = new ArrayList<String>(size);
          for (int index = first; index <= max; index++) {
             // Since the documentId is same thing as the key in each key, value pairing. We can just get the documentId
             // from Lucene and then get it from the cache.
 
             // The extractor.extract.id gives me the documentId that we need.
 
-            Object cacheKey = extractor.extract(index).id;
+            String cacheKey = extractor.extract(index).id.toString(); // these are always strings
             keysForCache.add(cacheKey);
          }
 
          // Loop through my list of keys and get it from the cache. Put each object that I get into a separate list.
          List<Object> listToReturn = new ArrayList<Object>(size);
-         for (Object key : keysForCache) {
-            listToReturn.add(cache.get(key));
+         for (String key : keysForCache) {
+            listToReturn.add(cache.get(KeyTransformationHandler.stringToKey(key)));
          }
 
 



More information about the infinispan-commits mailing list