cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From slebre...@apache.org
Subject svn commit: r1101116 - in /cassandra/branches/cassandra-0.8.1: ./ src/java/org/apache/cassandra/cli/ src/java/org/apache/cassandra/config/ src/java/org/apache/cassandra/db/marshal/ src/java/org/apache/cassandra/utils/ test/unit/org/apache/cassandra/db/...
Date Mon, 09 May 2011 17:08:24 GMT
Author: slebresne
Date: Mon May  9 17:08:23 2011
New Revision: 1101116

URL: http://svn.apache.org/viewvc?rev=1101116&view=rev
Log:
Allow comparator parameters and add generic ReverseType
patch by slebresne; reviewed by jbellis for CASSANDRA-2355

Added:
    cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/ReversedType.java
    cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/TypeParser.java
    cassandra/branches/cassandra-0.8.1/test/unit/org/apache/cassandra/db/marshal/TypeParserTest.java
Modified:
    cassandra/branches/cassandra-0.8.1/CHANGES.txt
    cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cli/CliClient.java
    cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/CFMetaData.java
    cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/ColumnDefinition.java
    cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/AbstractType.java
    cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/utils/FBUtilities.java

Modified: cassandra/branches/cassandra-0.8.1/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/CHANGES.txt?rev=1101116&r1=1101115&r2=1101116&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.8.1/CHANGES.txt Mon May  9 17:08:23 2011
@@ -3,6 +3,9 @@
  * add support for IN to cql SELECT, UPDATE (CASSANDRA-2553)
  * add timestamp support to cql INSERT, UPDATE, and BATCH (CASSANDRA-2555)
 
+0.8.1
+ * add support for comparator parameters and a generic ReverseType
+   (CASSANDRA-2355)
 
 0.8.0-?
  * faster flushes and compaction from fixing excessively pessimistic 

Modified: cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cli/CliClient.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cli/CliClient.java?rev=1101116&r1=1101115&r2=1101116&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cli/CliClient.java (original)
+++ cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cli/CliClient.java Mon
May  9 17:08:23 2011
@@ -602,7 +602,7 @@ public class CliClient
             // setting value for output
             valueAsString = valueValidator.getString(ByteBuffer.wrap(columnValue));
             // updating column value validator class
