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

org.bridje.orm.impl.ORMEnvironmentImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017 Bridje Framework.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.bridje.orm.impl;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bridje.ioc.Inject;
import org.bridje.ioc.Ioc;
import org.bridje.ioc.thls.Thls;
import org.bridje.ioc.thls.ThlsAction;
import org.bridje.ioc.thls.ThlsActionException;
import org.bridje.ioc.thls.ThlsActionException2;
import org.bridje.orm.EntityContext;
import org.bridje.orm.ORMEnvironment;
import org.bridje.sql.SQLEnvironment;

class ORMEnvironmentImpl implements ORMEnvironment, EntityContext
{
    private static final Logger LOG = Logger.getLogger(ORMEnvironmentImpl.class.getName());

    private final EnvironmentBuilderImpl config;

    private final Map, Object> models;

    private final Map, EntityCache> cacheMap;

    private final Map, List> fieldsMap;

    private final Map, Constructor> contructorsMap;

    public ORMEnvironmentImpl(EnvironmentBuilderImpl config)
    {
        this.config = config;
        this.models = new HashMap<>();
        this.cacheMap = new HashMap<>();
        this.fieldsMap = new HashMap<>();
        this.contructorsMap = new HashMap<>();
    }

    @Override
    public  T getModel(Class modelCls)
    {
        T result = (T)models.get(modelCls);
        if(result == null)
        {
            result = createModel(modelCls);
            if(result != null) models.put(modelCls, result);
        }
        return result;
    }

    private  T createModel(Class modelCls)
    {
        SQLEnvironment sqlEnv = config.get(modelCls);
        if(sqlEnv == null) return null;
        T result = instantiateModel(modelCls, sqlEnv);
        return result;
    }

    private  T instantiateModel(Class modelCls, SQLEnvironment env)
    {
        try
        {
            Constructor defConst = getDefConstructor(modelCls);
            if(defConst != null)
            {
                T object = (T)defConst.newInstance();
                injectModels(object, env);
                return object;
            }
        }
        catch (IllegalAccessException | IllegalArgumentException | InstantiationException | SecurityException | InvocationTargetException e)
        {
            LOG.log(Level.SEVERE, e.getMessage(), e);
        }
        return null;
    }

    @Override
    public  boolean contains(Class entity, Object id)
    {
        EntityCache cache = cacheMap.get(entity);
        if(cache != null) return cache.contains(id);
        return false;
    }

    @Override
    public  T get(Class entity, Object id)
    {
        EntityCache cache = cacheMap.get(entity);
        if(cache != null) return (T)cache.get(id);
        return null;
    }

    @Override
    public  void put(Object id, T entity)
    {
        if(entity == null) return;
        EntityCache cache = cacheMap.get(entity.getClass());
        if(cache == null)
        {
            cache = new EntityCache();
            cacheMap.put(entity.getClass(), cache);
        }
        cache.put(id, entity);
    }

    @Override
    public  void remove(Class entity, Object id)
    {
        EntityCache cache = cacheMap.get(entity);
        if(cache != null) cache.remove(id);
    }

    @Override
    public  void clear(Class entity)
    {
        EntityCache cache = cacheMap.get(entity);
        if(cache != null) cache.clear();
    }

    @Override
    public void clear()
    {
        cacheMap.clear();
    }

    private  void injectModels(T object, SQLEnvironment env)
    {
        Class currentCls = object.getClass();
        while(currentCls != Object.class)
        {
            List lst = getFieldList(currentCls);
            for (Field field : lst)
            {
                Object value = getValueForField(field, env);
                setFieldValue(field, object, value);
            }
            currentCls = currentCls.getSuperclass();
        }
    }

    private List getFieldList(Class cls)
    {
        List result = fieldsMap.get(cls);
        if(result == null)
        {
            result = findFieldList(cls);
            if(result != null) fieldsMap.put(cls, result);
        }
        return result;
    }

    private List findFieldList(Class cls)
    {
        List fieldsLst = new ArrayList<>();
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields)
        {
            Inject inject = field.getAnnotation(Inject.class);
            if(inject != null)
            {
                fieldsLst.add(field);
            }
        }
        return fieldsLst;
    }

    private Object getValueForField(Field field, SQLEnvironment env)
    {
        if(field.getType() == EntityContext.class)
        {
            return this;
        }
        else if(field.getType() == SQLEnvironment.class)
        {
            return env;
        }
        else 
        {
            if(config.contains(field.getType()))
            {
                return getModel(field.getType());
            }
            else
            {
                return Ioc.context().findGeneric(field.getGenericType());
            }
        }
    }

    private void setFieldValue(Field field, Object comp, Object value)
    {
        if(value != null)
        {
            try
            {
                field.setAccessible(true);
                field.set(comp, value);
            }
            catch (IllegalAccessException | IllegalArgumentException | SecurityException e)
            {
                LOG.log(Level.SEVERE, e.getMessage(), e);
            }
        }
    }

    private Constructor findDefConstructor(Class modelCls)
    {
        for (Constructor constructor : modelCls.getDeclaredConstructors())
        {
            constructor.setAccessible(true);
            if(constructor.getParameterTypes().length == 0)
            {
                return constructor;
            }
        }
        return null;
    }

    private  Constructor getDefConstructor(Class modelCls)
    {
        Constructor defConst = contructorsMap.get(modelCls);
        if(defConst == null)
        {
            defConst = findDefConstructor(modelCls);
            if(defConst != null) contructorsMap.put(modelCls, defConst);
        }
        return defConst;
    }

    @Override
    public  T doWith(ThlsAction action)
    {
        return Thls.doAs(action, ORMEnvironment.class, this);
    }

    @Override
    public  T doWithEx(ThlsActionException action) throws E
    {
        return Thls.doAsEx(action, ORMEnvironment.class, this);
    }

    @Override
    public  T doWithEx2(ThlsActionException2 action) throws E, E2
    {
        return Thls.doAsEx2(action, ORMEnvironment.class, this);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy