View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */ 
17  
18  package org.apache.commons.betwixt;
19  
20  import org.apache.commons.betwixt.strategy.AttributeSuppressionStrategy;
21  import org.apache.commons.betwixt.strategy.ClassNormalizer;
22  import org.apache.commons.betwixt.strategy.CollectiveTypeStrategy;
23  import org.apache.commons.betwixt.strategy.DefaultNameMapper;
24  import org.apache.commons.betwixt.strategy.DefaultPluralStemmer;
25  import org.apache.commons.betwixt.strategy.ElementSuppressionStrategy;
26  import org.apache.commons.betwixt.strategy.MappingDerivationStrategy;
27  import org.apache.commons.betwixt.strategy.NameMapper;
28  import org.apache.commons.betwixt.strategy.NamespacePrefixMapper;
29  import org.apache.commons.betwixt.strategy.PluralStemmer;
30  import org.apache.commons.betwixt.strategy.PropertySuppressionStrategy;
31  import org.apache.commons.betwixt.strategy.SimpleTypeMapper;
32  import org.apache.commons.betwixt.strategy.StandardSimpleTypeMapper;
33  import org.apache.commons.betwixt.strategy.TypeBindingStrategy;
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  
37  /***
38   * <p>Stores introspection phase binding configuration.</p>
39   * <p>
40   * There are two phase in Betwixt's processing. 
41   * The first phase is the introspection of the bean. 
42   * Strutural configuration settings effect this phase. 
43   * The second phase comes when Betwixt dynamically uses reflection 
44   * to execute the mapping. 
45   * This object stores configuration settings pertaining to the first phase.
46   * </p>
47   * <p>
48   * These common settings have been collected into one class so that they can  
49   * be more easily shared not only between the objects that execute the introspection
50   * but also (by a user) between different <code>XMLIntrospector</code>s.
51   * </p>
52   * @author <a href='http://jakarta.apache.org/'>Jakarta Commons Team</a>
53   * @version $Revision: 471234 $
54   */
55  public class IntrospectionConfiguration {
56  
57      /*** should attributes or elements be used for primitive types */
58      private boolean attributesForPrimitives = false;
59      
60      /*** should we wrap collections in an extra element? */
61      private boolean wrapCollectionsInElement = true;
62  
63      /*** Should the existing bean info search path for java.reflect.Introspector be used? */
64      private boolean useBeanInfoSearchPath = false;
65      
66      /*** Should existing BeanInfo classes be used at all for java.reflect.Introspector */
67      private boolean ignoreAllBeanInfo = false;
68  
69      // pluggable strategies        
70      /*** The strategy used to detect matching singular and plural properties */
71      private PluralStemmer pluralStemmer;
72      
73      /*** The strategy used to convert bean type names into element names */
74      private NameMapper elementNameMapper;
75  
76      /*** Strategy normalizes the Class of the Object before introspection */
77      private ClassNormalizer classNormalizer = new ClassNormalizer(); 
78      
79      /*** Log for introspection messages */
80      private Log introspectionLog = LogFactory.getLog(XMLIntrospector.class);
81  
82      /***
83       * The strategy used to convert bean type names into attribute names
84       * It will default to the normal nameMapper.
85       */
86      private NameMapper attributeNameMapper;
87  
88      /*** Prefix naming strategy */
89      private NamespacePrefixMapper prefixMapper = new NamespacePrefixMapper();
90      /*** Mapping strategy for simple types */
91      private SimpleTypeMapper simpleTypeMapper = new StandardSimpleTypeMapper();
92      /*** Binding strategy for Java type */
93      private TypeBindingStrategy typeBindingStrategy = TypeBindingStrategy.DEFAULT;
94      /*** Strategy used for determining which types are collective */
95      private CollectiveTypeStrategy collectiveTypeStrategy = CollectiveTypeStrategy.DEFAULT;
96  
97      /*** Strategy for suppressing attributes */
98      private AttributeSuppressionStrategy attributeSuppressionStrategy = AttributeSuppressionStrategy.DEFAULT;   
99      /*** Strategy for suppressing elements */
100     private ElementSuppressionStrategy elementSuppressionStrategy = ElementSuppressionStrategy.DEFAULT;
101 
102     
103     /*** 
104      * Strategy used to determine whether the bind or introspection time type is to be used to  
105      * determine the mapping.
106      */
107     	private MappingDerivationStrategy mappingDerivationStrategy = MappingDerivationStrategy.DEFAULT;
108     
109     	/***
110     	 * Strategy used to determine which properties should be ignored
111     	 */
112     	private PropertySuppressionStrategy propertySuppressionStrategy = PropertySuppressionStrategy.DEFAULT;
113     	
114     /***
115       * Gets the <code>ClassNormalizer</code> strategy.
116       * This is used to determine the Class to be introspected
117       * (the normalized Class). 
118       *
119       * @return the <code>ClassNormalizer</code> used to determine the Class to be introspected
120       * for a given Object.
121       */
122     public ClassNormalizer getClassNormalizer() {
123         return classNormalizer;
124     }
125     
126     /***
127       * Sets the <code>ClassNormalizer</code> strategy.
128       * This is used to determine the Class to be introspected
129       * (the normalized Class). 
130       *
131       * @param classNormalizer the <code>ClassNormalizer</code> to be used to determine 
132       * the Class to be introspected for a given Object.
133       */    
134     public void setClassNormalizer(ClassNormalizer classNormalizer) {
135         this.classNormalizer = classNormalizer;
136     }
137 
138     /*** 
139       * Should attributes (or elements) be used for primitive types.
140       * @return true if primitive types will be mapped to attributes in the introspection
141       */
142     public boolean isAttributesForPrimitives() {
143         return attributesForPrimitives;
144     }
145 
146     /*** 
147       * Set whether attributes (or elements) should be used for primitive types. 
148       * @param attributesForPrimitives pass trus to map primitives to attributes,
149       *        pass false to map primitives to elements
150       */
151     public void setAttributesForPrimitives(boolean attributesForPrimitives) {
152         this.attributesForPrimitives = attributesForPrimitives;
153     }
154     
155     /***
156      * Should collections be wrapped in an extra element?
157      * 
158      * @return whether we should we wrap collections in an extra element? 
159      */
160     public boolean isWrapCollectionsInElement() {
161         return wrapCollectionsInElement;
162     }
163 
164     /*** 
165      * Sets whether we should we wrap collections in an extra element.
166      *
167      * @param wrapCollectionsInElement pass true if collections should be wrapped in a
168      *        parent element
169      */
170     public void setWrapCollectionsInElement(boolean wrapCollectionsInElement) {
171         this.wrapCollectionsInElement = wrapCollectionsInElement;
172     }    
173 
174     /*** 
175      * Get singular and plural matching strategy.
176      *
177      * @return the strategy used to detect matching singular and plural properties 
178      */
179     public PluralStemmer getPluralStemmer() {
180         if ( pluralStemmer == null ) {
181             pluralStemmer = createPluralStemmer();
182         }
183         return pluralStemmer;
184     }
185     
186     /*** 
187      * Sets the strategy used to detect matching singular and plural properties 
188      *
189      * @param pluralStemmer the PluralStemmer used to match singular and plural
190      */
191     public void setPluralStemmer(PluralStemmer pluralStemmer) {
192         this.pluralStemmer = pluralStemmer;
193     }
194     
195     /***
196      * Gets the name mapping strategy used to convert bean names into elements.
197      *
198      * @return the strategy used to convert bean type names into element 
199      * names. If no element mapper is currently defined then a default one is created.
200      */
201     public NameMapper getElementNameMapper() {
202         if ( elementNameMapper == null ) {
203             elementNameMapper = createNameMapper();
204          }
205         return elementNameMapper;
206     }
207      
208     /***
209      * Sets the strategy used to convert bean type names into element names
210      * @param nameMapper the NameMapper to use for the conversion
211      */
212     public void setElementNameMapper(NameMapper nameMapper) {
213         this.elementNameMapper = nameMapper;
214     }
215     
216     /***
217      * Gets the name mapping strategy used to convert bean names into attributes.
218      *
219      * @return the strategy used to convert bean type names into attribute
220      * names. If no attributeNamemapper is known, it will default to the ElementNameMapper
221      */
222     public NameMapper getAttributeNameMapper() {
223         if (attributeNameMapper == null) {
224             attributeNameMapper = createNameMapper();
225         }
226         return attributeNameMapper;
227      }
228 
229 
230     /***
231      * Sets the strategy used to convert bean type names into attribute names
232      * @param nameMapper the NameMapper to use for the convertion
233      */
234     public void setAttributeNameMapper(NameMapper nameMapper) {
235         this.attributeNameMapper = nameMapper;
236     }
237     
238     /***
239      * <p>Should the original <code>java.reflect.Introspector</code> bean info search path be used?</p>
240      * <p>
241      * Default is false.
242      * </p>
243      * 
244      * @return boolean if the beanInfoSearchPath should be used.
245      */
246     public boolean useBeanInfoSearchPath() {
247         return useBeanInfoSearchPath;
248     }
249 
250     /***
251      * Specifies if you want to use the beanInfoSearchPath 
252      * @see java.beans.Introspector for more details
253      * @param useBeanInfoSearchPath 
254      */
255     public void setUseBeanInfoSearchPath(boolean useBeanInfoSearchPath) {
256         this.useBeanInfoSearchPath = useBeanInfoSearchPath;
257     }
258     
259     /***
260      * <p>Should existing BeanInfo classes be ignored by <code>java.reflect.Introspector</code>.</p>
261      * <p>
262      * Default is false.
263      * </p>
264      * 
265      * @return boolean if the BeanInfo classes should be used.
266      */
267     public boolean ignoreAllBeanInfo() {
268         return ignoreAllBeanInfo;
269     }
270     
271     /***
272      * Specifies if you want to ignore existing BeanInfo classes at all for introspection
273      * @see java.beans.Introspector for more details
274      * @param ignoreAllBeanInfo set to true to ignore all BeanInfo classes
275      * @since 0.8
276      */
277     public void setIgnoreAllBeanInfo(boolean ignoreAllBeanInfo) {
278         this.ignoreAllBeanInfo = ignoreAllBeanInfo;
279     }
280     
281     
282     /*** 
283      * A Factory method to lazily create a new strategy 
284      * to detect matching singular and plural properties.
285      *
286      * @return new defualt PluralStemmer implementation
287      */
288     protected PluralStemmer createPluralStemmer() {
289         return new DefaultPluralStemmer();
290     }
291     
292     /*** 
293      * A Factory method to lazily create a strategy 
294      * used to convert bean type names into element names.
295      *
296      * @return new default NameMapper implementation
297      */
298     protected NameMapper createNameMapper() {
299         return new DefaultNameMapper();
300     }
301     
302     /***
303      * Gets the common Log used for introspection.
304      * It is more convenient to use a single Log
305      * that can be easily configured.
306      * @return Log, not null
307      */
308     public Log getIntrospectionLog() {
309         return introspectionLog;
310     }
311 
312     /***
313      * Sets the common Log used by introspection.
314      * It is more convenient to use a single Log
315      * that can be easily configured.
316      * @param log Log, not null
317      */
318     public void setIntrospectionLog(Log log) {
319         introspectionLog = log;
320     }
321 
322     
323     /***
324      * Gets the <code>NamespacePrefixMapper</code> used to convert namespace URIs 
325      * into prefixes.
326      * @return NamespacePrefixMapper, not null
327      */
328     public NamespacePrefixMapper getPrefixMapper() {
329         return prefixMapper;
330     }
331 
332     /***
333      * Sets the <code>NamespacePrefixMapper</code> used to convert namespave URIs
334      * into prefixes.
335      * @param mapper NamespacePrefixMapper, not null
336      */
337     public void setPrefixMapper(NamespacePrefixMapper mapper) {
338         prefixMapper = mapper;
339     }
340     
341     
342     /***
343      * Gets the simple type binding strategy.
344      * @return SimpleTypeMapper, not null
345      */
346     public SimpleTypeMapper getSimpleTypeMapper() {
347         return simpleTypeMapper;
348     }
349 
350     /***
351      * Sets the simple type binding strategy.
352      * @param mapper SimpleTypeMapper, not null
353      */
354     public void setSimpleTypeMapper(SimpleTypeMapper mapper) {
355         simpleTypeMapper = mapper;
356     }
357 
358     /***
359      * Gets the <code>TypeBindingStrategy</code> to be used
360      * to determine the binding for Java types.
361      * @return the <code>TypeBindingStrategy</code> to be used, 
362      * not null
363      */
364     public TypeBindingStrategy getTypeBindingStrategy() {
365         return typeBindingStrategy;
366     }
367     
368     /***
369      * Sets the <code>TypeBindingStrategy</code> to be used
370      * to determine the binding for Java types.
371      * @param typeBindingStrategy the <code>TypeBindingStrategy</code> to be used,
372      * not null
373      */
374     public void setTypeBindingStrategy(TypeBindingStrategy typeBindingStrategy) {
375         this.typeBindingStrategy = typeBindingStrategy;
376     }
377     
378     
379     /***
380      * Gets the <code>MappingDerivationStrategy</code>
381      * used to determine whether the bind or introspection time
382      * type should determine the mapping.
383      * @since 0.7
384      * @return <code>MappingDerivationStrategy</code>, not null
385      */
386     public MappingDerivationStrategy getMappingDerivationStrategy() {
387         return mappingDerivationStrategy;
388     }
389     /***
390      * Sets the <code>MappingDerivationStrategy</code>
391      * used to determine whether the bind or introspection time
392      * type should determine the mapping.
393      * @since 0.7
394      * @param mappingDerivationStrategy <code>MappingDerivationStrategy</code>, not null
395      */
396     public void setMappingDerivationStrategy(
397             MappingDerivationStrategy mappingDerivationStrategy) {
398         this.mappingDerivationStrategy = mappingDerivationStrategy;
399     }
400 
401     /***
402      * Gets the strategy which determines the properties to be ignored.
403      * @since 0.7
404      * @return the <code>PropertySuppressionStrategy</code> to be used for introspection, not null
405      */
406     public PropertySuppressionStrategy getPropertySuppressionStrategy() {
407         return propertySuppressionStrategy;
408     }
409     
410     /***
411      * Sets the strategy which determines the properties to be ignored.
412      * @since 0.7
413      * @param propertySuppressionStrategy the <code>PropertySuppressionStrategy</code> to be used for introspection, not null
414      */
415     public void setPropertySuppressionStrategy(
416             PropertySuppressionStrategy propertySuppressionStrategy) {
417         this.propertySuppressionStrategy = propertySuppressionStrategy;
418     }
419     
420     /***
421      * Gets the strategy used to determine which types are collective.
422      * @return <code>CollectiveTypeStrategy</code>, not null
423      * @since 0.8
424      */
425     public CollectiveTypeStrategy getCollectiveTypeStrategy() {
426         return collectiveTypeStrategy;
427     }
428 
429     /***
430      * Sets the strategy used to determine which types are collective.
431      * @param collectiveTypeStrategy <code>CollectiveTypeStrategy</code>, not null
432      * @since 0.8
433      */
434     public void setCollectiveTypeStrategy(
435             CollectiveTypeStrategy collectiveTypeStrategy) {
436         this.collectiveTypeStrategy = collectiveTypeStrategy;
437     }
438 
439     /*** 
440      * Is this a loop type class?
441      * @since 0.7
442      * @param type is this <code>Class</code> a loop type?
443      * @return true if the type is a loop type, or if type is null 
444      */
445     public boolean isLoopType(Class type) {
446         return getCollectiveTypeStrategy().isCollective(type);
447     }
448 
449 
450     /***
451      * Returns the <code>AttributeSuppressionStrategy</code>. 
452      * This is used to suppress attributes, e.g. for versioning.
453      * 
454      * @since 0.8
455      * @return the strategy
456      */
457     public AttributeSuppressionStrategy getAttributeSuppressionStrategy() {
458         return attributeSuppressionStrategy;
459     }
460 
461     /***
462      * Sets the <code>AttributeSuppressionStrategy</code>. 
463      * This is used to suppress attributes, e.g. for versioning.
464      * 
465      * @since 0.8
466      * @param attributeSuppressionStrategy the strategy 
467      */
468     public void setAttributeSuppressionStrategy(
469             AttributeSuppressionStrategy attributeSuppressionStrategy) {
470         this.attributeSuppressionStrategy = attributeSuppressionStrategy;
471     }
472 
473     /***
474      * Returns the <code>ElementSuppressionStrategy</code>. 
475      * This is used to suppress elements, e.g. for versioning.
476      * 
477      * @since 0.8
478      * @return the strategy
479      */
480     public ElementSuppressionStrategy getElementSuppressionStrategy() {
481         return elementSuppressionStrategy;
482     }
483 
484     /***
485      * Sets the <code>ElementSuppressionStrategy</code>. 
486      * This is used to suppress elements, e.g. for versioning.
487      * 
488      * @since 0.8
489      * @param elementSuppressionStrategy the strategy 
490      */
491     public void setElementSuppressionStrategy(
492             ElementSuppressionStrategy elementSuppressionStrategy) {
493         this.elementSuppressionStrategy = elementSuppressionStrategy;
494     }
495 }