1 /**
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Intalio, Inc. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Intalio, Inc. Exolab is a registered
23 * trademark of Intalio, Inc.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 1999-2004 (C) Intalio, Inc. All Rights Reserved.
42 *
43 * $Id$
44 */
45
46 package org.exolab.castor.xml;
47
48 import java.util.HashMap;
49 import java.util.HashSet;
50 import java.util.Iterator;
51 import java.util.Map;
52 import java.util.Set;
53 import java.util.Vector;
54
55 import org.castor.xml.BackwardCompatibilityContext;
56 import org.castor.xml.InternalContext;
57 import org.castor.xml.AbstractInternalContext;
58 import org.castor.xml.JavaNaming;
59 import org.exolab.castor.mapping.ClassDescriptor;
60 import org.exolab.castor.mapping.CollectionHandler;
61 import org.exolab.castor.mapping.FieldDescriptor;
62 import org.exolab.castor.mapping.MappingException;
63 import org.exolab.castor.mapping.loader.CollectionHandlers;
64 import org.exolab.castor.util.ReflectionUtil;
65
66
67 /**
68 * A core class for common code shared throughout the
69 * Marshalling Framework
70 *
71 * @author <a href="mailto:kvisco-at-intalio.com">Keith Visco</a>
72 * @version $Revision$ $Date: 2005-12-13 14:58:48 -0700 (Tue, 13 Dec 2005) $
73 */
74 abstract class MarshalFramework {
75
76
77
78 //--------------------------/
79 //- Public class variables -/
80 //--------------------------/
81
82 /**
83 * JDK version 1.5 .
84 */
85 private static final double JDK_VERSION_1_5 = 1.5;
86
87 /**
88 * The XSI Namespace URI.
89 **/
90 public static final String XSI_NAMESPACE
91 = "http://www.w3.org/2001/XMLSchema-instance";
92
93 /**
94 * The name of the Schema location attribute.
95 **/
96 public static final String XSI_SCHEMA_LOCATION = "schemaLocation";
97
98 /**
99 * The name of the no namespace schema location attribute.
100 **/
101 public static final String XSI_NO_NAMESPACE_SCHEMA_LOCATION
102 = "noNamespaceSchemaLocation";
103
104 /**
105 * The xml:lang attribute name.
106 */
107 public static final String XML_LANG_ATTR = "xml:lang";
108
109 /**
110 * The xml:lang attribute, without the "xml:" prefix.
111 */
112 public static final String LANG_ATTR = "lang";
113
114 /**
115 * The xsi:nil attribute, without the "xsi:" prefix.
116 */
117 public static final String NIL_ATTR = "nil";
118
119 /**
120 * The xsi:nil attribute.
121 */
122 public static final String XSI_NIL_ATTR = "xsi:nil";
123
124 /**
125 * The xml:space attribute name.
126 */
127 public static final String XML_SPACE_ATTR = "xml:space";
128
129 /**
130 * The xml:space attribute name, without the "xml:" prefix.
131 */
132 public static final String SPACE_ATTR = "space";
133
134 /**
135 * The xsi:type attribute name, without the "xsi:" prefix.
136 */
137 public static final String TYPE_ATTR = "type";
138
139 /**
140 * The value of 'true'.
141 */
142 public static final String TRUE_VALUE = "true";
143
144 //-----------------------------/
145 //- Protected class variables -/
146 //-----------------------------/
147
148 /**
149 * A constant to indicate a wrong name without setting null.
150 */
151 static final String INTERNAL_XML_NAME = "-error-if-this-is-used-";
152
153 /**
154 * The default prefix used for specifying the
155 * xsi:type as a classname instead of a schema name.
156 * This is a Castor specific hack.
157 */
158 static final String JAVA_PREFIX = "java:";
159
160 /**
161 * The name of the QName type.
162 */
163 static final String QNAME_NAME = "QName";
164
165 /**
166 * An empty array of field descriptors.
167 */
168 static final XMLFieldDescriptor[] NO_FIELD_DESCRIPTORS
169 = new XMLFieldDescriptor[0];
170
171 //-----------------------------/
172 //- Private variables -/
173 //-----------------------------/
174
175 /**
176 * The {@link AbstractInternalContext} to use at all un-marshal actions.
177 * @since 1.1.3
178 */
179 private InternalContext _internalContext;
180
181 //-----------------------------/
182 //- Public methods -/
183 //-----------------------------/
184
185 /**
186 * We need some stuff initialized here. MarshalFramework requires internally
187 * an {@link InternalContext}, so either one is given or {@link BackwardCompatibilityContext}
188 * is instantiated! Mind that instantiating {@link BackwardCompatibilityContext}
189 * means to (re-)read configuration files.
190 * @param internalContext either an {@link InternalContext} comes from outside
191 * or {@link BackwardCompatibilityContext} is instantiated
192 */
193 public MarshalFramework(final InternalContext internalContext) {
194 if (internalContext == null) {
195 _internalContext = new BackwardCompatibilityContext();
196 } else {
197 _internalContext = internalContext;
198 }
199 }
200
201 /**
202 * To get the {@link JavaNaming} instance to be used.
203 * @return the JavaNaming to be used
204 */
205 public JavaNaming getJavaNaming() {
206 return _internalContext.getJavaNaming();
207 }
208
209 /**
210 * To set the {@link JavaNaming} instance to be used.
211 * @param javaNaming the JavaNaming to be used
212 * TODO: joachim remove me if possible!
213 */
214 private void setJavaNaming(final JavaNaming javaNaming) {
215 _internalContext.setJavaNaming(javaNaming);
216 }
217
218 /**
219 * To get the {@link AbstractInternalContext} to use.
220 * @return the {@link AbstractInternalContext} to use
221 */
222 public InternalContext getInternalContext() {
223 return _internalContext;
224 }
225
226 /**
227 * To set the {@link AbstractInternalContext} to use.
228 * @param internalContext the {@link AbstractInternalContext} to use
229 */
230 public void setInternalContext(final InternalContext internalContext) {
231 _internalContext = internalContext;
232 }
233
234 /**
235 * Returns true if the given Class is a considered a
236 * collection by the marshalling framework.
237 * @param clazz the Class to check
238 * @return true if the given Class is considered a collection.
239 * TODO: joachim: this code exists somewhere else too!!
240 */
241 public static boolean isCollection(final Class clazz) {
242 return CollectionHandlers.hasHandler(clazz);
243 } //-- isCollection
244
245 /**
246 * Returns the CollectionHandler associated with the
247 * given collection, or null if no such handler exists.
248 * @param clazz the Class to check
249 * @return the CollectionHandler for the associated type.
250 */
251 public CollectionHandler getCollectionHandler(final Class clazz) {
252 CollectionHandler handler = null;
253 try {
254 handler = CollectionHandlers.getHandler(clazz);
255 }
256 catch (MappingException mx) {
257 //-- Not a collection, or no handler exists, return null.
258 }
259 return handler;
260 } //-- getCollectionHandler
261
262
263 /**
264 * Returns true if the given class should be treated as a primitive
265 * type. This method will return true for all Java primitive
266 * types, the set of primitive object wrappers, as well
267 * as Strings.
268 * @param type the Class to check
269 * @return true if the given class should be treated as a primitive type
270 * TODO: joachim: this code exists somewhere else too!!
271 **/
272 static boolean isPrimitive(final Class type) {
273
274 if (type == null) {
275 return false;
276 }
277
278 //-- java primitive
279 if (type.isPrimitive()) {
280 return true;
281 }
282
283 //-- we treat strings as primitives
284 if (type == String.class) {
285 return true;
286 }
287
288 //-- primtive wrapper classes
289 if ((type == Boolean.class) || (type == Character.class)) {
290 return true;
291 }
292
293 Class superClass = type.getSuperclass();
294 if (superClass == Number.class) {
295 return true;
296 }
297
298 if (superClass != null) {
299 return superClass.getName().equals("java.lang.Enum");
300 }
301
302 return false;
303
304 } //-- isPrimitive
305
306 /**
307 * Returns true if the given class should be treated as an enum type. This method
308 * will return true for all Java 5 (or later) enums, and for enum-style
309 * classes.
310 * @param type the Class to check
311 * @return true if the given class should be treated as an enum
312 **/
313 static boolean isEnum(final Class type) {
314
315 if (type == null) {
316 return false;
317 }
318
319 float javaVersion =
320 Float.valueOf(System.getProperty("java.specification.version")).floatValue();
321 if (javaVersion >= JDK_VERSION_1_5) {
322 try {
323 Boolean isEnum = ReflectionUtil.isEnumViaReflection(type);
324 return isEnum.booleanValue();
325 } catch (Exception e) {
326 // nothing to report; implies that there's no such method
327 }
328 }
329
330 // TODO: add code to cover 1.4 enum-stype classes as well.
331
332 return false;
333
334 } //-- isPrimitive
335
336 // /**
337 // * Calls isEnum() method on target class vi areflection to find out
338 // * whether the given type is a Java 5 enumeration.
339 // * @param type The type to analyze.
340 // * @return True if the type given is a Java 5.0 enum.
341 // * @throws NoSuchMethodException If the method can not be found.
342 // * @throws IllegalAccessException If access to this method is illegal
343 // * @throws InvocationTargetException If the target method can not be invoked.
344 // */
345 // private static Boolean isEnumViaReflection(Class type)
346 // throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
347 // Method isEnumMethod = type.getClass().getMethod("isEnum", (Class[]) null);
348 // return (Boolean) isEnumMethod.invoke(type, (Object[]) null);
349 // }
350 //
351
352 /**
353 * Returns true if any of the fields associated with the given
354 * XMLClassDescriptor are located at, or beneath, the given location.
355 *
356 * @param location the location to compare against
357 * @param classDesc the XMLClassDescriptor in which to check the field
358 * locations
359 * @return true if any of the fields has a location associated
360 */
361 static final boolean hasFieldsAtLocation
362 (final String location, final XMLClassDescriptor classDesc) {
363 //-- check elements
364 XMLFieldDescriptor[] descriptors = classDesc.getElementDescriptors();
365 for (int i = 0; i < descriptors.length; i++) {
366 if (descriptors[i] == null) {
367 continue;
368 }
369 String tmpLocation = descriptors[i].getLocationPath();
370 if ((tmpLocation != null) && (tmpLocation.startsWith(location))) {
371 return true;
372 }
373 }
374
375 //-- check attributes
376 descriptors = classDesc.getAttributeDescriptors();
377 for (int i = 0; i < descriptors.length; i++) {
378 if (descriptors[i] == null) {
379 continue;
380 }
381 String tmpLocation = descriptors[i].getLocationPath();
382 if ((tmpLocation != null) && (tmpLocation.startsWith(location))) {
383 return true;
384 }
385 }
386
387 //-- check content/text
388 XMLFieldDescriptor content = classDesc.getContentDescriptor();
389 if (content != null) {
390 String tmpLocation = content.getLocationPath();
391 if ((tmpLocation != null) && (tmpLocation.startsWith(location))) {
392 return true;
393 }
394 }
395 return false;
396 } //-- hasFieldsAtLocation
397
398 /**
399 * Compares the given namespaces (as strings) for equality.
400 * null and empty values are considered equal.
401 *
402 * @param ns1 the namespace to compare to argument ns2
403 * @param ns2 the namespace to compare to argument ns1
404 * @return true if the namespaces are considert equal
405 * TODO: joachim put it into XMLNaming!
406 */
407 public static boolean namespaceEquals(final String ns1, final String ns2) {
408 if (ns1 == null) {
409 return ((ns2 == null) || (ns2.length() == 0));
410 }
411 if (ns2 == null) {
412 return (ns1.length() == 0);
413 }
414 return ns1.equals(ns2);
415 } //-- namespaceEquals
416
417 /**
418 * Returns true if the given classes are both the same
419 * primitive or primitive wrapper class. For exmaple, if
420 * class "a" is an int (Integer.TYPE) and class "b" is
421 * either an int or Integer.class then true will be
422 * returned, otherwise false.
423 * @param a compare a with b
424 * @param b compare a with b
425 * @return true if both a and b are considered equal
426 */
427 static boolean primitiveOrWrapperEquals(final Class a, final Class b) {
428 if (!isPrimitive(a)) {
429 return false;
430 }
431 if (!isPrimitive(b)) {
432 return false;
433 }
434
435 if (a == b) {
436 return true;
437 }
438
439 //-- Boolean/boolean
440 if ((a == Boolean.class) || (a == Boolean.TYPE)) {
441 return ((b == Boolean.class) || (b == Boolean.TYPE));
442 }
443 //-- Byte/byte
444 else if ((a == Byte.class) || (a == Byte.TYPE)) {
445 return ((b == Byte.class) || (b == Byte.TYPE));
446 }
447 //-- Character/char
448 else if ((a == Character.class) || (a == Character.TYPE)) {
449 return ((b == Character.class) || (b == Character.TYPE));
450 }
451 //-- Double/double
452 else if ((a == Double.class) || (a == Double.TYPE)) {
453 return ((b == Double.class) || (b == Double.TYPE));
454 }
455 else if ((a == Float.class) || (a == Float.TYPE)) {
456 return ((b == Float.class) || (b == Float.TYPE));
457 }
458 //-- Integer/int
459 else if ((a == Integer.class) || (a == Integer.TYPE)) {
460 return ((b == Integer.class) || (b == Integer.TYPE));
461 }
462 //-- Long/long
463 else if ((a == Long.class) || (a == Long.TYPE)) {
464 return ((b == Long.class) || (b == Long.TYPE));
465 }
466 //-- Short/short
467 else if ((a == Short.class) || (a == Short.TYPE)) {
468 return ((b == Short.class) || (b == Short.TYPE));
469 }
470
471 return false;
472 } //-- primitiveOrWrapperEquals
473
474 /**
475 *
476 */
477 private static final InheritanceMatch[] NO_MATCH_ARRAY = new InheritanceMatch[0];
478
479 /**
480 * Search there is a field descriptor which can accept one of the class
481 * descriptor which match the given name and namespace.
482 *
483 * @param name XML name of the field
484 * @param namespace namespace of the field
485 * @param classDesc the class descriptor to match against
486 * @param cdResolver the class descriptor resolver to use
487 * @return An array of InheritanceMatch.
488 * @throws MarshalException if the resolver called fails fatally
489 */
490 protected InheritanceMatch[] searchInheritance(final String name,
491 final String namespace,
492 final XMLClassDescriptor classDesc)
493 throws MarshalException {
494 Iterator classDescriptorIterator = null;
495
496 try {
497 //-- A little required logic for finding Not-Yet-Loaded
498 //-- descriptors
499 String className = getJavaNaming().toJavaClassName(name);
500 //-- should use namespace-to-prefix mappings, but
501 //-- just create package for now.
502 Class clazz = classDesc.getJavaClass();
503 String pkg = null;
504 if (clazz != null) {
505 while (clazz.getDeclaringClass() != null) {
506 clazz = clazz.getDeclaringClass();
507 }
508 pkg = clazz.getName();
509 int idx = pkg.lastIndexOf('.');
510 if (idx >= 0) {
511 pkg = pkg.substring(0, idx + 1);
512 className = pkg + className;
513 }
514 }
515 getInternalContext().getXMLClassDescriptorResolver().resolve(
516 className, classDesc.getClass().getClassLoader());
517 //-- end Not-Yet-Loaded descriptor logic
518
519 //-- resolve all by XML name + namespace URI
520 classDescriptorIterator =
521 getInternalContext().getXMLClassDescriptorResolver().resolveAllByXMLName(
522 name, namespace, null);
523 }
524 catch (ResolverException rx) {
525 Throwable actual = rx.getCause();
526 if (actual instanceof MarshalException) {
527 throw (MarshalException) actual;
528 }
529 if (actual != null) {
530 throw new MarshalException(actual);
531 }
532 throw new MarshalException(rx);
533 }
534
535 Vector inheritanceList = null;
536 XMLFieldDescriptor descriptor = null;
537 XMLFieldDescriptor[] descriptors = classDesc.getElementDescriptors();
538 XMLClassDescriptor cdInherited = null;
539
540 if (classDescriptorIterator.hasNext()) {
541 while (classDescriptorIterator.hasNext() && (descriptor == null)) {
542 cdInherited = (XMLClassDescriptor) classDescriptorIterator.next();
543 Class subclass = cdInherited.getJavaClass();
544
545 for (int i = 0; i < descriptors.length; i++) {
546
547 if (descriptors[i] == null) {
548 continue;
549 }
550
551 //-- skip descriptors with special internal name
552 if (INTERNAL_XML_NAME.equals(descriptors[i].getXMLName())) {
553 continue;
554 }
555
556 //-- check for inheritence
557 Class superclass = descriptors[i].getFieldType();
558
559 // It is possible that the superclass is of type object if we use any node.
560 if (superclass.isAssignableFrom(subclass) && (superclass != Object.class)) {
561 descriptor = descriptors[i];
562 if (inheritanceList == null) {
563 inheritanceList = new Vector(3);
564 }
565 inheritanceList.addElement(new InheritanceMatch(descriptor, cdInherited));
566 }
567 }
568 }
569 //-- reset inherited class descriptor, if necessary
570 if (descriptor == null) {
571 cdInherited = null;
572 }
573 }
574
575 if (inheritanceList != null) {
576 InheritanceMatch[] result = new InheritanceMatch[inheritanceList.size()];
577 inheritanceList.toArray(result);
578 return result;
579 }
580 return NO_MATCH_ARRAY;
581
582 }
583
584 /**
585 * Used to store the information when we find a possible inheritance. It
586 * store the XMLClassDescriptor of the object to instantiate and the
587 * XMLFieldDescriptor of the parent, where the instance of the
588 * XMLClassDescriptor will be put.
589 */
590 public static class InheritanceMatch {
591 /**
592 * The field descriptor of the parent.
593 */
594 public XMLFieldDescriptor parentFieldDesc;
595 /**
596 * The class descriptor to instantiate.
597 */
598 public XMLClassDescriptor inheritedClassDesc;
599
600 public InheritanceMatch(XMLFieldDescriptor fieldDesc, XMLClassDescriptor classDesc) {
601 parentFieldDesc = fieldDesc;
602 inheritedClassDesc = classDesc;
603 }
604 }
605
606
607
608 /**
609 * An internal implementation of XMLClassDescriptor used by
610 * the Unmarshaller and Marshaller...
611 */
612 class InternalXMLClassDescriptor implements XMLClassDescriptor {
613
614 private XMLClassDescriptor _classDesc = null;
615
616 /**
617 * Cached arrays.
618 */
619 private XMLFieldDescriptor[] _attributes = null;
620 /**
621 * Cached arrays.
622 */
623 private XMLFieldDescriptor[] _elements = null;
624 /**
625 * Cached arrays.
626 */
627 private FieldDescriptor[] _fields = null;
628
629 /**
630 * Map holding the properties set and read by Natures.
631 */
632 private Map _properties = new HashMap();
633
634 /**
635 * Map holding the available natures.
636 */
637 private Set _natures = new HashSet();
638
639 /**
640 * Creates a new InternalXMLClassDescriptor for the given
641 * XMLClassDescriptor.
642 */
643 protected InternalXMLClassDescriptor(XMLClassDescriptor classDesc)
644 {
645 if (classDesc == null) {
646 String err = "The argument 'classDesc' must not be null.";
647 throw new IllegalArgumentException(err);
648 }
649
650 //-- prevent wrapping another InternalXMLClassDescriptor,
651 while (classDesc instanceof InternalXMLClassDescriptor) {
652 classDesc = ((InternalXMLClassDescriptor) classDesc).getClassDescriptor();
653 }
654 _classDesc = classDesc;
655 }
656
657 /**
658 * Returns the XMLClassDescriptor that this InternalXMLClassDescriptor
659 * wraps.
660 *
661 * @return the XMLClassDescriptor
662 */
663 public XMLClassDescriptor getClassDescriptor() {
664 return _classDesc;
665 } //-- getClassDescriptor
666
667
668 /**
669 * Returns the set of XMLFieldDescriptors for all members
670 * that should be marshalled as XML attributes. This
671 * includes namespace nodes.
672 *
673 * @return an array of XMLFieldDescriptors for all members
674 * that should be marshalled as XML attributes.
675 */
676 public XMLFieldDescriptor[] getAttributeDescriptors() {
677 if (_attributes == null) {
678 _attributes = _classDesc.getAttributeDescriptors();
679 }
680 return _attributes;
681 } //-- getAttributeDescriptors
682
683 /**
684 * Returns the XMLFieldDescriptor for the member
685 * that should be marshalled as text content.
686 *
687 * @return the XMLFieldDescriptor for the member
688 * that should be marshalled as text content.
689 */
690 public XMLFieldDescriptor getContentDescriptor() {
691 return _classDesc.getContentDescriptor();
692 } //-- getContentDescriptor
693
694
695 /**
696 * Returns the XML field descriptor matching the given
697 * xml name and nodeType. If NodeType is null, then
698 * either an AttributeDescriptor, or ElementDescriptor
699 * may be returned. Null is returned if no matching
700 * descriptor is available.
701 *
702 * @param name the xml name to match against
703 * @param namespace the xml namespace to match
704 * @param nodeType the NodeType to match against, or null if
705 * the node type is not known.
706 * @return the matching descriptor, or null if no matching
707 * descriptor is available.
708 *
709 */
710 public XMLFieldDescriptor getFieldDescriptor
711 (final String name, final String namespace, final NodeType nodeType)
712 {
713 return _classDesc.getFieldDescriptor(name, namespace, nodeType);
714 } //-- getFieldDescriptor
715
716 /**
717 * Returns the set of XMLFieldDescriptors for all members
718 * that should be marshalled as XML elements.
719 *
720 * @return an array of XMLFieldDescriptors for all members
721 * that should be marshalled as XML elements.
722 */
723 public XMLFieldDescriptor[] getElementDescriptors() {
724 if (_elements == null) {
725 _elements = _classDesc.getElementDescriptors();
726 }
727 return _elements;
728 } //-- getElementDescriptors
729
730 /**
731 * @return the namespace prefix to use when marshalling as XML.
732 */
733 public String getNameSpacePrefix() {
734 return _classDesc.getNameSpacePrefix();
735 } //-- getNameSpacePrefix
736
737 /**
738 * @return the namespace URI used when marshalling and unmarshalling as XML.
739 */
740 public String getNameSpaceURI() {
741 return _classDesc.getNameSpaceURI();
742 } //-- getNameSpaceURI
743
744 /**
745 * Returns a specific validator for the class described by
746 * this ClassDescriptor. A null value may be returned
747 * if no specific validator exists.
748 *
749 * @return the type validator for the class described by this
750 * ClassDescriptor.
751 */
752 public TypeValidator getValidator() {
753 return _classDesc.getValidator();
754 } //-- getValidator
755
756 /**
757 * Returns the XML Name for the Class being described.
758 *
759 * @return the XML name.
760 */
761 public String getXMLName() {
762 return _classDesc.getXMLName();
763 } //-- getXMLName
764
765 /**
766 * Returns true if the wrapped ClassDescriptor was created
767 * by introspection.
768 *
769 * @return true if the wrapped ClassDescriptor was created
770 * by introspection.
771 */
772 public boolean introspected() {
773 return Introspector.introspected(_classDesc);
774 } //-- introspected
775
776 /**
777 * @see org.exolab.castor.xml.XMLClassDescriptor#canAccept(
778 * java.lang.String, java.lang.String, java.lang.Object)
779 */
780 public boolean canAccept(final String name, final String namespace, final Object object) {
781 return _classDesc.canAccept(name, namespace, object);
782 } //-- canAccept
783
784 /**
785 * {@inheritDoc}
786 *
787 * @see org.exolab.castor.xml.XMLClassDescriptor#checkDescriptorForCorrectOrderWithinSequence(org.exolab.castor.xml.XMLFieldDescriptor, org.exolab.castor.xml.UnmarshalState, java.lang.String)
788 */
789 public void checkDescriptorForCorrectOrderWithinSequence(
790 final XMLFieldDescriptor elementDescriptor,
791 final UnmarshalState parentState,
792 final String xmlName)
793 throws ValidationException {
794 _classDesc.checkDescriptorForCorrectOrderWithinSequence(elementDescriptor, parentState, xmlName);
795 }
796
797 //-------------------------------------/
798 //- Implementation of ClassDescriptor -/
799 //-------------------------------------/
800
801 /**
802 * Returns the Java class represented by this descriptor.
803 *
804 * @return The Java class
805 */
806 public Class getJavaClass() {
807 return _classDesc.getJavaClass();
808 } //-- getJavaClass
809
810
811 /**
812 * Returns a list of fields represented by this descriptor.
813 *
814 * @return A list of fields
815 */
816 public FieldDescriptor[] getFields() {
817 if (_fields == null) {
818 _fields = _classDesc.getFields();
819 }
820 return _fields;
821 } //-- getFields
822
823
824 /**
825 * Returns the class descriptor of the class extended by this class.
826 *
827 * @return The extended class descriptor
828 */
829 public ClassDescriptor getExtends() {
830 return _classDesc.getExtends();
831 } //-- getExtends
832
833
834 /**
835 * Returns the identity field, null if this class has no identity.
836 *
837 * @return The identity field
838 */
839 public FieldDescriptor getIdentity() {
840 return _classDesc.getIdentity();
841 } //-- getIdentity
842
843 /**
844 * {@inheritDoc}
845 *
846 * @see org.exolab.castor.xml.XMLClassDescriptor#isChoice()
847 */
848 public boolean isChoice() {
849 return false;
850 }
851
852 /**
853 * @see org.exolab.castor.builder.info.nature.PropertyHolder#
854 * getProperty(java.lang.String)
855 * @param name
856 * of the property
857 * @return value of the property
858 */
859 public Object getProperty(final String name) {
860 return _properties.get(name);
861 }
862
863 /**
864 * @see org.exolab.castor.builder.info.nature.PropertyHolder#
865 * setProperty(java.lang.String, java.lang.Object)
866 * @param name
867 * of the property
868 * @param value
869 * of the property
870 */
871 public void setProperty(final String name, final Object value) {
872 _properties.put(name, value);
873 }
874
875 /**
876 * @see org.exolab.castor.builder.info.nature.NatureExtendable#
877 * addNature(java.lang.String)
878 * @param nature
879 * ID of the Nature
880 */
881 public void addNature(final String nature) {
882 _natures.add(nature);
883 }
884
885 /**
886 * @see org.exolab.castor.builder.info.nature.NatureExtendable#
887 * hasNature(java.lang.String)
888 * @param nature
889 * ID of the Nature
890 * @return true if the Nature ID was added.
891 */
892 public boolean hasNature(final String nature) {
893 return _natures.contains(nature);
894 }
895
896 } //-- InternalXMLClassDescriptor
897
898
899 } //-- MarshalFramework