-            updateColumnMetaData(cfDef, columnName, valueValidator.getClass().getName());
+            updateColumnMetaData(cfDef, columnName, valueValidator.toString());
         }
         else
         {
@@ -2159,7 +2159,7 @@ public class CliClient
             // performing ColumnDef local validator update
             if (withUpdate)
             {
-                updateColumnMetaData(columnFamily, columnName, validator.getClass().getName());
+                updateColumnMetaData(columnFamily, columnName, validator.toString());
             }
 
             return value;

Modified: cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/CFMetaData.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/CFMetaData.java?rev=1101116&r1=1101115&r2=1101116&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/CFMetaData.java
(original)
+++ cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/CFMetaData.java
Mon May  9 17:08:23 2011
@@ -322,17 +322,17 @@ public final class CFMetaData
         cf.keyspace = new Utf8(ksName);
         cf.name = new Utf8(cfName);
         cf.column_type = new Utf8(cfType.name());
-        cf.comparator_type = new Utf8(comparator.getClass().getName());
+        cf.comparator_type = new Utf8(comparator.toString());
         if (subcolumnComparator != null)
-            cf.subcomparator_type = new Utf8(subcolumnComparator.getClass().getName());
+            cf.subcomparator_type = new Utf8(subcolumnComparator.toString());
         cf.comment = new Utf8(comment);
         cf.row_cache_size = rowCacheSize;
         cf.key_cache_size = keyCacheSize;
         cf.read_repair_chance = readRepairChance;
         cf.replicate_on_write = replicateOnWrite;
         cf.gc_grace_seconds = gcGraceSeconds;
-        cf.default_validation_class = new Utf8(defaultValidator.getClass().getName());
-        cf.key_validation_class = new Utf8(keyValidator.getClass().getName());
+        cf.default_validation_class = new Utf8(defaultValidator.toString());
+        cf.key_validation_class = new Utf8(keyValidator.toString());
         cf.min_compaction_threshold = minCompactionThreshold;
         cf.max_compaction_threshold = maxCompactionThreshold;
         cf.row_cache_save_period_in_seconds = rowCacheSavePeriodInSeconds;
@@ -763,10 +763,10 @@ public final class CFMetaData
         org.apache.cassandra.thrift.CfDef def = new org.apache.cassandra.thrift.CfDef(cfm.ksName,
cfm.cfName);
         def.setId(cfm.cfId);
         def.setColumn_type(cfm.cfType.name());
-        def.setComparator_type(cfm.comparator.getClass().getName());
+        def.setComparator_type(cfm.comparator.toString());
         if (cfm.subcolumnComparator != null)
         {
-            def.setSubcomparator_type(cfm.subcolumnComparator.getClass().getName());
+            def.setSubcomparator_type(cfm.subcolumnComparator.toString());
             def.setColumn_type("Super");
         }
         def.setComment(enforceCommentNotNull(cfm.comment));
@@ -775,8 +775,8 @@ public final class CFMetaData
         def.setRead_repair_chance(cfm.readRepairChance);
         def.setReplicate_on_write(cfm.replicateOnWrite);
         def.setGc_grace_seconds(cfm.gcGraceSeconds);
-        def.setDefault_validation_class(cfm.defaultValidator.getClass().getName());
-        def.setKey_validation_class(cfm.keyValidator.getClass().getName());
+        def.setDefault_validation_class(cfm.defaultValidator.toString());
+        def.setKey_validation_class(cfm.keyValidator.toString());
         def.setMin_compaction_threshold(cfm.minCompactionThreshold);
         def.setMax_compaction_threshold(cfm.maxCompactionThreshold);
         def.setRow_cache_save_period_in_seconds(cfm.rowCacheSavePeriodInSeconds);
@@ -793,7 +793,7 @@ public final class CFMetaData
             tcd.setIndex_name(cd.getIndexName());
             tcd.setIndex_type(cd.getIndexType());
             tcd.setName(cd.name);
-            tcd.setValidation_class(cd.getValidator().getClass().getName());
+            tcd.setValidation_class(cd.getValidator().toString());
             column_meta.add(tcd);
         }
         def.setColumn_metadata(column_meta);
@@ -808,10 +808,10 @@ public final class CFMetaData
         def.keyspace = cfm.ksName;
         def.id = cfm.cfId;
         def.column_type = cfm.cfType.name();
-        def.comparator_type = cfm.comparator.getClass().getName();
+        def.comparator_type = cfm.comparator.toString();
         if (cfm.subcolumnComparator != null)
         {
-            def.subcomparator_type = cfm.subcolumnComparator.getClass().getName();
+            def.subcomparator_type = cfm.subcolumnComparator.toString();
             def.column_type = "Super";
         }
         def.comment = enforceCommentNotNull(cfm.comment);
@@ -820,7 +820,7 @@ public final class CFMetaData
         def.read_repair_chance = cfm.readRepairChance;
         def.replicate_on_write = cfm.replicateOnWrite;
         def.gc_grace_seconds = cfm.gcGraceSeconds;
-        def.default_validation_class = cfm.defaultValidator == null ? null : cfm.defaultValidator.getClass().getName();
+        def.default_validation_class = cfm.defaultValidator == null ? null : cfm.defaultValidator.toString();
         def.min_compaction_threshold = cfm.minCompactionThreshold;
         def.max_compaction_threshold = cfm.maxCompactionThreshold;
         def.row_cache_save_period_in_seconds = cfm.rowCacheSavePeriodInSeconds;
@@ -838,7 +838,7 @@ public final class CFMetaData
             tcd.index_name = cd.getIndexName();
             tcd.index_type = cd.getIndexType() == null ? null : org.apache.cassandra.db.migration.avro.IndexType.valueOf(cd.getIndexType().name());
             tcd.name = ByteBufferUtil.clone(cd.name);
-            tcd.validation_class = cd.getValidator().getClass().getName();
+            tcd.validation_class = cd.getValidator().toString();
             column_meta.add(tcd);
         }
         def.column_metadata = column_meta; 

