blob: 5cff53e9454be6508df5d7780d1398a9e904f4ed [file] [log] [blame]
/*
* 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.ignite.cache.store.cassandra.common;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.Row;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.ignite.cache.store.cassandra.persistence.PojoFieldAccessor;
import org.apache.ignite.cache.store.cassandra.serializer.Serializer;
/**
* Helper class providing bunch of methods to discover fields of POJO objects and
* map builtin Java types to appropriate Cassandra types.
*/
public class PropertyMappingHelper {
/** Bytes array Class type. */
private static final Class BYTES_ARRAY_CLASS = (new byte[] {}).getClass();
/** Mapping from Java to Cassandra types. */
private static final Map<Class, DataType.Name> JAVA_TO_CASSANDRA_MAPPING = new HashMap<Class, DataType.Name>() {{
put(String.class, DataType.Name.TEXT);
put(Integer.class, DataType.Name.INT);
put(int.class, DataType.Name.INT);
put(Short.class, DataType.Name.SMALLINT);
put(short.class, DataType.Name.SMALLINT);
put(Long.class, DataType.Name.BIGINT);
put(long.class, DataType.Name.BIGINT);
put(Double.class, DataType.Name.DOUBLE);
put(double.class, DataType.Name.DOUBLE);
put(Boolean.class, DataType.Name.BOOLEAN);
put(boolean.class, DataType.Name.BOOLEAN);
put(Float.class, DataType.Name.FLOAT);
put(float.class, DataType.Name.FLOAT);
put(ByteBuffer.class, DataType.Name.BLOB);
put(BYTES_ARRAY_CLASS, DataType.Name.BLOB);
put(BigDecimal.class, DataType.Name.DECIMAL);
put(InetAddress.class, DataType.Name.INET);
put(Date.class, DataType.Name.TIMESTAMP);
put(UUID.class, DataType.Name.UUID);
put(BigInteger.class, DataType.Name.VARINT);
}};
/**
* Maps Cassandra type to specified Java type.
*
* @param clazz java class.
*
* @return Cassandra type.
*/
public static DataType.Name getCassandraType(Class clazz) {
return JAVA_TO_CASSANDRA_MAPPING.get(clazz);
}
/**
* Returns property accessor by class property name.
*
* @param clazz class from which to get property accessor.
* @param prop name of the property.
*
* @return property accessor.
*/
public static PojoFieldAccessor getPojoFieldAccessor(Class clazz, String prop) {
PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(clazz);
if (descriptors != null) {
for (PropertyDescriptor descriptor : descriptors) {
if (descriptor.getName().equals(prop)) {
Field field = null;
try {
field = clazz.getDeclaredField(prop);
}
catch (Throwable ignore) {
}
return new PojoFieldAccessor(descriptor, field);
}
}
}
try {
return new PojoFieldAccessor(clazz.getDeclaredField(prop));
}
catch (Throwable e) {
throw new IllegalArgumentException("POJO class " + clazz.getName() + " doesn't have '" + prop + "' property");
}
}
/**
* Returns value of specific column in the row returned by CQL statement.
*
* @param row row returned by CQL statement.
* @param col column name.
* @param clazz java class to which column value should be casted.
* @param serializer serializer to use if column stores BLOB otherwise could be null.
*
* @return row column value.
*/
public static Object getCassandraColumnValue(Row row, String col, Class clazz, Serializer serializer) {
if (String.class.equals(clazz))
return row.getString(col);
if (Integer.class.equals(clazz))
return row.isNull(col) ? null : row.getInt(col);
if (int.class.equals(clazz)) {
if (row.isNull(col)) {
throw new IllegalArgumentException("Can't cast null value from Cassandra table column '" + col +
"' to " + "int value used in domain object model");
}
return row.getInt(col);
}
if (Short.class.equals(clazz))
return row.isNull(col) ? null : row.getShort(col);
if (short.class.equals(clazz)) {
if (row.isNull(col)) {
throw new IllegalArgumentException("Can't cast null value from Cassandra table column '" + col +
"' to " + "short value used in domain object model");
}
return row.getShort(col);
}
if (Long.class.equals(clazz))
return row.isNull(col) ? null : row.getLong(col);
if (long.class.equals(clazz)) {
if (row.isNull(col)) {
throw new IllegalArgumentException("Can't cast null value from Cassandra table column '" + col +
"' to " + "long value used in domain object model");
}
return row.getLong(col);
}
if (Double.class.equals(clazz))
return row.isNull(col) ? null : row.getDouble(col);
if (double.class.equals(clazz)) {
if (row.isNull(col)) {
throw new IllegalArgumentException("Can't cast null value from Cassandra table column '" + col +
"' to " + "double value used in domain object model");
}
return row.getDouble(col);
}
if (Boolean.class.equals(clazz))
return row.isNull(col) ? null : row.getBool(col);
if (boolean.class.equals(clazz)) {
if (row.isNull(col)) {
throw new IllegalArgumentException("Can't cast null value from Cassandra table column '" + col +
"' to " + "boolean value used in domain object model");
}
return row.getBool(col);
}
if (Float.class.equals(clazz))
return row.isNull(col) ? null : row.getFloat(col);
if (float.class.equals(clazz)) {
if (row.isNull(col)) {
throw new IllegalArgumentException("Can't cast null value from Cassandra table column '" + col +
"' to " + "float value used in domain object model");
}
return row.getFloat(col);
}
if (ByteBuffer.class.equals(clazz))
return row.getBytes(col);
if (PropertyMappingHelper.BYTES_ARRAY_CLASS.equals(clazz)) {
ByteBuffer buf = row.getBytes(col);
return buf == null ? null : buf.array();
}
if (BigDecimal.class.equals(clazz))
return row.getDecimal(col);
if (InetAddress.class.equals(clazz))
return row.getInet(col);
if (Date.class.equals(clazz))
return row.getTimestamp(col);
if (UUID.class.equals(clazz))
return row.getUUID(col);
if (BigInteger.class.equals(clazz))
return row.getVarint(col);
if (serializer == null) {
throw new IllegalStateException("Can't deserialize value from '" + col + "' Cassandra column, " +
"cause there is no BLOB serializer specified");
}
ByteBuffer buf = row.getBytes(col);
return buf == null ? null : serializer.deserialize(buf);
}
}