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