Source Code Cross Referenced for XMLMappingLoader.java in  » Database-ORM » castor » org » exolab » castor » xml » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » castor » org.exolab.castor.xml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Redistribution and use of this software and associated documentation
003:         * ("Software"), with or without modification, are permitted provided
004:         * that the following conditions are met:
005:         *
006:         * 1. Redistributions of source code must retain copyright
007:         *    statements and notices.  Redistributions must also contain a
008:         *    copy of this document.
009:         *
010:         * 2. Redistributions in binary form must reproduce the
011:         *    above copyright notice, this list of conditions and the
012:         *    following disclaimer in the documentation and/or other
013:         *    materials provided with the distribution.
014:         *
015:         * 3. The name "Exolab" must not be used to endorse or promote
016:         *    products derived from this Software without prior written
017:         *    permission of Intalio, Inc.  For written permission,
018:         *    please contact info@exolab.org.
019:         *
020:         * 4. Products derived from this Software may not be called "Exolab"
021:         *    nor may "Exolab" appear in their names without prior written
022:         *    permission of Intalio, Inc. Exolab is a registered
023:         *    trademark of Intalio, Inc.
024:         *
025:         * 5. Due credit should be given to the Exolab Project
026:         *    (http://www.exolab.org/).
027:         *
028:         * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
029:         * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
030:         * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
031:         * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
032:         * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
033:         * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
034:         * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
035:         * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
036:         * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
037:         * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
038:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
039:         * OF THE POSSIBILITY OF SUCH DAMAGE.
040:         *
041:         * Copyright 1999-2004(C) Intalio, Inc. All Rights Reserved.
042:         *
043:         * This file was originally developed by Keith Visco during the
044:         * course of employment at Intalio Inc.
045:         * All portions of this file developed by Keith Visco after Jan 19 2005 are
046:         * Copyright (C) 2005 Keith Visco. All Rights Reserved.
047:         *
048:         * $Id: XMLMappingLoader.java 6910 2007-03-31 15:14:38Z wguttmn $
049:         */package org.exolab.castor.xml;
050:
051:        import org.castor.mapping.BindingType;
052:        import org.exolab.castor.mapping.ClassDescriptor;
053:        import org.exolab.castor.mapping.FieldDescriptor;
054:        import org.exolab.castor.mapping.FieldHandler;
055:        import org.exolab.castor.mapping.MapItem;
056:        import org.exolab.castor.mapping.MappingException;
057:        import org.exolab.castor.mapping.TypeConvertor;
058:        import org.exolab.castor.mapping.CollectionHandler;
059:        import org.exolab.castor.mapping.loader.AbstractFieldDescriptor;
060:        import org.exolab.castor.mapping.loader.CollectionHandlers;
061:        import org.exolab.castor.mapping.loader.AbstractMappingLoader;
062:        import org.exolab.castor.mapping.loader.FieldHandlerImpl;
063:        import org.exolab.castor.mapping.loader.TypeInfo;
064:        import org.exolab.castor.mapping.loader.Types;
065:        import org.exolab.castor.mapping.xml.ClassMapping;
066:        import org.exolab.castor.mapping.xml.FieldMapping;
067:        import org.exolab.castor.mapping.xml.BindXml;
068:        import org.exolab.castor.mapping.xml.MapTo;
069:        import org.exolab.castor.mapping.xml.MappingRoot;
070:        import org.exolab.castor.mapping.xml.Property;
071:        import org.exolab.castor.mapping.xml.types.BindXmlAutoNamingType;
072:        import org.exolab.castor.mapping.xml.types.FieldMappingCollectionType;
073:        import org.exolab.castor.util.LocalConfiguration;
074:
075:        import org.exolab.castor.xml.handlers.ContainerFieldHandler;
076:        import org.exolab.castor.xml.handlers.ToStringFieldHandler;
077:        import org.exolab.castor.xml.util.XMLClassDescriptorResolverImpl;
078:        import org.exolab.castor.xml.util.ContainerElement;
079:        import org.exolab.castor.xml.util.XMLClassDescriptorImpl;
080:        import org.exolab.castor.xml.util.XMLClassDescriptorAdapter;
081:        import org.exolab.castor.xml.util.XMLContainerElementFieldDescriptor;
082:        import org.exolab.castor.xml.util.XMLFieldDescriptorImpl;
083:        import org.exolab.castor.xml.validators.IdRefValidator;
084:        import org.exolab.castor.xml.validators.NameValidator;
085:
086:        import java.lang.reflect.Constructor;
087:        import java.lang.reflect.Method;
088:        import java.lang.reflect.Modifier;
089:        import java.util.ArrayList;
090:        import java.util.List;
091:
092:        /**
093:         * An XML implementation of mapping helper. Creates XML class
094:         * descriptors from the mapping file.
095:         *
096:         * @author <a href="keith AT kvisco DOT com">Keith Visco</a>
097:         * @author <a href="arkin@intalio.com">Assaf Arkin</a>
098:         * @version $Revision: 6910 $ $Date: 2006-02-23 01:37:50 -0700 (Thu, 23 Feb 2006) $
099:         */
100:        public final class XMLMappingLoader extends AbstractMappingLoader {
101:            //-----------------------------------------------------------------------------------
102:
103:            /** The default xml prefix used on certain attributes such as xml:lang, xml:base,
104:             *  etc. */
105:            private static final String XML_PREFIX = "xml:";
106:
107:            /** Empty array of class types used for reflection. */
108:            private static final Class[] EMPTY_ARGS = new Class[0];
109:
110:            /** The NCName Schema type. */
111:            private static final String NCNAME = "NCName";
112:
113:            /** The string argument for the valueOf method, used for introspection. */
114:            private static final Class[] STRING_ARG = { String.class };
115:
116:            /** Factory method name for type-safe enumerations. This is primarily for allowing
117:             *  users to map classes that were created by Castor's SourceGenerator. */
118:            private static final String VALUE_OF = "valueOf";
119:
120:            //-----------------------------------------------------------------------------------
121:
122:            /** A reference to the internal ClassDescriptorResolver. */
123:            private XMLClassDescriptorResolverImpl _cdResolver;
124:
125:            /** The default NodeType for primitives. */
126:            private NodeType _primitiveNodeType = null;
127:
128:            /** Naming conventions. */
129:            private XMLNaming _naming = null;
130:
131:            //-----------------------------------------------------------------------------------
132:
133:            /**
134:             * Creates a new XMLMappingLoader
135:             */
136:            public XMLMappingLoader(ClassLoader loader) {
137:                super (loader);
138:
139:                LocalConfiguration config = LocalConfiguration.getInstance();
140:                _primitiveNodeType = config.getPrimitiveNodeType();
141:                _naming = config.getXMLNaming();
142:            }
143:
144:            //-----------------------------------------------------------------------------------
145:
146:            /**
147:             * {@inheritDoc}
148:             */
149:            public BindingType getBindingType() {
150:                return BindingType.XML;
151:            }
152:
153:            //-----------------------------------------------------------------------------------
154:
155:            /**
156:             * {@inheritDoc}
157:             */
158:            public void loadMapping(final MappingRoot mapping,
159:                    final Object param) throws MappingException {
160:                if (loadMapping()) {
161:                    createClassDescriptors(mapping);
162:                }
163:            }
164:
165:            //-----------------------------------------------------------------------------------
166:
167:            protected final ClassDescriptor createClassDescriptor(
168:                    final ClassMapping clsMap) throws MappingException {
169:                if (clsMap.getAutoComplete()) {
170:                    if ((clsMap.getMapTo() == null)
171:                            && ((clsMap.getClassChoice() == null) || (clsMap
172:                                    .getClassChoice().getFieldMappingCount() == 0))
173:                            && (clsMap.getIdentityCount() == 0)) {
174:                        // If we make it here we simply try to load a compiled mapping
175:                        if (_cdResolver == null) {
176:                            createResolver();
177:                        }
178:                        try {
179:                            ClassDescriptor clsDesc = _cdResolver
180:                                    .resolve(clsMap.getName());
181:                            if (clsDesc != null) {
182:                                return clsDesc;
183:                            }
184:                        } catch (ResolverException rx) {
185:
186:                        }
187:                    }
188:                }
189:
190:                // Create the class descriptor.
191:                XMLClassDescriptorAdapter xmlClassDesc = new XMLClassDescriptorAdapter();
192:
193:                // Obtain the Java class.
194:                Class javaClass = resolveType(clsMap.getName());
195:                if (clsMap.getVerifyConstructable()) {
196:                    if (!Types.isConstructable(javaClass, true)) {
197:                        throw new MappingException(
198:                                "mapping.classNotConstructable", javaClass
199:                                        .getName());
200:                    }
201:                }
202:                xmlClassDesc.setJavaClass(javaClass);
203:
204:                // Obtain XML name.
205:                String xmlName;
206:                MapTo mapTo = clsMap.getMapTo();
207:                if ((mapTo != null) && (mapTo.getXml() != null)) {
208:                    xmlName = mapTo.getXml();
209:                } else {
210:                    String clsName = javaClass.getName();
211:                    int idx = clsName.lastIndexOf('.');
212:                    if (idx >= 0) {
213:                        clsName = clsName.substring(idx + 1);
214:                    }
215:                    xmlName = _naming.toXMLName(clsName);
216:                }
217:                xmlClassDesc.setXMLName(xmlName);
218:
219:                // If this class extends another class, we need to obtain the extended
220:                // class and make sure this class indeed extends it.
221:                ClassDescriptor extDesc = getExtended(clsMap, javaClass);
222:                xmlClassDesc.setExtends((XMLClassDescriptor) extDesc);
223:
224:                // Create all field descriptors.
225:                AbstractFieldDescriptor[] allFields = createFieldDescriptors(
226:                        clsMap, javaClass);
227:
228:                // Make sure there are no two fields with the same name.
229:                checkFieldNameDuplicates(allFields, javaClass);
230:
231:                // Identify identity and normal fields. Note that order must be preserved.
232:                List fieldList = new ArrayList(allFields.length);
233:                List idList = new ArrayList();
234:                if (extDesc == null) {
235:                    // Sort fields into 2 lists based on identity definition of field.
236:                    for (int i = 0; i < allFields.length; i++) {
237:                        if (!allFields[i].isIdentity()) {
238:                            fieldList.add(allFields[i]);
239:                        } else {
240:                            idList.add(allFields[i]);
241:                        }
242:                    }
243:
244:                    if (idList.size() == 0) {
245:                        // Found no identities based on identity definition of field.
246:                        // Try to find identities based on identity definition on class.
247:                        String[] idNames = clsMap.getIdentity();
248:
249:                        FieldDescriptor identity;
250:                        for (int i = 0; i < idNames.length; i++) {
251:                            identity = findIdentityByName(fieldList,
252:                                    idNames[i], javaClass);
253:                            if (identity != null) {
254:                                idList.add(identity);
255:                            } else {
256:                                throw new MappingException(
257:                                        "mapping.identityMissing", idNames[i],
258:                                        javaClass.getName());
259:                            }
260:                        }
261:                    }
262:                } else {
263:                    // Add all fields of extending class to field list.
264:                    for (int i = 0; i < allFields.length; i++) {
265:                        fieldList.add(allFields[i]);
266:                    }
267:
268:                    // Add identity of extended class to identity list.
269:                    if (extDesc.getIdentity() != null) {
270:                        idList.add(extDesc.getIdentity());
271:                    }
272:
273:                    // Search redefined identities in extending class.
274:                    FieldDescriptor identity;
275:                    for (int i = 0; i < idList.size(); i++) {
276:                        String idname = ((FieldDescriptor) idList.get(i))
277:                                .getFieldName();
278:                        identity = findIdentityByName(fieldList, idname,
279:                                javaClass);
280:                        if (identity != null) {
281:                            idList.set(i, identity);
282:                        }
283:                    }
284:                }
285:
286:                FieldDescriptor xmlId = null;
287:                if (idList.size() != 0) {
288:                    xmlId = (FieldDescriptor) idList.get(0);
289:                }
290:
291:                if (xmlId != null) {
292:                    xmlClassDesc.setIdentity((XMLFieldDescriptorImpl) xmlId);
293:                }
294:                for (int i = 0; i < fieldList.size(); i++) {
295:                    FieldDescriptor fieldDesc = (FieldDescriptor) fieldList
296:                            .get(i);
297:                    if (fieldDesc != null) {
298:                        xmlClassDesc
299:                                .addFieldDescriptor((XMLFieldDescriptorImpl) fieldDesc);
300:                    }
301:                }
302:
303:                if (clsMap.getAutoComplete()) {
304:
305:                    XMLClassDescriptor referenceDesc = null;
306:
307:                    Class type = xmlClassDesc.getJavaClass();
308:
309:                    //-- check compiled descriptors 
310:                    if (_cdResolver == null) {
311:                        createResolver();
312:                    }
313:                    try {
314:                        referenceDesc = (XMLClassDescriptor) _cdResolver
315:                                .resolve(type);
316:                    } catch (ResolverException rx) {
317:                        throw new MappingException(rx);
318:                    }
319:
320:                    if (referenceDesc == null) {
321:                        Introspector introspector = new Introspector();
322:                        try {
323:                            referenceDesc = introspector
324:                                    .generateClassDescriptor(type);
325:                            if (clsMap.getExtends() != null) {
326:                                //-- clear parent from introspected descriptor since
327:                                //-- a mapping was provided in the mapping file
328:                                ((XMLClassDescriptorImpl) referenceDesc)
329:                                        .setExtends(null);
330:                            }
331:                        } catch (MarshalException mx) {
332:                            String error = "unable to introspect class '"
333:                                    + type.getName() + "' for auto-complete: ";
334:                            throw new MappingException(error + mx.getMessage());
335:                        }
336:                    }
337:
338:                    //-- check for identity
339:                    String identity = "";
340:                    if (clsMap.getIdentityCount() > 0)
341:                        identity = clsMap.getIdentity(0);
342:
343:                    FieldDescriptor[] xmlFields2 = xmlClassDesc.getFields();
344:
345:                    // Attributes
346:                    XMLFieldDescriptor[] introFields = referenceDesc
347:                            .getAttributeDescriptors();
348:                    for (int i = 0; i < introFields.length; ++i) {
349:                        if (!isMatchFieldName(xmlFields2, introFields[i]
350:                                .getFieldName())) {
351:                            // If there is no field with this name, we can add it
352:                            if (introFields[i].getFieldName().equals(identity)) {
353:                                xmlClassDesc.setIdentity(introFields[i]);
354:                            } else {
355:                                xmlClassDesc.addFieldDescriptor(introFields[i]);
356:                            }
357:                        }
358:                    }
359:
360:                    // Elements
361:                    introFields = referenceDesc.getElementDescriptors();
362:                    for (int i = 0; i < introFields.length; ++i) {
363:                        if (!isMatchFieldName(xmlFields2, introFields[i]
364:                                .getFieldName())) {
365:                            // If there is no field with this name, we can add it
366:                            if (introFields[i].getFieldName().equals(identity)) {
367:                                xmlClassDesc.setIdentity(introFields[i]);
368:                            } else {
369:                                xmlClassDesc.addFieldDescriptor(introFields[i]);
370:                            }
371:                        }
372:                    }
373:
374:                    // Content
375:                    XMLFieldDescriptor field = referenceDesc
376:                            .getContentDescriptor();
377:                    if (field != null)
378:                        if (!isMatchFieldName(xmlFields2, field.getFieldName()))
379:                            // If there is no field with this name, we can add
380:                            xmlClassDesc.addFieldDescriptor(field);
381:
382:                }
383:
384:                // Copy ns-uri + ns-prefix + element-definition
385:                if (mapTo != null) {
386:                    xmlClassDesc.setNameSpacePrefix(mapTo.getNsPrefix());
387:                    xmlClassDesc.setNameSpaceURI(mapTo.getNsUri());
388:                    xmlClassDesc.setElementDefinition(mapTo
389:                            .getElementDefinition());
390:                }
391:
392:                return xmlClassDesc;
393:            }
394:
395:            protected final FieldDescriptor findIdentityByName(
396:                    final List fldList, final String idName,
397:                    final Class javaClass) {
398:                for (int i = 0; i < fldList.size(); i++) {
399:                    FieldDescriptor field = (FieldDescriptor) fldList.get(i);
400:                    if (idName.equals(field.getFieldName())) {
401:                        fldList.remove(i);
402:                        return field;
403:                    }
404:                }
405:                return null;
406:            }
407:
408:            protected final void resolveRelations(ClassDescriptor clsDesc) {
409:                FieldDescriptor[] fields;
410:
411:                fields = clsDesc.getFields();
412:                for (int i = 0; i < fields.length; ++i) {
413:                    if (fields[i].getClassDescriptor() != null)
414:                        continue;
415:                    ClassDescriptor relDesc;
416:
417:                    Class fieldType = fields[i].getFieldType();
418:                    if (fieldType != null) {
419:                        relDesc = getDescriptor(fieldType.getName());
420:                        if (relDesc != null
421:                                && relDesc instanceof  XMLClassDescriptor
422:                                && fields[i] instanceof  XMLFieldDescriptorImpl) {
423:                            ((XMLFieldDescriptorImpl) fields[i])
424:                                    .setClassDescriptor(relDesc);
425:                        }
426:                    }
427:                }
428:                if (clsDesc instanceof  XMLClassDescriptorImpl)
429:                    ((XMLClassDescriptorImpl) clsDesc).sortDescriptors();
430:            }
431:
432:            //-----------------------------------------------------------------------------------
433:
434:            private void createResolver() {
435:                _cdResolver = (XMLClassDescriptorResolverImpl) ClassDescriptorResolverFactory
436:                        .createClassDescriptorResolver(BindingType.XML);
437:                _cdResolver.setIntrospection(false);
438:                _cdResolver.setLoadPackageMappings(false);
439:            }
440:
441:            /**
442:             * Match if a field named <code>fieldName</code> is in fields
443:             */
444:            private boolean isMatchFieldName(FieldDescriptor[] fields,
445:                    String fieldName) {
446:                for (int i = 0; i < fields.length; ++i)
447:                    if (fields[i].getFieldName().equals(fieldName))
448:                        return true;
449:
450:                return false;
451:            } //-- method: isMatchFieldName
452:
453:            protected AbstractFieldDescriptor createFieldDesc(Class javaClass,
454:                    FieldMapping fieldMap) throws MappingException {
455:
456:                FieldDescriptor fieldDesc;
457:                FieldMappingCollectionType colType = fieldMap.getCollection();
458:                String xmlName = null;
459:                NodeType nodeType = null;
460:                String match = null;
461:                XMLFieldDescriptorImpl xmlDesc;
462:                boolean isReference = false;
463:                boolean isXMLTransient = false;
464:
465:                //-- handle special case for HashMap/Hashtable
466:                if ((fieldMap.getType() == null) && (colType != null)) {
467:                    if ((colType == FieldMappingCollectionType.HASHTABLE)
468:                            || (colType == FieldMappingCollectionType.MAP)
469:                            || (colType == FieldMappingCollectionType.SORTEDMAP)) {
470:                        fieldMap.setType(MapItem.class.getName());
471:                    }
472:                }
473:
474:                // Create an XML field descriptor
475:                fieldDesc = super .createFieldDesc(javaClass, fieldMap);
476:
477:                BindXml xml = fieldMap.getBindXml();
478:
479:                boolean deriveNameByClass = false;
480:
481:                if (xml != null) {
482:                    //-- xml name
483:                    xmlName = xml.getName();
484:
485:                    //-- node type
486:                    if (xml.getNode() != null)
487:                        nodeType = NodeType.getNodeType(xml.getNode()
488:                                .toString());
489:
490:                    //-- matches
491:                    match = xml.getMatches();
492:
493:                    //-- reference
494:                    isReference = xml.getReference();
495:
496:                    //-- XML transient
497:                    isXMLTransient = xml.getTransient();
498:
499:                    //-- autonaming
500:                    BindXmlAutoNamingType autoName = xml.getAutoNaming();
501:                    if (autoName != null) {
502:                        deriveNameByClass = (autoName == BindXmlAutoNamingType.DERIVEBYCLASS);
503:                    }
504:
505:                }
506:
507:                //-- transient
508:                //-- XXXX -> if it's transient we probably shouldn't do all
509:                //-- XXXX -> the unecessary work
510:                isXMLTransient = isXMLTransient || fieldDesc.isTransient();
511:
512:                //--
513:
514:                //-- handle QName for xmlName
515:                String namespace = null;
516:                if ((xmlName != null) && (xmlName.length() > 0)) {
517:                    if (xmlName.charAt(0) == '{') {
518:                        int idx = xmlName.indexOf('}');
519:                        if (idx < 0) {
520:                            throw new MappingException("Invalid QName: "
521:                                    + xmlName);
522:                        }
523:                        namespace = xmlName.substring(1, idx);
524:                        xmlName = xmlName.substring(idx + 1);
525:                    } else if (xmlName.startsWith(XML_PREFIX)) {
526:                        namespace = Namespaces.XML_NAMESPACE;
527:                        xmlName = xmlName.substring(4);
528:                    }
529:                }
530:
531:                if (nodeType == null) {
532:                    if (isPrimitive(javaClass))
533:                        nodeType = _primitiveNodeType;
534:                    else
535:                        nodeType = NodeType.Element;
536:                }
537:
538:                //-- Create XML name if necessary. Note if name is to be derived
539:                //-- by class..we just make sure we set the name to null...
540:                //-- the Marshaller does this during runtime. This allows
541:                //-- Collections to be handled properly.
542:                if ((!deriveNameByClass)
543:                        && ((xmlName == null) && (match == null))) {
544:                    xmlName = _naming.toXMLName(fieldDesc.getFieldName());
545:                    match = xmlName + ' ' + fieldDesc.getFieldName();
546:                }
547:
548:                xmlDesc = new XMLFieldDescriptorImpl(fieldDesc, xmlName,
549:                        nodeType, _primitiveNodeType);
550:
551:                //-- transient?
552:                xmlDesc.setTransient(isXMLTransient);
553:
554:                //--set a default fieldValidator
555:                xmlDesc.setValidator(new FieldValidator());
556:
557:                //-- enable use parent namespace if explicit one doesn't exist
558:                xmlDesc.setUseParentsNamespace(true);
559:
560:                //-- If deriveNameByClass we need to reset the name to
561:                //-- null because XMLFieldDescriptorImpl tries to be smart
562:                //-- and automatically creates the name.
563:                if (deriveNameByClass) {
564:                    xmlDesc.setXMLName(null);
565:                }
566:
567:                //-- namespace
568:                if (namespace != null) {
569:                    xmlDesc.setNameSpaceURI(namespace);
570:                }
571:
572:                //-- matches
573:                if (match != null) {
574:                    xmlDesc.setMatches(match);
575:                    //-- special fix for xml-name since XMLFieldDescriptorImpl
576:                    //-- will create a default name based off the field name
577:                    if (xmlName == null)
578:                        xmlDesc.setXMLName(null);
579:                }
580:
581:                //-- reference
582:                xmlDesc.setReference(isReference);
583:                if (isReference) {
584:                    if (colType == null) {
585:                        FieldValidator fieldValidator = new FieldValidator();
586:                        fieldValidator.setValidator(new IdRefValidator());
587:                        xmlDesc.setValidator(fieldValidator);
588:                    } else {
589:                        // TODO handle other cases
590:                    }
591:                }
592:
593:                xmlDesc.setContainer(fieldMap.getContainer());
594:
595:                if (xml != null) {
596:
597:                    //-- has class descriptor for type specified
598:                    if (xml.getClassMapping() != null) {
599:                        ClassDescriptor cd = createClassDescriptor(xml
600:                                .getClassMapping());
601:                        xmlDesc.setClassDescriptor(cd);
602:                    }
603:
604:                    //-- has location path?
605:                    if (xml.getLocation() != null) {
606:                        xmlDesc.setLocationPath(xml.getLocation());
607:                    }
608:                    //is the value type needs specific handling
609:                    //such as QName or NCName support?
610:                    String xmlType = xml.getType();
611:                    xmlDesc.setSchemaType(xmlType);
612:                    xmlDesc.setQNamePrefix(xml.getQNamePrefix());
613:                    TypeValidator validator = null;
614:                    if (NCNAME.equals(xmlType)) {
615:                        validator = new NameValidator(
616:                                XMLConstants.NAME_TYPE_NCNAME);
617:                        xmlDesc.setValidator(new FieldValidator(validator));
618:                    }
619:
620:                    //-- special properties?
621:                    Property[] props = xml.getProperty();
622:                    if ((props != null) && (props.length > 0)) {
623:                        for (int pIdx = 0; pIdx < props.length; pIdx++) {
624:                            Property prop = props[pIdx];
625:                            xmlDesc
626:                                    .setProperty(prop.getName(), prop
627:                                            .getValue());
628:                        }
629:                    }
630:                }
631:
632:                //-- Get collection type
633:                if (colType == null) {
634:                    //-- just in case user forgot to use collection="..."
635:                    //-- in the mapping file
636:                    Class type = fieldDesc.getFieldType();
637:                    if (type != null && CollectionHandlers.hasHandler(type)) {
638:                        String typeName = CollectionHandlers
639:                                .getCollectionName(type);
640:                        colType = FieldMappingCollectionType.valueOf(typeName);
641:                    }
642:                }
643:
644:                //-- isMapped item
645:                if (colType != null) {
646:                    if ((colType == FieldMappingCollectionType.HASHTABLE)
647:                            || (colType == FieldMappingCollectionType.MAP)
648:                            || (colType == FieldMappingCollectionType.SORTEDMAP)) {
649:                        //-- Make sure user is not using an addMethod
650:                        //-- before setting the mapped field to true.
651:                        String methodName = fieldMap.getSetMethod();
652:                        if (methodName != null) {
653:                            if (!methodName.startsWith("add")) {
654:                                xmlDesc.setMapped(true);
655:                            }
656:                        } else
657:                            xmlDesc.setMapped(true);
658:                    }
659:
660:                    //-- special NodeType.Namespace handling
661:                    //-- prevent FieldHandlerImpl from using CollectionHandler
662:                    //-- during calls to #getValue
663:                    if ((nodeType == NodeType.Namespace)
664:                            || (xmlDesc.isMapped())) {
665:                        Object handler = xmlDesc.getHandler();
666:                        if (handler instanceof  FieldHandlerImpl) {
667:                            FieldHandlerImpl handlerImpl = (FieldHandlerImpl) handler;
668:                            handlerImpl.setConvertFrom(new IdentityConvertor());
669:                        }
670:                    }
671:                    //-- wrap collection in element?
672:                    if (nodeType == NodeType.Element) {
673:                        if (fieldMap.hasContainer()
674:                                && (!fieldMap.getContainer())) {
675:                            xmlDesc = wrapCollection(xmlDesc);
676:                        }
677:                    }
678:                }
679:
680:                //-- is Type-Safe Enumeration?
681:                //-- This is not very clean, we should have a way
682:                //-- to specify something is a type-safe enumeration
683:                //-- without having to guess.
684:                else if ((!isReference) && (!isXMLTransient)) {
685:                    Class fieldType = xmlDesc.getFieldType();
686:                    if (!isPrimitive(fieldType)) {
687:                        //-- make sure no default constructor
688:                        Constructor cons = null;
689:                        try {
690:                            cons = fieldType.getConstructor(EMPTY_ARGS);
691:                            if (!Modifier.isPublic(cons.getModifiers())) {
692:                                cons = null;
693:                            }
694:                        } catch (NoSuchMethodException nsmx) {
695:                            //-- Do nothing
696:                        }
697:                        try {
698:                            if (cons == null) {
699:                                //-- make sure a valueOf factory method
700:                                //-- exists and no user specified handler exists
701:                                Method method = fieldType.getMethod(VALUE_OF,
702:                                        STRING_ARG);
703:                                Class returnType = method.getReturnType();
704:                                if ((returnType != null)
705:                                        && fieldType
706:                                                .isAssignableFrom(returnType)) {
707:                                    if (fieldMap.getHandler() == null) {
708:                                        //-- Use EnumFieldHandler
709:                                        //-- mapping loader now supports a basic EnumFieldHandler
710:                                        //-- for xml we simply need to make sure the toString()
711:                                        //-- method is called during getValue()
712:                                        //FieldHandler handler = xmlDesc.getHandler();
713:                                        //handler = new EnumFieldHandler(fieldType, handler);
714:
715:                                        FieldHandler handler = new ToStringFieldHandler(
716:                                                fieldType, xmlDesc.getHandler());
717:
718:                                        xmlDesc.setHandler(handler);
719:                                        xmlDesc.setImmutable(true);
720:                                    }
721:                                }
722:                            }
723:                        } catch (NoSuchMethodException nsmx) {
724:                            //-- Do nothing
725:                        }
726:                    }
727:                }
728:
729:                //-- constructor argument?
730:                String setter = fieldMap.getSetMethod();
731:                if (setter != null) {
732:                    if (setter.startsWith("%")) {
733:                        int index = 0;
734:                        setter = setter.substring(1);
735:                        index = Integer.parseInt(setter);
736:                        if ((index < 1) || (index > 9)) {
737:                            throw new MappingException(
738:                                    "mapper.invalidParameterIndex", setter);
739:                        }
740:                        //-- adjust index to base zero
741:                        --index;
742:                        xmlDesc.setConstructorArgumentIndex(index);
743:                    }
744:                }
745:
746:                return xmlDesc;
747:            }
748:
749:            /**
750:             * Sets whether or not to look for and load package specific
751:             * mapping files (".castor.xml" files).
752:             *
753:             * @param loadPackageMappings a boolean that enables or
754:             * disables the loading of package specific mapping files
755:             */
756:            public void setLoadPackageMappings(boolean loadPackageMappings) {
757:                if (_cdResolver == null) {
758:                    createResolver();
759:                }
760:                _cdResolver.setLoadPackageMappings(loadPackageMappings);
761:            } //-- setLoadPackageMappings
762:
763:            protected TypeInfo getTypeInfo(Class fieldType,
764:                    CollectionHandler colHandler, FieldMapping fieldMap)
765:                    throws MappingException {
766:                return new TypeInfo(fieldType, null, null, null, fieldMap
767:                        .getRequired(), null, colHandler, false);
768:            }
769:
770:            /**
771:             * This method allows a collection to be treated as a first class
772:             * object (and not a container) so that it has an element representation
773:             * in the marshalled XML.
774:             */
775:            private XMLFieldDescriptorImpl wrapCollection(
776:                    XMLFieldDescriptorImpl fieldDesc) throws MappingException {
777:                //-- If we have a field 'c' that is a collection and
778:                //-- we want to wrap that field in an element <e>, we
779:                //-- need to create a field descriptor for
780:                //-- an object that represents the element <e> and
781:                //-- acts as a go-between from the parent of 'c'
782:                //-- denoted as P(c) and 'c' itself
783:                //
784:                //   object model: P(c) -> c
785:                //   xml : <p><e><c></e><p>
786:
787:                //-- Make new class descriptor for the field that
788:                //-- will represent the container element <e>
789:                Class type = ContainerElement.class;
790:                XMLClassDescriptorImpl classDesc = new XMLClassDescriptorImpl(
791:                        type);
792:                //-- make copy of fieldDesc and add it to our new class descriptor
793:                XMLFieldDescriptorImpl newFieldDesc = new XMLFieldDescriptorImpl(
794:                        fieldDesc, fieldDesc.getXMLName(), fieldDesc
795:                                .getNodeType(), _primitiveNodeType);
796:                //-- nullify xmlName so that auto-naming will be enabled,
797:                //-- we can't do this in the constructor because
798:                //-- XMLFieldDescriptorImpl will create a default one.
799:                newFieldDesc.setXMLName(null);
800:                newFieldDesc.setMatches("*");
801:
802:                //-- add the field descriptor to our new class descriptor
803:                classDesc.addFieldDescriptor(newFieldDesc);
804:                //-- reassociate the orignal class descriptor (for 'c')
805:                // of fieldDesc with our new classDesc
806:                fieldDesc.setClassDescriptor(classDesc);
807:
808:                //-- wrap the field handler in a special container field
809:                //-- handler that will actually do the delgation work
810:                FieldHandler handler = new ContainerFieldHandler(fieldDesc
811:                        .getHandler());
812:                newFieldDesc.setHandler(handler);
813:                fieldDesc.setHandler(handler);
814:
815:                //-- Change fieldType of original field descriptor and
816:                //-- return new descriptor
817:                return new XMLContainerElementFieldDescriptor(fieldDesc,
818:                        _primitiveNodeType);
819:            } //-- createWrapperDescriptor
820:
821:            /**
822:             * A special TypeConvertor that simply returns the object
823:             * given. This is used for preventing the FieldHandlerImpl
824:             * from using a CollectionHandler when getValue is called.
825:             **/
826:            class IdentityConvertor implements  TypeConvertor {
827:                public Object convert(Object object, String param)
828:                        throws ClassCastException {
829:                    return object;
830:                }
831:            } //-- class: IdentityConvertor
832:        } //-- class: XMLMappingLoader
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.