001/* 002 * Copyright 2010, 2011 Chris Pheby 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.jadira.bindings.core.binder; 017 018import java.io.File; 019import java.io.IOException; 020import java.lang.annotation.Annotation; 021import java.lang.reflect.Constructor; 022import java.lang.reflect.Method; 023import java.math.BigDecimal; 024import java.math.BigInteger; 025import java.net.InetAddress; 026import java.net.URI; 027import java.net.URL; 028import java.util.ArrayList; 029import java.util.Calendar; 030import java.util.Currency; 031import java.util.Date; 032import java.util.Enumeration; 033import java.util.HashMap; 034import java.util.HashSet; 035import java.util.List; 036import java.util.Locale; 037import java.util.Map; 038import java.util.Set; 039import java.util.TimeZone; 040import java.util.UUID; 041import java.util.concurrent.ConcurrentHashMap; 042import java.util.concurrent.atomic.AtomicBoolean; 043import java.util.concurrent.atomic.AtomicInteger; 044import java.util.concurrent.atomic.AtomicLong; 045 046import javax.enterprise.inject.Typed; 047 048import org.jadira.bindings.core.annotation.BindingScope; 049import org.jadira.bindings.core.annotation.DefaultBinding; 050import org.jadira.bindings.core.api.Binding; 051import org.jadira.bindings.core.api.Converter; 052import org.jadira.bindings.core.api.FromUnmarshaller; 053import org.jadira.bindings.core.api.ToMarshaller; 054import org.jadira.bindings.core.general.binding.CompositeBinding; 055import org.jadira.bindings.core.general.binding.InverseCompositeBinding; 056import org.jadira.bindings.core.general.converter.FromUnmarshallerConverter; 057import org.jadira.bindings.core.general.converter.ToMarshallerConverter; 058import org.jadira.bindings.core.general.marshaller.ConverterToMarshaller; 059import org.jadira.bindings.core.general.marshaller.MethodToMarshaller; 060import org.jadira.bindings.core.general.unmarshaller.ConstructorFromUnmarshaller; 061import org.jadira.bindings.core.general.unmarshaller.ConverterFromUnmarshaller; 062import org.jadira.bindings.core.general.unmarshaller.MethodFromUnmarshaller; 063import org.jadira.bindings.core.jdk.AtomicBooleanStringBinding; 064import org.jadira.bindings.core.jdk.AtomicIntegerStringBinding; 065import org.jadira.bindings.core.jdk.AtomicLongStringBinding; 066import org.jadira.bindings.core.jdk.BigDecimalStringBinding; 067import org.jadira.bindings.core.jdk.BigIntegerStringBinding; 068import org.jadira.bindings.core.jdk.BooleanStringBinding; 069import org.jadira.bindings.core.jdk.ByteStringBinding; 070import org.jadira.bindings.core.jdk.CalendarStringBinding; 071import org.jadira.bindings.core.jdk.CharSequenceStringBinding; 072import org.jadira.bindings.core.jdk.CharacterStringBinding; 073import org.jadira.bindings.core.jdk.ClassStringBinding; 074import org.jadira.bindings.core.jdk.CurrencyStringBinding; 075import org.jadira.bindings.core.jdk.DateStringBinding; 076import org.jadira.bindings.core.jdk.DoubleStringBinding; 077import org.jadira.bindings.core.jdk.FileStringBinding; 078import org.jadira.bindings.core.jdk.FloatStringBinding; 079import org.jadira.bindings.core.jdk.InetAddressStringBinding; 080import org.jadira.bindings.core.jdk.IntegerStringBinding; 081import org.jadira.bindings.core.jdk.LocaleStringBinding; 082import org.jadira.bindings.core.jdk.LongStringBinding; 083import org.jadira.bindings.core.jdk.PackageStringBinding; 084import org.jadira.bindings.core.jdk.ShortStringBinding; 085import org.jadira.bindings.core.jdk.StringBufferStringBinding; 086import org.jadira.bindings.core.jdk.StringBuilderStringBinding; 087import org.jadira.bindings.core.jdk.StringStringBinding; 088import org.jadira.bindings.core.jdk.TimeZoneStringBinding; 089import org.jadira.bindings.core.jdk.URIStringBinding; 090import org.jadira.bindings.core.jdk.URLStringBinding; 091import org.jadira.bindings.core.jdk.UUIDStringBinding; 092import org.jadira.bindings.core.loader.BindingConfiguration; 093import org.jadira.bindings.core.loader.BindingConfigurationEntry; 094import org.jadira.bindings.core.loader.BindingXmlLoader; 095import org.jadira.bindings.core.loader.Extension; 096import org.jadira.bindings.core.loader.Provider; 097import org.jadira.bindings.core.spi.ConverterProvider; 098import org.jadira.bindings.core.utils.lang.IterableEnumeration; 099import 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({}) 114public 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}