Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
ElementDescriptor |
|
| 1.8205128205128205;1.821 |
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; |
|
17 | ||
18 | import java.util.ArrayList; |
|
19 | import java.util.List; |
|
20 | ||
21 | import org.apache.commons.betwixt.expression.Expression; |
|
22 | ||
23 | /** <p><code>ElementDescriptor</code> describes the XML elements |
|
24 | * to be created for a bean instance.</p> |
|
25 | * |
|
26 | * <p> It contains <code>AttributeDescriptor</code>'s for all it's attributes |
|
27 | * and <code>ElementDescriptor</code>'s for it's child elements. |
|
28 | * |
|
29 | * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> |
|
30 | * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a> |
|
31 | */ |
|
32 | public class ElementDescriptor extends NodeDescriptor { |
|
33 | ||
34 | /** |
|
35 | * Descriptors for attributes this element contains. |
|
36 | * <strong>Note:</strong> Constructed lazily on demand from a List. |
|
37 | * {@link #getAttributeDescriptor()} should be called rather than accessing this |
|
38 | * field directly. |
|
39 | */ |
|
40 | private AttributeDescriptor[] attributeDescriptors; |
|
41 | /** |
|
42 | * Descriptors for child elements. |
|
43 | * <strong>Note:</strong> Constructed lazily on demand from a List. |
|
44 | * {@link #getElementDescriptor()} should be called rather than accessing this |
|
45 | * field directly. |
|
46 | */ |
|
47 | private ElementDescriptor[] elementDescriptors; |
|
48 | ||
49 | /** |
|
50 | * Descriptors for child content. |
|
51 | * <strong>Note:</strong> Constructed lazily on demand from a List. |
|
52 | * {@link #getContentDescriptor()} should be called rather than accessing this |
|
53 | * field directly. |
|
54 | */ |
|
55 | private Descriptor[] contentDescriptors; |
|
56 | ||
57 | /** |
|
58 | * The List used on construction. It will be GC'd |
|
59 | * after initilization and the array is lazily constructed |
|
60 | */ |
|
61 | private List attributeList; |
|
62 | ||
63 | /** |
|
64 | * The List used on construction. It will be GC'd |
|
65 | * after initilization and the array is lazily constructed |
|
66 | */ |
|
67 | private List elementList; |
|
68 | ||
69 | /** |
|
70 | * The list used o construct array. It will be GC'd after |
|
71 | * initialization when the array is lazily constructed. |
|
72 | */ |
|
73 | private List contentList; |
|
74 | ||
75 | /** the expression used to evaluate the new context of this node |
|
76 | * or null if the same context is to be used */ |
|
77 | private Expression contextExpression; |
|
78 | ||
79 | /** Whether this element refers to a primitive type (or property of a parent object) */ |
|
80 | private boolean primitiveType; |
|
81 | /** Is this a collective type? */ |
|
82 | private boolean isCollectiveType; |
|
83 | ||
84 | /** |
|
85 | * Is this element hollow? |
|
86 | * In other words, is this descriptor a place holder indicating the name |
|
87 | * and update for a root ElementDescriptor for this type obtained by introspection |
|
88 | * TODO: this would probably be better modeled as a separate subclass |
|
89 | */ |
|
90 | 27834 | private boolean isHollow = false; |
91 | ||
92 | /** |
|
93 | * Whether this collection element can be used |
|
94 | * as a collection element. Defaults to true |
|
95 | */ |
|
96 | 27834 | private boolean wrapCollectionsInElement = true; |
97 | ||
98 | /** specifies a separate implementation class that should be instantiated |
|
99 | * when reading beans |
|
100 | * or null if there is no separate implementation */ |
|
101 | 27834 | private Class implementationClass = null; |
102 | ||
103 | /** |
|
104 | * Should the bind time type determine the mapping? |
|
105 | * (As opposed to the introspection time type.) |
|
106 | * Note that this attribute is write once, read many (WORM). |
|
107 | */ |
|
108 | 27834 | private Boolean useBindTimeTypeForMapping = null; |
109 | ||
110 | /** |
|
111 | * Constructs an <code>ElementDescriptor</code> that refers to a primitive type. |
|
112 | */ |
|
113 | 26794 | public ElementDescriptor() { |
114 | 26794 | } |
115 | ||
116 | /** |
|
117 | * Base constructor. |
|
118 | * @param primitiveType if true, this element refers to a primitive type |
|
119 | * @deprecated 0.6 PrimitiveType property has been removed |
|
120 | */ |
|
121 | 0 | public ElementDescriptor(boolean primitiveType) { |
122 | 0 | this.primitiveType = primitiveType; |
123 | 0 | } |
124 | ||
125 | /** |
|
126 | * Creates a ElementDescriptor with no namespace URI or prefix. |
|
127 | * |
|
128 | * @param localName the (xml) local name of this node. |
|
129 | * This will be used to set both qualified and local name for this name. |
|
130 | */ |
|
131 | public ElementDescriptor(String localName) { |
|
132 | 949 | super( localName ); |
133 | 949 | } |
134 | ||
135 | ||
136 | ||
137 | /** |
|
138 | * Creates a <code>ElementDescriptor</code> with namespace URI and qualified name |
|
139 | * @param localName the (xml) local name of this node |
|
140 | * @param qualifiedName the (xml) qualified name of this node |
|
141 | * @param uri the (xml) namespace prefix of this node |
|
142 | */ |
|
143 | public ElementDescriptor(String localName, String qualifiedName, String uri) { |
|
144 | 91 | super(localName, qualifiedName, uri); |
145 | 91 | } |
146 | ||
147 | /** |
|
148 | * Returns true if this element has child <code>ElementDescriptors</code> |
|
149 | * @return true if this element has child elements |
|
150 | * @see #getElementDescriptors |
|
151 | */ |
|
152 | public boolean hasChildren() { |
|
153 | 11882 | return getElementDescriptors().length > 0; |
154 | } |
|
155 | ||
156 | /** |
|
157 | * Returns true if this element has <code>AttributeDescriptors</code> |
|
158 | * @return true if this element has attributes |
|
159 | * @see #getAttributeDescriptors |
|
160 | */ |
|
161 | public boolean hasAttributes() { |
|
162 | 23679 | return getAttributeDescriptors().length > 0; |
163 | } |
|
164 | ||
165 | /** |
|
166 | * Returns true if this element has child content. |
|
167 | * @return true if this element has either child mixed content or child elements |
|
168 | * @see #getContentDescriptors |
|
169 | * @since 0.5 |
|
170 | */ |
|
171 | public boolean hasContent() { |
|
172 | 104 | return getContentDescriptors().length > 0; |
173 | } |
|
174 | ||
175 | /** |
|
176 | * <p>Is this a simple element?</p> |
|
177 | * <p> |
|
178 | * A simple element is one without child elements or attributes. |
|
179 | * This corresponds to the simple type concept used in XML Schema. |
|
180 | * TODO: need to consider whether it's sufficient to calculate |
|
181 | * which are simple types (and so don't get IDs assigned etc). |
|
182 | * </p> |
|
183 | * @return true if it is a <code>SimpleType</code> element |
|
184 | */ |
|
185 | public boolean isSimple() { |
|
186 | 14755 | return !(hasAttributes()) && !(hasChildren()); |
187 | } |
|
188 | ||
189 | ||
190 | /** |
|
191 | * Sets whether <code>Collection</code> bean properties should wrap items in a parent element. |
|
192 | * In other words, should the mapping for bean properties which are <code>Collection</code>s |
|
193 | * enclosed the item elements within a parent element. |
|
194 | * Normally only used when this describes a collection bean property. |
|
195 | * |
|
196 | * @param wrapCollectionsInElement true if the elements for the items in the collection |
|
197 | * should be contained in a parent element |
|
198 | * @deprecated 0.6 moved to a declarative style of descriptors where the alrogithmic should |
|
199 | * be done during introspection |
|
200 | */ |
|
201 | public void setWrapCollectionsInElement(boolean wrapCollectionsInElement) { |
|
202 | 0 | this.wrapCollectionsInElement = wrapCollectionsInElement; |
203 | 0 | } |
204 | ||
205 | /** |
|
206 | * Returns true if collective bean properties should wrap the items in a parent element. |
|
207 | * In other words, should the mapping for bean properties which are <code>Collection</code>s |
|
208 | * enclosed the item elements within a parent element. |
|
209 | * Normally only used when this describes a collection bean property. |
|
210 | * |
|
211 | * @return true if the elements for the items in the collection should be contained |
|
212 | * in a parent element |
|
213 | * @deprecated 0.6 moved to a declarative style of descriptors where the alrogithmic should |
|
214 | * be done during introspection |
|
215 | */ |
|
216 | public boolean isWrapCollectionsInElement() { |
|
217 | 39 | return this.wrapCollectionsInElement; |
218 | } |
|
219 | ||
220 | /** |
|
221 | * Adds an attribute to the element this <code>ElementDescriptor</code> describes |
|
222 | * @param descriptor the <code>AttributeDescriptor</code> that will be added to the |
|
223 | * attributes associated with element this <code>ElementDescriptor</code> describes |
|
224 | */ |
|
225 | public void addAttributeDescriptor(AttributeDescriptor descriptor) { |
|
226 | 2717 | if ( attributeList == null ) { |
227 | 1599 | attributeList = new ArrayList(); |
228 | } |
|
229 | 2717 | getAttributeList().add( descriptor ); |
230 | 2717 | attributeDescriptors = null; |
231 | 2717 | } |
232 | ||
233 | ||
234 | /** |
|
235 | * Returns the attribute descriptors for this element |
|
236 | * |
|
237 | * @return descriptors for the attributes of the element that this |
|
238 | * <code>ElementDescriptor</code> describes |
|
239 | */ |
|
240 | public AttributeDescriptor[] getAttributeDescriptors() { |
|
241 | 54364 | if ( attributeDescriptors == null ) { |
242 | 15851 | if ( attributeList == null ) { |
243 | 14460 | attributeDescriptors = new AttributeDescriptor[0]; |
244 | } else { |
|
245 | 1391 | attributeDescriptors = new AttributeDescriptor[ attributeList.size() ]; |
246 | 1391 | attributeList.toArray( attributeDescriptors ); |
247 | ||
248 | // allow GC of List when initialized |
|
249 | 1391 | attributeList = null; |
250 | } |
|
251 | } |
|
252 | 54364 | return attributeDescriptors; |
253 | } |
|
254 | ||
255 | /** |
|
256 | * Sets the <code>AttributesDescriptors</code> for this element. |
|
257 | * This sets descriptors for the attributes of the element describe by the |
|
258 | * <code>ElementDescriptor</code>. |
|
259 | * |
|
260 | * @param attributeDescriptors the <code>AttributeDescriptor</code> describe the attributes |
|
261 | * of the element described by this <code>ElementDescriptor</code> |
|
262 | */ |
|
263 | public void setAttributeDescriptors(AttributeDescriptor[] attributeDescriptors) { |
|
264 | 1365 | this.attributeDescriptors = attributeDescriptors; |
265 | 1365 | this.attributeList = null; |
266 | 1365 | } |
267 | ||
268 | /** |
|
269 | * Adds a descriptor for a child element. |
|
270 | * |
|
271 | * @param descriptor the <code>ElementDescriptor</code> describing the child element to add |
|
272 | */ |
|
273 | public void addElementDescriptor(ElementDescriptor descriptor) { |
|
274 | 8645 | if ( elementList == null ) { |
275 | 3666 | elementList = new ArrayList(); |
276 | } |
|
277 | 8645 | getElementList().add( descriptor ); |
278 | 8645 | elementDescriptors = null; |
279 | 8645 | addContentDescriptor( descriptor ); |
280 | 8645 | } |
281 | ||
282 | /** |
|
283 | * Returns descriptors for the child elements of the element this describes. |
|
284 | * @return the <code>ElementDescriptor</code> describing the child elements |
|
285 | * of the element that this <code>ElementDescriptor</code> describes |
|
286 | */ |
|
287 | public ElementDescriptor[] getElementDescriptors() { |
|
288 | 66290 | if ( elementDescriptors == null ) { |
289 | 17521 | if ( elementList == null ) { |
290 | 14765 | elementDescriptors = new ElementDescriptor[0]; |
291 | } else { |
|
292 | 2756 | elementDescriptors = new ElementDescriptor[ elementList.size() ]; |
293 | 2756 | elementList.toArray( elementDescriptors ); |
294 | ||
295 | // allow GC of List when initialized |
|
296 | 2756 | elementList = null; |
297 | } |
|
298 | } |
|
299 | 66290 | return elementDescriptors; |
300 | } |
|
301 | ||
302 | /** |
|
303 | * Gets a child ElementDescriptor matching the given name if one exists. |
|
304 | * Note that (so long as there are no better matches), a null name |
|
305 | * acts as a wildcard. In other words, an |
|
306 | * <code>ElementDescriptor</code> the first descriptor |
|
307 | * with a null name will match any name |
|
308 | * passed in, unless some other matches the name exactly. |
|
309 | * |
|
310 | * @param name the localname to be matched, not null |
|
311 | * @return the child ElementDescriptor with the given name if one exists, |
|
312 | * otherwise null |
|
313 | */ |
|
314 | public ElementDescriptor getElementDescriptor(String name) { |
|
315 | ||
316 | 8085 | ElementDescriptor elementDescriptor = null; |
317 | 8085 | ElementDescriptor descriptorWithNullName = null; |
318 | 8085 | ElementDescriptor firstPolymorphic = null; |
319 | 8085 | ElementDescriptor[] elementDescriptors = getElementDescriptors(); |
320 | 17444 | for (int i=0, size=elementDescriptors.length; i<size; i++) { |
321 | 16418 | if (firstPolymorphic == null && elementDescriptors[i].isPolymorphic()) { |
322 | 545 | firstPolymorphic = elementDescriptors[i]; |
323 | } |
|
324 | 16418 | String elementName = elementDescriptors[i].getQualifiedName(); |
325 | 16418 | if (name.equals(elementName)) { |
326 | 7059 | elementDescriptor = elementDescriptors[i]; |
327 | 7059 | break; |
328 | } |
|
329 | 9359 | if (descriptorWithNullName == null && elementName == null) { |
330 | 545 | descriptorWithNullName = elementDescriptors[i]; |
331 | } |
|
332 | } |
|
333 | 8085 | if (elementDescriptor == null) { |
334 | 1026 | elementDescriptor = firstPolymorphic; |
335 | } |
|
336 | 8085 | if (elementDescriptor == null) { |
337 | 494 | elementDescriptor = descriptorWithNullName; |
338 | } |
|
339 | 8085 | return elementDescriptor; |
340 | } |
|
341 | ||
342 | ||
343 | /** |
|
344 | * Sets the descriptors for the child element of the element this describes. |
|
345 | * Also sets the child content descriptors for this element |
|
346 | * |
|
347 | * @param elementDescriptors the <code>ElementDescriptor</code>s of the element |
|
348 | * that this describes |
|
349 | */ |
|
350 | public void setElementDescriptors(ElementDescriptor[] elementDescriptors) { |
|
351 | 5530 | this.elementDescriptors = elementDescriptors; |
352 | 5530 | this.elementList = null; |
353 | 5530 | setContentDescriptors( elementDescriptors ); |
354 | 5530 | } |
355 | ||
356 | /** |
|
357 | * Adds a descriptor for child content. |
|
358 | * |
|
359 | * @param descriptor the <code>Descriptor</code> describing the child content to add |
|
360 | * @since 0.5 |
|
361 | */ |
|
362 | public void addContentDescriptor(Descriptor descriptor) { |
|
363 | 8736 | if ( contentList == null ) { |
364 | 3731 | contentList = new ArrayList(); |
365 | } |
|
366 | 8736 | getContentList().add( descriptor ); |
367 | 8736 | contentDescriptors = null; |
368 | 8736 | } |
369 | ||
370 | /** |
|
371 | * Returns descriptors for the child content of the element this describes. |
|
372 | * @return the <code>Descriptor</code> describing the child elements |
|
373 | * of the element that this <code>ElementDescriptor</code> describes |
|
374 | * @since 0.5 |
|
375 | */ |
|
376 | public Descriptor[] getContentDescriptors() { |
|
377 | 20953 | if ( contentDescriptors == null ) { |
378 | 8825 | if ( contentList == null ) { |
379 | 6472 | contentDescriptors = new Descriptor[0]; |
380 | } else { |
|
381 | 2353 | contentDescriptors = new Descriptor[ contentList.size() ]; |
382 | 2353 | contentList.toArray( contentDescriptors ); |
383 | ||
384 | // allow GC of List when initialized |
|
385 | 2353 | contentList = null; |
386 | } |
|
387 | } |
|
388 | 20953 | return contentDescriptors; |
389 | } |
|
390 | ||
391 | /** |
|
392 | * <p>Gets the primary descriptor for body text of this element. |
|
393 | * Betwixt collects all body text for any element together. |
|
394 | * This makes it rounds tripping difficult for beans that write more than one |
|
395 | * mixed content property. |
|
396 | * </p><p> |
|
397 | * The algorithm used in the default implementation is that the first TextDescriptor |
|
398 | * found amongst the descriptors is returned. |
|
399 | * |
|
400 | * @return the primary descriptor or null if this element has no mixed body content |
|
401 | * @since 0.5 |
|
402 | */ |
|
403 | public TextDescriptor getPrimaryBodyTextDescriptor() { |
|
404 | // todo: this probably isn't the most efficent algorithm |
|
405 | // but should avoid premature optimization |
|
406 | 3450 | Descriptor[] descriptors = getContentDescriptors(); |
407 | 8305 | for (int i=0, size=descriptors.length; i<size; i++) { |
408 | 4881 | if (descriptors[i] instanceof TextDescriptor) { |
409 | 26 | return (TextDescriptor) descriptors[i]; |
410 | } |
|
411 | } |
|
412 | // if we haven't found anything, return null. |
|
413 | 3424 | return null; |
414 | } |
|
415 | ||
416 | /** |
|
417 | * Sets the descriptors for the child content of the element this describes. |
|
418 | * @param contentDescriptors the <code>Descriptor</code>s of the element |
|
419 | * that this describes |
|
420 | * @since 0.5 |
|
421 | */ |
|
422 | public void setContentDescriptors(Descriptor[] contentDescriptors) { |
|
423 | 5530 | this.contentDescriptors = contentDescriptors; |
424 | 5530 | this.contentList = null; |
425 | 5530 | } |
426 | ||
427 | /** |
|
428 | * Returns the expression used to evaluate the new context of this element. |
|
429 | * @return the expression used to evaluate the new context of this element |
|
430 | */ |
|
431 | public Expression getContextExpression() { |
|
432 | 13857 | return contextExpression; |
433 | } |
|
434 | ||
435 | /** |
|
436 | * Sets the expression used to evaluate the new context of this element |
|
437 | * @param contextExpression the expression used to evaluate the new context of this element |
|
438 | */ |
|
439 | public void setContextExpression(Expression contextExpression) { |
|
440 | 6388 | this.contextExpression = contextExpression; |
441 | 6388 | } |
442 | ||
443 | /** |
|
444 | * Returns true if this element refers to a primitive type property |
|
445 | * @return whether this element refers to a primitive type (or property of a parent object) |
|
446 | * @deprecated 0.6 moved to a declarative style of descriptors where the alrogithmic should |
|
447 | * be done during introspection |
|
448 | */ |
|
449 | public boolean isPrimitiveType() { |
|
450 | 0 | return primitiveType; |
451 | } |
|
452 | ||
453 | /** |
|
454 | * Sets whether this element refers to a primitive type (or property of a parent object) |
|
455 | * @param primitiveType true if this element refers to a primitive type |
|
456 | * @deprecated 0.6 moved to a declarative style of descriptors where the alrogithmic should |
|
457 | * be done during introspection |
|
458 | */ |
|
459 | public void setPrimitiveType(boolean primitiveType) { |
|
460 | 0 | this.primitiveType = primitiveType; |
461 | 0 | } |
462 | ||
463 | // Implementation methods |
|
464 | //------------------------------------------------------------------------- |
|
465 | ||
466 | /** |
|
467 | * Lazily creates the mutable List. |
|
468 | * This nullifies the attributeDescriptors array so that |
|
469 | * as items are added to the list the Array is ignored until it is |
|
470 | * explicitly asked for. |
|
471 | * |
|
472 | * @return list of <code>AttributeDescriptors</code>'s describing the attributes |
|
473 | * of the element that this <code>ElementDescriptor</code> describes |
|
474 | */ |
|
475 | protected List getAttributeList() { |
|
476 | 2717 | if ( attributeList == null ) { |
477 | 0 | if ( attributeDescriptors != null ) { |
478 | 0 | int size = attributeDescriptors.length; |
479 | 0 | attributeList = new ArrayList( size ); |
480 | 0 | for ( int i = 0; i < size; i++ ) { |
481 | 0 | attributeList.add( attributeDescriptors[i] ); |
482 | } |
|
483 | // force lazy recreation later |
|
484 | 0 | attributeDescriptors = null; |
485 | } else { |
|
486 | 0 | attributeList = new ArrayList(); |
487 | } |
|
488 | } |
|
489 | 2717 | return attributeList; |
490 | } |
|
491 | ||
492 | /** |
|
493 | * Lazily creates the mutable List of child elements. |
|
494 | * This nullifies the elementDescriptors array so that |
|
495 | * as items are added to the list the Array is ignored until it is |
|
496 | * explicitly asked for. |
|
497 | * |
|
498 | * @return list of <code>ElementDescriptor</code>'s describe the child elements of |
|
499 | * the element that this <code>ElementDescriptor</code> describes |
|
500 | */ |
|
501 | protected List getElementList() { |
|
502 | 8645 | if ( elementList == null ) { |
503 | 0 | if ( elementDescriptors != null ) { |
504 | 0 | int size = elementDescriptors.length; |
505 | 0 | elementList = new ArrayList( size ); |
506 | 0 | for ( int i = 0; i < size; i++ ) { |
507 | 0 | elementList.add( elementDescriptors[i] ); |
508 | } |
|
509 | // force lazy recreation later |
|
510 | 0 | elementDescriptors = null; |
511 | } else { |
|
512 | 0 | elementList = new ArrayList(); |
513 | } |
|
514 | } |
|
515 | 8645 | return elementList; |
516 | } |
|
517 | ||
518 | /** |
|
519 | * Lazily creates the mutable List of child content descriptors. |
|
520 | * This nullifies the contentDescriptors array so that |
|
521 | * as items are added to the list the Array is ignored until it is |
|
522 | * explicitly asked for. |
|
523 | * |
|
524 | * @return list of <code>Descriptor</code>'s describe the child content of |
|
525 | * the element that this <code>Descriptor</code> describes |
|
526 | * @since 0.5 |
|
527 | */ |
|
528 | protected List getContentList() { |
|
529 | 8736 | if ( contentList == null ) { |
530 | 0 | if ( contentDescriptors != null ) { |
531 | 0 | int size = contentDescriptors.length; |
532 | 0 | contentList = new ArrayList( size ); |
533 | 0 | for ( int i = 0; i < size; i++ ) { |
534 | 0 | contentList.add( contentDescriptors[i] ); |
535 | } |
|
536 | // force lazy recreation later |
|
537 | 0 | contentDescriptors = null; |
538 | } else { |
|
539 | 0 | contentList = new ArrayList(); |
540 | } |
|
541 | } |
|
542 | 8736 | return contentList; |
543 | } |
|
544 | ||
545 | /** |
|
546 | * Gets the class which should be used for instantiation. |
|
547 | * @return the class which should be used for instantiation of beans |
|
548 | * mapped from this element, null if the standard class should be used |
|
549 | */ |
|
550 | public Class getImplementationClass() { |
|
551 | 3235 | return implementationClass; |
552 | } |
|
553 | ||
554 | /** |
|
555 | * Sets the class which should be used for instantiation. |
|
556 | * @param implementationClass the class which should be used for instantiation |
|
557 | * or null to use the mapped type |
|
558 | * @since 0.5 |
|
559 | */ |
|
560 | public void setImplementationClass(Class implementationClass) { |
|
561 | 26 | this.implementationClass = implementationClass; |
562 | 26 | } |
563 | ||
564 | /** |
|
565 | * Does this describe a collective? |
|
566 | */ |
|
567 | public boolean isCollective() { |
|
568 | // TODO is this implementation correct? |
|
569 | // maybe this method is unnecessary |
|
570 | 1638 | return isCollectiveType; |
571 | } |
|
572 | ||
573 | /** |
|
574 | * Sets whether the element described is a collective. |
|
575 | * @since 0.7 |
|
576 | * @param isCollectiveType |
|
577 | */ |
|
578 | public void setCollective(boolean isCollectiveType) { |
|
579 | 11326 | this.isCollectiveType = isCollectiveType; |
580 | 11326 | } |
581 | ||
582 | /** |
|
583 | * Finds the parent of the given descriptor. |
|
584 | * @param elementDescriptor <code>ElementDescriptor</code> |
|
585 | * @return <code>ElementDescriptor</code>, not null |
|
586 | */ |
|
587 | public ElementDescriptor findParent(ElementDescriptor elementDescriptor) { |
|
588 | //TODO: is this really a good design? |
|
589 | 0 | ElementDescriptor result = null; |
590 | 0 | ElementDescriptor[] elementDescriptors = getElementDescriptors(); |
591 | 0 | for (int i=0, size=elementDescriptors.length; i<size; i++) { |
592 | 0 | if (elementDescriptors[i].equals(elementDescriptor)) { |
593 | 0 | result = this; |
594 | 0 | break; |
595 | } |
|
596 | else |
|
597 | { |
|
598 | 0 | result = elementDescriptors[i].findParent(elementDescriptor); |
599 | 0 | if (result != null) { |
600 | 0 | break; |
601 | } |
|
602 | } |
|
603 | } |
|
604 | 0 | return result; |
605 | } |
|
606 | ||
607 | /** |
|
608 | * Returns something useful for logging. |
|
609 | * |
|
610 | * @return a string useful for logging |
|
611 | */ |
|
612 | public String toString() { |
|
613 | 39 | return |
614 | 78 | "ElementDescriptor[qname=" + getQualifiedName() + ",pname=" + getPropertyName() |
615 | 39 | + ",class=" + getPropertyType() + ",singular=" + getSingularPropertyType() |
616 | 39 | + ",updater=" + getUpdater() + ",wrap=" + isWrapCollectionsInElement() + "]"; |
617 | } |
|
618 | ||
619 | /** |
|
620 | * <p>Is this decriptor hollow?</p> |
|
621 | * <p> |
|
622 | * A hollow descriptor is one which gives only the class that the subgraph |
|
623 | * is mapped to rather than describing the entire subgraph. |
|
624 | * A new <code>XMLBeanInfo</code> should be introspected |
|
625 | * and that used to describe the subgraph. |
|
626 | * A hollow descriptor should not have any child descriptors. |
|
627 | * TODO: consider whether a subclass would be better |
|
628 | * </p> |
|
629 | * @return true if this is hollow |
|
630 | */ |
|
631 | public boolean isHollow() { |
|
632 | 11029 | return isHollow; |
633 | } |
|
634 | ||
635 | /** |
|
636 | * Sets whether this descriptor is hollow. |
|
637 | * A hollow descriptor is one which gives only the class that the subgraph |
|
638 | * is mapped to rather than describing the entire subgraph. |
|
639 | * A new <code>XMLBeanInfo</code> should be introspected |
|
640 | * and that used to describe the subgraph. |
|
641 | * A hollow descriptor should not have any child descriptors. |
|
642 | * TODO: consider whether a subclass would be better |
|
643 | * @param isHollow true if this is hollow |
|
644 | */ |
|
645 | public void setHollow(boolean isHollow) { |
|
646 | 9595 | this.isHollow = isHollow; |
647 | 9595 | } |
648 | ||
649 | /** |
|
650 | * <p>Is the bind time type to be used to determine the mapping?</p> |
|
651 | * <p> |
|
652 | * The mapping for an object property value can either be the |
|
653 | * introspection time type (based on the logical type of the property) |
|
654 | * or the bind time type (based on the type of the actual instance). |
|
655 | * </p> |
|
656 | * @since 0.7 |
|
657 | * @return true if the bind time type is to be used to determine the mapping, |
|
658 | * false if the introspection time type is to be used |
|
659 | */ |
|
660 | public boolean isUseBindTimeTypeForMapping() { |
|
661 | 14452 | boolean result = true; |
662 | 14452 | if ( this.useBindTimeTypeForMapping != null ) { |
663 | 11254 | result = this.useBindTimeTypeForMapping.booleanValue(); |
664 | } |
|
665 | 14452 | return result; |
666 | } |
|
667 | ||
668 | /** |
|
669 | * <p>Sets whether the bind time type to be used to determine the mapping. |
|
670 | * The mapping for an object property value can either be the |
|
671 | * introspection time type (based on the logical type of the property) |
|
672 | * or the bind time type (based on the type of the actual instance). |
|
673 | * </p><p> |
|
674 | * <strong>Note:</strong> this property is write once, read many. |
|
675 | * So, the first time that this method is called the value will be set |
|
676 | * but subsequent calls will be ignored. |
|
677 | * </p> |
|
678 | * @since 0.7 |
|
679 | * @param useBindTimeTypeForMapping true if the bind time type is to be used to |
|
680 | * determine the mapping, false if the introspection time type is to be used |
|
681 | */ |
|
682 | public void setUseBindTimeTypeForMapping(boolean useBindTimeTypeForMapping) { |
|
683 | 21362 | if ( this.useBindTimeTypeForMapping == null ) { |
684 | 21349 | this.useBindTimeTypeForMapping = new Boolean(useBindTimeTypeForMapping); |
685 | } |
|
686 | 21362 | } |
687 | ||
688 | /** |
|
689 | * <p>Is this a polymorphic element?</p> |
|
690 | * <p> |
|
691 | * A polymorphic element's name is not fixed at |
|
692 | * introspection time and it's resolution is postponed to bind time. |
|
693 | * </p> |
|
694 | * @since 0.7 |
|
695 | * @return true if {@link #getQualifiedName} is null, |
|
696 | * false otherwise |
|
697 | */ |
|
698 | public boolean isPolymorphic() { |
|
699 | 23585 | return (getQualifiedName() == null); |
700 | } |
|
701 | } |