Package com.googlecode.mjorm.annotations

Source Code of com.googlecode.mjorm.annotations.AnnotationsObjectDescriptorParser

package com.googlecode.mjorm.annotations;

import java.beans.BeanInfo;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bson.types.ObjectId;

import com.googlecode.mjorm.DiscriminatorType;
import com.googlecode.mjorm.MjormException;
import com.googlecode.mjorm.MappingUtil;
import com.googlecode.mjorm.ObjectDescriptor;
import com.googlecode.mjorm.ObjectIdValueGenerator;
import com.googlecode.mjorm.PropertyDescriptor;
import com.googlecode.mjorm.ReflectionUtil;
import com.googlecode.mjorm.ValueGenerator;
import com.googlecode.mjorm.convert.JavaType;

/**
* "Parses" objects with mapping annotations and
* returns {@link ObjectDescriptor}s.
*/
public class AnnotationsObjectDescriptorParser {

  /**
   * Parses the given {@link Class<?>}s and returns {@link ObjectDescriptor}s
   * for them.
   * @param classes the classes to parse
   * @return the {@link ObjectDescriptor}s
   */
  public List<ObjectDescriptor> parseClasses(Class<?>... classes) {
    List<ObjectDescriptor> ret = new ArrayList<ObjectDescriptor>();
    for (Class<?> clazz : classes) {
      ret.add(parseClass(clazz, ret));
    }
    return ret;
  }

  /**
   * Parses the given {@link Class<?>}s and returns {@link ObjectDescriptor}s
   * for them.
   * @param classes the classes to parse
   * @return the {@link ObjectDescriptor}s
   */
  public List<ObjectDescriptor> parseClasses(Collection<Class<?>> classes) {
    return parseClasses(classes.toArray(new Class<?>[0]));
  }

  /**
   * Parses the given {@link Class<?>} and returns an {@link ObjectDescriptor}
   * for it.
   * @param clazz the class to parse
   * @return the {@link ObjectDescriptor}
   */
  private ObjectDescriptor parseClass(Class<?> clazz, List<ObjectDescriptor> descriptors) {

    // get the entity annotation
    Entity entity = clazz.getAnnotation(Entity.class);
    if (entity==null) {
      throw new MjormException(
        clazz.getName()+" does not have an "+Entity.class.getName()+" annotation");
    }

    // parse entity date
    String discriminatorName = entity.discriminatorName();
    DiscriminatorType discriminatorType = entity.discriminatorType();
    SubClass[] subClasses = entity.subClasses();

    // create an object descriptor
    ObjectDescriptor desc = new ObjectDescriptor();
    desc.setType(clazz);
    desc.setDiscriminatorName(discriminatorName);
    desc.setDiscriminatorType(discriminatorType.toString());

    // get BeanInfo
    BeanInfo info = ReflectionUtil.getBeanInfo(clazz);
    Map<Method, java.beans.PropertyDescriptor> methodMap
      = new HashMap<Method, java.beans.PropertyDescriptor>();
    for (java.beans.PropertyDescriptor pd : info.getPropertyDescriptors()) {
      methodMap.put(pd.getReadMethod(), pd);
      methodMap.put(pd.getWriteMethod(), pd);
    }

    // get all of the methods
    for (Method method : clazz.getMethods()) {

      // look for the annotations
      Property property = method.getAnnotation(Property.class);
      Id id = method.getAnnotation(Id.class);
      if (property==null) {
        continue;
      }

      // find pd
      java.beans.PropertyDescriptor pd = methodMap.get(method);
      if (pd==null) {
        throw new MjormException(
          method.getName()+" is not not a valid bean method.");
      }

      // "parse" data
      String propField = !property.field().equals("")
        ? property.field()
        : pd.getName();
      Type propType = !property.type().equals(void.class)
        ? property.type()
        : pd.getReadMethod().getGenericReturnType();
      Type storageType = !property.storageType().equals(void.class)
        ? property.storageType()
        : null;
      Class<?> valueGeneratorClass = !property.valueGeneratorClass().equals(void.class)
        ? property.valueGeneratorClass()
        : null;
      Type[] genericParameterTypes = property.genericParameterTypes().length>0
        ? property.genericParameterTypes()
        : new Type[0];
      boolean propIsIdentifier = (id!=null);
      boolean propIsAutoGen = (id!=null && id.autoGenerated());

      // get the hints
      Map<String, Object> hints = new HashMap<String, Object>();
      if (property.typeConversionHints()!=null) {
        for (TypeConversionHint hint : property.typeConversionHints()) {
          hints.put(hint.name(), hint.stringValue());
        }
      }

      // create the PropertyDescriptor
      PropertyDescriptor prop = new PropertyDescriptor();
      prop.setName(pd.getName());
      prop.setFieldName(propField);
      prop.setGetter(pd.getReadMethod());
      prop.setSetter(pd.getWriteMethod());
      prop.setIdentifier(propIsIdentifier);
      prop.setType(JavaType.fromType(propType));
      prop.setAutoGenerated(propIsAutoGen);
      prop.setConversionHints(hints);
      prop.setGenericParameterTypes(genericParameterTypes);
      if (propIsAutoGen) {
        ValueGenerator<?> valueGenerator = null;
        if (valueGeneratorClass==null) {
          valueGenerator = ObjectIdValueGenerator.INSTANCE;
          storageType =  ObjectId.class;
        } else {
          try {
            valueGenerator = ValueGenerator.class.cast(valueGeneratorClass.newInstance());
          } catch(Exception e) {
            throw new IllegalArgumentException(
              "Unable to create ValueGenerator for "+valueGeneratorClass.getName(), e);
          }
        }
        prop.setValueGenerator(valueGenerator);
      }

      // set the storage type
      if (storageType!=null) {
        prop.setStorageType(JavaType.fromType(storageType));
      }

      // add to descriptor
      desc.addPropertyDescriptor(prop);
    }

    // parse subclasses
    for (SubClass subClassAnot : subClasses) {

      // get discriminator value
      Object discriminatorValue = MappingUtil.parseDiscriminator(
        subClassAnot.discriminiatorValue(), discriminatorType);

      // parse sub class
      ObjectDescriptor subClass = parseClass(subClassAnot.entityClass(), descriptors);

      // add subclass
      desc.addSubClassObjectDescriptor(discriminatorValue, subClass);
      descriptors.add(subClass);
    }

    // return it
    return desc;
  }

}
TOP

Related Classes of com.googlecode.mjorm.annotations.AnnotationsObjectDescriptorParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.