View Javadoc

1   package org.apache.commons.digester3.binder;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static java.lang.String.format;
23  
24  import java.util.Arrays;
25  
26  import org.apache.commons.digester3.ObjectCreateRule;
27  
28  /**
29   * Builder chained when invoking {@link LinkedRuleBuilder#createObject()}.
30   *
31   * @since 3.0
32   */
33  public final class ObjectCreateBuilder
34      extends AbstractBackToLinkedRuleBuilder<ObjectCreateRule>
35  {
36  
37      private final ClassLoader classLoader;
38  
39      private Class<?> type;
40  
41      private String attributeName;
42  
43      /**
44       * The constructor argument types
45       *
46       * @since 3.2
47       */
48      private Class<?>[] constructorArgumentsType;
49  
50      /**
51       * Default constructor arguments.
52       *
53       * @since 3.2
54       */
55      private Object[] defaultConstructorArguments;
56  
57      ObjectCreateBuilder( String keyPattern, String namespaceURI, RulesBinder mainBinder, LinkedRuleBuilder mainBuilder,
58                           ClassLoader classLoader )
59      {
60          super( keyPattern, namespaceURI, mainBinder, mainBuilder );
61          this.classLoader = classLoader;
62      }
63  
64      /**
65       * Construct an object with the specified class name.
66       *
67       * @param className Java class name of the object to be created
68       * @return this builder instance
69       */
70      public ObjectCreateBuilder ofType( String className )
71      {
72          if ( className == null )
73          {
74              reportError( "createObject().ofType( String )", "NULL Java type not allowed" );
75              return this;
76          }
77  
78          try
79          {
80              return ofType( this.classLoader.loadClass( className ) );
81          }
82          catch ( ClassNotFoundException e )
83          {
84              reportError( "createObject().ofType( String )", String.format( "class '%s' cannot be load", className ) );
85              return this;
86          }
87      }
88  
89      /**
90       * Construct an object with the specified class.
91       *
92       * @param <T> any java type
93       * @param type Java class of the object to be created
94       * @return this builder instance
95       */
96      public <T> ObjectCreateBuilder ofType( Class<T> type )
97      {
98          if ( type == null )
99          {
100             reportError( "createObject().ofType( Class<?> )", "NULL Java type not allowed" );
101             return this;
102         }
103 
104         this.type = type;
105 
106         return this;
107     }
108 
109     /**
110      * Allows specify the attribute containing an override class name if it is present.
111      *
112      * @param attributeName The attribute containing an override class name if it is present
113      * @return this builder instance
114      */
115     public ObjectCreateBuilder ofTypeSpecifiedByAttribute( /* @Nullable */String attributeName )
116     {
117         this.attributeName = attributeName;
118         return this;
119     }
120 
121     /**
122      * Allows users to specify constructor argument type names.
123      *
124      * @param paramTypeNames the constructor argument type names
125      * @return this builder instance
126      * @since 3.2
127      */
128     public ObjectCreateBuilder usingConstructor( String...paramTypeNames )
129     {
130         if ( paramTypeNames == null )
131         {
132             reportError( "createObject().usingConstructor( String[] )", "NULL parametersTypes not allowed" );
133             return this;
134         }
135 
136         Class<?>[] paramTypes = new Class<?>[paramTypeNames.length];
137         for ( int i = 0; i < paramTypeNames.length; i++ )
138         {
139             try
140             {
141                 paramTypes[i] = classLoader.loadClass( paramTypeNames[i] );
142             }
143             catch ( ClassNotFoundException e )
144             {
145                 this.reportError( format( "createObject().usingConstructor( %s )",
146                                           Arrays.toString( paramTypeNames ) ),
147                                   format( "class '%s' cannot be loaded", paramTypeNames[i] ) );
148             }
149         }
150 
151         return usingConstructor( paramTypes );
152     }
153 
154     /**
155      * Allows users to specify constructor argument types.
156      *
157      * @param constructorArgumentTypes the constructor argument types
158      * @return this builder instance
159      * @since 3.2
160      */
161     public ObjectCreateBuilder usingConstructor( Class<?>... constructorArgumentTypes )
162     {
163         if ( constructorArgumentTypes == null )
164         {
165             reportError( "createObject().usingConstructor( Class<?>[] )",
166                          "NULL constructorArgumentTypes not allowed" );
167             return this;
168         }
169 
170         this.constructorArgumentsType = constructorArgumentTypes;
171 
172         return this;
173     }
174 
175     /**
176      * Allows users to specify default constructor arguments.
177      *
178      * @param defaultConstructorArguments the default constructor arguments.
179      * @return this builder instance
180      * @since 3.2
181      */
182     public ObjectCreateBuilder usingDefaultConstructorArguments( Object... defaultConstructorArguments )
183     {
184         if ( defaultConstructorArguments == null )
185         {
186             reportError( "createObject().usingDefaultConstructorArguments( Object[] )",
187                          "NULL defaultConstructorArguments not allowed" );
188             return this;
189         }
190 
191         this.defaultConstructorArguments = defaultConstructorArguments;
192 
193         return this;
194 
195     }
196 
197     /**
198      * {@inheritDoc}
199      */
200     @Override
201     protected ObjectCreateRule createRule()
202     {
203         ObjectCreateRule objectCreateRule = new ObjectCreateRule( attributeName, type );
204 
205         if ( constructorArgumentsType != null )
206         {
207             objectCreateRule.setConstructorArgumentTypes( constructorArgumentsType );
208         }
209         if ( defaultConstructorArguments != null )
210         {
211             objectCreateRule.setDefaultConstructorArguments( defaultConstructorArguments );
212         }
213 
214         return objectCreateRule;
215     }
216 
217 }