Modified: cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/ColumnDefinition.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/ColumnDefinition.java?rev=1101116&r1=1101115&r2=1101116&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/ColumnDefinition.java
(original)
+++ cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/config/ColumnDefinition.java
Mon May  9 17:08:23 2011
@@ -79,7 +79,7 @@ public class ColumnDefinition
     {
         org.apache.cassandra.db.migration.avro.ColumnDef cd = new org.apache.cassandra.db.migration.avro.ColumnDef();
         cd.name = name;
-        cd.validation_class = new Utf8(validator.getClass().getName());
+        cd.validation_class = new Utf8(validator.toString());
         cd.index_type = index_type == null ? null :
             Enum.valueOf(org.apache.cassandra.db.migration.avro.IndexType.class, index_type.name());
         cd.index_name = index_name == null ? null : new Utf8(index_name);

Modified: cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/AbstractType.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/AbstractType.java?rev=1101116&r1=1101115&r2=1101116&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/AbstractType.java
(original)
+++ cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/AbstractType.java
Mon May  9 17:08:23 2011
@@ -24,7 +24,9 @@ package org.apache.cassandra.db.marshal;
 import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.Comparator;
+import java.util.Map;
 
+import org.apache.cassandra.config.ConfigurationException;
 import org.apache.cassandra.db.IColumn;
 import static org.apache.cassandra.io.sstable.IndexHelper.IndexInfo;
 
@@ -159,4 +161,28 @@ public abstract class AbstractType<T> im
     public abstract int getScale(T obj);
     public abstract int getJdbcType();
     public abstract boolean needsQuotes();
+
+    public static AbstractType parseDefaultParameters(AbstractType baseType, TypeParser parser)
throws ConfigurationException
+    {
+        Map<String, String> parameters = parser.getKeyValueParameters();
+        String reversed = parameters.get("reversed");
+        if (reversed != null && (reversed.isEmpty() || reversed.equals("true")))
+        {
+            return ReversedType.getInstance(baseType);
+        }
+        else
+        {
+            return baseType;
+        }
+    }
+
+    /**
+     * This must be overriden by subclasses if necessary so that for any
+     * AbstractType, this == TypeParser.parse(toString()).
+     */
+    @Override
+    public String toString()
+    {
+        return getClass().getName();
+    }
 }

Added: cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/ReversedType.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/ReversedType.java?rev=1101116&view=auto
==============================================================================
--- cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/ReversedType.java
(added)
+++ cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/ReversedType.java
Mon May  9 17:08:23 2011
@@ -0,0 +1,129 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cassandra.db.marshal;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ReversedType<T> extends AbstractType<T>
+{
+    // interning instances
+    private static final Map<AbstractType, ReversedType> instances = new HashMap<AbstractType,
ReversedType>();
+
+    // package protected for unit tests sake
+    final AbstractType<T> baseType;
+
+    public static synchronized <T> ReversedType<T> getInstance(AbstractType<T>
baseType)
+    {
+        ReversedType type = instances.get(baseType);
+        if (type == null)
+        {
+            type = new ReversedType(baseType);
+            instances.put(baseType, type);
+        }
+        return (ReversedType<T>) type;
+    }
+
+    private ReversedType(AbstractType<T> baseType)
+    {
+        this.baseType = baseType;
+    }
+
+    public int compare(ByteBuffer o1, ByteBuffer o2)
+    {
+        return -baseType.compare(o1, o2);
+    }
+
+    public String getString(ByteBuffer bytes)
+    {
+        return baseType.getString(bytes);
+    }
+
+    public ByteBuffer fromString(String source)
+    {
+        return baseType.fromString(source);
+    }
+
+    public void validate(ByteBuffer bytes) throws MarshalException
+    {
+        baseType.validate(bytes);
+    }
+
+    public T compose(ByteBuffer bytes)
+    {
+        return baseType.compose(bytes);
+    }
+
+    public ByteBuffer decompose(T value)
+    {
+        return baseType.decompose(value);
+    }
+
+    public Class<T> getType()
+    {
+        return baseType.getType();
+    }
+
+    public String toString(T t)
+    {
+        return baseType.toString(t);
+    }
+
+    public boolean isSigned()
+    {
+        return baseType.isSigned();
+    }
+
+    public boolean isCaseSensitive()
+    {
+        return baseType.isCaseSensitive();
+    }
+
+    public boolean isCurrency()
+    {
+        return baseType.isCurrency();
+    }
+
+    public int getPrecision(T obj)
+    {
+        return baseType.getPrecision(obj);
+    }
+
+    public int getScale(T obj)
+    {
+        return baseType.getScale(obj);
+    }
+
+    public int getJdbcType()
+    {
+        return baseType.getJdbcType();
+    }
+
+    public boolean needsQuotes()
+    {
+        return baseType.needsQuotes();
+    }
+
+    @Override
+    public String toString()
+    {
+        return getClass().getName() + "(" + baseType + ")";
+    }
+}

