All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kasource.commons.reflection.annotation.AnnotationBuilder Maven / Gradle / Ivy

There is a newer version: 2.1
Show newest version
package org.kasource.commons.reflection.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;



import net.sf.cglib.proxy.Enhancer;

import org.kasource.commons.reflection.annotation.cglib.AnnotationMethodInterceptor;

public class AnnotationBuilder {
    private Class annotationClass;
    private Map attributes = new HashMap();
    private Map attributeData = new HashMap();
    
    public AnnotationBuilder(Class annotationClass) {
        this.annotationClass = annotationClass;
        setAttributes();
        setAttributeData();
    }
    
    public AnnotationBuilder(Class annotationClass, Object value) {
       this(annotationClass);
       value(value);
    }
    
    public AnnotationBuilder value(Object value) {
        validateAttributeName("value");
        validateAttributeType("value", value.getClass());
        setAttributeData("value", value);
        return this;
    }
    
    public AnnotationBuilder attr(String name, Object value) {
        validateAttributeName(name);
        validateAttributeType(name, value.getClass());
        setAttributeData(name, value);
        return this;
    }
    
    
    @SuppressWarnings("unchecked")
    public T build() {
        validateAttributeData();
        Object instance = Enhancer.create(annotationClass, new AnnotationMethodInterceptor(annotationClass, attributes, attributeData));
        return (T) instance;
    }
    
    private void setAttributeData(String name, Object value) {
        Method method = attributes.get(name);
        Class returnType = method.getReturnType();
        if (returnType.isArray() && !value.getClass().isArray()) {
            Object array = Array.newInstance(returnType.getComponentType(), 1); 
            Array.set(array, 0, value);
            attributeData.put(name, array);
        } else {
            attributeData.put(name, value);
        }
    }
    
    private void validateAttributeName(String name) {
        if(!attributes.containsKey(name)) {
            throw new IllegalArgumentException("Invalid attribute: @" + annotationClass.getName() + " does not have any attribute named '" + name + "'");
        }
    }
    
    private void validateAttributeType(String name, Class type) {
        Method method = attributes.get(name);
        Class returnType = method.getReturnType();
        if (returnType.isArray()) {
            if (!type.isArray() && !returnType.getComponentType().isAssignableFrom(type)) {
                throw new IllegalArgumentException("Invalid attribute type: " + type.getName() +", attribute '" + name + "' of @" + annotationClass.getName() + " should be " + returnType.getComponentType().getName() + " or " + returnType.getComponentType().getName() + "[]");
            } else if (type.isArray() && !returnType.isAssignableFrom(type)){
                throw new IllegalArgumentException("Invalid attribute type: " + type.getComponentType().getName() + "[], attribute '" + name + "' of @" + annotationClass.getName() + " should be " + returnType.getComponentType().getName()+"[]");
            }
        } else if (returnType.isPrimitive()){
            if (type.isPrimitive()) {
                if (!returnType.equals(type)) {
                    throw new IllegalArgumentException("Invalid attribute type: " + type.getName() + ", attribute '" + name + "' of @" + annotationClass.getName() + " should be " + returnType.getName());
                }
            } else {
                // If wrapper class TYPE field should be present
                try {
                    Class wrappedType = (Class) type.getField("TYPE").get(null);
                    if (!returnType.equals(wrappedType)) {
                        throw new IllegalArgumentException("Invalid attribute type: " + type.getName() + ", attribute '" + name + "' of @" + annotationClass.getName() + " should be " + returnType.getName());
                    }
                } catch (final Exception e) {
                    throw new IllegalArgumentException("Invalid attribute type: " + type.getName() + ", attribute '" + name + "' of @" + annotationClass.getName() + " should be " + returnType.getName());
                }
            }
        } else {
            if (!returnType.isAssignableFrom(type)) {
                throw new IllegalArgumentException("Invalid attribute type: " + type.getName() + ", attribute '" + name + "' of @" + annotationClass.getName() + " should be " + returnType.getName());
            }  
            
        }
      
    }
    
    private void validateAttributeData() {
        for(Map.Entry data : attributeData.entrySet()) {
            if (data.getValue() == null) {
                throw new IllegalStateException("Missing attribute value: attribute '" + data.getKey() + "' of @" + annotationClass.getName() + " has not been set");
            }
        }
    }
    
    private void setAttributes() {
        for (Method method : annotationClass.getMethods()) {
            
            if (method.getParameterTypes().length == 0
                && !method.getName().equals("annotationType")
                && !method.getName().equals("hashCode")
                && !method.getName().equals("toString")
                && !method.getReturnType().equals(Void.TYPE)) {
                
                attributes.put(method.getName(), method);
            }
        }
    }
    
    private void setAttributeData() {
        for (Map.Entry attribute : attributes.entrySet()) {
            attributeData.put(attribute.getKey(), attribute.getValue().getDefaultValue());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy