View Javadoc

    1   /*
    2    * Copyright 2004-2009 the Seasar Foundation and the Others.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    13   * either express or implied. See the License for the specific language
    14   * governing permissions and limitations under the License.
    15   */
    16  package org.seasar.cubby.spi.impl;
    17
    18  import static org.seasar.cubby.internal.util.LogMessages.format;
    19
    20  import java.util.Collection;
    21  import java.util.Map;
    22  import java.util.TreeMap;
    23
    24  import org.seasar.cubby.converter.Converter;
    25  import org.seasar.cubby.spi.ConverterProvider;
    26
    27  /**
    28   * コンバータプロバイダのスケルトン実装です。
    29   *
    30   * @author baba
    31   */
    32  public abstract class AbstractConverterProvider implements ConverterProvider {
    33
    34  	/**
    35  	 * コンバータの一覧を返します。
    36  	 *
    37  	 * @return コンバータの一覧
    38  	 */
    39  	protected abstract Collection<Converter> getConverters();
    40
    41  	/**
    42  	 * {@inheritDoc}
    43  	 */
    44  	public Converter getConverter(final Class<? extends Converter> converterType) {
    45  		for (final Converter converter : getConverters()) {
    46  			if (converterType.isAssignableFrom(converter.getClass())) {
    47  				return converter;
    48  			}
    49  		}
    50  		throw new IllegalArgumentException(format("ECUB0110", converterType));
    51  	}
    52
    53  	/**
    54  	 * {@inheritDoc}
    55  	 */
    56  	public Converter getConverter(final Class<?> parameterType,
    57  			final Class<?> objectType) {
    58  		final Class<?> destType = ConversionUtils
    59  				.getWrapperClassIfPrimitive(objectType);
    60  		final Converter converter = getDistanceTable(parameterType, destType);
    61  		return converter;
    62  	}
    63
    64  	private Converter getDistanceTable(final Class<?> parameterType,
    65  			final Class<?> objectType) {
    66  		final Map<Integer, Converter> distanceTable = new TreeMap<Integer, Converter>();
    67  		for (final Converter converter : getConverters()) {
    68  			if (!converter.canConvert(parameterType, objectType)) {
    69  				continue;
    70  			}
    71  			final int distance = getDistance(converter.getObjectType(),
    72  					objectType);
    73  			distanceTable.put(distance, converter);
    74  		}
    75  		if (distanceTable.isEmpty()) {
    76  			return null;
    77  		}
    78  		return distanceTable.values().iterator().next();
    79  	}
    80
    81  	private int getDistance(final Class<?> assigner, final Class<?> assignee) {
    82  		return getDistance(assigner, assignee, 0);
    83  	}
    84
    85  	private int getDistance(final Class<?> assigner, final Class<?> assignee,
    86  			final int distance) {
    87  		if (assignee.equals(assigner)) {
    88  			return distance;
    89  		}
    90  		if (Enum.class.equals(assigner) && assignee.isEnum()) {
    91  			return distance + 5;
    92  		}
    93  		if (isImplements(assigner, assignee)) {
    94  			return distance + 5;
    95  		}
    96
    97  		final Class<?> superClass = assigner.getSuperclass();
    98  		if (superClass == null) {
    99  			return distance + 10;
    100 		}
    101 		return getDistance(superClass, assignee, distance + 10);
    102 	}
    103
    104 	private boolean isImplements(final Class<?> assigner,
    105 			final Class<?> assignee) {
    106 		return !assigner.isInterface() && assignee.isInterface()
    107 				&& assignee.isAssignableFrom(assigner);
    108 	}
    109
    110 }