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

br.com.anteros.nosql.persistence.mongodb.mapping.DefaultMongoCreator Maven / Gradle / Ivy

There is a newer version: 1.0.6
Show newest version
package br.com.anteros.nosql.persistence.mongodb.mapping;


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

import org.bson.Document;


import br.com.anteros.core.log.LogLevel;
import br.com.anteros.core.log.Logger;
import br.com.anteros.core.log.LoggerProvider;
import br.com.anteros.nosql.persistence.converters.NoSQLMappingException;
import br.com.anteros.nosql.persistence.metadata.NoSQLDescriptionField;
import br.com.anteros.nosql.persistence.session.mapping.AbstractNoSQLObjectMapper;
import br.com.anteros.nosql.persistence.session.mapping.NoSQLMapperOptions;
import br.com.anteros.nosql.persistence.session.mapping.NoSQLObjectFactory;



public class DefaultMongoCreator implements NoSQLObjectFactory {

	private static Logger LOG = LoggerProvider.getInstance().getLogger(NoSQLObjectFactory.class);

    private Map> classNameCache = new ConcurrentHashMap<>();

    private NoSQLMapperOptions options = null;


    public DefaultMongoCreator() {
    }


    public DefaultMongoCreator(final NoSQLMapperOptions options) {
        this.options = options;
    }

    private static  Constructor getNoArgsConstructor(final Class type) {
        try {
            final Constructor constructor = type.getDeclaredConstructor();
            constructor.setAccessible(true);
            return constructor;
        } catch (NoSuchMethodException e) {
            throw new NoSQLMappingException("No usable constructor for " + type.getName(), e);
        }
    }



    @Override
    @SuppressWarnings("unchecked")
    public  T createInstance(final Class clazz) {
        try {
            return getNoArgsConstructor(clazz).newInstance();
        } catch (Exception e) {
            if (Collection.class.isAssignableFrom(clazz)) {
                return (T) createList(null);
            } else if (Map.class.isAssignableFrom(clazz)) {
                return (T) createMap(null);
            } else if (Set.class.isAssignableFrom(clazz)) {
                return (T) createSet(null);
            }
            throw new NoSQLMappingException("No usable constructor for " + clazz.getName(), e);
        }
    }

    @Override
    public  T createInstance(final Class clazz, final Object dbObj) {
        Class c = getClass((Document)dbObj);
        if (c == null) {
            c = clazz;
        }
        return createInstance(c);
    }

    @Override
    @SuppressWarnings("unchecked")
    public Object createInstance(final AbstractNoSQLObjectMapper mapper, final NoSQLDescriptionField descriptionField, final Object dbObj) {
        Class c = getClass((Document)dbObj);
        if (c == null) {
            c = descriptionField.isSimple() ? descriptionField.getConcreteType() : descriptionField.getSubClass();
            if (c.equals(Object.class)) {
                c = descriptionField.getConcreteType();
            }
        }
        try {
            return createInstance(c, dbObj);
        } catch (RuntimeException e) {
            if (!descriptionField.hasConstructorArgs()) {
                throw e;
            }
            final Object[] args = new Object[descriptionField.getConstructorArgs().length];
            final Class[] argTypes = new Class[descriptionField.getConstructorArgs().length];
            for (int i = 0; i < descriptionField.getConstructorArgs().length; i++) {
                final Object val = ((Document)dbObj).get(descriptionField.getConstructorArgs()[i]);
                args[i] = val;
                argTypes[i] = val.getClass();
            }
            try {
                final Constructor constructor = c.getDeclaredConstructor(argTypes);
                constructor.setAccessible(true);
                return constructor.newInstance(args);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public List createList(final NoSQLDescriptionField descriptionField) {
        return newInstance(descriptionField != null ? descriptionField.getConstructor() : null, ArrayList.class);
    }

    @Override
    @SuppressWarnings("unchecked")
    public Map createMap(final NoSQLDescriptionField descriptionField) {
        return newInstance(descriptionField != null ? descriptionField.getConstructor() : null, HashMap.class);
    }

    @Override
    @SuppressWarnings("unchecked")
    public Set createSet(final NoSQLDescriptionField descriptionField) {
        return newInstance(descriptionField != null ? descriptionField.getConstructor() : null, HashSet.class);
    }

   
    public Map> getClassNameCache() {
        HashMap> copy = new HashMap>();
        copy.putAll(classNameCache);
        return copy;
    }

    protected ClassLoader getClassLoaderForClass() {
        return Thread.currentThread().getContextClassLoader();
    }

    private  Class getClass(final Document dbObj) {
        Class c = null;
        if (dbObj.containsKey(AbstractNoSQLObjectMapper.CLASS_NAME_FIELDNAME)) {
            final String className = (String) dbObj.get(AbstractNoSQLObjectMapper.CLASS_NAME_FIELDNAME);
            try {
                if (options != null && options.isCacheClassLookups()) {
                    c = classNameCache.get(className);
                    if (c == null) {
                        c = Class.forName(className, true, getClassLoaderForClass());
                        classNameCache.put(className, c);
                    }
                } else {
                    c = Class.forName(className, true, getClassLoaderForClass());
                }
            } catch (ClassNotFoundException e) {
                if (LOG.isWarnEnabled()) {
                    LOG.log(LogLevel.WARN,"Class not found defined in dbObj: ", e);
                }
            }
        }
        return c;
    }

  
    private  T 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 createInstance(fallbackType);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy