/* * 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 com.hmsonline.storm.cassandra.client; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.UUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import storm.trident.tuple.TridentTuple; import backtype.storm.tuple.Tuple; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.hmsonline.storm.cassandra.StormCassandraConstants; import com.hmsonline.storm.cassandra.bolt.mapper.Equality; import com.hmsonline.storm.cassandra.bolt.mapper.TridentTupleMapper; import com.hmsonline.storm.cassandra.bolt.mapper.TupleCounterMapper; import com.hmsonline.storm.cassandra.bolt.mapper.TupleMapper; import com.netflix.astyanax.AstyanaxConfiguration; import com.netflix.astyanax.AstyanaxContext; import com.netflix.astyanax.Keyspace; import com.netflix.astyanax.MutationBatch; import com.netflix.astyanax.Serializer; import com.netflix.astyanax.annotations.Component; import com.netflix.astyanax.connectionpool.ConnectionPoolConfiguration; import com.netflix.astyanax.connectionpool.ConnectionPoolMonitor; import com.netflix.astyanax.connectionpool.NodeDiscoveryType; import com.netflix.astyanax.connectionpool.OperationResult; import com.netflix.astyanax.connectionpool.impl.ConnectionPoolConfigurationImpl; import com.netflix.astyanax.connectionpool.impl.ConnectionPoolType; import com.netflix.astyanax.connectionpool.impl.SimpleAuthenticationCredentials; import com.netflix.astyanax.connectionpool.impl.Slf4jConnectionPoolMonitorImpl; import com.netflix.astyanax.impl.AstyanaxConfigurationImpl; import com.netflix.astyanax.model.ByteBufferRange; import com.netflix.astyanax.model.Column; import com.netflix.astyanax.model.ColumnFamily; import com.netflix.astyanax.model.ColumnList; import com.netflix.astyanax.model.Composite; import com.netflix.astyanax.query.RowQuery; import com.netflix.astyanax.serializers.AnnotatedCompositeSerializer; import com.netflix.astyanax.serializers.BigIntegerSerializer; import com.netflix.astyanax.serializers.BooleanSerializer; import com.netflix.astyanax.serializers.ByteBufferSerializer; import com.netflix.astyanax.serializers.ByteSerializer; import com.netflix.astyanax.serializers.BytesArraySerializer; import com.netflix.astyanax.serializers.CompositeRangeBuilder; import com.netflix.astyanax.serializers.CompositeSerializer; import com.netflix.astyanax.serializers.DateSerializer; import com.netflix.astyanax.serializers.DoubleSerializer; import com.netflix.astyanax.serializers.FloatSerializer; import com.netflix.astyanax.serializers.Int32Serializer; import com.netflix.astyanax.serializers.LongSerializer; import com.netflix.astyanax.serializers.ObjectSerializer; import com.netflix.astyanax.serializers.ShortSerializer; import com.netflix.astyanax.serializers.StringSerializer; import com.netflix.astyanax.serializers.UUIDSerializer; import com.netflix.astyanax.thrift.ThriftFamilyFactory; import com.netflix.astyanax.util.RangeBuilder; /** * * @param <K> * @param <C> * @param <V> */ public class AstyanaxClient<K, C, V> { private static final Logger LOG = LoggerFactory.getLogger(AstyanaxClient.class); public static final String CASSANDRA_CLUSTER_NAME = "cassandra.clusterName"; public static final String ASTYANAX_CONFIGURATION = "astyanax.configuration"; public static final String ASTYANAX_CONNECTION_POOL_CONFIGURATION = "astyanax.connectionPoolConfiguration"; public static final String ASTYANAX_CONNECTION_POOL_MONITOR = "astyanax.connectioPoolMonitor"; private Map<String, AstyanaxContext<Keyspace>> astyanaxContext = new HashMap<String, AstyanaxContext<Keyspace>>(); // not static since we're carting instances around and do not want to share // them // between bolts private final Map<String, Object> DEFAULTS = new ImmutableMap.Builder<String, Object>() .put(CASSANDRA_CLUSTER_NAME, "ClusterName") .put(ASTYANAX_CONFIGURATION, new AstyanaxConfigurationImpl().setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE) .setConnectionPoolType(ConnectionPoolType.TOKEN_AWARE)) .put(ASTYANAX_CONNECTION_POOL_CONFIGURATION, new ConnectionPoolConfigurationImpl("MyConnectionPool")) .put(ASTYANAX_CONNECTION_POOL_MONITOR, new Slf4jConnectionPoolMonitorImpl()).build(); protected List<AstyanaxContext<Keyspace>> createContext(Map<String, Object> config) { List<AstyanaxContext<Keyspace>> returnVal = new ArrayList<AstyanaxContext<Keyspace>>(); Map<String, Object> settings = Maps.newHashMap(); for (Map.Entry<String, Object> defaultEntry : DEFAULTS.entrySet()) { if (config.containsKey(defaultEntry.getKey())) { settings.put(defaultEntry.getKey(), config.get(defaultEntry.getKey())); } else { settings.put(defaultEntry.getKey(), defaultEntry.getValue()); } } // in the defaults case, we don't know the seed hosts until context // creation time if (settings.get(ASTYANAX_CONNECTION_POOL_CONFIGURATION) instanceof ConnectionPoolConfigurationImpl) { ConnectionPoolConfigurationImpl cpConfig = (ConnectionPoolConfigurationImpl) settings .get(ASTYANAX_CONNECTION_POOL_CONFIGURATION); cpConfig.setSeeds((String) config.get(StormCassandraConstants.CASSANDRA_HOST)); Long port = (Long)config.get(StormCassandraConstants.CASSANDRA_PORT); if(port != null){ cpConfig.setPort(port.intValue()); } // String user = (String) config.get(StormCassandraConstants.CASSANDRA_USERNAME); if( user != null && ! user.trim().isEmpty() ){ String password = config.containsKey(StormCassandraConstants.CASSANDRA_PASSWORD) ? (String) config.get(StormCassandraConstants.CASSANDRA_PASSWORD) : "password"; cpConfig.setAuthenticationCredentials( new SimpleAuthenticationCredentials(new String(user), new String(password))); } } @SuppressWarnings("unchecked") Collection<String> keyspaces = (Collection<String>) config.get(StormCassandraConstants.CASSANDRA_KEYSPACE); for (String keyspace : keyspaces) { returnVal.add(new AstyanaxContext.Builder() .forCluster((String) settings.get(CASSANDRA_CLUSTER_NAME)) .forKeyspace(keyspace) .withAstyanaxConfiguration((AstyanaxConfiguration) settings.get(ASTYANAX_CONFIGURATION)) .withConnectionPoolConfiguration( (ConnectionPoolConfiguration) settings .get(ASTYANAX_CONNECTION_POOL_CONFIGURATION)) .withConnectionPoolMonitor( (ConnectionPoolMonitor) settings.get(ASTYANAX_CONNECTION_POOL_MONITOR)) .buildKeyspace(ThriftFamilyFactory.getInstance())); } return returnVal; } public void start(Map<String, Object> config) { try { List<AstyanaxContext<Keyspace>> contexts = createContext(config); for (AstyanaxContext<Keyspace> context : contexts) { this.addAstyanaxContext(context.getKeyspaceName(), context); this.getAstyanaxContext(context.getKeyspaceName()).start(); // test the connection this.getKeyspace(context.getKeyspaceName()).describeKeyspace(); } } catch (Throwable e) { LOG.warn("Astyanax initialization failed.", e); throw new IllegalStateException("Failed to prepare Astyanax", e); } } public void stop() { this.getAstyanaxContext().shutdown(); } @SuppressWarnings("unchecked") public Map<C, V> lookup(TupleMapper<K, C, V> tupleMapper, Tuple input) throws Exception { String cf = tupleMapper.mapToColumnFamily(input); String keyspace = tupleMapper.mapToKeyspace(input); K rowKey = tupleMapper.mapToRowKey(input); Class<K> keyClass = tupleMapper.getKeyClass(); Class<C> colClass = tupleMapper.getColumnNameClass(); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(cf, (Serializer<K>) serializerFor(keyClass), (Serializer<C>) serializerFor(colClass)); OperationResult<ColumnList<C>> result; result = this.getKeyspace(keyspace).prepareQuery(columnFamily).getKey(rowKey).execute(); ColumnList<C> columns = (ColumnList<C>) result.getResult(); HashMap<C, V> retval = new HashMap<C, V>(); Iterator<Column<C>> it = columns.iterator(); while (it.hasNext()) { Column<C> col = it.next(); retval.put(col.getName(), col.getValue((Serializer<V>) serializerFor(tupleMapper.getColumnValueClass()))); } return retval; } @SuppressWarnings("unchecked") public Map<C, V> lookup(TridentTupleMapper<K, C, V> tupleMapper, TridentTuple input) throws Exception { String cf = tupleMapper.mapToColumnFamily(input); String keyspace = tupleMapper.mapToKeyspace(input); K rowKey = tupleMapper.mapToRowKey(input); Class<K> keyClass = tupleMapper.getKeyClass(); Class<C> colClass = tupleMapper.getColumnNameClass(); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(cf, (Serializer<K>) serializerFor(keyClass), (Serializer<C>) serializerFor(colClass)); OperationResult<ColumnList<C>> result; result = this.getKeyspace(keyspace).prepareQuery(columnFamily).getKey(rowKey).execute(); ColumnList<C> columns = (ColumnList<C>) result.getResult(); HashMap<C, V> retval = new HashMap<C, V>(); Iterator<Column<C>> it = columns.iterator(); while (it.hasNext()) { Column<C> col = it.next(); retval.put(col.getName(), col.getValue((Serializer<V>) serializerFor(tupleMapper.getColumnValueClass()))); } return retval; } @SuppressWarnings("unchecked") public Map<C, V> lookup(TupleMapper<K, C, V> tupleMapper, Tuple input, List<C> slice) throws Exception { String cf = tupleMapper.mapToColumnFamily(input); String keyspace = tupleMapper.mapToKeyspace(input); K rowKey = tupleMapper.mapToRowKey(input); Class<K> keyClass = tupleMapper.getKeyClass(); Class<C> colClass = tupleMapper.getColumnNameClass(); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(cf, (Serializer<K>) serializerFor(keyClass), (Serializer<C>) serializerFor(colClass)); HashMap<C, V> retval = new HashMap<C, V>(); for (C c : slice) { RowQuery<K, C> query = this.getKeyspace(keyspace).prepareQuery(columnFamily).getKey(rowKey); query = query.withColumnRange(getRangeBuilder(c, c, null, (Serializer<C>) serializerFor(colClass))); OperationResult<ColumnList<C>> result = query.execute(); Iterator<Column<C>> it = result.getResult().iterator(); while (it.hasNext()) { Column<C> col = it.next(); retval.put(col.getName(), col.getValue((Serializer<V>) serializerFor(tupleMapper.getColumnValueClass()))); } } return retval; } @SuppressWarnings("unchecked") public Map<C, V> lookup(TridentTupleMapper<K, C, V> tupleMapper, TridentTuple input, List<C> slice) throws Exception { String cf = tupleMapper.mapToColumnFamily(input); String keyspace = tupleMapper.mapToKeyspace(input); K rowKey = tupleMapper.mapToRowKey(input); Class<K> keyClass = tupleMapper.getKeyClass(); Class<C> colClass = tupleMapper.getColumnNameClass(); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(cf, (Serializer<K>) serializerFor(keyClass), (Serializer<C>) serializerFor(colClass)); HashMap<C, V> retval = new HashMap<C, V>(); for (C c : slice) { RowQuery<K, C> query = this.getKeyspace(keyspace).prepareQuery(columnFamily).getKey(rowKey); query = query.withColumnRange(getRangeBuilder(c, c, null, (Serializer<C>) serializerFor(colClass))); OperationResult<ColumnList<C>> result = query.execute(); LOG.debug("Selecting [" + c.toString() + "] returned [" + result.getResult().size() + "] results."); Iterator<Column<C>> it = result.getResult().iterator(); while (it.hasNext()) { Column<C> col = it.next(); LOG.debug("Adding [" + col.getName() + "]=>[" + col.getStringValue() + "]"); retval.put(col.getName(), col.getValue((Serializer<V>) serializerFor(tupleMapper.getColumnValueClass()))); } } return retval; } @SuppressWarnings("unchecked") public Map<C, V> lookup(TupleMapper<K, C, V> tupleMapper, Tuple input, C start, C end, Equality equality) throws Exception { if (start == null || end == null) { return null; } String cf = tupleMapper.mapToColumnFamily(input); String keyspace = tupleMapper.mapToKeyspace(input); K rowKey = tupleMapper.mapToRowKey(input); Class<K> keyClass = tupleMapper.getKeyClass(); Class<C> colClass = tupleMapper.getColumnNameClass(); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(cf, (Serializer<K>) serializerFor(keyClass), (Serializer<C>) serializerFor(colClass)); OperationResult<ColumnList<C>> result = this.getKeyspace(keyspace).prepareQuery(columnFamily).getKey(rowKey) .withColumnRange(getRangeBuilder(start, end, equality, (Serializer<C>) serializerFor(colClass))) .execute(); ColumnList<C> columns = (ColumnList<C>) result.getResult(); HashMap<C, V> retval = new HashMap<C, V>(); Iterator<Column<C>> it = columns.iterator(); while (it.hasNext()) { Column<C> col = it.next(); retval.put(col.getName(), col.getValue((Serializer<V>) serializerFor(tupleMapper.getColumnValueClass()))); } return retval; } @SuppressWarnings("unchecked") public Map<C, V> lookup(TridentTupleMapper<K, C, V> tupleMapper, TridentTuple input, C start, C end, Equality equality) throws Exception { if (start == null || end == null) { return null; } String cf = tupleMapper.mapToColumnFamily(input); String keyspace = tupleMapper.mapToKeyspace(input); K rowKey = tupleMapper.mapToRowKey(input); Class<K> keyClass = tupleMapper.getKeyClass(); Class<C> colClass = tupleMapper.getColumnNameClass(); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(cf, (Serializer<K>) serializerFor(keyClass), (Serializer<C>) serializerFor(colClass)); RowQuery<K, C> query = this.getKeyspace(keyspace).prepareQuery(columnFamily).getKey(rowKey); query = query.withColumnRange(getRangeBuilder(start, end, equality, (Serializer<C>) serializerFor(colClass))); OperationResult<ColumnList<C>> result = query.execute(); ColumnList<C> columns = (ColumnList<C>) result.getResult(); HashMap<C, V> retval = new HashMap<C, V>(); Iterator<Column<C>> it = columns.iterator(); while (it.hasNext()) { Column<C> col = it.next(); retval.put(col.getName(), col.getValue((Serializer<V>) serializerFor(tupleMapper.getColumnValueClass()))); } return retval; } @SuppressWarnings("unchecked") public void writeTuple(Tuple input, TupleMapper<K, C, V> tupleMapper) throws Exception { String columnFamilyName = tupleMapper.mapToColumnFamily(input); String keyspace = tupleMapper.mapToKeyspace(input); K rowKey = tupleMapper.mapToRowKey(input); MutationBatch mutation = getKeyspace(keyspace).prepareMutationBatch(); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(columnFamilyName, (Serializer<K>) serializerFor(tupleMapper.getKeyClass()), (Serializer<C>) serializerFor(tupleMapper.getColumnNameClass())); this.addTupleToMutation(input, columnFamily, rowKey, mutation, tupleMapper); mutation.execute(); } @SuppressWarnings("unchecked") public void writeTuple(TridentTuple input, TridentTupleMapper<K, C, V> tupleMapper) throws Exception { String columnFamilyName = tupleMapper.mapToColumnFamily(input); String keyspace = tupleMapper.mapToKeyspace(input); K rowKey = tupleMapper.mapToRowKey(input); MutationBatch mutation = getKeyspace(keyspace).prepareMutationBatch(); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(columnFamilyName, (Serializer<K>) serializerFor(tupleMapper.getKeyClass()), (Serializer<C>) serializerFor(tupleMapper.getColumnNameClass())); this.addTupleToMutation(input, columnFamily, rowKey, mutation, tupleMapper); mutation.execute(); } @SuppressWarnings({ "static-access", "unchecked" }) public void writeTuples(List<TridentTuple> inputs, TridentTupleMapper<K, C, V> tupleMapper) throws Exception { Map<String, MutationBatch> mutations = new HashMap<String, MutationBatch>(); for (TridentTuple input : inputs) { String keyspace = tupleMapper.mapToKeyspace(input); MutationBatch mutation = mutations.get(keyspace); if(mutation == null) { mutation = getKeyspace(keyspace).prepareMutationBatch(); mutations.put(keyspace, mutation); } String columnFamilyName = tupleMapper.mapToColumnFamily(input); K rowKey = tupleMapper.mapToRowKey(input); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(columnFamilyName, (Serializer<K>) serializerFor(tupleMapper.getKeyClass()), (Serializer<C>) this.serializerFor(tupleMapper.getColumnNameClass())); this.addTupleToMutation(input, columnFamily, rowKey, mutation, tupleMapper); } for(String key : mutations.keySet()) { mutations.get(key).execute(); } } @SuppressWarnings({ "static-access", "unchecked" }) public void writeTuples(List<Tuple> inputs, TupleMapper<K, C, V> tupleMapper) throws Exception { Map<String, MutationBatch> mutations = new HashMap<String, MutationBatch>(); for (Tuple input : inputs) { String keyspace = tupleMapper.mapToKeyspace(input); MutationBatch mutation = mutations.get(keyspace); if(mutation == null) { mutation = getKeyspace(keyspace).prepareMutationBatch(); mutations.put(keyspace, mutation); } String columnFamilyName = tupleMapper.mapToColumnFamily(input); K rowKey = tupleMapper.mapToRowKey(input); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(columnFamilyName, (Serializer<K>) serializerFor(tupleMapper.getKeyClass()), (Serializer<C>) this.serializerFor(tupleMapper.getColumnNameClass())); this.addTupleToMutation(input, columnFamily, rowKey, mutation, tupleMapper); } for(String key : mutations.keySet()) { mutations.get(key).execute(); } } @SuppressWarnings({ "static-access", "unchecked" }) private void addTupleToMutation(Tuple input, ColumnFamily<K, C> columnFamily, K rowKey, MutationBatch mutation, TupleMapper<K, C, V> tupleMapper) { Map<C, V> columns = tupleMapper.mapToColumns(input); for (Map.Entry<C, V> entry : columns.entrySet()) { mutation.withRow(columnFamily, rowKey).putColumn(entry.getKey(), entry.getValue(), (Serializer<V>) this.serializerFor(tupleMapper.getColumnValueClass()), null); } } private void addTupleToMutation(TridentTuple input, ColumnFamily<K, C> columnFamily, K rowKey, MutationBatch mutation, TridentTupleMapper<K, C, V> tupleMapper) { Map<C, V> columns = tupleMapper.mapToColumns(input); if (tupleMapper.shouldDelete(input)) { for (Map.Entry<C, V> entry : columns.entrySet()) { mutation.withRow(columnFamily, rowKey).deleteColumn(entry.getKey()); } } else { for (Map.Entry<C, V> entry : columns.entrySet()) { mutation.withRow(columnFamily, rowKey).putColumn(entry.getKey(), entry.getValue(), serializerFor(tupleMapper.getColumnValueClass()), null); } } } @SuppressWarnings("unchecked") public void incrementCountColumn(Tuple input, TupleCounterMapper<K,C> tupleMapper) throws Exception { String columnFamilyName = tupleMapper.mapToColumnFamily(input); String keyspace = tupleMapper.mapToKeyspace(input); K rowKey = tupleMapper.mapToRowKey(input); long incrementAmount = tupleMapper.mapToIncrementAmount(input); MutationBatch mutation = getKeyspace(keyspace).prepareMutationBatch(); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(columnFamilyName, (Serializer<K>) serializerFor(tupleMapper.getKeyClass()), (Serializer<C>) serializerFor(tupleMapper.getColumnNameClass())); for (C columnName : tupleMapper.mapToColumnList(input)) { mutation.withRow(columnFamily, rowKey).incrementCounterColumn(columnName, incrementAmount); } mutation.execute(); } @SuppressWarnings("unchecked") public void incrementCountColumns(List<Tuple> inputs, TupleCounterMapper<K,C> tupleMapper) throws Exception { Map<String, MutationBatch> mutations = new HashMap<String, MutationBatch>(); for (Tuple input : inputs) { String keyspace = tupleMapper.mapToKeyspace(input); MutationBatch mutation = mutations.get(keyspace); if(mutation == null) { mutation = getKeyspace(keyspace).prepareMutationBatch(); mutations.put(keyspace, mutation); } String columnFamilyName = tupleMapper.mapToColumnFamily(input); K rowKey = tupleMapper.mapToRowKey(input); long incrementAmount = tupleMapper.mapToIncrementAmount(input); ColumnFamily<K, C> columnFamily = new ColumnFamily<K, C>(columnFamilyName, (Serializer<K>) serializerFor(tupleMapper.getKeyClass()), (Serializer<C>) serializerFor(tupleMapper.getColumnNameClass())); for (C columnName : tupleMapper.mapToColumnList(input)) { mutation.withRow(columnFamily, rowKey).incrementCounterColumn(columnName, incrementAmount); } } for(String key : mutations.keySet()) { mutations.get(key).execute(); } } @SuppressWarnings({ "rawtypes" }) private ByteBufferRange getRangeBuilder(C start, C end, Equality equality, Serializer<C> serializer) throws IllegalAccessException, IntrospectionException, InvocationTargetException { if (!(serializer instanceof AnnotatedCompositeSerializer)) { return new RangeBuilder().setStart(start, serializerFor(start.getClass())) .setEnd(end, serializerFor(end.getClass())).build(); } else { AnnotatedCompositeSerializer compositeSerializer = (AnnotatedCompositeSerializer) serializer; CompositeRangeBuilder rangeBuilder = compositeSerializer.buildRange(); List<ComponentField> componentFields = componentFieldsForClass(start.getClass()); List<ComponentField> nonNullFields = new ArrayList<ComponentField>(); for (ComponentField field : componentFields) { if ((field.getValue(start) != null) && field.getValue(end) != null) { nonNullFields.add(field); } } for (int i = 0; i < nonNullFields.size(); i++) { Object objStart = nonNullFields.get(i).getValue(start); Object objEnd = nonNullFields.get(i).getValue(end); if (i + 1 != nonNullFields.size()) { rangeBuilder.withPrefix(objStart); LOG.debug("withPrefix(" + objStart + ")"); } else { rangeBuilder.greaterThanEquals(objStart); LOG.debug("greaterThanEquals(" + objStart + ")"); rangeBuilder.lessThanEquals(objEnd); LOG.debug("lessThanEquals(" + objEnd + ")"); } } return rangeBuilder; } } static class ComponentField implements Comparable<ComponentField> { private Method getter; private int ordinal; ComponentField(Method getter, int ordinal) { this.getter = getter; this.ordinal = ordinal; } Object getValue(Object obj) throws IllegalAccessException, InvocationTargetException { return getter.invoke(obj); } @Override public int compareTo(ComponentField other) { return this.ordinal - other.ordinal; } } private static List<ComponentField> componentFieldsForClass(Class<?> c) throws IntrospectionException { ArrayList<ComponentField> retval = new ArrayList<ComponentField>(); List<Field> fields = getInheritedFields(c); for (Field field : fields) { Component comp = field.getAnnotation(Component.class); if (comp != null) { retval.add(new ComponentField(new PropertyDescriptor(field.getName(), c).getReadMethod(), comp.ordinal())); } } Collections.sort(retval); return retval; } private static boolean containsComponentAnnotation(Class<?> c) { List<Field> fields = getInheritedFields(c); for (Field field : fields) { if (field.getAnnotation(Component.class) != null) { return true; } } return false; } private static List<Field> getInheritedFields(Class<?> type) { List<Field> result = new ArrayList<Field>(); Class<?> i = type; while (i != null && i != Object.class) { for (Field field : i.getDeclaredFields()) { if (!field.isSynthetic()) { result.add(field); } } i = i.getSuperclass(); } return result; } @SuppressWarnings({ "rawtypes", "unchecked" }) private static <T> Serializer<T> serializerFor(Class<?> valueClass) { Serializer serializer = null; if (valueClass.equals(UUID.class)) { serializer = UUIDSerializer.get(); } else if (valueClass.equals(String.class)) { serializer = StringSerializer.get(); } else if (valueClass.equals(Long.class) || valueClass.equals(long.class)) { serializer = LongSerializer.get(); } else if (valueClass.equals(Integer.class) || valueClass.equals(int.class)) { serializer = Int32Serializer.get(); } else if (valueClass.equals(Short.class) || valueClass.equals(short.class)) { serializer = ShortSerializer.get(); } else if (valueClass.equals(Byte.class) || valueClass.equals(byte.class)) { serializer = ByteSerializer.get(); } else if (valueClass.equals(Float.class) || valueClass.equals(float.class)) { serializer = FloatSerializer.get(); } else if (valueClass.equals(Double.class) || valueClass.equals(double.class)) { serializer = DoubleSerializer.get(); } else if (valueClass.equals(BigInteger.class)) { serializer = BigIntegerSerializer.get(); // } else if (valueClass.equals(BigDecimal.class)) { // serializer = BigDecimalSerializer.get(); } else if (valueClass.equals(Boolean.class) || valueClass.equals(boolean.class)) { serializer = BooleanSerializer.get(); } else if (valueClass.equals(byte[].class)) { serializer = BytesArraySerializer.get(); } else if (valueClass.equals(ByteBuffer.class)) { serializer = ByteBufferSerializer.get(); } else if (valueClass.equals(Date.class)) { serializer = DateSerializer.get(); } else if (valueClass.equals(Composite.class)) { serializer = CompositeSerializer.get(); } if (serializer == null) { if (containsComponentAnnotation(valueClass)) { serializer = new AnnotatedCompositeSerializer(valueClass); } else { serializer = ObjectSerializer.get(); } } return serializer; } public Keyspace getKeyspace() { return this.getAstyanaxContext().getEntity(); } public Keyspace getKeyspace(String keyspace) { return this.getAstyanaxContext(keyspace).getEntity(); } public AstyanaxContext<Keyspace> getAstyanaxContext() { if(astyanaxContext.size() == 1) { return astyanaxContext.values().iterator().next(); } else { throw new IllegalArgumentException("if using no args get context there can only be one keyspace, instead there was " + astyanaxContext.size()); } } public AstyanaxContext<Keyspace> getAstyanaxContext(String keyspace) { String keyspaceLower = keyspace.toLowerCase(); AstyanaxContext<Keyspace> returnVal = astyanaxContext.get(keyspaceLower); if(returnVal == null) { throw new IllegalArgumentException("Cannnot find client for keyspace: " + keyspaceLower); } return returnVal; } public void addAstyanaxContext(String keyspace, AstyanaxContext<Keyspace> astyanaxContext) { this.astyanaxContext.put(keyspace.toLowerCase(), astyanaxContext); } }