Subversion Repositories bacoAlunos

Rev

Blame | Compare with Previous | Last modification | View Log | RSS feed

package genson.reflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public abstract class BeanCreator extends genson.Wrapper<AnnotatedElement> implements Comparable<BeanCreator> {
  // The type of object it can create
  protected final Class<?> ofClass;
  protected final Map<String, BeanCreatorProperty> parameters;
  protected final Map<String, BeanCreatorProperty> paramsAndAliases;

  public BeanCreator(Class<?> ofClass, Class<?> declaringClass, Class<?> concreteClass,
                     1.5.0/docs/api/java/lang/String.html">String[] parameterNames, 1.5.0/docs/api/java/lang/reflect/Type.html">Type[] types, 5+0%2Fdocs%2Fapi+Annotation">Annotation[][] anns) {
    this.ofClass = ofClass;
    this.parameters = new LinkedHashMap<String, BeanCreatorProperty>(parameterNames.length);
    for (int i = 0; i < parameterNames.length; i++) {
      this.parameters.put(parameterNames[i], new BeanCreatorProperty(parameterNames[i],
        types[i], i, anns[i], declaringClass, concreteClass, this));
    }

    paramsAndAliases = new LinkedHashMap<String, BeanCreatorProperty>();
    for (BeanCreatorProperty p : parameters.values()) {
      paramsAndAliases.put(p.getName(), p);
      for (1.5.0/docs/api/java/lang/String.html">String alias : p.aliases()) paramsAndAliases.put(alias, p);
    }
  }

  public int contains(List<String> properties) {
    int cnt = 0;
    for (1.5.0/docs/api/java/lang/String.html">String prop : properties)
      if (parameters.containsKey(prop)) cnt++;
    return cnt;
  }

  public int compareTo(BeanCreator o) {
    int comp = o.priority() - priority();
    return comp != 0 ? comp : parameters.size() - o.parameters.size();
  }

  public abstract 5+0%2Fdocs%2Fapi+Object">Object create(5+0%2Fdocs%2Fapi+Object">Object... args);

  protected abstract 1.5.0/docs/api/java/lang/String.html">String signature();

  public abstract int priority();

  protected genson.JsonBindingException couldNotCreate(1.5.0/docs/api/java/lang/Exception.html">Exception e) {
    return new genson.JsonBindingException("Could not create bean of type " + ofClass.getName()
      + " using creator " + signature(), e);
  }

  public Map<String, BeanCreatorProperty> getProperties() {
    return new LinkedHashMap<String, BeanCreatorProperty>(parameters);
  }

  public abstract int getModifiers();

  public static class ConstructorBeanCreator extends BeanCreator {
    protected final Constructor<?> constructor;

    public ConstructorBeanCreator(Class<?> ofClass, Constructor<?> constructor,
                                  1.5.0/docs/api/java/lang/String.html">String[] parameterNames, 1.5.0/docs/api/java/lang/reflect/Type.html">Type[] expandedParameterTypes) {
      // We can use the same class, as anyway we don't want to use constructors
      super(ofClass, ofClass, ofClass, parameterNames, expandedParameterTypes, constructor.getParameterAnnotations());
      this.constructor = constructor;
      if (!constructor.isAccessible()) {
        constructor.setAccessible(true);
      }
      decorate(constructor);
    }

    public 5+0%2Fdocs%2Fapi+Object">Object create(5+0%2Fdocs%2Fapi+Object">Object... args) {
      try {
        return constructor.newInstance(args);
      } catch (1.5.0/docs/api/java/lang/IllegalArgumentException.html">IllegalArgumentException e) {
        throw couldNotCreate(e);
      } catch (1.5.0/docs/api/java/lang/InstantiationException.html">InstantiationException e) {
        throw couldNotCreate(e);
      } catch (1.5.0/docs/api/java/lang/IllegalAccessException.html">IllegalAccessException e) {
        throw couldNotCreate(e);
      } catch (1.5.0/docs/api/java/lang/reflect/InvocationTargetException.html">InvocationTargetException e) {
        throw couldNotCreate(e);
      }
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    protected 1.5.0/docs/api/java/lang/String.html">String signature() {
      return constructor.toGenericString();
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public int priority() {
      return 50;
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public int getModifiers() {
      return constructor.getModifiers();
    }
  }

  public static class MethodBeanCreator extends BeanCreator {
    protected final 1.5.0/docs/api/java/lang/reflect/Method.html">Method _creator;

    public MethodBeanCreator(1.5.0/docs/api/java/lang/reflect/Method.html">Method method, 1.5.0/docs/api/java/lang/String.html">String[] parameterNames,
                             1.5.0/docs/api/java/lang/reflect/Type.html">Type[] expandedParameterTypes, Class<?> concreteClass) {
      super(method.getReturnType(), method.getDeclaringClass(), concreteClass, parameterNames,
          expandedParameterTypes, method.getParameterAnnotations());
      if (!1.5.0/docs/api/java/lang/reflect/Modifier.html">Modifier.isStatic(method.getModifiers()))
        throw new 1.5.0/docs/api/java/lang/IllegalStateException.html">IllegalStateException("Only static methods can be used as creators!");
      this._creator = method;
      if (!_creator.isAccessible()) {
        _creator.setAccessible(true);
      }
      decorate(_creator);
    }

    public 5+0%2Fdocs%2Fapi+Object">Object create(5+0%2Fdocs%2Fapi+Object">Object... args) {
      try {
        // we will handle only static method creators
        return ofClass.cast(_creator.invoke(null, args));
      } catch (1.5.0/docs/api/java/lang/IllegalArgumentException.html">IllegalArgumentException e) {
        throw couldNotCreate(e);
      } catch (1.5.0/docs/api/java/lang/IllegalAccessException.html">IllegalAccessException e) {
        throw couldNotCreate(e);
      } catch (1.5.0/docs/api/java/lang/reflect/InvocationTargetException.html">InvocationTargetException e) {
        throw couldNotCreate(e);
      }
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    protected 1.5.0/docs/api/java/lang/String.html">String signature() {
      return _creator.toGenericString();
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public int priority() {
      return 100;
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public int getModifiers() {
      return _creator.getModifiers();
    }
  }

  public static class BeanCreatorProperty extends genson.reflect.PropertyMutator {
    protected final int index;
    protected final 5+0%2Fdocs%2Fapi+Annotation">Annotation[] annotations;
    protected final BeanCreator creator;
    protected final boolean doThrowMutateException;

    protected BeanCreatorProperty(1.5.0/docs/api/java/lang/String.html">String name, 1.5.0/docs/api/java/lang/reflect/Type.html">Type type, int index, 5+0%2Fdocs%2Fapi+Annotation">Annotation[] annotations,
                                  Class<?> declaringClass, Class<?> concreteClass, BeanCreator creator) {
      this(name, type, index, annotations, declaringClass, concreteClass, creator, false);
    }

    protected BeanCreatorProperty(1.5.0/docs/api/java/lang/String.html">String name, 1.5.0/docs/api/java/lang/reflect/Type.html">Type type, int index, 5+0%2Fdocs%2Fapi+Annotation">Annotation[] annotations,
                                  Class<?> declaringClass, Class<?> concreteClass, BeanCreator creator,
                                  boolean doThrowMutateException) {
      super(name, type, declaringClass, concreteClass, annotations, 0);
      this.index = index;
      this.annotations = annotations;
      this.creator = creator;
      this.doThrowMutateException = doThrowMutateException;
    }

    public int getIndex() {
      return index;
    }

    public 5+0%2Fdocs%2Fapi+Annotation">Annotation[] getAnnotations() {
      return annotations;
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public int priority() {
      return -1000;
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public 1.5.0/docs/api/java/lang/String.html">String signature() {
      return new 1.5.0/docs/api/java/lang/StringBuilder.html">StringBuilder(type.toString()).append(' ').append(name).append(" from ")
        .append(creator.signature()).toString();
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public int getModifiers() {
      return creator.getModifiers();
    }

    @1.5.0/docs/api/java/lang/Override.html">Override
    public void mutate(5+0%2Fdocs%2Fapi+Object">Object target, 5+0%2Fdocs%2Fapi+Object">Object value) {
      if (doThrowMutateException) {
        throw new 1.5.0/docs/api/java/lang/IllegalStateException.html">IllegalStateException(
          "Method mutate should not be called on a mutator of type "
            + getClass().getName()
            + ", this property exists only as constructor parameter!");
      }
    }

  }
}