Package com.alibaba.toolkit.util.typeconvert

Source Code of com.alibaba.toolkit.util.typeconvert.ConvertManager$ChainImpl

/*
* Copyright 2010 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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 com.alibaba.toolkit.util.typeconvert;

import com.alibaba.toolkit.util.enumeration.Enum;
import com.alibaba.toolkit.util.enumeration.EnumConverter;
import com.alibaba.toolkit.util.enumeration.FlagSet;
import com.alibaba.toolkit.util.enumeration.FlagSetConverter;
import com.alibaba.toolkit.util.typeconvert.converters.BigDecimalConverter;
import com.alibaba.toolkit.util.typeconvert.converters.BigIntegerConverter;
import com.alibaba.toolkit.util.typeconvert.converters.BooleanConverter;
import com.alibaba.toolkit.util.typeconvert.converters.ByteConverter;
import com.alibaba.toolkit.util.typeconvert.converters.CharacterConverter;
import com.alibaba.toolkit.util.typeconvert.converters.DoubleConverter;
import com.alibaba.toolkit.util.typeconvert.converters.FloatConverter;
import com.alibaba.toolkit.util.typeconvert.converters.IntegerConverter;
import com.alibaba.toolkit.util.typeconvert.converters.LongConverter;
import com.alibaba.toolkit.util.typeconvert.converters.ObjectArrayConverter;
import com.alibaba.toolkit.util.typeconvert.converters.ObjectConverter;
import com.alibaba.toolkit.util.typeconvert.converters.ShortConverter;
import com.alibaba.toolkit.util.typeconvert.converters.SqlDateConverter;
import com.alibaba.toolkit.util.typeconvert.converters.SqlTimeConverter;
import com.alibaba.toolkit.util.typeconvert.converters.SqlTimestampConverter;
import com.alibaba.toolkit.util.typeconvert.converters.StringConverter;

import java.math.BigDecimal;
import java.math.BigInteger;

import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;

/**
* <code>Converter</code>������.
*
* @version $Id: ConvertManager.java,v 1.1 2003/07/03 07:26:36 baobao Exp $
* @author Michael Zhou
*/
public class ConvertManager {
    private static final Object NO_DEFAULT_VALUE = new Object();
    private Map                 registry = Collections.synchronizedMap(new HashMap());
    private Map                 aliases  = Collections.synchronizedMap(new HashMap());

    /**
     * ����һ��ת����.
     */
    public ConvertManager() {
        register(BigDecimal.class, new BigDecimalConverter());
        register(BigInteger.class, new BigIntegerConverter());
        register(Boolean.class, new BooleanConverter());
        register(Byte.class, new ByteConverter());
        register(Character.class, new CharacterConverter());
        register(Double.class, new DoubleConverter());
        register(Float.class, new FloatConverter());
        register(Integer.class, new IntegerConverter());
        register(Long.class, new LongConverter());
        register(Short.class, new ShortConverter());
        register(Date.class, new SqlDateConverter());
        register(Time.class, new SqlTimeConverter());
        register(Timestamp.class, new SqlTimestampConverter());
        register(String.class, new StringConverter());
        register(Object[].class, new ObjectArrayConverter());
        register(Object.class, new ObjectConverter());
        register(Enum.class, new EnumConverter());
        register(FlagSet.class, new FlagSetConverter());


        // �ǼDZ���.
        registerAlias("string", String.class);
        registerAlias("enum", Enum.class);
    }

    /**
     * ��¼һ��ת����.
     *
     * @param type      ת������Ŀ������
     * @param converter ת��������
     */
    public void register(Class type, Converter converter) {
        synchronized (registry) {
            if (Boolean.class.equals(type) || Boolean.TYPE.equals(type)) {
                internalRegister(Boolean.class, converter);
                internalRegister(Boolean.TYPE, converter);
            } else if (Byte.class.equals(type) || Byte.TYPE.equals(type)) {
                internalRegister(Byte.class, converter);
                internalRegister(Byte.TYPE, converter);
            } else if (Character.class.equals(type) || Character.TYPE.equals(type)) {
                internalRegister(Character.class, converter);
                internalRegister(Character.TYPE, converter);
            } else if (Double.class.equals(type) || Double.TYPE.equals(type)) {
                internalRegister(Double.class, converter);
                internalRegister(Double.TYPE, converter);
            } else if (Float.class.equals(type) || Float.TYPE.equals(type)) {
                internalRegister(Float.class, converter);
                internalRegister(Float.TYPE, converter);
            } else if (Integer.class.equals(type) || Integer.TYPE.equals(type)) {
                internalRegister(Integer.class, converter);
                internalRegister(Integer.TYPE, converter);
            } else if (Long.class.equals(type) || Long.TYPE.equals(type)) {
                internalRegister(Long.class, converter);
                internalRegister(Long.TYPE, converter);
            } else if (Short.class.equals(type) || Short.TYPE.equals(type)) {
                internalRegister(Short.class, converter);
                internalRegister(Short.TYPE, converter);
            } else {
                internalRegister(type, converter);
            }
        }
    }

