1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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 }