com.gzj.tulip.jade.rowmapper.DefaultRowMapperFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.gzj.tulip.jade.rowmapper.DefaultRowMapperFactory.java

Source

/*
 * Copyright 2009-2010 the original author or authors.
 *
 * 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 i 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.gzj.tulip.jade.rowmapper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.gzj.tulip.jade.annotation.RowHandler;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;

import com.gzj.tulip.jade.annotation.StatementAware;
import com.gzj.tulip.jade.statement.StatementMetaData;

/**
 * ?DAO
 * <p>
 * <ul>
 * <li>int?longprimitive??1</li>
 * <li>Integer?Long??01</li>
 * <li>String?BigDecimal?01</li>
 * <li>java.util.Date???01</li>
 * <li>byte[]????byte[](blob)</li>
 * <li>Blob?Clob?01</li>
 * <li><code>(int[]?String[])?</li>
 * <li>(User[])</li>
 * <li>?(List&lt;Integer&gt;?Set&lt;String&gt): ?</li>
 * <li>?(List&lt;User&gt;?Set&lt;User&gt): ?</li>
 * <li>(Map&lt;String, Date&gt): 2</li>
 * <li>(Map&lt;String, User&gt): </li>
 * <li>(Map&lt;String, String[]&gt): </li>
 * <ul>
 * 
 * @author  [qieqie.wang@gmail.com]
 * @author  [in355hz@gmail.com]
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class DefaultRowMapperFactory implements RowMapperFactory {

    private static Log logger = LogFactory.getLog(RowMapperFactory.class);

    private Map<String, RowMapper> rowMappers = new HashMap<String, RowMapper>();

    @Override
    public RowMapper getRowMapper(StatementMetaData smd) {
        RowHandler rowHandler = smd.getAnnotation(RowHandler.class);

        // ?  RowMapper
        RowMapper rowMapper = null;

        if (rowHandler != null) {
            if (rowHandler.rowMapper() != RowHandler.NotSettingRowMapper.class) {
                try {
                    rowMapper = rowHandler.rowMapper().newInstance();
                } catch (Exception ex) {
                    throw new BeanInstantiationException(rowHandler.rowMapper(), ex.getMessage(), ex);
                }
            } else if (rowHandler.rowMapperFactory() != RowHandler.NotSettingRowMapperFactory.class) {
                try {
                    RowMapperFactory rowMapperFactory = rowHandler.rowMapperFactory().newInstance();
                    rowMapper = rowMapperFactory.getRowMapper(smd);
                } catch (Exception ex) {
                    throw new BeanInstantiationException(rowHandler.rowMapper(), ex.getMessage(), ex);
                }
            }
        }
        // 
        if (rowMapper == null) {
            //

            Class<?> returnClassType = smd.getMethod().getReturnType();
            Class<?> rowType = getRowType(smd);

            // BUGFIX: SingleColumnRowMapper ?  Primitive Type 
            if (rowType.isPrimitive()) {
                rowType = ClassUtils.primitiveToWrapper(rowType);
            }

            // ?(?2Map)
            if (TypeUtils.isColumnType(rowType)) {
                if (Map.class.isAssignableFrom(returnClassType)) {
                    rowMapper = new MapEntryColumnRowMapper(smd, rowType);
                } else {
                    rowMapper = new SingleColumnRowMapper(rowType);
                }
            }
            // Bean??????
            else {
                if (rowType == Map.class) {
                    rowMapper = new ColumnMapRowMapper();
                } else if (rowType.isArray()) {
                    rowMapper = new ArrayRowMapper(rowType);
                } else if ((rowType == List.class) || (rowType == Collection.class)) {
                    rowMapper = new ListRowMapper(smd);
                } else if (rowType == Set.class) {
                    rowMapper = new SetRowMapper(smd);
                } else {
                    boolean checkColumns = (rowHandler == null) ? true : rowHandler.checkColumns();
                    boolean checkProperties = (rowHandler == null) ? false : rowHandler.checkProperties();
                    String key = rowType.getName() + "[checkColumns=" + checkColumns + "&checkProperties="
                            + checkProperties + "]";
                    rowMapper = rowMappers.get(key);
                    if (rowMapper == null) {
                        rowMapper = new BeanPropertyRowMapper(rowType, checkColumns, checkProperties); // jade's BeanPropertyRowMapper here
                        rowMappers.put(key, rowMapper);
                    }
                }
                // DAOMaprowMapper?Map.Entry
                if (Map.class.isAssignableFrom(returnClassType)) {
                    rowMapper = new MapEntryRowMapper(smd, rowMapper);
                }
            }
        }

        //

        if (rowMapper instanceof StatementAware) {
            ((StatementAware) rowMapper).setStatementMetaData(smd);
        }

        if (logger.isInfoEnabled()) {
            logger.info("using rowMapper " + rowMapper + " for " + smd);
        }

        return rowMapper;
    }

    // ?
    private static Class<?> getRowType(StatementMetaData statementMetaData) {
        Class<?> returnClassType = statementMetaData.getReturnType();
        if (Collection.class.isAssignableFrom(returnClassType)//
                || Iterable.class == returnClassType // 
                || Iterator.class == returnClassType) {
            return getRowTypeFromCollectionType(statementMetaData, returnClassType);
        } //
        else if (Map.class.isAssignableFrom(returnClassType)) {
            return getRowTypeFromMapType(statementMetaData, returnClassType);
        }
        //
        else if (returnClassType.isArray() && returnClassType != byte[].class) {
            // , ??
            return returnClassType.getComponentType();
        }

        // DAO?
        return returnClassType;
    }

    private static Class<?> getRowTypeFromMapType(StatementMetaData modifier, Class<?> returnClassType) {
        Class<?> rowType;
        // ?  Map<K, V> 
        Class<?>[] genericTypes = modifier.getGenericReturnTypes();
        if (genericTypes.length != 2) {
            throw new IllegalArgumentException("the returned generic type '" + returnClassType.getName()
                    + "' should has two actual type parameters.");
        }
        rowType = genericTypes[1]; // ?  V 
        return rowType;
    }

    private static Class<?> getRowTypeFromCollectionType(StatementMetaData modifier, Class<?> returnClassType) {
        Class<?> rowType;
        // ?  List/ArrayList/LinkedList, CollectionIterable/Iterator, Set/HashSet
        if ((returnClassType != List.class) && (returnClassType != ArrayList.class)
                && (returnClassType != LinkedList.class)//
                && (returnClassType != Collection.class) && (returnClassType != Iterable.class)
                && (returnClassType != Iterator.class) && (returnClassType != Set.class)
                && (returnClassType != HashSet.class)) {
            throw new IllegalArgumentException("error collection type " + returnClassType.getName()
                    + "; only support List/ArrayList/LinkedList, CollectionIterable/Iterator, Set/HashSet");
        }
        // ??
        Class<?>[] genericTypes = modifier.getGenericReturnTypes();
        if (genericTypes.length != 1) {
            throw new IllegalArgumentException("the returned generic type '" + returnClassType.getName()
                    + "' should has a actual type parameter.");
        }
        rowType = genericTypes[0];
        return rowType;
    }

}