/* * Copyright (c) 2012-2014 Savoir Technologies, Inc. * * Licensed 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.savoirtech.hecate.cql3; import com.datastax.driver.core.Row; import com.savoirtech.hecate.cql3.exception.HecateException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; public final class FieldMapper { //---------------------------------------------------------------------------------------------------------------------- // Fields //---------------------------------------------------------------------------------------------------------------------- public static final Map<String, String> fromCassandra = new HashMap<>(); public static final Map<String, String> toCassandra = new HashMap<>(); private final static Logger logger = LoggerFactory.getLogger(FieldMapper.class); private static final String TYPE_NAME_PREFIX = "class "; //---------------------------------------------------------------------------------------------------------------------- // Static Methods //---------------------------------------------------------------------------------------------------------------------- static { { fromCassandra.put("TEXT", String.class.getName()); fromCassandra.put("VARCHAR", String.class.getName()); fromCassandra.put("BIGINT", Long.class.getName()); fromCassandra.put("BOOLEAN", Boolean.class.getName()); fromCassandra.put("DOUBLE", Double.class.getName()); fromCassandra.put("FLOAT", Float.class.getName()); fromCassandra.put("INT", Integer.class.getName()); fromCassandra.put("UUID", UUID.class.getName()); fromCassandra.put("TIMESTAMP", Date.class.getName()); for (Map.Entry<String, String> entry : fromCassandra.entrySet()) { toCassandra.put(entry.getValue(), entry.getKey()); } toCassandra.put(int.class.getName(), "INT"); toCassandra.put(boolean.class.getName(), "BOOLEAN"); toCassandra.put(float.class.getName(), "FLOAT"); toCassandra.put(double.class.getName(), "DOUBLE"); toCassandra.put(long.class.getName(), "BIGINT"); } } public static String getCassandraType(Field field) throws HecateException { String fieldType = toCassandra.get(field.getType().getName()); if (fieldType != null) { return fieldType; } if (field.getType().isAssignableFrom(List.class)) { Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; String csType = getStorageType(pt.getActualTypeArguments()[0]); if (!csType.equals("blob")) { return "list<" + csType + ">"; } else { try { return "list<" + FieldMapper.getCassandraTypeForFieldName(ReflectionUtils.getIdName(Class.forName(getClassName( pt.getActualTypeArguments()[0]))), Class.forName(getClassName(pt.getActualTypeArguments()[0]))) + ">"; } catch (ClassNotFoundException e) { logger.error("Class error " + e); } } } return "list<blob>"; } if (field.getType().isAssignableFrom(Set.class)) { Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; String csType = getStorageType(pt.getActualTypeArguments()[0]); if (!csType.equals("blob")) { return "set<" + csType + ">"; } else { try { return "set<" + FieldMapper.getCassandraTypeForFieldName(ReflectionUtils.getIdName(Class.forName(getClassName( pt.getActualTypeArguments()[0]))), Class.forName(getClassName(pt.getActualTypeArguments()[0]))) + ">"; } catch (ClassNotFoundException e) { logger.error("Class error " + e); } } } return "set<blob>"; } if (field.getType().isAssignableFrom(Map.class)) { Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; if ("blob".equals(getStorageType(pt.getActualTypeArguments()[0]))) { throw new HecateException("Complex keys not supported"); } if ("blob".equals(getStorageType(pt.getActualTypeArguments()[1]))) { try { return "map<" + getStorageType(pt.getActualTypeArguments()[0]) + "," + FieldMapper.getCassandraTypeForFieldName(ReflectionUtils.getIdName(Class.forName(getClassName( pt.getActualTypeArguments()[1]))), Class.forName(getClassName(pt.getActualTypeArguments()[1]))) + ">"; } catch (ClassNotFoundException e) { logger.error("Class error " + e); } } return "map<" + getStorageType(pt.getActualTypeArguments()[0]) + "," + getStorageType(pt.getActualTypeArguments()[1]) + ">"; } return "map<blob,blob>"; } System.out.println("Field " + field.getName() + " maps as " + FieldMapper.getCassandraTypeForFieldName(field.getName(), field.getType())); return FieldMapper.getCassandraTypeForFieldName(ReflectionUtils.getIdName(field.getType()), field.getType()); } public static String getCassandraTypeForFieldName(String field, Class cls) throws HecateException { for (Field f : ReflectionUtils.getFieldsUpTo(cls, null)) { if (field.equals(f.getName())) { return getCassandraType(f); } } return null; } private static String getClassName(Type type) { if (type == null) { return ""; } String className = type.toString(); if (className.startsWith(TYPE_NAME_PREFIX)) { className = className.substring(TYPE_NAME_PREFIX.length()); } return className; } public static Object getJavaObject(String type, String column, Row row) { if ("TEXT".equalsIgnoreCase(type)) { return row.getString(column); } if ("VARCHAR".equalsIgnoreCase(type)) { return row.getString(column); } if ("BIGINT".equalsIgnoreCase(type)) { return row.getLong(column); } if ("BOOLEAN".equalsIgnoreCase(type)) { return row.getBool(column); } if ("DOUBLE".equalsIgnoreCase(type)) { return row.getDouble(column); } if ("FLOAT".equalsIgnoreCase(type)) { return row.getFloat(column); } if ("INT".equalsIgnoreCase(type)) { return row.getInt(column); } if (type.startsWith("LIST")) { return row.getList(column, Object.class); } if (type.startsWith("SET")) { return row.getSet(column, Object.class); } if (type.startsWith("MAP")) { return row.getMap(column, Object.class, Object.class); } if ("UUID".equalsIgnoreCase(type)) { return row.getUUID(column); } if ("TIMESTAMP".equalsIgnoreCase(type)) { return row.getDate(column); } return row.getBytes(column); } public static String getRawCassandraType(Field field) throws HecateException { String fieldType = toCassandra.get(field.getType().getName()); if (fieldType != null) { return fieldType; } if (field.getType().isAssignableFrom(List.class)) { Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; String csType = getStorageType(pt.getActualTypeArguments()[0]); if (!csType.equals("blob")) { return "list<" + csType + ">"; } } return "list<blob>"; } if (field.getType().isAssignableFrom(Set.class)) { Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; String csType = getStorageType(pt.getActualTypeArguments()[0]); if (!csType.equals("blob")) { return "set<" + csType + ">"; } } return "set<blob>"; } if (field.getType().isAssignableFrom(Map.class)) { Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; if ("blob".equals(getStorageType(pt.getActualTypeArguments()[0]))) { throw new HecateException("Complex keys not supported"); } return "map<" + getStorageType(pt.getActualTypeArguments()[0]) + "," + getStorageType(pt.getActualTypeArguments()[1]) + ">"; } return "map<blob,blob>"; } //We have an Object, we need to covert the Object's Cassandra ID to a Key value //create a new Table Statement and then add this entity. return FieldMapper.getRawCassandraTypeForFieldName(ReflectionUtils.getIdName(field.getType()), field.getType()); } private static String getRawCassandraTypeForFieldName(String idName, Class<?> type) throws HecateException { for (Field f : ReflectionUtils.getFieldsUpTo(type, null)) { if (idName.equals(f.getName())) { return getRawCassandraType(f); } } return null; } private static String getStorageType(Type type) { String csClass = toCassandra.get(getClassName(type)); if (csClass != null && !StringUtils.isEmpty(csClass)) { return csClass; } //This is actually an Object. //Figure out what the Id Key is and how it'll be used. return "blob"; } //---------------------------------------------------------------------------------------------------------------------- // Constructors //---------------------------------------------------------------------------------------------------------------------- private FieldMapper() { } }