com.bstek.dorado.data.type.manager.DefaultDataTypeManager.java Source code

Java tutorial

Introduction

Here is the source code for com.bstek.dorado.data.type.manager.DefaultDataTypeManager.java

Source

/*
 * This file is part of Dorado 7.x (http://dorado7.bsdn.org).
 * 
 * Copyright (c) 2002-2012 BSTEK Corp. All rights reserved.
 * 
 * This file is dual-licensed under the AGPLv3 (http://www.gnu.org/licenses/agpl-3.0.html) 
 * and BSDN commercial (http://www.bsdn.org/licenses) licenses.
 * 
 * If you are unsure which license is appropriate for your use, please contact the sales department
 * at http://www.bstek.com/contact.
 */

package com.bstek.dorado.data.type.manager;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.bstek.dorado.config.definition.Definition;
import com.bstek.dorado.data.config.definition.DataTypeDefinition;

/**
 * DataType?
 * 
 * @author Benny Bao (mailto:benny.bao@bstek.com)
 * @since Mar 9, 2008
 */
public class DefaultDataTypeManager extends DataTypeManagerSupport {
    private static final Log logger = LogFactory.getLog(DefaultDataTypeManager.class);

    private static final String ARRAY = "Array";

    private class DataTypeWrapper {
        private DataTypeDefinition dataType;
        private Class<?> type;

        public DataTypeWrapper(DataTypeDefinition dataType, Class<?> type) {
            this.dataType = dataType;
            this.type = type;
        }

        public DataTypeDefinition getDataType() {
            return dataType;
        }

        public Class<?> getType() {
            return type;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof DataTypeWrapper) {
                DataTypeWrapper dtw = (DataTypeWrapper) obj;
                return (type.equals(dtw.getType()) && dataType.equals(dtw.getDataType()));
            } else {
                return false;
            }
        }

        @Override
        public int hashCode() {
            return (dataType.hashCode() >> 4) + type.hashCode();
        }

    }

    /**
     * ????DataType???Class<br>
     * ???DataTypeDefinitionManager??
     * 
     * @param type
     *            Class
     * @throws Exception
     */
    @Override
    protected DataTypeDefinition getDataTypeDefinition(Type type) throws Exception {
        DataTypeDefinition dataType = null;
        if (type instanceof Class<?> && ((Class<?>) type).isArray()) {
            Class<?> cl = (Class<?>) type;
            DataTypeDefinition componentDataType = getDataTypeDefinitionByType(cl.getComponentType());
            String name = ARRAY + '[' + componentDataType.getName() + ']';
            dataType = getDataTypeDefinitionManager().getDefinition(name);
        } else if (type instanceof ParameterizedType) {
            Class<?> elementType = null;
            Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
            if (actualTypeArguments.length > 0) {
                elementType = (Class<?>) actualTypeArguments[0];
            }
            if (elementType != null) {
                DataTypeDefinition elementDataType = getDataTypeDefinitionByType(elementType);
                if (elementDataType != null) {
                    String name = '[' + elementDataType.getName() + ']';
                    dataType = getDataTypeDefinitionManager().getDefinition(name);
                }
            }
        }
        if (dataType == null && type instanceof Class<?>) {
            dataType = getDataTypeDefinitionByType((Class<?>) type);
        }
        return dataType;
    }

    protected DataTypeDefinition getDataTypeDefinitionByType(Class<?> type) {
        DataTypeDefinition dataType = null;
        Set<DataTypeWrapper> dtws = findAllMatchingDataTypes(type);

        // ???DataType
        filterMatchingDataTypes(dtws);

        // ?DataType
        int size = dtws.size();
        if (size == 1) {
            DataTypeWrapper dtw = dtws.iterator().next();
            dataType = dtw.getDataType();
        } else if (size > 1) {
            logger.warn("More than one matching DataTypes found for [" + type.getName() + "]!");
        }
        return dataType;
    }

    /**
     * ??DataType
     */
    private Set<DataTypeWrapper> findMatchingDataTypeForInterface(Class<?> type) {
        Set<DataTypeWrapper> dtws = new HashSet<DataTypeWrapper>();
        Class<?>[] interfaces = type.getInterfaces();
        for (Class<?> interfaceType : interfaces) {
            DataTypeDefinition dataType = getDefinedDataTypeDefinition(interfaceType);
            if (dataType != null) {
                dtws.add(new DataTypeWrapper(dataType, interfaceType));
            } else {
                dtws.addAll(findMatchingDataTypeForInterface(interfaceType));
            }
        }
        return dtws;
    }

    /**
     * Class?DataType
     */
    private Set<DataTypeWrapper> findAllMatchingDataTypes(Class<?> type) {
        Set<DataTypeWrapper> dtws = new HashSet<DataTypeWrapper>();

        DataTypeDefinition dataType = getDefinedDataTypeDefinition(type);
        if (dataType != null) {
            dtws.add(new DataTypeWrapper(dataType, type));

        }

        // ??
        dtws.addAll(findMatchingDataTypeForInterface(type));

        // ?
        for (Class<?> tempType = type.getSuperclass(); tempType != null; tempType = tempType.getSuperclass()) {
            // ??
            dtws.addAll(findMatchingDataTypeForInterface(tempType));

            if (type.isEnum() && tempType.equals(Object.class)) {
                tempType = String.class;
            }

            dataType = getDefinedDataTypeDefinition(tempType);
            if (dataType != null) {
                dtws.add(new DataTypeWrapper(dataType, tempType));
                break;
            }
        }
        return dtws;
    }

    /**
     * ??????
     */
    protected boolean isChildTypeOf(DataTypeDefinition dataType, DataTypeDefinition parentDataType) {
        Definition[] parents = dataType.getParents();
        if (parents != null) {
            for (Definition parent : parents) {
                if (parent == parentDataType) {
                    return true;
                } else {
                    boolean isChild = isChildTypeOf((DataTypeDefinition) parent, parentDataType);
                    if (isChild) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * ??DataType???DataType
     */
    private void filterMatchingDataTypes(Set<DataTypeWrapper> dtws) {
        DataTypeWrapper[] dtwArray = new DataTypeWrapper[dtws.size()];
        dtws.toArray(dtwArray);

        for (DataTypeWrapper dtw1 : dtwArray) {
            Iterator<DataTypeWrapper> iter = dtws.iterator();
            while (iter.hasNext()) {
                DataTypeWrapper dtw2 = iter.next();
                if (dtw1 != dtw2) {
                    if (dtw1.getType().isAssignableFrom(dtw2.getType())) {
                        dtws.remove(dtw1);
                        break;
                    }

                    if (isChildTypeOf(dtw2.getDataType(), dtw1.getDataType())) {
                        dtws.remove(dtw1);
                        break;
                    }
                }
            }
        }
    }

}