org.tinygroup.factory.impl.SimpleFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.tinygroup.factory.impl.SimpleFactory.java

Source

/**
 *  Copyright (c) 1997-2013, www.tinygroup.org (luo_guo@icloud.com).
 *
 *  Licensed under the GPL, Version 3.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.gnu.org/licenses/gpl.html
 *
 *  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.tinygroup.factory.impl;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.tinygroup.factory.Factory;
import org.tinygroup.factory.FactoryAware;
import org.tinygroup.factory.config.*;
import org.tinygroup.factory.exception.BeanFactoryRuntimeException;
import org.tinygroup.logger.LogLevel;
import org.tinygroup.logger.Logger;
import org.tinygroup.logger.LoggerFactory;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.Map;

/**
 * 
 * : 
 * <p>
    
 * ?: renhui <br>
 * ?: 2013-2-25 <br>
 * <br>
 */
public class SimpleFactory implements Factory {
    private static final String BY_TYPE = "byType";
    private static final String BY_NAME = "byName";
    private static final String SINGLETON = "singleton";
    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleFactory.class);
    private Map<String, Object> idMap = new HashMap<String, Object>();
    private Map<String, Object> nameMap = new HashMap<String, Object>();
    private Map<String, Object> nameClassMap = new HashMap<String, Object>();
    private Map<Class<?>, Object> classMap = new HashMap<Class<?>, Object>();
    private List<Beans> beansList = new ArrayList<Beans>();
    private Map<Object, Bean> objectBeanMap = new HashMap<Object, Bean>();
    private Map<Object, Boolean> readyMap = new HashMap<Object, Boolean>();

    public void clean() {
        idMap.clear();
        nameMap.clear();
        nameClassMap.clear();
        classMap.clear();
        beansList.clear();
        objectBeanMap.clear();
        readyMap.clear();
    }

    private void addBean(Bean bean, Object object) {
        addBeanWithId(bean, object);
        addBeanWithName(bean, object);
        addBeanWithClass(bean, object);
        addBeanWithNameClass(bean, object);
    }

    private void addBeanWithNameClass(Bean bean, Object object) {
        nameClassMap.put(String.format("%s|%s", bean.getName(), bean.getType()), object);
    }

    private void addBeanWithClass(Bean bean, Object object) {
        try {
            classMap.put(Class.forName(bean.getType()), object);
        } catch (ClassNotFoundException e) {
            LOGGER.errorMessage("[{0}] {0}", e, e.getMessage());
        }
    }

    private void addBeanWithName(Bean bean, Object object) {
        if (bean.getName() != null && bean.getName().length() > 0) {
            String[] names = bean.getName().split(",");
            for (String name : names) {
                if (name.length() > 0) {
                    // ????
                    nameMap.put(name, object);
                }
            }
        }
    }

    private void addBeanWithId(Bean bean, Object object) {
        if (bean.getId() != null && bean.getId().length() > 0) {
            Bean oldBean = objectBeanMap.get(bean.getId());
            if (oldBean != null) {
                LOGGER.logMessage(LogLevel.ERROR,
                        "[{}]  bean id [{}] ?[{}Bean]?",
                        bean.getClassName(), bean.getId(), oldBean.getClassName());
            }
            objectBeanMap.put(object, bean);
            idMap.put(bean.getId(), object);
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T getBean(String name) {
        Object object = getObject(name);
        if (object != null) {
            return checkScope((T) object);
        }
        throw new BeanFactoryRuntimeException(String.format("???[%s]Bean.", name));
    }

    private Object getObject(String name) {
        Object object = idMap.get(name);
        if (object == null) {
            object = nameMap.get(name);
        }
        if (object != null) {
            Boolean ready = readyMap.get(object);
            if (ready == null) {
                assembleBean(object);
            }
        }
        return object;
    }

    @SuppressWarnings("unchecked")
    private <T> T checkScope(T object) {
        try {
            if (object != null) {
                Bean bean = objectBeanMap.get(object);
                String scope = bean.getScope();
                if (scope.equals(SINGLETON)) {
                    return object;
                } else if (("prototype").equals(scope)) {
                    T newObject = (T) retriveClass(bean.getClassName()).newInstance();
                    BeanUtils.copyProperties(newObject, object);// Prototype?
                    return newObject;
                }
            }
            throw new BeanFactoryRuntimeException(String.format("Bean?"));
        } catch (Exception e) {
            throw new BeanFactoryRuntimeException(e);
        }
    }

    private void assembleBean(Object object) {
        if (readyMap.get(object) == null || readyMap.get(object).equals(false)) {
            loadProperties(object);
        }
    }

    private void autoAssembleBean(Bean beanDefine, Object newInstance) {
        for (PropertyDescriptor propertyDescriptor : PropertyUtils.getPropertyDescriptors(newInstance)) {
            try {
                if (propertyDescriptor.getPropertyType().equals(Class.class)) {
                    continue;
                }
                if (beanDefine.getAutowire().equalsIgnoreCase(BY_NAME)) {
                    Object bean = getBean(propertyDescriptor.getName());
                    if (bean != null && propertyDescriptor.getPropertyType().isInstance(bean)) {
                        BeanUtils.setProperty(newInstance, propertyDescriptor.getName(), bean);
                    }
                } else if (beanDefine.getAutowire().equalsIgnoreCase(BY_TYPE)) {
                    Object bean = getBean(propertyDescriptor.getPropertyType());
                    if (bean != null) {
                        BeanUtils.setProperty(newInstance, propertyDescriptor.getName(), bean);
                    }
                }
            } catch (Exception e) {
                LOGGER.errorMessage("{0}", e, propertyDescriptor.getName());
            }
        }
    }

    private void loadProperties(Object object) {
        Bean bean = objectBeanMap.get(object);
        try {
            if (bean.getAutowire() != null) {
                autoAssembleBean(bean, object);
                return;// ??
            }
            if (bean.getProperties() != null) {
                for (Property property : bean.getProperties()) {
                    if (property.getValue() != null) {
                        BeanUtils.setProperty(object, property.getName(), property.getValue());
                    } else if (property.getRef() != null) {
                        BeanUtils.setProperty(object, property.getName(), getObject(property.getRef()));
                    } else if (property.getList() != null) {
                        loadListProperty(object, property);
                    } else if (property.getMap() != null) {
                        loadMapProperty(object, property);
                    }
                }
            }
            readyMap.put(object, true);
        } catch (Exception e) {
            readyMap.put(object, false);
            LOGGER.errorMessage(e.getMessage(), e);
        }
    }

    private void loadMapProperty(Object object, Property property)
            throws IllegalAccessException, InvocationTargetException {
        Map<String, Object> valueMap = new HashMap<String, Object>();
        for (Entry entry : property.getMap().getEntry()) {
            if (entry.getValue() != null) {
                valueMap.put(entry.getKey(), entry.getValue());
            } else if (entry.getValueRef() != null) {
                valueMap.put(entry.getKey(), getObject(entry.getValueRef()));
            }
        }
        BeanUtils.setProperty(object, property.getName(), valueMap);
    }

    private void loadListProperty(Object object, Property property)
            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        List<Object> valueList = new ArrayList<Object>();
        for (Ref ref : property.getList()) {
            valueList.add(getObject(ref));
        }
        if (PropertyUtils.getPropertyDescriptor(object, property.getName()).getPropertyType()
                .isAssignableFrom(List.class)) {
            BeanUtils.setProperty(object, property.getName(), valueList);
        } else if (PropertyUtils.getPropertyDescriptor(object, property.getName()).getPropertyType()
                .isAssignableFrom(Set.class)) {
            Set<Object> set = new HashSet<Object>();
            set.addAll(valueList);
            BeanUtils.setProperty(object, property.getName(), set);
        }
    }

    private Object getObject(Ref ref) {
        if (ref.getId() != null) {
            return getBean(ref.getId());// 20130130 getObjectgetBean
        } else if (ref.getName() != null) {
            return getBean(ref.getName());
        } else if (ref.getClassName() != null) {
            return getBean(getType(ref.getClassName()));
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public <T> T getBean(String name, Class<T> clazz) {
        Object object = nameClassMap.get(String.format("%s|%s", name, clazz.getName()));
        if (object != null && readyMap.get(object)) {
            return checkScope((T) object);
        }

        throw new BeanFactoryRuntimeException(String.format("?[%s]Bean.", clazz.getName()));
    }

    @SuppressWarnings("unchecked")
    public <T> T getBean(Class<T> clazz) {
        Object object = classMap.get(clazz);
        if (object != null) {
            Boolean ready = readyMap.get(object);
            if (ready == null) {
                assembleBean(object);
            }
            ready = readyMap.get(object);
            if (ready) {
                return checkScope((T) object);
            }
        }

        throw new BeanFactoryRuntimeException(String.format("?[%s]Bean.", clazz.getName()));

    }

    public boolean containsBean(String name) {
        return nameMap.containsKey(name);
    }

    public Class<?> getType(String name) {
        try {
            return retriveClass(name);
        } catch (ClassNotFoundException e) {
            throw new BeanFactoryRuntimeException(e);
        }
    }

    private Class<?> retriveClass(String name) throws ClassNotFoundException {
        return Class.forName(name);
    }

    public void init() {
        // ?Bean
        for (Beans beans : beansList) {
            loadBeas(beans);
        }
        for (Object object : objectBeanMap.keySet()) {
            assembleBean(object);
        }
    }

    private void loadBeas(Beans beans) {
        if (beans.getBeanList() != null) {
            for (Bean bean : beans.getBeanList()) {
                loadBean(bean);
            }
        }
    }

    private void loadBean(Bean bean) {
        try {
            if (objectBeanMap.values().contains(bean)) {
                return;
            }
            Object object = Class.forName(bean.getClassName()).newInstance();
            if (object instanceof FactoryAware) {
                FactoryAware factoryAware = (FactoryAware) object;
                factoryAware.setFactory(this);
            }
            addBean(bean, object);
        } catch (Exception e) {
            LOGGER.errorMessage("?[{0}] {1}", e, bean.getType(), e.getMessage());
        }
    }

    public void addBeans(Beans beans) {
        // packageName?beans?
        if (beans.getPackageName() != null) {
            for (Beans b : beansList) {
                if (b.getPackageName() != null && beans.getPackageName().equals(b.getPackageName())) {
                    beansList.remove(b);
                    break;
                }
            }
        }
        beansList.add(beans);
    }

    @SuppressWarnings("unchecked")
    public <T> T createBean(String className) {
        try {
            return (T) getType(className).newInstance();
        } catch (Exception e) {
            throw new BeanFactoryRuntimeException(e);
        }
    }

    public void removeBeans(Beans beans) {

        for (Bean bean : beans.getBeanList()) {
            removeBean(bean);
        }

        // beansList
        if (beans.getPackageName() != null) {
            for (Beans b : beansList) {
                if (b.getPackageName() != null && beans.getPackageName().equals(b.getPackageName())) {
                    beansList.remove(b);
                    LOGGER.logMessage(LogLevel.INFO, "beansListBeans[package-name:{0}]",
                            beans.getPackageName());
                    break;
                }
            }
        }

    }

    private void removeBean(Bean bean) {
        removeBeanWithNameClass(bean);
        removeBeanWithClass(bean);
        removeBeanWithName(bean);
        removeBeanWithId(bean);
    }

    private void removeBeanWithNameClass(Bean bean) {
        nameClassMap.remove(String.format("%s|%s", bean.getName(), bean.getType()));
    }

    private void removeBeanWithClass(Bean bean) {
        classMap.remove(bean.getClass());
    }

    private void removeBeanWithName(Bean bean) {
        if (bean.getName() != null && bean.getName().length() > 0) {
            String[] names = bean.getName().split(",");
            for (String name : names) {
                if (name.length() > 0) {
                    // ????
                    nameMap.remove(name);
                }
            }
        }
    }

    private void removeBeanWithId(Bean bean) {
        if (bean.getId() != null && bean.getId().length() > 0) {
            Object object = idMap.remove(bean.getId());
            objectBeanMap.remove(object);
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T createBean(Class<?> clazz) {
        try {
            return (T) clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}