1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
32
33 public abstract class AbstractConverterProvider implements ConverterProvider {
34
35
36
37
38
39
40 protected abstract Collection<Converter> getConverters();
41
42
43
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
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 }