DefaultCreator.java :  » MongoDB » morphia » com » google » code » morphia » mapping » Java Open Source

Java Open Source » MongoDB » morphia 
morphia » com » google » code » morphia » mapping » DefaultCreator.java
/**
 * 
 */
package com.google.code.morphia.mapping;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.code.morphia.ObjectFactory;
import com.google.code.morphia.annotations.ConstructorArgs;
import com.google.code.morphia.logging.Logr;
import com.google.code.morphia.logging.MorphiaLoggerFactory;
import com.mongodb.DBObject;

/**
 * @author ScottHernandez
 */
@SuppressWarnings({"unchecked","rawtypes"})
public class DefaultCreator implements ObjectFactory {
  private static final Logr log = MorphiaLoggerFactory.get(DefaultCreator.class);

  /* (non-Javadoc)
   * @see com.google.code.morphia.ObjectFactory#createInstance(java.lang.Class)
   */
  public Object createInstance(Class clazz) { 
    return createInst(clazz);
  }
  
  /* (non-Javadoc)
   * @see com.google.code.morphia.ObjectFactory#createInstance(java.lang.Class, com.mongodb.DBObject)
   */
  public Object createInstance(Class clazz, DBObject dbObj) {
    Class c = getClass(dbObj);
    if (c == null)
      c = clazz;
    return createInstance(c);  
  }
  
  /* (non-Javadoc)
   * @see com.google.code.morphia.ObjectFactory#createInstance(com.google.code.morphia.mapping.Mapper, com.google.code.morphia.mapping.MappedField, com.mongodb.DBObject)
   */
  public Object createInstance(Mapper mapr, MappedField mf, DBObject dbObj) {
    Class c = getClass(dbObj);
    if (c == null)
      c = mf.isSingleValue ? mf.getConcreteType() : mf.getSubClass();
    try {
      return createInstance(c, dbObj);
    } catch (RuntimeException e) {
      ConstructorArgs argAnn = mf.getAnnotation(ConstructorArgs.class);
      if (argAnn == null)
        throw e;
      //TODO: now that we have a mapr, get the arg types that way by getting the fields by name. + Validate names
      Object[] args = new Object[argAnn.value().length];
      Class[] argTypes = new Class[argAnn.value().length];
      for(int i = 0; i < argAnn.value().length; i++) {
        //TODO: run converters and stuff against these. Kinda like the List of List stuff, using a fake MappedField to hold the value
        Object val = dbObj.get(argAnn.value()[i]);
        args[i] = val;
        argTypes[i] = val.getClass();
      }
          try {
            Constructor ctor = c.getDeclaredConstructor(argTypes);
            ctor.setAccessible(true);
              return ctor.newInstance(args);
      } catch (Exception ex) {
              throw new RuntimeException(ex);
          }
    }
  }

  private Class getClass(DBObject dbObj) {
    // see if there is a className value
    String className = (String) dbObj.get(Mapper.CLASS_NAME_FIELDNAME);
    Class c = null;
    if (className != null) {
      // try to Class.forName(className) as defined in the dbObject first,
      // otherwise return the entityClass
      try {
        c = Class.forName(className, true, Thread.currentThread().getContextClassLoader());
      } catch (ClassNotFoundException e) {
        if (log.isWarningEnabled())
          log.warning("Class not found defined in dbObj: " , e);
      }
    }
    return c;
  }

  /* (non-Javadoc)
   * @see com.google.code.morphia.ObjectFactory#createMap(com.google.code.morphia.mapping.MappedField)
   */
  public Map createMap(MappedField mf) {
    return (Map) newInstance(mf.getCTor(), HashMap.class);
  }

  /* (non-Javadoc)
   * @see com.google.code.morphia.ObjectFactory#createList(com.google.code.morphia.mapping.MappedField)
   */
  public List createList(MappedField mf) {
    return (List) newInstance(mf.getCTor(), ArrayList.class);
  }

  /* (non-Javadoc)
   * @see com.google.code.morphia.ObjectFactory#createSet(com.google.code.morphia.mapping.MappedField)
   */
  public Set createSet(MappedField mf) {
    return (Set) newInstance(mf.getCTor(), HashSet.class);
  }

  
  public static Object createInst(Class clazz) {
    try {
      return getNoArgsConstructor(clazz).newInstance();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  
    /** creates an instance of testType (if it isn't Object.class or null) or fallbackType */
    private static Object newInstance(final Constructor tryMe, final Class fallbackType) {
    if (tryMe != null) {
      tryMe.setAccessible(true);
      try {
        return tryMe.newInstance();
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
    return createInst(fallbackType);
    }
    
  private static Constructor getNoArgsConstructor(final Class ctorType) {
    try {
      Constructor ctor = ctorType.getDeclaredConstructor();
      ctor.setAccessible(true);
      return ctor;
    } catch (NoSuchMethodException e) {
      throw new MappingException("No usable constructor for " + ctorType.getName(), e);
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.