    /**
     * �ǼDZ���.
     *
     * @param alias   ����
     * @param type    Ŀ������
     */
    public void registerAlias(String alias, Class type) {
        synchronized (aliases) {
            if ((alias != null) && (type != null) && !aliases.containsKey(alias)) {
                aliases.put(alias, type);
            }
        }
    }

    /**
     * �ڲ�����: �Ǽ�һ��ת����.  �����primitive����, ��ͬ��.
     *
     * @param type      ת������Ŀ������
     * @param converter ת��������
     */
    private void internalRegister(Class type, Converter converter) {
        LinkedList converters = (LinkedList) registry.get(type);

        if (converters == null) {
            converters = new LinkedList();
            registry.put(type, converters);
        }

        if (!converters.contains(converter)) {
            converters.addFirst(converter);
            registerAlias(type.getName(), type);
        }
    }

    /**
     * ��ָ��ֵת����<code>boolean</code>����.
     *
     * @param value   Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public boolean asBoolean(Object value) {
        return ((Boolean) asType(Boolean.class, value)).booleanValue();
    }

    /**
     * ��ָ��ֵת����<code>boolean</code>����.
     *
     * @param value         Ҫת����ֵ
     * @param defaultValue  Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public boolean asBoolean(Object value, boolean defaultValue) {
        return ((Boolean) asType(Boolean.class, value, new Boolean(defaultValue))).booleanValue();
    }

    /**
     * ��ָ��ֵת����<code>byte</code>����.
     *
     * @param value   Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public byte asByte(Object value) {
        return ((Byte) asType(Byte.class, value)).byteValue();
    }

    /**
     * ��ָ��ֵת����<code>byte</code>����.
     *
     * @param value         Ҫת����ֵ
     * @param defaultValue  Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public byte asByte(Object value, byte defaultValue) {
        return ((Byte) asType(Byte.class, value, new Byte(defaultValue))).byteValue();
    }

    /**
     * ��ָ��ֵת����<code>char</code>����.
     *
     * @param value   Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public char asChar(Object value) {
        return ((Character) asType(Character.class, value)).charValue();
    }

    /**
     * ��ָ��ֵת����<code>char</code>����.
     *
     * @param value         Ҫת����ֵ
     * @param defaultValue  Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public char asChar(Object value, char defaultValue) {
        return ((Character) asType(Character.class, value, new Character(defaultValue))).charValue();
    }

    /**
     * ��ָ��ֵת����<code>double</code>����.
     *
     * @param value   Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public double asDouble(Object value) {
        return ((Double) asType(Double.class, value)).doubleValue();
    }

    /**
     * ��ָ��ֵת����<code>double</code>����.
     *
     * @param value         Ҫת����ֵ
     * @param defaultValue  Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public double asDouble(Object value, double defaultValue) {
        return ((Double) asType(Double.class, value, new Double(defaultValue))).doubleValue();
    }

    /**
     * ��ָ��ֵת����<code>float</code>����.
     *
     * @param value   Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public float asFloat(Object value) {
        return ((Float) asType(Float.class, value)).floatValue();
    }

    /**
     * ��ָ��ֵת����<code>float</code>����.
     *
     * @param value         Ҫת����ֵ
     * @param defaultValue  Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public float asFloat(Object value, float defaultValue) {
        return ((Float) asType(Float.class, value, new Float(defaultValue))).floatValue();
    }

    /**
     * ��ָ��ֵת����<code>int</code>����.
     *
     * @param value   Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public int asInt(Object value) {
        return ((Integer) asType(Integer.class, value)).intValue();
    }

    /**
     * ��ָ��ֵת����<code>int</code>����.
     *
     * @param value         Ҫת����ֵ
     * @param defaultValue  Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public int asInt(Object value, int defaultValue) {
        return ((Integer) asType(Integer.class, value, new Integer(defaultValue))).intValue();
    }

    /**
     * ��ָ��ֵת����<code>long</code>����.
     *
     * @param value   Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public long asLong(Object value) {
        return ((Long) asType(Long.class, value)).longValue();
    }

    /**
     * ��ָ��ֵת����<code>long</code>����.
     *
     * @param value         Ҫת����ֵ
     * @param defaultValue  Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public long asLong(Object value, long defaultValue) {
        return ((Long) asType(Long.class, value, new Long(defaultValue))).longValue();
    }

    /**
     * ��ָ��ֵת����<code>short</code>����.
     *
     * @param value   Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public short asShort(Object value) {
        return ((Short) asType(Short.class, value)).shortValue();
    }

    /**
     * ��ָ��ֵת����<code>short</code>����.
     *
     * @param value         Ҫת����ֵ
     * @param defaultValue  Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public short asShort(Object value, short defaultValue) {
        return ((Short) asType(Short.class, value, new Short(defaultValue))).shortValue();
    }

    /**
     * ��ָ��ֵת����<code>String</code>����.
     *
     * @param value   Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public String asString(Object value) {
        return (String) asType(String.class, value);
    }

    /**
     * ��ָ��ֵת����<code>String</code>����.
     *
     * @param value         Ҫת����ֵ
     * @param defaultValue  Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public String asString(Object value, String defaultValue) {
        return (String) asType(String.class, value, defaultValue);
    }

    /**
     * ��ָ��ֵת����ָ������.
     *
     * @param targetType Ҫת����Ŀ������
     * @param value      Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public Object asType(Object targetType, Object value) {
        return asType(targetType, value, NO_DEFAULT_VALUE);
    }

    /**
     * ��ָ��ֵת����ָ������.
     *
     * @param targetType   Ҫת����Ŀ������
     * @param value        Ҫת����ֵ
     * @param defaultValue Ĭ��ֵ
     *
     * @return ת�����ֵ
     */
    public Object asType(Object targetType, Object value, Object defaultValue) {
        try {
            return new ChainImpl(this, getTargetType(targetType)).convert(value);
        } catch (ConvertFailedException e) {
            if (e.isDefaultValueSet()) {
                return (defaultValue == NO_DEFAULT_VALUE) ? e.getDefaultValue()
                                                          : defaultValue;
            }

            throw e;
        }
    }

    /**
     * ��ָ��ֵת����ָ������.  ��ʹת��ʧ��, Ҳ���᷵��Ĭ��ֵ, ���׳�һ���쳣.
     *
     * @param targetType   Ҫת����Ŀ������
     * @param value        Ҫת����ֵ
     *
     * @return ת�����ֵ
     */
    public Object asTypeWithoutDefaultValue(Object targetType, Object value) {
        return new ChainImpl(this, getTargetType(targetType)).convert(value);
    }

    /**
     * ȡ��target type�����.
     *
     * @param targetType  target type������
     *
     * @return target type�����
     */
    private Class getTargetType(Object targetType) {
        if (targetType instanceof Class) {
            return (Class) targetType;
        }

        if (targetType instanceof String) {
            Class type = (Class) aliases.get(targetType);

            if (type != null) {
                return type;
            }
        }

        throw new IllegalArgumentException("Invalid targetType " + targetType);
    }

    /**
     * ת������. ���γ���: Convertible.getConverter(targetType), targetType��Ӧ��ת����,
     * targetType�Ļ���(������Object��)��Ӧ��ת����, targetType�Ľӿڶ�Ӧ��ת����, Object������Ӧ��ת����.
     */
    private class ChainImpl implements ConvertChain {
        private static final int     STATE_START              = 0;
        private static final int     STATE_TARGET_TYPE        = STATE_START + 1;
        private static final int     STATE_BASE_TYPE          = STATE_TARGET_TYPE + 1;
        private static final int     STATE_INTERFACE          = STATE_BASE_TYPE + 1;
        private static final int     STATE_OBJECT             = STATE_INTERFACE + 1;
        private static final int     STATE_END                = STATE_OBJECT + 1;
        private final ConvertManager manager;
        private final TypeInfo       targetTypeInfo;
        private int                  state                    = STATE_START;
        private Convertible          previousConvertibleValue;
        private Iterator             converterIterator;
        private Iterator             superclassIterator;
        private Iterator             interfaceIterator;

        /**
         * ����ת����.
         *
         * @param manager            ����������<code>ConvertManager</code>
         * @param targetType         ת����Ŀ������
         */
        ChainImpl(ConvertManager manager, Class targetType) {
            this.manager        = manager;
            this.targetTypeInfo = TypeInfo.getTypeInfo(targetType);
        }

        /**
         * ȡ�ô���������<code>ConvertManager</code>.
         *
         * @return ����������<code>ConvertManager</code>
         */
        public ConvertManager getConvertManager() {
            return manager;
        }

        /**
         * ȡ��ת����Ŀ������.
         *
         * @return Ŀ������
         */
        public Class getTargetType() {
            return targetTypeInfo.getType();
        }

