1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jadira.bindings.core.binder;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.lang.annotation.Annotation;
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.Method;
23 import java.math.BigDecimal;
24 import java.math.BigInteger;
25 import java.net.InetAddress;
26 import java.net.URI;
27 import java.net.URL;
28 import java.util.ArrayList;
29 import java.util.Calendar;
30 import java.util.Currency;
31 import java.util.Date;
32 import java.util.Enumeration;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.List;
36 import java.util.Locale;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.TimeZone;
40 import java.util.UUID;
41 import java.util.concurrent.ConcurrentHashMap;
42 import java.util.concurrent.atomic.AtomicBoolean;
43 import java.util.concurrent.atomic.AtomicInteger;
44 import java.util.concurrent.atomic.AtomicLong;
45
46 import javax.enterprise.inject.Typed;
47
48 import org.jadira.bindings.core.annotation.BindingScope;
49 import org.jadira.bindings.core.annotation.DefaultBinding;
50 import org.jadira.bindings.core.api.Binding;
51 import org.jadira.bindings.core.api.Converter;
52 import org.jadira.bindings.core.api.FromUnmarshaller;
53 import org.jadira.bindings.core.api.ToMarshaller;
54 import org.jadira.bindings.core.general.binding.CompositeBinding;
55 import org.jadira.bindings.core.general.binding.InverseCompositeBinding;
56 import org.jadira.bindings.core.general.converter.FromUnmarshallerConverter;
57 import org.jadira.bindings.core.general.converter.ToMarshallerConverter;
58 import org.jadira.bindings.core.general.marshaller.ConverterToMarshaller;
59 import org.jadira.bindings.core.general.marshaller.MethodToMarshaller;
60 import org.jadira.bindings.core.general.unmarshaller.ConstructorFromUnmarshaller;
61 import org.jadira.bindings.core.general.unmarshaller.ConverterFromUnmarshaller;
62 import org.jadira.bindings.core.general.unmarshaller.MethodFromUnmarshaller;
63 import org.jadira.bindings.core.jdk.AtomicBooleanStringBinding;
64 import org.jadira.bindings.core.jdk.AtomicIntegerStringBinding;
65 import org.jadira.bindings.core.jdk.AtomicLongStringBinding;
66 import org.jadira.bindings.core.jdk.BigDecimalStringBinding;
67 import org.jadira.bindings.core.jdk.BigIntegerStringBinding;
68 import org.jadira.bindings.core.jdk.BooleanStringBinding;
69 import org.jadira.bindings.core.jdk.ByteStringBinding;
70 import org.jadira.bindings.core.jdk.CalendarStringBinding;
71 import org.jadira.bindings.core.jdk.CharSequenceStringBinding;
72 import org.jadira.bindings.core.jdk.CharacterStringBinding;
73 import org.jadira.bindings.core.jdk.ClassStringBinding;
74 import org.jadira.bindings.core.jdk.CurrencyStringBinding;
75 import org.jadira.bindings.core.jdk.DateStringBinding;
76 import org.jadira.bindings.core.jdk.DoubleStringBinding;
77 import org.jadira.bindings.core.jdk.FileStringBinding;
78 import org.jadira.bindings.core.jdk.FloatStringBinding;
79 import org.jadira.bindings.core.jdk.InetAddressStringBinding;
80 import org.jadira.bindings.core.jdk.IntegerStringBinding;
81 import org.jadira.bindings.core.jdk.LocaleStringBinding;
82 import org.jadira.bindings.core.jdk.LongStringBinding;
83 import org.jadira.bindings.core.jdk.PackageStringBinding;
84 import org.jadira.bindings.core.jdk.ShortStringBinding;
85 import org.jadira.bindings.core.jdk.StringBufferStringBinding;
86 import org.jadira.bindings.core.jdk.StringBuilderStringBinding;
87 import org.jadira.bindings.core.jdk.StringStringBinding;
88 import org.jadira.bindings.core.jdk.TimeZoneStringBinding;
89 import org.jadira.bindings.core.jdk.URIStringBinding;
90 import org.jadira.bindings.core.jdk.URLStringBinding;
91 import org.jadira.bindings.core.jdk.UUIDStringBinding;
92 import org.jadira.bindings.core.loader.BindingConfiguration;
93 import org.jadira.bindings.core.loader.BindingConfigurationEntry;
94 import org.jadira.bindings.core.loader.BindingXmlLoader;
95 import org.jadira.bindings.core.loader.Extension;
96 import org.jadira.bindings.core.loader.Provider;
97 import org.jadira.bindings.core.spi.ConverterProvider;
98 import org.jadira.bindings.core.utils.lang.IterableEnumeration;
99 import org.jadira.bindings.core.utils.reflection.ClassLoaderUtils;
100
101
102
103
104
105
106
107
108
109
110
111
112
113 @Typed({})
114 public class BasicBinder implements Binder, RegisterableBinder {
115
116
117
118
119
120 private final List<ConverterProvider> converterProviders = new ArrayList<ConverterProvider>();
121
122
123
124
125 private ConcurrentHashMap<ConverterKey<?,?>, Converter<?,?>> registeredConverters = new ConcurrentHashMap<ConverterKey<?,?>, Converter<?,?>>();
126
127
128
129
130 private ConcurrentHashMap<Class<?>, Object> extendedBinders = new ConcurrentHashMap<Class<?>, Object>();
131
132
133
134
135 private final Set<Class<?>> inspectedClasses = new HashSet<Class<?>>();
136
137
138
139
140 public BasicBinder() {
141 this(true);
142 }
143
144
145
146
147
148 public BasicBinder(boolean includeBuiltInBindings) {
149
150 initExtendedBinders();
151
152 if (includeBuiltInBindings) {
153
154 initJdkBindings();
155
156
157
158
159
160 initBuiltInBindings();
161
162
163 initRegisteredBindings();
164 }
165 }
166
167
168
169
170
171
172
173
174
175
176 private void initExtendedBinders() {
177 extendedBinders.put(StringBinder.class, this);
178 }
179
180
181
182
183 private void initJdkBindings() {
184
185 registerBinding(AtomicBoolean.class, String.class, new AtomicBooleanStringBinding());
186 registerBinding(AtomicInteger.class, String.class, new AtomicIntegerStringBinding());
187 registerBinding(AtomicLong.class, String.class, new AtomicLongStringBinding());
188 registerBinding(BigDecimal.class, String.class, new BigDecimalStringBinding());
189 registerBinding(BigInteger.class, String.class, new BigIntegerStringBinding());
190 registerBinding(Boolean.class, String.class, new BooleanStringBinding());
191 registerBinding(Byte.class, String.class, new ByteStringBinding());
192 registerBinding(Calendar.class, String.class, new CalendarStringBinding());
193 registerBinding(Character.class, String.class, new CharacterStringBinding());
194 registerBinding(CharSequence.class, String.class, new CharSequenceStringBinding());
195 registerBinding(Class.class, String.class, new ClassStringBinding());
196 registerBinding(Currency.class, String.class, new CurrencyStringBinding());
197 registerBinding(Date.class, String.class, new DateStringBinding());
198 registerBinding(Double.class, String.class, new DoubleStringBinding());
199 registerBinding(File.class, String.class, new FileStringBinding());
200 registerBinding(Float.class, String.class, new FloatStringBinding());
201 registerBinding(InetAddress.class, String.class, new InetAddressStringBinding());
202 registerBinding(Integer.class, String.class, new IntegerStringBinding());
203 registerBinding(Locale.class, String.class, new LocaleStringBinding());
204 registerBinding(Long.class, String.class, new LongStringBinding());
205 registerBinding(Package.class, String.class, new PackageStringBinding());
206 registerBinding(Short.class, String.class, new ShortStringBinding());
207 registerBinding(StringBuffer.class, String.class, new StringBufferStringBinding());
208 registerBinding(StringBuilder.class, String.class, new StringBuilderStringBinding());
209 registerBinding(String.class, String.class, new StringStringBinding());
210 registerBinding(TimeZone.class, String.class, new TimeZoneStringBinding());
211 registerBinding(URI.class, String.class, new URIStringBinding());
212 registerBinding(URL.class, String.class, new URLStringBinding());
213 registerBinding(UUID.class, String.class, new UUIDStringBinding());
214 }
215
216
217
218
219
220 private void initBuiltInBindings() {
221
222 final URL builtInBindingsUrl = getBuiltInBindingsURL();
223 registerConfiguration(builtInBindingsUrl);
224 }
225
226 private URL getBuiltInBindingsURL() {
227
228 String classResource = BasicBinder.class.getCanonicalName().replace('.', '/') + ".class";
229
230 URL bindingClassUrl = Thread.currentThread().getContextClassLoader().getResource(classResource);
231
232 String classPrefix = bindingClassUrl.toString().substring(0,
233 bindingClassUrl.toString().indexOf(classResource));
234
235 final URL builtInBindingsUrl;
236 try {
237 builtInBindingsUrl = new URL(classPrefix + "META-INF/bindings.xml");
238 } catch (IOException e) {
239 throw new IllegalStateException("Error registering bindings: " + e.getMessage(), e);
240 }
241 return builtInBindingsUrl;
242 }
243
244
245
246
247 private void initRegisteredBindings() {
248
249 Enumeration<URL> bindingsConfiguration;
250 try {
251 bindingsConfiguration = ClassLoaderUtils.getClassLoader().getResources("META-INF/bindings.xml");
252 } catch (IOException e) {
253 throw new IllegalStateException("Error registering bindings: " + e.getMessage(), e);
254 }
255
256 registerConfigurations(bindingsConfiguration);
257 }
258
259
260
261
262
263
264
265
266
267 protected <X> void registerConfigurations(Enumeration<URL> bindingsConfiguration) {
268 List<BindingConfiguration> configs = new ArrayList<BindingConfiguration>();
269 for (URL nextLocation : IterableEnumeration.wrapEnumeration(bindingsConfiguration)) {
270
271
272 URL builtIn = getBuiltInBindingsURL();
273 if (!builtIn.toString().equals(nextLocation.toString())) {
274 configs.add(BindingXmlLoader.load(nextLocation));
275 }
276 }
277
278 for (BindingConfiguration nextConfig : configs) {
279 for (Provider nextProvider : nextConfig.getProviders()) {
280
281 try {
282 registerConverterProvider(nextProvider.getProviderClass().newInstance());
283 } catch (InstantiationException e) {
284 throw new IllegalStateException("Cannot instantiate binding provider class: " + nextProvider.getProviderClass().getName());
285 } catch (IllegalAccessException e) {
286 throw new IllegalStateException("Cannot access binding provider class: " + nextProvider.getProviderClass().getName());
287 }
288 }
289
290 for (Extension<?> nextExtension : nextConfig.getExtensions()) {
291 try {
292 @SuppressWarnings("unchecked") Extension<X> myExtension = (Extension<X>)nextExtension;
293 @SuppressWarnings("unchecked") X myImplementation = (X) nextExtension.getImplementationClass().newInstance();
294 registerExtendedBinder(myExtension.getExtensionClass(), myImplementation);
295 } catch (InstantiationException e) {
296 throw new IllegalStateException("Cannot instantiate binder extension class: " + nextExtension.getExtensionClass().getName());
297 } catch (IllegalAccessException e) {
298 throw new IllegalStateException("Cannot access binder extension class: " + nextExtension.getExtensionClass().getName());
299 }
300 }
301
302 registerBindingConfigurationEntries(nextConfig.getBindingEntries());
303 }
304 }
305
306
307
308
309 public final void registerConfiguration(URL nextLocation) {
310
311 BindingConfiguration configuration = BindingXmlLoader.load(nextLocation);
312
313 for (Provider nextProvider : configuration.getProviders()) {
314
315 try {
316 registerConverterProvider(nextProvider.getProviderClass().newInstance());
317 } catch (InstantiationException e) {
318 throw new IllegalStateException("Cannot instantiate binding provider class: " + nextProvider.getProviderClass().getName());
319 } catch (IllegalAccessException e) {
320 throw new IllegalStateException("Cannot access binding provider class: " + nextProvider.getProviderClass().getName());
321 }
322 }
323
324 registerBindingConfigurationEntries(configuration.getBindingEntries());
325 }
326
327
328
329
330
331
332
333 public void registerConverterProviders(ConverterProvider... providers) {
334
335 for (ConverterProvider nextProvider : providers) {
336 registerConverterProvider(nextProvider);
337 }
338 }
339
340
341
342
343
344 public void registerConverterProvider(ConverterProvider provider) {
345 this.converterProviders.add(provider);
346 }
347
348
349
350
351
352
353 protected void registerBindingConfigurationEntries(Iterable<BindingConfigurationEntry> bindings) {
354
355 for (BindingConfigurationEntry nextBinding : bindings) {
356 try {
357 registerBindingConfigurationEntry(nextBinding);
358 } catch (IllegalStateException e) {
359
360 }
361 }
362 }
363
364
365
366
367
368
369
370 protected <S,T> void registerBindingConfigurationEntry(BindingConfigurationEntry theBinding) {
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390 if (Binding.class.isAssignableFrom(theBinding.getBindingClass())) {
391
392
393
394
395
396
397
398
399 try {
400 @SuppressWarnings("unchecked")
401 Binding<S,T> binding = (Binding<S,T>)theBinding.getBindingClass().newInstance();
402 registerBinding(binding.getBoundClass(), binding.getTargetClass(), binding, theBinding.getQualifier());
403 } catch (InstantiationException e) {
404 throw new IllegalStateException("Cannot instantiate binding class: " + theBinding.getBindingClass().getName());
405 } catch (IllegalAccessException e) {
406 throw new IllegalStateException("Cannot access binding class: " + theBinding.getBindingClass().getName());
407 }
408 } else if (FromUnmarshaller.class.isAssignableFrom(theBinding.getBindingClass())) {
409
410
411
412
413
414
415
416
417 try {
418 @SuppressWarnings("unchecked")
419 FromUnmarshaller<S,T> fromUnmarshaller = (FromUnmarshaller<S,T>)theBinding.getBindingClass().newInstance();
420 registerUnmarshaller(fromUnmarshaller.getBoundClass(), fromUnmarshaller.getTargetClass(), fromUnmarshaller, theBinding.getQualifier());
421 } catch (InstantiationException e) {
422 throw new IllegalStateException("Cannot instantiate binding class: " + theBinding.getBindingClass().getName());
423 } catch (IllegalAccessException e) {
424 throw new IllegalStateException("Cannot access binding class: " + theBinding.getBindingClass().getName());
425 }
426 } else if (ToMarshaller.class.isAssignableFrom(theBinding.getBindingClass())) {
427
428
429
430
431
432
433
434
435 try {
436 @SuppressWarnings("unchecked")
437 ToMarshaller<S,T> toMarshaller = (ToMarshaller<S,T>)theBinding.getBindingClass().newInstance();
438 registerMarshaller(toMarshaller.getBoundClass(), toMarshaller.getTargetClass(), toMarshaller, theBinding.getQualifier());
439 } catch (InstantiationException e) {
440 throw new IllegalStateException("Cannot instantiate binding class: " + theBinding.getBindingClass().getName());
441 } catch (IllegalAccessException e) {
442 throw new IllegalStateException("Cannot access binding class: " + theBinding.getBindingClass().getName());
443 }
444 } else if (Converter.class.isAssignableFrom(theBinding.getBindingClass())) {
445
446
447
448
449
450
451
452
453 try {
454 @SuppressWarnings("unchecked")
455 Converter<S,T> converter = (Converter<S,T>)theBinding.getBindingClass().newInstance();
456 registerConverter(converter.getInputClass(), converter.getOutputClass(), converter, theBinding.getQualifier());
457 } catch (InstantiationException e) {
458 throw new IllegalStateException("Cannot instantiate binding class: " + theBinding.getBindingClass().getName());
459 } catch (IllegalAccessException e) {
460 throw new IllegalStateException("Cannot access binding class: " + theBinding.getBindingClass().getName());
461 }
462 } else if (theBinding.getBindingClass() != null) {
463
464
465
466
467 registerAnnotatedClasses(theBinding.getBindingClass());
468 } else {
469
470
471
472
473 @SuppressWarnings("unchecked")
474 ConverterKey<S,T> converterKey = new ConverterKey<S,T>((Class<S>)theBinding.getSourceClass(), (Class<T>)theBinding.getTargetClass(), theBinding.getQualifier());
475 @SuppressWarnings("unchecked")
476 Constructor<S> fromConstructor = (Constructor<S>)theBinding.getFromConstructor();
477
478 registerForMethods(converterKey, theBinding.getToMethod(), theBinding.getFromMethod(), fromConstructor);
479 }
480 }
481
482
483
484
485
486 public void registerAnnotatedClasses(Class<?>... classesToInspect) {
487
488 for (Class<?> nextClass : classesToInspect) {
489
490 Class<?> loopClass = nextClass;
491 while ((loopClass != Object.class) && (!inspectedClasses.contains(loopClass))) {
492
493 attachForAnnotations(loopClass);
494
495 loopClass = loopClass.getSuperclass();
496 }
497 }
498 }
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513 protected <I, T extends I> void registerExtendedBinder(Class<I> iface, T provider) {
514 extendedBinders.put(iface, provider);
515 }
516
517
518
519
520
521
522
523 @SuppressWarnings("unchecked")
524 protected <I> I getExtendedBinder(Class<I> cls) {
525 return (I) extendedBinders.get(cls);
526 }
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544 public final <S, T> void registerBinding(Class<S> source, Class<T> target, Binding<S, T> converter) {
545 Class<? extends Annotation> scope = matchImplementationToScope(converter.getClass());
546 registerBinding(new ConverterKey<S,T>(source, target, scope == null ? DefaultBinding.class : scope), converter);
547 }
548
549
550
551
552
553
554
555
556 public final <S, T> void registerUnmarshaller(Class<S> source, Class<T> target, FromUnmarshaller<S, T> converter) {
557 Class<? extends Annotation> scope = matchImplementationToScope(converter.getClass());
558 registerUnmarshaller(new ConverterKey<S,T>(source, target, scope == null ? DefaultBinding.class : scope), converter);
559 }
560
561
562
563
564
565
566
567
568 public final <S, T> void registerMarshaller(Class<S> source, Class<T> target, ToMarshaller<S, T> converter) {
569 Class<? extends Annotation> scope = matchImplementationToScope(converter.getClass());
570 registerMarshaller(new ConverterKey<S,T>(source, target, scope == null ? DefaultBinding.class : scope), converter);
571 }
572
573
574
575
576
577
578
579
580 public final <S, T> void registerConverter(Class<S> input, Class<T> output, Converter<S, T> converter) {
581 Class<? extends Annotation> scope = matchImplementationToScope(converter.getClass());
582 registerConverter(new ConverterKey<S,T>(input, output, scope == null ? DefaultBinding.class : scope), converter);
583 }
584
585
586
587
588
589
590
591
592
593
594
595
596 public final <S, T> void registerBinding(Class<S> source, Class<T> target, Binding<S, T> converter, Class<? extends Annotation> qualifier) {
597 registerBinding(new ConverterKey<S,T>(source, target, qualifier == null ? DefaultBinding.class : qualifier), converter);
598 }
599
600
601
602
603
604
605
606
607
608
609 public final <S, T> void registerBinding(ConverterKey<S,T> key, Binding<S, T> converter) {
610 registerConverter(key.invert(), new FromUnmarshallerConverter<S,T>(converter));
611 registerConverter(key, new ToMarshallerConverter<S,T>(converter));
612 }
613
614
615
616
617
618
619
620
621
622
623 public final <S, T> void registerUnmarshaller(Class<S> source, Class<T> target, FromUnmarshaller<S, T> converter, Class<? extends Annotation> qualifier) {
624 registerUnmarshaller(new ConverterKey<S,T>(source, target, qualifier == null ? DefaultBinding.class : qualifier), converter);
625 }
626
627
628
629
630
631
632
633 public final <S, T> void registerUnmarshaller(ConverterKey<S,T> key, FromUnmarshaller<S, T> converter) {
634 registerConverter(key.invert(), new FromUnmarshallerConverter<S,T>(converter));
635 }
636
637
638
639
640
641
642
643
644
645 public final <S, T> void registerMarshaller(Class<S> source, Class<T> target, ToMarshaller<S, T> converter, Class<? extends Annotation> qualifier) {
646 registerMarshaller(new ConverterKey<S,T>(source, target, qualifier == null ? DefaultBinding.class : qualifier), converter);
647 }
648
649
650
651
652
653
654
655 public final <S, T> void registerMarshaller(ConverterKey<S,T> key, ToMarshaller<S, T> converter) {
656 registerConverter(key, new ToMarshallerConverter<S,T>(converter));
657 }
658
659
660
661
662
663
664
665
666
667 public final <S, T> void registerConverter(Class<S> input, Class<T> output, Converter<S, T> converter, Class<? extends Annotation> qualifier) {
668 registerConverter(new ConverterKey<S,T>(input, output, qualifier == null ? DefaultBinding.class : qualifier), converter);
669 }
670
671
672
673
674
675
676
677 public final <S, T> void registerConverter(ConverterKey<S,T> key, Converter<S, T> converter) {
678
679 if (key.getInputClass() == null) {
680 throw new IllegalArgumentException("Input Class must not be null");
681 }
682 if (key.getOutputClass() == null) {
683 throw new IllegalArgumentException("Output Class must not be null");
684 }
685 if (converter == null) {
686 throw new IllegalArgumentException("Converter must not be null");
687 }
688
689 if (key.getQualifierAnnotation() == null) {
690 throw new IllegalArgumentException("Qualifier must not be null");
691 }
692
693 Converter<?,?> old = registeredConverters.putIfAbsent(key, converter);
694 if (old != null && (!isSameConverter(old, converter))) {
695 throw new IllegalStateException("Converter already registered for key: " + key);
696 }
697 }
698
699 @SuppressWarnings("unlikely-arg-type")
700 private boolean isSameConverter(Converter<?,?> old, Converter<?,?> converter) {
701
702 if (old.getClass().equals(converter.getClass())) {
703 return true;
704 }
705
706
707 if (old instanceof FromUnmarshallerConverter && converter instanceof ToMarshallerConverter
708 && (((FromUnmarshallerConverter<?, ?>)old).getUnmarshaller().equals(((ToMarshallerConverter<?, ?>)converter).getMarshaller()))) {
709 return true;
710 }
711 if (old instanceof ToMarshallerConverter && converter instanceof FromUnmarshallerConverter
712 && (((ToMarshallerConverter<?, ?>)old).getMarshaller().equals(((FromUnmarshallerConverter<?, ?>)converter).getUnmarshaller()))) {
713 return true;
714 }
715 return false;
716 }
717
718
719
720
721
722
723
724
725
726
727
728
729
730 public <S, T> T convertTo(Class<T> output, Object object) {
731 return convertTo(output, object, DefaultBinding.class);
732 }
733
734
735
736
737
738
739
740
741 public <S, T> T convertTo(Class<T> output, Object object, Class<? extends Annotation> qualifier) {
742
743 if (object == null) {
744 return null;
745 }
746
747 @SuppressWarnings("unchecked")
748 Converter<S, T> conv = (Converter<S, T>) determineConverter(object.getClass(), output, qualifier == null ? DefaultBinding.class : qualifier);
749
750 if (conv == null) {
751 @SuppressWarnings("unchecked")
752 Class<S> inputClass = (Class<S>)object.getClass();
753 throw new NoConverterFoundException(new ConverterKey<S,T>(inputClass, output, qualifier == null ? DefaultBinding.class : qualifier));
754 }
755
756 @SuppressWarnings("unchecked")
757 S myObject = (S)object;
758 return conv.convert(myObject);
759 }
760
761 private <S, T> Converter<S, T> determineConverter(Class<S> candidateClass, Class<T> output, Class<? extends Annotation> qualifier) {
762
763 if (!candidateClass.equals(Object.class)) {
764 Converter<S, T> match = findConverter(candidateClass, output, qualifier);
765 if (match != null) {
766 return match;
767 }
768
769 @SuppressWarnings("unchecked")
770 Class<S>[] interfaces = (Class<S>[])candidateClass.getInterfaces();
771 for (Class<S> candidateInterface : interfaces) {
772 match = determineConverter(candidateInterface, output, qualifier);
773 if (match != null) {
774 return match;
775 }
776 }
777
778 Class<? super S> superClass = (Class<? super S>)candidateClass.getSuperclass();
779
780 @SuppressWarnings("unchecked")
781 Converter<S,T> superMatch = (Converter<S, T>) determineConverter(superClass, output, qualifier);
782 return superMatch;
783 } else {
784 return null;
785 }
786 }
787
788
789
790
791
792
793
794 public <S, T> T convertTo(Class<S> input, Class<T> output, Object object) {
795 return convertTo(new ConverterKey<S,T>(input, output, DefaultBinding.class), object);
796 }
797
798
799
800
801
802
803
804
805 public <S, T> T convertTo(Class<S> input, Class<T> output, Object object, Class<? extends Annotation> qualifier) {
806
807 return convertTo(new ConverterKey<S,T>(input, output, qualifier), object);
808 }
809
810
811
812
813
814
815 public <S, T> T convertTo(ConverterKey<S,T> key, Object object) {
816
817 if (object == null) {
818 return null;
819 }
820
821 Converter<S, T> conv = findConverter(key.getInputClass(), key.getOutputClass(), key.getQualifierAnnotation() == null ? DefaultBinding.class : key.getQualifierAnnotation());
822
823 if (conv == null) {
824 throw new NoConverterFoundException(key);
825 }
826
827 @SuppressWarnings("unchecked")
828 S myObject = (S)object;
829 return conv.convert(myObject);
830 }
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847 public <S, T> Binding<S, T> findBinding(Class<S> source, Class<T> target) {
848 return findBinding(new ConverterKey<S,T>(source, target, DefaultBinding.class));
849 }
850
851
852
853
854
855
856
857 public <S, T> ToMarshaller<S, T> findMarshaller(Class<S> source, Class<T> target) {
858 return findMarshaller(new ConverterKey<S,T>(source, target, DefaultBinding.class));
859 }
860
861
862
863
864
865
866
867 public <S, T> Converter<S, T> findConverter(Class<S> input, Class<T> output) {
868 return findConverter(new ConverterKey<S,T>(input, output, DefaultBinding.class));
869 }
870
871
872
873
874
875
876
877 public <S, T> FromUnmarshaller<S, T> findUnmarshaller(Class<S> source, Class<T> target) {
878 return findUnmarshaller(new ConverterKey<S,T>(source, target, DefaultBinding.class));
879 }
880
881
882
883
884
885
886
887
888
889
890
891 public <S, T> Binding<S, T> findBinding(Class<S> source, Class<T> target, Class<? extends Annotation> qualifier) {
892 return findBinding(new ConverterKey<S,T>(source, target, qualifier == null ? DefaultBinding.class : qualifier));
893 }
894
895
896
897
898
899
900
901
902
903 @SuppressWarnings("unlikely-arg-type")
904 public <S, T> Binding<S, T> findBinding(ConverterKey<S,T> key) {
905
906 FromUnmarshaller<?,?> fromUnmarshaller = null;
907 ToMarshaller<?,?> toMarshaller = null;
908
909 Converter<S, T> toTarget = findConverter(key);
910 if (toTarget instanceof FromUnmarshallerConverter<?, ?>) {
911 fromUnmarshaller = ((FromUnmarshallerConverter<?, ?>) toTarget).getUnmarshaller();
912 } else if (toTarget instanceof ToMarshallerConverter<?, ?>) {
913 toMarshaller = ((ToMarshallerConverter<?, ?>) toTarget).getMarshaller();
914 }
915 Converter<T, S> toSource = findConverter(key.invert());
916 if (toSource instanceof FromUnmarshallerConverter<?, ?>) {
917 fromUnmarshaller = ((FromUnmarshallerConverter<?, ?>) toSource).getUnmarshaller();
918 } else if (toSource instanceof ToMarshallerConverter<?, ?>) {
919 toMarshaller = ((ToMarshallerConverter<?, ?>) toSource).getMarshaller();
920 }
921
922 if (fromUnmarshaller != null && toMarshaller != null) {
923
924 if (fromUnmarshaller.equals(toMarshaller) && Binding.class.isAssignableFrom(fromUnmarshaller.getClass())) {
925 Binding<?,?> theBinding = (Binding<?,?>)fromUnmarshaller;
926 if (theBinding.getBoundClass().equals(key.getInputClass())) {
927 @SuppressWarnings("unchecked")
928 final Binding<S, T>myBinding = (Binding<S, T>)theBinding;
929 return myBinding;
930 }
931 }
932
933 if (fromUnmarshaller.getBoundClass().equals(key.getInputClass())) {
934 @SuppressWarnings("unchecked")
935 final Binding<S, T>myBinding = new CompositeBinding<S,T>((ToMarshaller<S,T>)toMarshaller, (FromUnmarshaller<S,T>)fromUnmarshaller);
936 return myBinding;
937 } else {
938 @SuppressWarnings("unchecked")
939 final Binding<S, T> myBinding = new InverseCompositeBinding<S,T>((ToMarshaller<T,S>)toMarshaller, (FromUnmarshaller<T,S>)fromUnmarshaller);
940 return myBinding;
941 }
942 }
943 return null;
944 }
945
946
947
948
949
950
951
952
953 public <S, T> ToMarshaller<S, T> findMarshaller(Class<S> source, Class<T> target, Class<? extends Annotation> qualifier) {
954 return findMarshaller(new ConverterKey<S,T>(source, target, qualifier == null ? DefaultBinding.class : qualifier));
955 }
956
957
958
959
960
961
962 public <S, T> ToMarshaller<S, T> findMarshaller(ConverterKey<S,T> key) {
963
964 Converter<S,T> converter = findConverter(key);
965
966 if (converter == null) {
967 return null;
968 }
969
970 if (ToMarshallerConverter.class.isAssignableFrom(converter.getClass())) {
971 return ((ToMarshallerConverter<S, T>)converter).getMarshaller();
972 } else {
973 return new ConverterToMarshaller<S, T>(converter);
974 }
975 }
976
977
978
979
980
981
982
983
984 public <S, T> Converter<S, T> findConverter(Class<S> source, Class<T> target, Class<? extends Annotation> qualifier) {
985 return findConverter(new ConverterKey<S,T>(source, target, qualifier == null ? DefaultBinding.class : qualifier));
986 }
987
988
989
990
991
992
993 public <S, T> Converter<S, T> findConverter(ConverterKey<S,T> key) {
994
995
996 @SuppressWarnings("unchecked")
997 Converter<S,T> converter = (Converter<S, T>) registeredConverters.get(key);
998 if (converter != null) {
999 return converter;
1000 }
1001
1002
1003 registerAnnotatedClasses(key.getInputClass(), key.getOutputClass());
1004
1005 @SuppressWarnings("unchecked")
1006 Converter<S,T> myConverter = (Converter<S, T>) registeredConverters.get(key);
1007 return myConverter;
1008 }
1009
1010
1011
1012
1013
1014
1015
1016
1017 public <S, T> FromUnmarshaller<S, T> findUnmarshaller(Class<S> source, Class<T> target, Class<? extends Annotation> qualifier) {
1018 return findUnmarshaller(new ConverterKey<S,T>(source, target, qualifier == null ? DefaultBinding.class : qualifier));
1019 }
1020
1021
1022
1023
1024
1025
1026 public <S, T> FromUnmarshaller<S, T> findUnmarshaller(ConverterKey<S,T> key) {
1027
1028 Converter<T,S> converter = findConverter(key.invert());
1029
1030 if (converter == null) {
1031 return null;
1032 }
1033
1034 if (FromUnmarshallerConverter.class.isAssignableFrom(converter.getClass())) {
1035 return ((FromUnmarshallerConverter<S, T>)converter).getUnmarshaller();
1036 } else {
1037 return new ConverterFromUnmarshaller<S, T>(converter);
1038 }
1039 }
1040
1041
1042
1043
1044 public Iterable<ConverterKey<?,?>> getConverterEntries() {
1045 return registeredConverters.keySet();
1046 }
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062 private <T> Class<? extends Annotation> matchImplementationToScope(Class<?> implementation) {
1063
1064 for (Annotation next : implementation.getAnnotations()) {
1065 Class<? extends Annotation> nextType = next.annotationType();
1066 if (nextType.getAnnotation(BindingScope.class) != null) {
1067 return nextType;
1068 }
1069 }
1070 return null;
1071 }
1072
1073 private <S, T> void attachForAnnotations(final Class<?> target) {
1074
1075
1076 synchronized(inspectedClasses) {
1077 if (inspectedClasses.contains(target)) {
1078 return;
1079 }
1080 inspectedClasses.add(target);
1081 }
1082
1083
1084 Set<ConverterKey<?,?>> previouslySeenKeys = new HashSet<ConverterKey<?,?>>();
1085
1086 Map<ConverterKey<?,?>, Method> toMethods = new HashMap<ConverterKey<?,?>, Method>();
1087 Map<ConverterKey<?,?>, Method> fromMethods = new HashMap<ConverterKey<?,?>, Method>();
1088 Map<ConverterKey<?,?>, Constructor<?>> fromConstructors = new HashMap<ConverterKey<?,?>, Constructor<?>>();
1089
1090 matchTo(target, previouslySeenKeys, toMethods);
1091
1092 matchFrom(target, previouslySeenKeys, fromMethods, fromConstructors);
1093
1094
1095 for (ConverterKey<?,?> next : previouslySeenKeys) {
1096
1097 @SuppressWarnings("unchecked")
1098 ConverterKey<S,T> nextKey = (ConverterKey<S,T>)next;
1099
1100 ConverterKey<?,?> inverse = next.invert();
1101 @SuppressWarnings("unchecked") Constructor<S> fromConstructor = (Constructor<S>) fromConstructors.get(inverse);
1102
1103 registerForMethods(nextKey, toMethods.get(next), fromMethods.get(inverse), fromConstructor);
1104 }
1105 }
1106
1107 private void matchTo(Class<?> target, Set<ConverterKey<?,?>> previouslySeenKeys, Map<ConverterKey<?,?>, Method> toMethods) {
1108
1109 for (ConverterProvider nextConverter : converterProviders) {
1110 Map<ConverterKey<?,?>, Method> nextMethods = nextConverter.matchToMethods(target);
1111 for(ConverterKey<?,?> currentKey : nextMethods.keySet()) {
1112 if (previouslySeenKeys.contains(currentKey)) {
1113 throw new IllegalStateException("Method is resolved by two converters: " + currentKey.toString());
1114 }
1115 previouslySeenKeys.add(currentKey);
1116 }
1117 toMethods.putAll(nextMethods);
1118 }
1119 }
1120
1121 private <T> void matchFrom(Class<T> target, Set<ConverterKey<?,?>> previouslySeenKeys, Map<ConverterKey<?,?>, Method> fromMethods, Map<ConverterKey<?,?>, Constructor<?>> fromConstructors) {
1122
1123 for (ConverterProvider nextConverter : converterProviders) {
1124 Map<ConverterKey<?,?>, Method> nextMethods = nextConverter.matchFromMethods(target);
1125 for (ConverterKey<?,?> currentKey : nextMethods.keySet()) {
1126 if (previouslySeenKeys.contains(currentKey)) {
1127 throw new IllegalStateException("Method is resolved by two converters: " + currentKey.toString());
1128 }
1129 previouslySeenKeys.add(currentKey);
1130 }
1131 fromMethods.putAll(nextMethods);
1132
1133 Map<ConverterKey<?,?>, Constructor<T>> nextConstructors = nextConverter.matchFromConstructors(target);
1134 for (ConverterKey<?,?> currentKey : nextConstructors.keySet()) {
1135 if (previouslySeenKeys.contains(currentKey)) {
1136 throw new IllegalStateException("ConverterKey is resolved by two converters: " + currentKey.toString());
1137 }
1138 previouslySeenKeys.add(currentKey);
1139 }
1140 fromConstructors.putAll(nextConstructors);
1141 }
1142 }
1143
1144 private <I,O> void registerForMethods(ConverterKey<I,O> key, Method toMethod, Method fromMethod, Constructor<I> con) {
1145
1146 if (toMethod != null) {
1147
1148 MethodToMarshaller<I,O> toMarshaller = new MethodToMarshaller<I,O>(key.getInputClass(), key.getOutputClass(), toMethod);
1149 if (con != null) {
1150
1151 ConstructorFromUnmarshaller<I,O> fromUnmarshaller = new ConstructorFromUnmarshaller<I,O>(con);
1152 registerBinding(key.getInputClass(), key.getOutputClass(), new CompositeBinding<I,O>(toMarshaller, fromUnmarshaller), key.getQualifierAnnotation());
1153 } else if (fromMethod != null) {
1154
1155 MethodFromUnmarshaller<I,O> fromUnmarshaller = new MethodFromUnmarshaller<I,O>(key.getInputClass(), fromMethod);
1156 registerBinding(key.getInputClass(), key.getOutputClass(), new CompositeBinding<I,O>(toMarshaller, fromUnmarshaller), key.getQualifierAnnotation());
1157 } else {
1158
1159 registerMarshaller(key.getInputClass(), key.getOutputClass(), toMarshaller, key.getQualifierAnnotation());
1160 }
1161 } else {
1162 if (con != null) {
1163
1164 registerUnmarshaller(key.getInputClass(), key.getOutputClass(), new ConstructorFromUnmarshaller<I,O>(con), key.getQualifierAnnotation());
1165 } else if (fromMethod != null) {
1166
1167 registerUnmarshaller(key.getInputClass(), key.getOutputClass(), new MethodFromUnmarshaller<I,O>(key.getInputClass(), fromMethod), key.getQualifierAnnotation());
1168 }
1169 }
1170 }
1171
1172
1173
1174
1175
1176
1177
1178 public <T> T convertFromString(Class<T> output, String object) {
1179 return convertTo(String.class, output, object);
1180 }
1181
1182 public <T> T convertFromString(Class<T> output, String object,
1183 Class<? extends Annotation> qualifier) {
1184 return convertTo(String.class, output, object, qualifier);
1185 }
1186
1187 public String convertToString(Object object) {
1188 return convertTo(String.class, object);
1189 }
1190
1191 public String convertToString(Object object,
1192 Class<? extends Annotation> qualifier) {
1193 return convertTo(String.class, object, qualifier);
1194 }
1195
1196 public <S> String convertToString(Class<S> input, Object object) {
1197 return convertTo(input, String.class, object);
1198 }
1199
1200 public <S> String convertToString(Class<S> input, Object object,
1201 Class<? extends Annotation> qualifier) {
1202 return convertTo(input, String.class, object, qualifier);
1203 }
1204 }