View Javadoc
1   /*
2    *  Copyright 2010, 2011 Chris Pheby
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, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
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  * Core binding capability.
103  * Typically you would obtain an instance of this class either
104  * by direct construction, or in JDK6 and above by using 
105  * <code>java.util.ServiceLoader</code>.
106  * 
107  * Default construction of this class registers bindings for core
108  * JDK classes, as well as any bindings specified using bindings.xml
109  * 
110  * You can also register additional bindings programmatically.
111  * @see Binding Binding is used to define a binding
112  */
113 @Typed({})
114 public class BasicBinder implements Binder, RegisterableBinder {
115 
116 	/**
117 	 * ConverterProviders are used to resolve converters using annotations on the target class.
118 	 * Because additional converter providers can be registered they provide a mechanism for extending the framework.
119 	 */
120 	private final List<ConverterProvider> converterProviders = new ArrayList<ConverterProvider>();
121 	
122 	/**
123 	 * A map of registered converters
124 	 */
125 	private ConcurrentHashMap<ConverterKey<?,?>, Converter<?,?>> registeredConverters = new ConcurrentHashMap<ConverterKey<?,?>, Converter<?,?>>();
126 
127 	/**
128 	 * A map of registered converters
129 	 */
130 	private ConcurrentHashMap<Class<?>, Object> extendedBinders = new ConcurrentHashMap<Class<?>, Object>();
131 	
132 	/**
133 	 * A reference of classes which have already been introspected for conversion annotations.
134 	 */
135     private final Set<Class<?>> inspectedClasses = new HashSet<Class<?>>();
136 	
137     /**
138      * Creates a new instance, initialised with standard, and registered bindings
139      */
140     public BasicBinder() {
141         this(true);
142     }
143 
144     /**
145      * Creates a new instance
146      * @param includeBuiltInBindings If true, initialise with standard, and registered bindings
147      */
148     public BasicBinder(boolean includeBuiltInBindings) {
149 
150     	initExtendedBinders();
151     	
152         if (includeBuiltInBindings) {
153 
154             initJdkBindings();
155 
156             // Before we load other configuration, load the binding
157             // configuration from
158             // jadira-bindings' jar to ensure no-one overrides our built-in
159             // mappings.
160             initBuiltInBindings();
161 
162             // Init bindings registered from other jars
163             initRegisteredBindings();
164         }
165     }
166 	
167     /******************
168      *                *
169      * Bootstrapping  * 
170      *                *
171      ******************/
172 
173 	/**
174 	 *  Initialise the instance with built in extended binders
175 	 */
176 	private void initExtendedBinders() {
177 		extendedBinders.put(StringBinder.class, this);
178 	}
179     
180     /**
181      * Initialises standard bindings for Java built in types
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      * Initialises bindings registered with the framework included bindings.xml
218      * This includes the built in support for converters for annotation processing and Joda Convert annotations.
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      * Initialises any bindings bundled with other (third-party / user) jars
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      * Registers a set of configurations for the given list of URLs. 
261      * This is typically used to process all the various bindings.xml files discovered in
262      * jars on the classpath. It is given protected scope to allow subclasses to register
263      * additional configurations
264      * @param bindingsConfiguration An enumeration of the URLs to process
265      * @param <X> Internally used type argument
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         	// Filter built in bindings - these are already registered by calling registerConfiguration directly
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      * Register the configuration file (bindings.xml) at the given URL 
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      * Method used to register one or more converter providers. Converters extend the binding framework to provide 
329      * additional mechanisms for discovering and registering bindings (e.g. using Joda Convert).
330      * This method is protected so that subclasses can register additional providers.
331      * @param providers A collection of providers
332      */
333     public void registerConverterProviders(ConverterProvider... providers) {
334 
335         for (ConverterProvider nextProvider : providers) {
336             registerConverterProvider(nextProvider);
337         }
338     }
339     
340     /**
341      * Register a single converter provider
342      * @param provider The provider.
343      */
344     public void registerConverterProvider(ConverterProvider provider) {
345         this.converterProviders.add(provider);
346     }
347     
348     /**
349      * Registers a list of binding configuration entries. A binding configuration entry described in a section of a bindings.xml file 
350      * and describes the use of a particular method for databinding.
351      * @param bindings The entries to register
352      */
353     protected void registerBindingConfigurationEntries(Iterable<BindingConfigurationEntry> bindings) {
354 
355         for (BindingConfigurationEntry nextBinding : bindings) {
356         	try {
357         		registerBindingConfigurationEntry(nextBinding);
358         	} catch (IllegalStateException e) {
359         		// Ignore this - it can happen when introspecting class mappings
360         	}
361         }
362     }
363     
364     /**
365      * Register a particular binding configuration entry.
366      * @param theBinding The entry to be registered
367      * @param <S> The Source type for the binding
368      * @param <T> The Target type for the binding
369      */
370 	protected <S,T> void registerBindingConfigurationEntry(BindingConfigurationEntry theBinding) {
371 		
372         /*
373          * BindingConfigurationEntry has two possible configurations:
374          * 
375          * bindingClass with an optional qualifier (this defaults to DefaultBinding)
376          * 
377          *  OR
378          *  
379          * sourceClass and
380          * targetClass and
381          * optional qualifier (defaults to DefaultBinding)
382          * with at least one of either
383          * toMethod and/or
384          * fromMethod and/or
385          * fromConstructor         
386          * 
387          * Depending on which components are populated the entry is interpreted differently.
388          */
389 		
390 		if (Binding.class.isAssignableFrom(theBinding.getBindingClass())) {
391         	
392         	/*
393          	 * If the binding class is an instance of the Binding interface then register it.
394          	 * When the binding class is an interface, you must define source and target class if they cannot be
395          	 * determined from introspecting the interface.
396          	 * 
397          	 * You can optionally supply a qualifier so that the binding is associated with a qualifier
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          	 * If the binding class is an instance of the FromUnmarshaller interface then register it.
412          	 * When the class is an interface, you must define source and target class if they cannot be
413          	 * determined from introspecting the interface.
414          	 * 
415          	 * You can optionally supply a qualifier so that the binding is associated with a qualifier
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          	 * If the binding class is an instance of the ToMarshaller interface then register it.
430          	 * When the class is an interface, you must define source and target class if they cannot be
431          	 * determined from introspecting the interface.
432          	 * 
433          	 * You can optionally supply a qualifier so that the binding is associated with a qualifier
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          	 * If the binding class is an instance of the Converter interface then register it.
448          	 * When the class is an interface, you must define source and target class if they cannot be
449          	 * determined from introspecting the interface.
450          	 * 
451          	 * You can optionally supply a qualifier so that the binding is associated with a qualifier
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     		 * If only the binding class is supplied, then inspect it for bindings, gathering all bindings identified
466     		 */
467 			registerAnnotatedClasses(theBinding.getBindingClass());
468         } else {
469         	
470     		/*
471     		 * Register the binding using the explicit method details provided 
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 	 * Inspect each of the supplied classes, processing any of the annotated methods found
484 	 * @param classesToInspect The classes to inspect for annotations
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      * Extended Binders   * 
503      *                    *
504      **********************/    
505 	
506     /**
507      * Register a custom, typesafe binder implementation which can be retrieved later
508 	 * @param iface The interface for the provider to be registered.
509      * @param provider The implementation.
510      * @param <I> The class to be registered
511      * @param <T> Implementation of the binder type, I.
512      */
513     protected <I, T extends I> void registerExtendedBinder(Class<I> iface, T provider) {
514         extendedBinders.put(iface, provider);
515     }
516     
517     /**
518      * Retrieves an extended binder
519      * @param cls The implementation.
520      * @param <I> Interface type for the extended binder
521      * @return The found extended binder
522      */
523     @SuppressWarnings("unchecked")
524 	protected <I> I getExtendedBinder(Class<I> cls) {
525         return (I) extendedBinders.get(cls);
526     }
527 	
528     /******************
529      *                *
530      * Registration   * 
531      *                *
532      ******************/
533     
534 	/**
535 	 * Register a Binding with the given source and target class.
536 	 * A binding unifies a marshaller and an unmarshaller and both must be available to resolve a binding.
537 	 * 
538 	 * The source class is considered the owning class of the binding. The source can be marshalled
539 	 * into the target class. Similarly, the target can be unmarshalled to produce an instance of the source type.
540 	 * @param source The source (owning) class
541 	 * @param target The target (foreign) class
542 	 * @param converter The binding to be registered
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 	 * Register an UnMarshaller with the given source and target class.
551 	 * The unmarshaller is used as follows: Instances of the source can be marshalled into the target class.
552 	 * @param source The source (input) class
553 	 * @param target The target (output) class
554 	 * @param converter The FromUnmarshaller to be registered  
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 	 * Register a Marshaller with the given source and target class.
563 	 * The marshaller is used as follows: Instances of the source can be marshalled into the target class.
564 	 * @param source The source (input) class
565 	 * @param target The target (output) class
566 	 * @param converter The ToMarshaller to be registered
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 	 * Register a Converter with the given input and output classes. Instances of the input class can be converted into 
575 	 * instances of the output class
576 	 * @param input The input class
577 	 * @param output The output class
578 	 * @param converter The Converter to be registered   
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 	 * Register a Binding with the given source and target class.
587 	 * A binding unifies a marshaller and an unmarshaller and both must be available to resolve a binding.
588 	 * 
589 	 * The source class is considered the owning class of the binding. The source can be marshalled
590 	 * into the target class. Similarly, the target can be unmarshalled to produce an instance of the source type.
591 	 * @param source The source (owning) class
592 	 * @param target The target (foreign) class
593 	 * @param converter The binding to be registered
594 	 * @param qualifier The qualifier for which the binding must be registered
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 	 * Register a Binding with the given source and target class.
602 	 * A binding unifies a marshaller and an unmarshaller and both must be available to resolve a binding.
603 	 * 
604 	 * The source class is considered the owning class of the binding. The source can be marshalled
605 	 * into the target class. Similarly, the target can be unmarshalled to produce an instance of the source type.
606 	 * @param key Converter Key to use
607 	 * @param converter The binding to be registered
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 	 * Register an UnMarshaller with the given source and target class.
617 	 * The unmarshaller is used as follows: Instances of the source can be marshalled into the target class.
618 	 * @param source The source (input) class
619 	 * @param target The target (output) class
620 	 * @param converter The FromUnmarshaller to be registered
621 	 * @param qualifier The qualifier for which the unmarshaller must be registered  
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 	 * Register an UnMarshaller with the given source and target class.
629 	 * The unmarshaller is used as follows: Instances of the source can be marshalled into the target class.
630 	 * @param key Converter Key to use
631 	 * @param converter The FromUnmarshaller to be registered
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 	 * Register a Marshaller with the given source and target class.
639 	 * The marshaller is used as follows: Instances of the source can be marshalled into the target class.
640 	 * @param source The source (input) class
641 	 * @param target The target (output) class
642 	 * @param converter The ToMarshaller to be registered
643 	 * @param qualifier The qualifier for which the marshaller must be registered 
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 	 * Register a Marshaller with the given source and target class.
651 	 * The marshaller is used as follows: Instances of the source can be marshalled into the target class.
652 	 * @param key Converter Key to use
653 	 * @param converter The ToMarshaller to be registered
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 	 * Register a Converter with the given input and output classes. Instances of the input class can be converted into 
661 	 * instances of the output class
662 	 * @param input The input class
663 	 * @param output The output class
664 	 * @param converter The Converter to be registered
665 	 * @param qualifier The qualifier for which the converter must be registered   
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 	 * Register a Converter with the given input and output classes. Instances of the input class can be converted into 
673 	 * instances of the output class
674 	 * @param key Converter Key to use
675 	 * @param converter The Converter to be registered
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 		// Special cases which arises when processing the identity function
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      * Conversion API * 
721      *                *
722      ******************/
723 	
724 	/**
725 	 * Convert an object to the given target class
726 	 * This method infers the source type for the conversion from the runtime type of object.
727 	 * @param output The target class to convert the object to
728 	 * @param object The object to be converted
729 	 */
730 	public <S, T> T convertTo(Class<T> output, Object object) {
731 		return convertTo(output, object, DefaultBinding.class);
732 	}
733 	
734 	/**
735 	 * Convert an object to the given target class
736 	 * This method infers the source type for the conversion from the runtime type of object.
737 	 * @param output The target class to convert the object to
738 	 * @param object The object to be converted
739 	 * @param qualifier The qualifier for which the binding must be registered
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 	 * Convert an object which is an instance of source class to the given target class
790 	 * @param input The class of the object to be converted
791 	 * @param output The target class to convert the object to
792 	 * @param object The object to be converted
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 	 * Convert an object which is an instance of source class to the given target class
800 	 * @param input The class of the object to be converted
801 	 * @param output The target class to convert the object to
802 	 * @param object The object to be converted
803 	 * @param qualifier Match the converter with the given qualifier
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 	 * Convert an object which is an instance of source class to the given target class
812 	 * @param key The converter key to use
813 	 * @param object The object to be converted
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      * Conversion Resolution * 
835      *                       *
836      *************************/
837 	
838 	/**
839 	 * Resolve a Binding with the given source and target class.
840 	 * A binding unifies a marshaller and an unmarshaller and both must be available to resolve a binding.
841 	 * 
842 	 * The source class is considered the owning class of the binding. The source can be marshalled
843 	 * into the target class. Similarly, the target can be unmarshalled to produce an instance of the source type.
844 	 * @param source The source (owning) class
845 	 * @param target The target (foreign) class
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 	 * Resolve a Marshaller with the given source and target class.
853 	 * The marshaller is used as follows: Instances of the source can be marshalled into the target class.
854 	 * @param source The source (input) class
855 	 * @param target The target (output) class 
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 	 * Resolve a Converter with the given input and output classes. Instances of the input class can be converted into 
863 	 * instances of the output class
864 	 * @param input The input class
865 	 * @param output The output class  
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 	 * Resolve an UnMarshaller with the given source and target class.
873 	 * The unmarshaller is used as follows: Instances of the source can be marshalled into the target class.
874 	 * @param source The source (input) class
875 	 * @param target The target (output) class 
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 	 * Resolve a Binding with the given source and target class.
883 	 * A binding unifies a marshaller and an unmarshaller and both must be available to resolve a binding.
884 	 * 
885 	 * The source class is considered the owning class of the binding. The source can be marshalled
886 	 * into the target class. Similarly, the target can be unmarshalled to produce an instance of the source type.
887 	 * @param source The source (owning) class
888 	 * @param target The target (foreign) class
889 	 * @param qualifier The qualifier for which the binding must be registered
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 	 * Resolve a Binding with the given source and target class.
897 	 * A binding unifies a marshaller and an unmarshaller and both must be available to resolve a binding.
898 	 * 
899 	 * The source class is considered the owning class of the binding. The source can be marshalled
900 	 * into the target class. Similarly, the target can be unmarshalled to produce an instance of the source type.
901 	 * @param key The key to look up
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 	 * Resolve a Marshaller with the given source and target class.
948 	 * The marshaller is used as follows: Instances of the source can be marshalled into the target class.
949 	 * @param source The source (input) class
950 	 * @param target The target (output) class
951 	 * @param qualifier The qualifier for which the marshaller must be registered 
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 	 * Resolve a Marshaller with the given source and target class.
959 	 * The marshaller is used as follows: Instances of the source can be marshalled into the target class.
960 	 * @param key The key to look up
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 	 * Resolve a Converter with the given input and output classes. Instances of the input class can be converted into 
979 	 * instances of the output class
980 	 * @param source The source class
981 	 * @param target The target class
982 	 * @param qualifier The qualifier for which the marshaller must be registered   
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 	 * Resolve a Converter with the given input and output classes. Instances of the input class can be converted into 
990 	 * instances of the output class
991 	 * @param key The key to look up
992 	 */
993 	public <S, T> Converter<S, T> findConverter(ConverterKey<S,T> key) {
994 		
995 		 // We check once before attempting introspection so we avoid that if possible
996 		@SuppressWarnings("unchecked")
997 		Converter<S,T> converter = (Converter<S, T>) registeredConverters.get(key);
998 		if (converter != null) {
999 			return converter;
1000 		}
1001 		
1002 		// Now try introspecting the relevant class
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 	 * Resolve an UnMarshaller with the given source and target class.
1012 	 * The unmarshaller is used as follows: Instances of the source can be marshalled into the target class.
1013 	 * @param source The source (input) class
1014 	 * @param target The target (output) class 
1015 	 * @param qualifier The qualifier for which the unmarshaller must be registered 
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 	 * Resolve an UnMarshaller with the given source and target class.
1023 	 * The unmarshaller is used as follows: Instances of the source can be marshalled into the target class.
1024 	 * @param key The key to look up 
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 	 * Return an iterable collection of ConverterKeys, one for each currently registered conversion
1043 	 */
1044 	public Iterable<ConverterKey<?,?>> getConverterEntries() {
1045 		return registeredConverters.keySet();
1046 	}
1047 
1048     /******************
1049      *                *
1050      * Helper Methods * 
1051      *                *
1052      ******************/
1053 
1054 	/**
1055 	 * This method assists in matching a given implementation class to its (programmer) defined scope.
1056 	 * The method searches for an annotation on the class defined as a binding scope. If one is found 
1057 	 * the implementation is matched to the scope. Note that the implementation scope can be overridden 
1058 	 * using bindings.xml configuration
1059 	 * @param implementation The class to examine
1060 	 * @return The found scope annotation
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 		// Only apply an annotation once
1076 		synchronized(inspectedClasses) {
1077 			if (inspectedClasses.contains(target)) {
1078 				return;
1079 			}
1080 			inspectedClasses.add(target);
1081 		}
1082 
1083 		// NB Don't worry about superclasses - that happens elsewhere
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 		// 2 Pass all the results into registerForMethods
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      * String Binder  * 
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 }