1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.convert;
20
21 import java.lang.reflect.Modifier;
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.Set;
26 import java.util.concurrent.ConcurrentHashMap;
27
28 import javax.imageio.spi.ServiceRegistry;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class Converters {
48 protected static final String DELIMITER = "->";
49 protected static final ConcurrentHashMap<String, Converter<?, ?>> converterMap = new ConcurrentHashMap<String, Converter<?, ?>>();
50 protected static final Set<ConverterCreator> creators = Collections.synchronizedSet(new HashSet<ConverterCreator>());
51 protected static final Set<String> noConversions = Collections.synchronizedSet(new HashSet<String>());
52
53 static {
54 registerCreator(new PassThruConverterCreator());
55 ClassLoader loader = Thread.currentThread().getContextClassLoader();
56 Iterator<ConverterLoader> converterLoaders = ServiceRegistry.lookupProviders(ConverterLoader.class, loader);
57 while (converterLoaders.hasNext()) {
58 try {
59 ConverterLoader converterLoader = converterLoaders.next();
60 converterLoader.loadConverters();
61 } catch (Exception e) {
62 e.printStackTrace();
63 }
64 }
65 }
66
67 private Converters() {}
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 public static <S, T> Converter<S, T> getConverter(Class<S> sourceClass, Class<T> targetClass) throws ClassNotFoundException {
86 String key = sourceClass.getName().concat(DELIMITER).concat(targetClass.getName());
87 OUTER:
88 do {
89 Converter<?, ?> result = converterMap.get(key);
90 if (result != null) {
91 return Util.cast(result);
92 }
93 if (noConversions.contains(key)) {
94 throw new ClassNotFoundException("No converter found for " + key);
95 }
96 Class<?> foundSourceClass = null;
97 Converter<?, ?> foundConverter = null;
98 for (Converter<?, ?> value : converterMap.values()) {
99 if (value.canConvert(sourceClass, targetClass)) {
100
101 if (foundSourceClass == null || foundSourceClass.isAssignableFrom(value.getSourceClass())) {
102
103
104
105 foundSourceClass = value.getSourceClass();
106 foundConverter = value;
107 }
108 }
109 }
110 if (foundConverter != null) {
111 converterMap.putIfAbsent(key, foundConverter);
112 continue OUTER;
113 }
114 for (ConverterCreator value : creators) {
115 result = createConverter(value, sourceClass, targetClass);
116 if (result != null) {
117 converterMap.putIfAbsent(key, result);
118 continue OUTER;
119 }
120 }
121 noConversions.add(key);
122 throw new ClassNotFoundException("No converter found for " + key);
123 } while (true);
124 }
125
126 private static <S, SS extends S, T, TT extends T> Converter<SS, TT> createConverter(ConverterCreator creater, Class<SS> sourceClass, Class<TT> targetClass) {
127 return creater.createConverter(sourceClass, targetClass);
128 }
129
130
131
132
133
134
135
136 public static void loadContainedConverters(Class<?> containerClass) {
137
138 for (Class<?> clz: containerClass.getClasses()) {
139 try {
140
141 if ((clz.getModifiers() & Modifier.ABSTRACT) == 0) {
142 Object value;
143 try {
144 value = clz.getConstructor().newInstance();
145 } catch (NoSuchMethodException e) {
146
147
148 continue;
149 }
150 if (value instanceof ConverterLoader) {
151 ConverterLoader loader = (ConverterLoader) value;
152 loader.loadConverters();
153 }
154 }
155 } catch (Exception e) {
156 e.printStackTrace();
157 }
158 }
159 }
160
161
162
163
164
165
166
167
168
169 public static <S, T> void registerCreator(ConverterCreator creator) {
170 creators.add(creator);
171 }
172
173
174
175
176
177
178
179
180
181 public static <S, T> void registerConverter(Converter<S, T> converter) {
182 registerConverter(converter, converter.getSourceClass(), converter.getTargetClass());
183 }
184
185
186
187
188
189
190
191
192
193
194
195 public static <S, T> void registerConverter(Converter<S, T> converter, Class<?> sourceClass, Class<?> targetClass) {
196 StringBuilder sb = new StringBuilder();
197 if (sourceClass != null) {
198 sb.append(sourceClass.getName());
199 } else {
200 sb.append("<null>");
201 }
202 sb.append(DELIMITER);
203 if (targetClass != null) {
204 sb.append(targetClass.getName());
205 } else {
206 sb.append("<null>");
207 }
208 String key = sb.toString();
209 converterMap.putIfAbsent(key, converter);
210 }
211
212 protected static class PassThruConverterCreator implements ConverterCreator{
213 protected PassThruConverterCreator() {
214 }
215
216 public <S, T> Converter<S, T> createConverter(Class<S> sourceClass, Class<T> targetClass) {
217 if (sourceClass == targetClass || targetClass == Object.class || Util.instanceOf(sourceClass, targetClass)) {
218 return new PassThruConverter<S, T>(sourceClass, targetClass);
219 } else {
220 return null;
221 }
222 }
223 }
224
225
226
227
228
229
230 protected static class PassThruConverter<S, T> implements Converter<S, T> {
231 private final Class<S> sourceClass;
232 private final Class<T> targetClass;
233
234 public PassThruConverter(Class<S> sourceClass, Class<T> targetClass) {
235 this.sourceClass = sourceClass;
236 this.targetClass = targetClass;
237 }
238
239 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
240 return this.sourceClass == sourceClass && this.targetClass == targetClass;
241 }
242
243 @SuppressWarnings("unchecked")
244 public T convert(S obj) throws ConversionException {
245 return (T) obj;
246 }
247
248 public Class<?> getSourceClass() {
249 return sourceClass;
250 }
251
252 public Class<?> getTargetClass() {
253 return targetClass;
254 }
255 }
256 }