        /**
         * �����ƽ������е���һ��ת����, ת��ָ����ֵ��ָ��������.
         *
         * @param value       Ҫת����ֵ
         *
         * @return ת�����ֵ
         */
        public Object convert(Object value) {
            Class targetType = targetTypeInfo.getType();

            // ���ȴ���ʵ��Convertible�ӿڵ�valueֵ,
            // ����ֹ��ͬһ��convertible value����������converter
            if (value instanceof Convertible && !value.equals(previousConvertibleValue)) {
                Converter converter = ((Convertible) value).getConverter(targetType);

                if (converter != null) {
                    previousConvertibleValue = (Convertible) value;
                    return converter.convert(value, this);
                }
            }

            // ��ʼ״̬
            if (state == STATE_START) {
                state++; // ����STATE_TARGET_TYPE״̬
                converterIterator = getConverterIterator(targetType);
            }

            // ����targetType��Ӧ��ת����
            if (state == STATE_TARGET_TYPE) {
                if (!hasNext(converterIterator)) {
                    state++; // ����STATE_BASE_TYPE״̬
                    superclassIterator = targetTypeInfo.getSuperclasses().iterator();
                    converterIterator  = getSuperclassConverterIterator();
                }
            }

            // ����targetType�Ļ����Ӧ��ת����
            if (state == STATE_BASE_TYPE) {
                if (!hasNext(converterIterator)) {
                    converterIterator = getSuperclassConverterIterator();

                    if (!hasNext(converterIterator)) {
                        state++; // ����STATE_INTERFACE״̬
                        interfaceIterator = targetTypeInfo.getInterfaces().iterator();
                        converterIterator = getInterfaceConverterIterator();
                    }
                }
            }

            // ����targetType�Ľӿڶ�Ӧ��ת����
            if (state == STATE_INTERFACE) {
                if (!hasNext(converterIterator)) {
                    converterIterator = getInterfaceConverterIterator();

                    if (!hasNext(converterIterator)) {
                        state++; // ����STATE_OBJECT״̬

                        if (!Object.class.equals(targetTypeInfo.getType())) {
                            converterIterator = getConverterIterator(Object.class);
                        }
                    }
                }
            }

            // ����Object���Ӧ��ת����
            if (state == STATE_OBJECT) {
                if (!hasNext(converterIterator)) {
                    state++; // ����STATE_END״̬
                }
            }

            // ��ʼת��
            if (state != STATE_END) {
                Converter converter = (Converter) converterIterator.next();

                return converter.convert(value, this);
            }

            // ����Ҳ���converter, ��ʧ��
            throw new ConvertFailedException();
        }

        /**
         * ȡ��ָ�����͵�����ת����.
         *
         * @param type  Ҫ����ת����������
         *
         * @return ת������<code>Iterator</code>, ���������, �򷵻�<code>null</code>
         */
        private Iterator getConverterIterator(Class type) {
            LinkedList converters = (LinkedList) registry.get(type);

            if ((converters != null) && (converters.size() > 0)) {
                return converters.iterator();
            }

            return null;
        }

        /**
         * ȡ��targetType����(������Object��)��ת����.
         *
         * @return �����ת������<code>Iterator</code>, ���������, �򷵻�<code>null</code>
         */
        private Iterator getSuperclassConverterIterator() {
            Iterator iterator = null;

            while (superclassIterator.hasNext()) {
                Class superclass = (Class) superclassIterator.next();

                if (!superclass.equals(Object.class)) {
                    iterator = getConverterIterator(superclass);

                    if (hasNext(iterator)) {
                        return iterator;
                    }
                }
            }

            return null;
        }

        /**
         * ȡ��targetType�ӿڵ�ת����.
         *
         * @return �ӿڵ�ת������<code>Iterator</code>, ���������, �򷵻�<code>null</code>
         */
        private Iterator getInterfaceConverterIterator() {
            Iterator iterator = null;

            while (interfaceIterator.hasNext()) {
                iterator = getConverterIterator((Class) interfaceIterator.next());

                if (hasNext(iterator)) {
                    return iterator;
                }
            }

            return null;
        }

        /**
         * ���iterator�Ƿ������һ��Ԫ��.
         *
         * @param iterator Ҫ����iterator
         *
         * @return ���iteratorΪ<code>null</code>, ��iterator�Ѿ��ߵ���, �򷵻�<code>false</code>
         */
        private boolean hasNext(Iterator iterator) {
            return (iterator != null) && iterator.hasNext();
        }
    }
}
TOP

Related Classes of com.alibaba.toolkit.util.typeconvert.ConvertManager$ChainImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.