@SuppressWarnings("unchecked") @Override public <P> Getter<GettableByIndexData, P> newGetter( Type target, DatastaxColumnKey key, ColumnDefinition<?, ?> columnDefinition) { Class<?> targetClass = TypeHelper.toClass(target); if (Date.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxDateGetter(key.getIndex()); } if (boolean.class.equals(targetClass) || Boolean.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxBooleanGetter(key.getIndex()); } if (InetAddress.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxInetAddressGetter(key.getIndex()); } if (TupleValue.class.equals(targetClass)) { return (Getter<GettableByIndexData, P>) new DatastaxTupleValueGetter(key.getIndex()); } if (Collection.class.isAssignableFrom(targetClass)) { Type elementType = TypeHelper.getComponentTypeOfListOrArray(target); Class<?> dataTypeClass = Object.class; Class<?> dataTypeElt = null; DataType dtElt = null; if (key.getDataType() != null) { DataType dataType = key.getDataType(); dataTypeClass = dataType.asJavaClass(); if (dataType.isCollection()) { dtElt = key.getDataType().getTypeArguments().get(0); dataTypeElt = dtElt.asJavaClass(); } } else { dataTypeElt = TypeHelper.toClass(elementType); } if (dataTypeElt != null) { if (TypeHelper.areEquals(elementType, dataTypeElt)) { if (Set.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxSetGetter(key.getIndex(), TypeHelper.toClass(elementType)); } } if (List.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxListGetter(key.getIndex(), TypeHelper.toClass(elementType)); } } } else { Converter<?, ?> converter = getConverter(elementType, dataTypeElt, dtElt); if (converter != null) { if (Set.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxSetWithConverterGetter(key.getIndex(), dataTypeElt, converter); } } if (List.class.equals(dataTypeClass)) { if (targetClass.isAssignableFrom(dataTypeClass)) { return new DatastaxListWithConverterGetter(key.getIndex(), dataTypeElt, converter); } } } } } } if (Map.class.equals(targetClass)) { Tuple2<Type, Type> keyValueTypeOfMap = TypeHelper.getKeyValueTypeOfMap(target); Class<?> dtKeyType = null; Class<?> dtValueType = null; DataType dtKey = null; DataType dtValue = null; if (key.getDataType() != null) { List<DataType> typeArguments = key.getDataType().getTypeArguments(); if (typeArguments.size() == 2) { dtKey = typeArguments.get(0); dtKeyType = dtKey.asJavaClass(); dtValue = typeArguments.get(1); dtValueType = dtValue.asJavaClass(); } } else { dtKeyType = TypeHelper.toClass(keyValueTypeOfMap.first()); dtValueType = TypeHelper.toClass(keyValueTypeOfMap.second()); } if (dtKeyType != null && dtValueType != null) { if (TypeHelper.areEquals(keyValueTypeOfMap.first(), dtKeyType) && TypeHelper.areEquals(keyValueTypeOfMap.second(), dtValueType)) { return new DatastaxMapGetter( key.getIndex(), TypeHelper.toClass(keyValueTypeOfMap.first()), TypeHelper.toClass(keyValueTypeOfMap.second())); } else { Converter<?, ?> keyConverter = getConverter(keyValueTypeOfMap.first(), dtKeyType, dtKey); Converter<?, ?> valueConverter = getConverter(keyValueTypeOfMap.second(), dtValueType, dtValue); if (keyConverter != null && valueConverter != null) { return new DatastaxMapWithConverterGetter( key.getIndex(), dtKeyType, dtValueType, keyConverter, valueConverter); } } } } if (Tuples.isTuple(target)) { if (key.getDataType() != null && key.getDataType() instanceof TupleType) { TupleType tt = (TupleType) key.getDataType(); List<DataType> typeArguments = tt.getTypeArguments(); TypeVariable<? extends Class<?>>[] typeParameters = targetClass.getTypeParameters(); if (typeArguments.size() <= typeParameters.length) { return (Getter<GettableByIndexData, P>) DatastaxTupleGetter.newInstance(datastaxMapperFactory, target, tt, key.getIndex()); } } } if (TypeHelper.isEnum(target)) { final Getter<GettableByIndexData, ? extends Enum> getter = enumGetter(key, TypeHelper.toClass(target)); if (getter != null) { return (Getter<GettableByIndexData, P>) getter; } } final GetterFactory<GettableByIndexData, DatastaxColumnKey> rowGetterFactory = getterFactories.get(targetClass); if (rowGetterFactory != null) { return rowGetterFactory.newGetter(target, key, columnDefinition); } final Getter<GettableByIndexData, P> getter = jodaTimeGetterFactory.newGetter(target, key, columnDefinition); if (getter != null) { return getter; } if (key.getDataType() != null && key.getDataType() instanceof UserType) { UserType ut = (UserType) key.getDataType(); return (Getter<GettableByIndexData, P>) DatastaxUDTGetter.newInstance(datastaxMapperFactory, target, ut, key.getIndex()); } return null; }
public static List<InstantiatorDefinition> extractDefinitions(final Type target) throws IOException { final List<InstantiatorDefinition> constructors = new ArrayList<InstantiatorDefinition>(); final Class<?> targetClass = TypeHelper.toClass(target); ClassLoader cl = targetClass.getClassLoader(); if (cl == null) { cl = ClassLoader.getSystemClassLoader(); } final String fileName = targetClass.getName().replace('.', '/') + ".class"; final InputStream is = cl.getResourceAsStream(fileName); try { if (is == null) { throw new IOException("Cannot find file " + fileName + " in " + cl); } ClassReader classReader = new ClassReader(is); classReader.accept( new ClassVisitor(Opcodes.ASM5) { List<String> genericTypeNames; @Override public void visit( int version, int access, String name, String signature, String superName, String[] interfaces) { if (signature != null) { genericTypeNames = AsmUtils.extractGenericTypeNames(signature); } else { genericTypeNames = Collections.emptyList(); } super.visit(version, access, name, signature, superName, interfaces); } @Override public MethodVisitor visitMethod( int access, final String methodName, String desc, String signature, String[] exceptions) { final boolean isConstructor = "<init>".equals(methodName); if ((Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC && (isConstructor || ((Opcodes.ACC_STATIC & access) == Opcodes.ACC_STATIC && !desc.endsWith("V")))) { final List<String> descTypes = AsmUtils.extractTypeNames(desc); final List<String> genericTypes; final List<String> names = new ArrayList<String>(); if (signature != null) { genericTypes = AsmUtils.extractTypeNames(signature); } else { genericTypes = descTypes; } if (!isConstructor) { if (descTypes.size() > 0) { try { final Type genericType = AsmUtils.toGenericType( descTypes.get(descTypes.size() - 1), genericTypeNames, target); if (!targetClass.isAssignableFrom(TypeHelper.toClass(genericType))) { return null; } } catch (ClassNotFoundException e) { return null; } } else return null; } return new MethodVisitor(Opcodes.ASM5) { Label firstLabel; Label lastLabel; @Override public void visitLabel(Label label) { if (firstLabel == null) { firstLabel = label; } lastLabel = label; } @Override public void visitLocalVariable( String name, String desc, String signature, Label start, Label end, int index) { if (start.equals(firstLabel) && end.equals(lastLabel) && !"this".equals(name)) { names.add(name); } } @Override public void visitEnd() { try { final List<Parameter> parameters = new ArrayList<Parameter>(); int l = descTypes.size() - (isConstructor ? 0 : 1); for (int i = 0; i < l; i++) { String name = "arg" + i; if (i < names.size()) { name = names.get(i); } parameters.add( createParameter(i, name, descTypes.get(i), genericTypes.get(i))); } final Member executable; if (isConstructor) { executable = targetClass.getDeclaredConstructor(toTypeArray(parameters)); } else { executable = targetClass.getDeclaredMethod(methodName, toTypeArray(parameters)); } constructors.add( new ExecutableInstantiatorDefinition( executable, parameters.toArray(new Parameter[0]))); } catch (Exception e) { ErrorHelper.rethrow(e); } } private Class<?>[] toTypeArray(List<Parameter> parameters) { Class<?>[] types = new Class<?>[parameters.size()]; for (int i = 0; i < types.length; i++) { types[i] = parameters.get(i).getType(); } return types; } private Parameter createParameter( int index, String name, String desc, String signature) { try { Type basicType = AsmUtils.toGenericType(desc, genericTypeNames, target); Type genericType = basicType; if (signature != null) { Type type = AsmUtils.toGenericType(signature, genericTypeNames, target); if (type != null) { genericType = type; } } return new Parameter(index, name, TypeHelper.toClass(basicType), genericType); } catch (ClassNotFoundException e) { throw new Error("Unexpected error " + e, e); } } }; } else { return null; } } }, 0); } finally { try { is.close(); } catch (Exception e) { } } return constructors; }