Added: cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/TypeParser.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/TypeParser.java?rev=1101116&view=auto
==============================================================================
--- cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/TypeParser.java
(added)
+++ cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/db/marshal/TypeParser.java
Mon May  9 17:08:23 2011
@@ -0,0 +1,430 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cassandra.db.marshal;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cassandra.config.ConfigurationException;
+import org.apache.cassandra.utils.FBUtilities;
+
+/**
+ * Parse a string containing an Type definition.
+ */
+public class TypeParser
+{
+    private final String str;
+    private int idx;
+
+    // A cache of parsed string, specially useful for DynamicCompositeType
+    private static final Map<String, AbstractType> cache = new HashMap<String, AbstractType>();
+
+    public static final TypeParser EMPTY_PARSER = new TypeParser("", 0);
+
+    private TypeParser(String str, int idx)
+    {
+        this.str = str;
+        this.idx = idx;
+    }
+
+    /**
+     * Parse a string containing an type definition.
+     */
+    public static AbstractType parse(String str) throws ConfigurationException
+    {
+        if (str == null)
+            return BytesType.instance;
+
+        AbstractType type = cache.get(str);
+
+        if (type != null)
+            return type;
+
+        // This could be simplier (i.e. new TypeParser(str).parse()) but we avoid creating
a TypeParser object if not really necessary.
+        int i = 0;
+        i = skipBlank(str, i);
+        int j = i;
+        while (!isEOS(str, i) && isIdentifierChar(str.charAt(i)))
+            ++i;
+
+        if (i == j)
+            return BytesType.instance;
+
+        String name = str.substring(j, i);
+        i = skipBlank(str, i);
+
+        if (!isEOS(str, i) && str.charAt(i) == '(')
+            type = getAbstractType(name, new TypeParser(str, i));
+        else
+            type = getAbstractType(name);
+
+        // We don't really care about concurrency here. Worst case scenario, we do some parsing
unnecessarily
+        cache.put(str, type);
+        return type;
+    }
+
+    /**
+     * Parse an AbstractType from current position of this parser.
+     */
+    private AbstractType parse() throws ConfigurationException
+    {
+        skipBlank();
+        String name = readNextIdentifier();
+
+        skipBlank();
+        if (!isEOS() && str.charAt(idx) == '(')
+            return getAbstractType(name, this);
+        else
+            return getAbstractType(name);
+    }
+
+    public Map<String, String> getKeyValueParameters() throws ConfigurationException
+    {
+        Map<String, String> map = new HashMap<String, String>();
+
+        if (isEOS())
+            return map;
+
+        if (str.charAt(idx) != '(')
+            throw new IllegalStateException();
+
+        ++idx; // skipping '('
+
+        while (skipBlankAndComma())
+        {
+            if (str.charAt(idx) == ')')
+            {
+                ++idx;
+                return map;
+            }
+
+            String k = readNextIdentifier();
+            String v = "";
+            skipBlank();
+            if (str.charAt(idx) == '=')
+            {
+                ++idx;
+                skipBlank();
+                v = readNextIdentifier();
+            }
+            else if (str.charAt(idx) != ',' && str.charAt(idx) != ')')
+            {
+                throwSyntaxError("unexpected character '" + str.charAt(idx) + "'");
+            }
+            map.put(k, v);
+        }
+        throw new ConfigurationException(String.format("Syntax error parsing '%s' at char
%d: unexpected end of string", str, idx));
+    }
+
+    public List<AbstractType> getTypeParameters() throws ConfigurationException
+    {
+        List<AbstractType> list = new ArrayList<AbstractType>();
+
+        if (isEOS())
+            return list;
+
+        if (str.charAt(idx) != '(')
+            throw new IllegalStateException();
+
+        ++idx; // skipping '('
+
+        while (skipBlankAndComma())
+        {
+            if (str.charAt(idx) == ')')
+            {
+                ++idx;
+                return list;
+            }
+
+            try
+            {
+                list.add(parse());
+            }
+            catch (ConfigurationException e)
+            {
+                ConfigurationException ex = new ConfigurationException(String.format("Exception
while parsing '%s' around char %d", str, idx));
+                ex.initCause(e);
+                throw ex;
+            }
+        }
+        throw new ConfigurationException(String.format("Syntax error parsing '%s' at char
%d: unexpected end of string", str, idx));
+    }
+
+    public Map<Byte, AbstractType> getAliasParameters() throws ConfigurationException
+    {
+        Map<Byte, AbstractType> map = new HashMap<Byte, AbstractType>();
+
+        if (isEOS())
+            return map;
+
+        if (str.charAt(idx) != '(')
+            throw new IllegalStateException();
+
+        ++idx; // skipping '('
+
+
+        while (skipBlankAndComma())
+        {
+            if (str.charAt(idx) == ')')
+            {
+                ++idx;
+                return map;
+            }
+
+            String alias = readNextIdentifier();
+            if (alias.length() != 1)
+                throwSyntaxError("An alias should be a single character");
+            char aliasChar = alias.charAt(0);
+            if (aliasChar < 33 || aliasChar > 127)
+                throwSyntaxError("An alias should be a single character in [0..9a..bA..B-+._&]");
+
+            skipBlank();
+            if (!(str.charAt(idx) == '=' && str.charAt(idx+1) == '>'))
+                throwSyntaxError("expecting '=>' token");
+
+            idx += 2;
+            skipBlank();
+            try
+            {
+                map.put((byte)aliasChar, parse());
+            }
+            catch (ConfigurationException e)
+            {
+                ConfigurationException ex = new ConfigurationException(String.format("Exception
while parsing '%s' around char %d", str, idx));
+                ex.initCause(e);
+                throw ex;
+            }
+        }
+        throw new ConfigurationException(String.format("Syntax error parsing '%s' at char
%d: unexpected end of string", str, idx));
+    }
+
+    private static AbstractType getAbstractType(String compareWith) throws ConfigurationException
+    {
+        String className = compareWith.contains(".") ? compareWith : "org.apache.cassandra.db.marshal."
+ compareWith;
+        Class<? extends AbstractType> typeClass = FBUtilities.<AbstractType>classForName(className,
"abstract-type");
+        try
+        {
+            Field field = typeClass.getDeclaredField("instance");
+            return (AbstractType) field.get(null);
+        }
+        catch (NoSuchFieldException e)
+        {
+            // Trying with empty parser
+            return getRawAbstractType(typeClass, EMPTY_PARSER);
+        }
+        catch (IllegalAccessException e)
+        {
+            // Trying with empty parser
+            return getRawAbstractType(typeClass, EMPTY_PARSER);
+        }
+    }
+
+    private static AbstractType getAbstractType(String compareWith, TypeParser parser) throws
ConfigurationException
+    {
+        String className = compareWith.contains(".") ? compareWith : "org.apache.cassandra.db.marshal."
+ compareWith;
+        Class<? extends AbstractType> typeClass = FBUtilities.<AbstractType>classForName(className,
"abstract-type");
+        try
+        {
+            Method method = typeClass.getDeclaredMethod("getInstance", TypeParser.class);
+            return (AbstractType) method.invoke(null, parser);
+        }
+        catch (NoSuchMethodException e)
+        {
+            // Trying to see if we have an instance field and apply the default parameter
to it
+            AbstractType type = getRawAbstractType(typeClass);
+            return AbstractType.parseDefaultParameters(type, parser);
+        }
+        catch (IllegalAccessException e)
+        {
+            // Trying to see if we have an instance field and apply the default parameter
to it
+            AbstractType type = getRawAbstractType(typeClass);
+            return AbstractType.parseDefaultParameters(type, parser);
+        }
+        catch (InvocationTargetException e)
+        {
+            ConfigurationException ex = new ConfigurationException("Invalid definition for
comparator " + typeClass.getName() + ".");
+            ex.initCause(e.getTargetException());
+            throw ex;
+        }
+    }
+
+    private static AbstractType getRawAbstractType(Class<? extends AbstractType> typeClass)
throws ConfigurationException
+    {
+        try
+        {
+            Field field = typeClass.getDeclaredField("instance");
+            return (AbstractType) field.get(null);
+        }
+        catch (NoSuchFieldException e)
+        {
+            throw new ConfigurationException("Invalid comparator class " + typeClass.getName()
+ ": must define a public static instance field or a public static method getInstance(TypeParser).");
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new ConfigurationException("Invalid comparator class " + typeClass.getName()
+ ": must define a public static instance field or a public static method getInstance(TypeParser).");
+        }
+    }
+
+    private static AbstractType getRawAbstractType(Class<? extends AbstractType> typeClass,
TypeParser parser) throws ConfigurationException
+    {
+        try
+        {
+            Method method = typeClass.getDeclaredMethod("getInstance", TypeParser.class);
+            return (AbstractType) method.invoke(null, parser);
+        }
+        catch (NoSuchMethodException e)
+        {
+            throw new ConfigurationException("Invalid comparator class " + typeClass.getName()
+ ": must define a public static instance field or a public static method getInstance(TypeParser).");
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new ConfigurationException("Invalid comparator class " + typeClass.getName()
+ ": must define a public static instance field or a public static method getInstance(TypeParser).");
+        }
+        catch (InvocationTargetException e)
+        {
+            ConfigurationException ex = new ConfigurationException("Invalid definition for
comparator " + typeClass.getName() + ".");
+            ex.initCause(e.getTargetException());
+            throw ex;
+        }
+    }
+
+    private void throwSyntaxError(String msg) throws ConfigurationException
+    {
+        throw new ConfigurationException(String.format("Syntax error parsing '%s' at char
%d: %s", str, idx, msg));
+    }
+
+    private boolean isEOS()
+    {
+        return isEOS(str, idx);
+    }
+
+    private static boolean isEOS(String str, int i)
+    {
+        return i >= str.length();
+    }
+
+    private static boolean isBlank(int c)
+    {
+        return c == ' ' || c == '\t' || c == '\n';
+    }
+
+    private void skipBlank()
+    {
+        idx = skipBlank(str, idx);
+    }
+
+    private static int skipBlank(String str, int i)
+    {
+        while (!isEOS(str, i) && isBlank(str.charAt(i)))
+            ++i;
+
+        return i;
+    }
+
+    // skip all blank and at best one comma, return true if there not EOS
+    private boolean skipBlankAndComma()
+    {
+        boolean commaFound = false;
+        while (!isEOS())
+        {
+            int c = str.charAt(idx);
+            if (c == ',')
+            {
+                if (commaFound)
+                    return true;
+                else
+                    commaFound = true;
+            }
+            else if (!isBlank(c))
+            {
+                return true;
+            }
+            ++idx;
+        }
+        return false;
+    }
+
+    /*
+     * [0..9a..bA..B-+._&]
+     */
+    private static boolean isIdentifierChar(int c)
+    {
+        return (c >= '0' && c <= '9')
+            || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+            || c == '-' || c == '+' || c == '.' || c == '_' || c == '&';
+    }
+
+    // left idx positioned on the character stopping the read
+    private String readNextIdentifier()
+    {
+        int i = idx;
+        while (!isEOS() && isIdentifierChar(str.charAt(idx)))
+            ++idx;
+
+        return str.substring(i, idx);
+    }
+
+    /**
+     * Helper function to ease the writing of AbstractType.toString() methods.
+     */
+    public static String stringifyAliasesParameters(Map<Byte, AbstractType> aliases)
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append('(');
+        Iterator<Map.Entry<Byte, AbstractType>> iter = aliases.entrySet().iterator();
+        if (iter.hasNext())
+        {
+            Map.Entry<Byte, AbstractType> entry = iter.next();
+            sb.append((char)(byte)entry.getKey()).append("=>").append(entry.getValue());
+        }
+        while (iter.hasNext())
+        {
+            Map.Entry<Byte, AbstractType> entry = iter.next();
+            sb.append(',').append((char)(byte)entry.getKey()).append("=>").append(entry.getValue());
+        }
+        sb.append(')');
+        return sb.toString();
+    }
+
+    /**
+     * Helper function to ease the writing of AbstractType.toString() methods.
+     */
+    public static String stringifyTypeParameters(List<AbstractType> types)
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append('(');
+        Iterator<AbstractType> iter = types.iterator();
+        if (iter.hasNext())
+        {
+            sb.append(iter.next());
+        }
+        while (iter.hasNext())
+        {
+            sb.append(',').append(iter.next());
+        }
+        sb.append(')');
+        return sb.toString();
+    }
+}

Modified: cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/utils/FBUtilities.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/utils/FBUtilities.java?rev=1101116&r1=1101115&r2=1101116&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/utils/FBUtilities.java
(original)
+++ cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/utils/FBUtilities.java
Mon May  9 17:08:23 2011
@@ -44,6 +44,7 @@ import org.apache.cassandra.config.Confi
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.db.DecoratedKey;
 import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.db.marshal.TypeParser;
 import org.apache.cassandra.dht.IPartitioner;
 import org.apache.cassandra.dht.Range;
 import org.apache.cassandra.dht.Token;
@@ -523,25 +524,7 @@ public class FBUtilities
 
     public static AbstractType getComparator(String compareWith) throws ConfigurationException
     {
-        String className = compareWith.contains(".") ? compareWith : "org.apache.cassandra.db.marshal."
+ compareWith;
-        Class<? extends AbstractType> typeClass = FBUtilities.<AbstractType>classForName(className,
"abstract-type");
-        try
-        {
-            Field field = typeClass.getDeclaredField("instance");
-            return (AbstractType) field.get(null);
-        }
-        catch (NoSuchFieldException e)
-        {
-            ConfigurationException ex = new ConfigurationException("Invalid comparator "
+ compareWith + " : must define a public static instance field.");
-            ex.initCause(e);
-            throw ex;
-        }
-        catch (IllegalAccessException e)
-        {
-            ConfigurationException ex = new ConfigurationException("Invalid comparator "
+ compareWith + " : must define a public static instance field.");
-            ex.initCause(e);
-            throw ex;
-        }
+        return TypeParser.parse(compareWith);
     }
 
     /**

Added: cassandra/branches/cassandra-0.8.1/test/unit/org/apache/cassandra/db/marshal/TypeParserTest.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/test/unit/org/apache/cassandra/db/marshal/TypeParserTest.java?rev=1101116&view=auto
==============================================================================
--- cassandra/branches/cassandra-0.8.1/test/unit/org/apache/cassandra/db/marshal/TypeParserTest.java
(added)
+++ cassandra/branches/cassandra-0.8.1/test/unit/org/apache/cassandra/db/marshal/TypeParserTest.java
Mon May  9 17:08:23 2011
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cassandra.db.marshal;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.junit.Test;
+import static org.junit.Assert.fail;
+
+import org.apache.cassandra.CleanupHelper;
+import org.apache.cassandra.Util;
+import org.apache.cassandra.config.ConfigurationException;
+import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.columniterator.IdentityQueryFilter;
+import org.apache.cassandra.db.filter.QueryFilter;
+import org.apache.cassandra.db.filter.QueryPath;
+import org.apache.cassandra.utils.*;
+
+public class TypeParserTest
+{
+    @Test
+    public void testParse() throws ConfigurationException
+    {
+        AbstractType type;
+
+        type = TypeParser.parse(null);
+        assert type == BytesType.instance;
+
+        type = TypeParser.parse("");
+        assert type == BytesType.instance;
+
+        type = TypeParser.parse("    ");
+        assert type == BytesType.instance;
+
+        type = TypeParser.parse("LongType");
+        assert type == LongType.instance;
+
+        type = TypeParser.parse("  LongType   ");
+        assert type == LongType.instance;
+
+        type = TypeParser.parse("LongType()");
+        assert type == LongType.instance;
+
+        type = TypeParser.parse("LongType(reversed=false)");
+        assert type == LongType.instance;
+
+        type = TypeParser.parse("LongType(reversed=true)");
+        assert type == ReversedType.getInstance(LongType.instance);
+        assert ((ReversedType)type).baseType == LongType.instance;
+
+        type = TypeParser.parse("LongType(reversed)");
+        assert type == ReversedType.getInstance(LongType.instance);
+        assert ((ReversedType)type).baseType == LongType.instance;
+    }
+
+    @Test
+    public void testParseError() throws ConfigurationException
+    {
+        try
+        {
+            TypeParser.parse("y");
+            fail("Should not pass");
+        }
+        catch (ConfigurationException e) {}
+
+        try
+        {
+            TypeParser.parse("LongType(reversed@)");
+            fail("Should not pass");
+        }
+        catch (ConfigurationException e) {}
+    }
+}



Mime
View raw message