View Javadoc

1   /*
2    * Copyright 2004-2010 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  
17  package org.seasar.cubby.spi.impl;
18  
19  import static org.seasar.cubby.internal.util.LogMessages.format;
20  
21  import java.util.Collection;
22  import java.util.Map;
23  import java.util.TreeMap;
24  
25  import org.seasar.cubby.converter.Converter;
26  import org.seasar.cubby.spi.ConverterProvider;
27  
28  /**
29   * コンバータプロバイダのスケルトン実装です。
30   * 
31   * @author baba
32   */
33  public abstract class AbstractConverterProvider implements ConverterProvider {
34  
35  	/**
36  	 * コンバータの一覧を返します。
37  	 * 
38  	 * @return コンバータの一覧
39  	 */
40  	protected abstract Collection<Converter> getConverters();
41  
42  	/**
43  	 * {@inheritDoc}
44  	 */
45  	public Converter getConverter(final Class<? extends Converter> converterType) {
46  		for (final Converter converter : getConverters()) {
47  			if (converterType.isAssignableFrom(converter.getClass())) {
48  				return converter;
49  			}
50  		}
51  		throw new IllegalArgumentException(format("ECUB0110", converterType));
52  	}
53  
54  	/**
55  	 * {@inheritDoc}
56  	 */
57  	public Converter getConverter(final Class<?> parameterType,
58  			final Class<?> objectType) {
59  		final Class<?> destType = ConversionUtils
60  				.getWrapperClassIfPrimitive(objectType);
61  		final Converter converter = getDistanceTable(parameterType, destType);
62  		return converter;
63  	}
64  
65  	private Converter getDistanceTable(final Class<?> parameterType,
66  			final Class<?> objectType) {
67  		final Map<Integer, Converter> distanceTable = new TreeMap<Integer, Converter>();
68  		for (final Converter converter : getConverters()) {
69  			if (!converter.canConvert(parameterType, objectType)) {
70  				continue;
71  			}
72  			final int distance = getDistance(converter.getObjectType(),
73  					objectType);
74  			distanceTable.put(distance, converter);
75  		}
76  		if (distanceTable.isEmpty()) {
77  			return null;
78  		}
79  		return distanceTable.values().iterator().next();
80  	}
81  
82  	private int getDistance(final Class<?> assigner, final Class<?> assignee) {
83  		return getDistance(assigner, assignee, 0);
84  	}
85  
86  	private int getDistance(final Class<?> assigner, final Class<?> assignee,
87  			final int distance) {
88  		if (assignee.equals(assigner)) {
89  			return distance;
90  		}
91  		if (Enum.class.equals(assigner) && assignee.isEnum()) {
92  			return distance + 5;
93  		}
94  		if (isImplements(assigner, assignee)) {
95  			return distance + 5;
96  		}
97  
98  		final Class<?> superClass = assigner.getSuperclass();
99  		if (superClass == null) {
100 			return distance + 10;
101 		}
102 		return getDistance(superClass, assignee, distance + 10);
103 	}
104 
105 	private boolean isImplements(final Class<?> assigner,
106 			final Class<?> assignee) {
107 		return !assigner.isInterface() && assignee.isInterface()
108 				&& assignee.isAssignableFrom(assigner);
109 	}
110 
111 }