1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  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.apache.commons.betwixt.io.read;
  17. import org.apache.commons.betwixt.ElementDescriptor;
  18. import org.apache.commons.logging.Log;
  19. /**
  20. * Group of factory methods for <code>ChainedBeanCreator</code>'s.
  21. * The standard implementations used by Betwixt are present here.
  22. *
  23. * @author Robert Burrell Donkin
  24. * @since 0.5
  25. */
  26. public class ChainedBeanCreatorFactory {
  27. /** Singleton instance for creating derived beans */
  28. private static final ChainedBeanCreator derivedBeanCreator
  29. = new ChainedBeanCreator() {
  30. public Object create(
  31. ElementMapping elementMapping,
  32. ReadContext context,
  33. BeanCreationChain chain) {
  34. String className
  35. = elementMapping
  36. .getAttributes().getValue( context.getClassNameAttribute() );
  37. if ( className != null ) {
  38. try {
  39. // load the class we should instantiate
  40. ClassLoader classLoader = context.getClassLoader();
  41. if ( classLoader == null ) {
  42. context.getLog().warn(
  43. "Could not create derived instance: read context classloader not set." );
  44. }
  45. Class clazz = classLoader.loadClass( className );
  46. return clazz.newInstance();
  47. } catch (Exception e) {
  48. // it would be nice to have a pluggable strategy for exception management
  49. context.getLog().warn( "Could not create instance of type: " + className );
  50. context.getLog().debug( "Create new instance failed: ", e );
  51. return null;
  52. }
  53. } else {
  54. // pass responsibility down the chain
  55. return chain.create( elementMapping, context );
  56. }
  57. }
  58. };
  59. /**
  60. * Creates a <code>ChainedBeanCreator</code> that constructs derived beans.
  61. * These have their classname set by an xml attribute.
  62. * @return <code>ChainedBeanCreator</code> that implements Derived beans logic, not null
  63. */
  64. public static final ChainedBeanCreator createDerivedBeanCreator() {
  65. return derivedBeanCreator;
  66. }
  67. /** Singleton instance that creates beans based on type */
  68. private static final ChainedBeanCreator elementTypeBeanCreator
  69. = new ChainedBeanCreator() {
  70. public Object create(
  71. ElementMapping element,
  72. ReadContext context,
  73. BeanCreationChain chain) {
  74. Log log = context.getLog();
  75. Class theClass = null;
  76. ElementDescriptor descriptor = element.getDescriptor();
  77. if ( descriptor != null ) {
  78. // created based on implementation class
  79. theClass = descriptor.getImplementationClass();
  80. }
  81. if ( theClass == null ) {
  82. // create based on type
  83. theClass = element.getType();
  84. }
  85. if ( log.isTraceEnabled() ) {
  86. log.trace(
  87. "Creating instance of class " + theClass.getName()
  88. + " for element " + element.getName());
  89. }
  90. try {
  91. return theClass.newInstance();
  92. } catch (Exception e) {
  93. // it would be nice to have a pluggable strategy for exception management
  94. context.getLog().warn(
  95. "Could not create instance of type: " + theClass.getName() );
  96. context.getLog().debug( "Create new instance failed: ", e );
  97. return null;
  98. }
  99. }
  100. };
  101. /**
  102. * Creates a <code>ChainedBeanCreator</code> that constructs beans based on element type.
  103. * @return <code>ChainedBeanCreator</code> that implements load by type beans logic, not null
  104. */
  105. public static final ChainedBeanCreator createElementTypeBeanCreator() {
  106. return elementTypeBeanCreator;
  107. }
  108. /** Singleton instance that creates beans based on IDREF */
  109. private static final ChainedBeanCreator idRefBeanCreator
  110. = new ChainedBeanCreator() {
  111. public Object create(
  112. ElementMapping elementMapping,
  113. ReadContext context,
  114. BeanCreationChain chain) {
  115. if ( context.getMapIDs() ) {
  116. String idref = elementMapping.getAttributes().getValue( "idref" );
  117. if ( idref != null ) {
  118. // XXX need to check up about ordering
  119. // XXX this is a very simple system that assumes that
  120. // XXX id occurs before idrefs
  121. // XXX would need some thought about how to implement a fuller system
  122. context.getLog().trace( "Found IDREF" );
  123. Object bean = context.getBean( idref );
  124. if ( bean != null ) {
  125. if ( context.getLog().isTraceEnabled() ) {
  126. context.getLog().trace( "Matched bean " + bean );
  127. }
  128. return bean;
  129. }
  130. context.getLog().trace( "No match found" );
  131. }
  132. }
  133. return chain.create( elementMapping, context );
  134. }
  135. };
  136. /**
  137. * Creates a <code>ChainedBeanCreator</code> that finds existing beans based on their IDREF.
  138. * @return <code>ChainedBeanCreator</code> that implements IDREF beans logic, not null
  139. */
  140. public static final ChainedBeanCreator createIDREFBeanCreator() {
  141. return idRefBeanCreator;
  142. }
  143. }