package org.etk.reflect.core; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import org.etk.reflect.api.ClassTypeInfo; import org.etk.reflect.api.TypeInfo; import org.etk.reflect.api.annotation.AnnotationParameterInfo; import org.etk.reflect.api.annotation.AnnotationParameterType; import org.etk.reflect.api.definition.LiteralKind; import org.etk.reflect.api.definition.TypeKind; public class AnnotationParameterInfoImpl<T, M, A, P, F, E, Z> implements AnnotationParameterInfo<Z> { private static final EnumMap<LiteralKind, AnnotationParameterType<?>> literalToAnnotationParameterType; static { EnumMap<LiteralKind, AnnotationParameterType<?>> tmp = new EnumMap<LiteralKind, AnnotationParameterType<?>>(LiteralKind.class); tmp.put(LiteralKind.BOOLEAN, AnnotationParameterType.BOOLEAN); tmp.put(LiteralKind.INT, AnnotationParameterType.INTEGER); tmp.put(LiteralKind.DOUBLE, AnnotationParameterType.DOUBLE); tmp.put(LiteralKind.BYTE, AnnotationParameterType.BYTE); tmp.put(LiteralKind.SHORT, AnnotationParameterType.SHORT); tmp.put(LiteralKind.LONG, AnnotationParameterType.LONG); tmp.put(LiteralKind.FLOAT, AnnotationParameterType.FLOAT); literalToAnnotationParameterType = tmp; } private final AnnotatedDelegate<T, M, A, P, F, E> owner; private final A annotation; private final P parameter; private final String name; private final AnnotationParameterType<Z> type; private final boolean multiValued; private List<Z> values; public AnnotationParameterInfoImpl(AnnotatedDelegate<T, M, A, P, F, E> owner, A annotation, P parameter) { // String name = owner.annotationModel.getAnnotationParameterName(parameter); // AnnotationParameterType<?> type; // *[] : unwrap component type T parameterType = owner.annotationModel.getAnnotationParameterType(parameter); TypeKind parameterTypeKind = owner.domain.typeMetadata.getKind(parameterType); boolean multiValued; if (parameterTypeKind == TypeKind.ARRAY) { parameterType = owner.domain.typeMetadata.getComponentType(parameterType); parameterTypeKind = owner.domain.typeMetadata.getKind(parameterType); multiValued = true; } else { multiValued = false; } // switch (parameterTypeKind) { case SIMPLE: LiteralKind parameterLiteralType = owner.domain.typeMetadata.getLiteralType(parameterType); type = literalToAnnotationParameterType.get(parameterLiteralType); break; case PARAMETERIZED: // We do handler Class<*> type T rawParameterType = owner.domain.typeMetadata.getRawType(parameterType); String className = owner.domain.typeMetadata.getClassName(rawParameterType); if (!className.equals(Class.class.getName())) { throw new AssertionError("Does not make any sense"); } type = AnnotationParameterType.CLASS; break; case CLASS: switch (owner.domain.typeMetadata.getClassKind(parameterType)) { case CLASS: String parameterClassName = owner.domain.typeMetadata.getClassName(parameterType); if (parameterClassName.equals(String.class.getName())) { type = AnnotationParameterType.STRING; } else if (parameterClassName.equals(Class.class.getName())) { type = AnnotationParameterType.CLASS; } else { throw new UnsupportedOperationException("Unsupported parameter class " + parameterClassName); } break; case ENUM: type = AnnotationParameterType.ENUM; break; case ANNOTATION: type = AnnotationParameterType.ANNOTATION; break; default: throw new UnsupportedOperationException(); } break; default: throw new UnsupportedOperationException("Unsupported parameter type kind " + parameterTypeKind + " for parameter " + parameter); } // this.owner = owner; this.annotation = annotation; this.parameter = parameter; this.name = name; this.type = (AnnotationParameterType<Z>)type; this.values = null; this.multiValued = multiValued; } public String getName() { return name; } public AnnotationParameterType<Z> getType() { return type; } public boolean isMultiValued() { return multiValued; } public List<Z> getValues() { if (values == null) { List<?> annotationParameterValue = owner.annotationModel.getAnnotationParameterValue(annotation, parameter); if (type == AnnotationParameterType.CLASS) { ArrayList<Object> abc = new ArrayList<Object>(annotationParameterValue.size()); for (Object anAnnotationParameterValue : annotationParameterValue) { T typeValue = (T)anAnnotationParameterValue; TypeInfo typeValueTI = owner.domain.resolve(typeValue); abc.add(typeValueTI); } values = (List<Z>)abc; } else if (type == AnnotationParameterType.ANNOTATION) { ArrayList<Object> abc = new ArrayList<Object>(annotationParameterValue.size()); for (Object anAnnotationParameterValue : annotationParameterValue) { A valueAnnotation = (A)anAnnotationParameterValue; T valueAnnotationType = owner.annotationModel.getAnnotationType(valueAnnotation); ClassTypeInfo valueAnnotationTI = (ClassTypeInfo)owner.domain.resolve(valueAnnotationType); AnnotationInfoImpl<T, M, A, P, F, E> valueAI = new AnnotationInfoImpl<T, M, A, P, F, E>(owner, valueAnnotationTI, (A)valueAnnotation); abc.add(valueAI); } values = (List<Z>)abc; } else { values = (List<Z>)annotationParameterValue; } } return values; } public Z getValue() { List<Z> values = getValues(); return values.isEmpty() ? null : values.get(0); } }