Source Code Cross Referenced for SchemaGenerator.java in  » XML » jibx-1.1.5 » org » jibx » binding » 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 » XML » jibx 1.1.5 » org.jibx.binding 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:        Copyright (c) 2004-2005, Dennis M. Sosnoski
0003:        All rights reserved.
0004:
0005:        Redistribution and use in source and binary forms, with or without modification,
0006:        are permitted provided that the following conditions are met:
0007:
0008:         * Redistributions of source code must retain the above copyright notice, this
0009:           list of conditions and the following disclaimer.
0010:         * Redistributions in binary form must reproduce the above copyright notice,
0011:           this list of conditions and the following disclaimer in the documentation
0012:           and/or other materials provided with the distribution.
0013:         * Neither the name of JiBX nor the names of its contributors may be used
0014:           to endorse or promote products derived from this software without specific
0015:           prior written permission.
0016:
0017:        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0018:        ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0019:        WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0020:        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
0021:        ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0022:        (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0023:        LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
0024:        ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0025:        (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0026:        SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0027:         */
0028:
0029:        package org.jibx.binding;
0030:
0031:        import java.io.File;
0032:        import java.io.FileInputStream;
0033:        import java.io.FileNotFoundException;
0034:        import java.io.FileOutputStream;
0035:        import java.io.IOException;
0036:        import java.net.MalformedURLException;
0037:        import java.net.URL;
0038:        import java.util.ArrayList;
0039:        import java.util.HashMap;
0040:        import java.util.Iterator;
0041:
0042:        import javax.xml.parsers.DocumentBuilderFactory;
0043:        import javax.xml.parsers.FactoryConfigurationError;
0044:        import javax.xml.parsers.ParserConfigurationException;
0045:        import javax.xml.transform.Result;
0046:        import javax.xml.transform.Transformer;
0047:        import javax.xml.transform.TransformerConfigurationException;
0048:        import javax.xml.transform.TransformerException;
0049:        import javax.xml.transform.TransformerFactory;
0050:        import javax.xml.transform.TransformerFactoryConfigurationError;
0051:        import javax.xml.transform.dom.DOMSource;
0052:        import javax.xml.transform.stream.StreamResult;
0053:
0054:        import org.jibx.binding.classes.ClassCache;
0055:        import org.jibx.binding.classes.ClassFile;
0056:        import org.jibx.binding.model.BindingElement;
0057:        import org.jibx.binding.model.ClassWrapper;
0058:        import org.jibx.binding.model.CollectionElement;
0059:        import org.jibx.binding.model.ContainerElementBase;
0060:        import org.jibx.binding.model.DefinitionContext;
0061:        import org.jibx.binding.model.ElementBase;
0062:        import org.jibx.binding.model.IClass;
0063:        import org.jibx.binding.model.IClassLocator;
0064:        import org.jibx.binding.model.MappingElement;
0065:        import org.jibx.binding.model.NestingAttributes;
0066:        import org.jibx.binding.model.NestingElementBase;
0067:        import org.jibx.binding.model.StructureElement;
0068:        import org.jibx.binding.model.StructureElementBase;
0069:        import org.jibx.binding.model.TemplateElementBase;
0070:        import org.jibx.binding.model.ValidationContext;
0071:        import org.jibx.binding.model.ValidationProblem;
0072:        import org.jibx.binding.model.ValueElement;
0073:        import org.jibx.binding.util.ObjectStack;
0074:        import org.jibx.runtime.JiBXException;
0075:        import org.jibx.runtime.ValidationException;
0076:        import org.w3c.dom.Document;
0077:        import org.w3c.dom.Element;
0078:
0079:        /**
0080:         * Binding generator. This loads the specified input classes and processes them
0081:         * to generate a default binding definition.
0082:         *
0083:         * @author Dennis M. Sosnoski
0084:         * @version 1.0
0085:         */
0086:
0087:        public class SchemaGenerator {
0088:            /** Generator version. */
0089:            private static String CURRENT_VERSION = "0.2";
0090:
0091:            /** Schema namespace URI. */
0092:            private static final String XSD_URI = "http://www.w3.org/2001/XMLSchema";
0093:
0094:            /** Fixed XML namespace. */
0095:            public static final String XML_URI = "http://www.w3.org/XML/1998/namespace";
0096:
0097:            /** Fixed XML namespace namespace. */
0098:            public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
0099:
0100:            /** Set of object types mapped to schema types. */
0101:            private static HashMap s_objectTypeMap = new HashMap();
0102:
0103:            static {
0104:                s_objectTypeMap.put("java.lang.Boolean", "xsd:boolean");
0105:                s_objectTypeMap.put("java.lang.Byte", "xsd:byte");
0106:                s_objectTypeMap.put("java.lang.Char", "xsd:unsignedInt");
0107:                s_objectTypeMap.put("java.lang.Double", "xsd:double");
0108:                s_objectTypeMap.put("java.lang.Float", "xsd:float");
0109:                s_objectTypeMap.put("java.lang.Integer", "xsd:int");
0110:                s_objectTypeMap.put("java.lang.Long", "xsd:long");
0111:                s_objectTypeMap.put("java.lang.Short", "xsd:short");
0112:                s_objectTypeMap.put("java.math.BigDecimal", "xsd:decimal");
0113:                s_objectTypeMap.put("java.math.BigInteger", "xsd:integer");
0114:                //#!j2me{
0115:                s_objectTypeMap.put("java.sql.Date", "xsd:date");
0116:                s_objectTypeMap.put("java.sql.Time", "xsd:time");
0117:                s_objectTypeMap.put("java.sql.Timestamp", "xsd:dateTime");
0118:                //#j2me}
0119:                s_objectTypeMap.put("java.util.Date", "xsd:dateTime");
0120:                s_objectTypeMap.put("byte[]", "xsd:base64");
0121:            }
0122:
0123:            /** Set of primitive types mapped to schema types. */
0124:            private static HashMap s_primitiveTypeMap = new HashMap();
0125:
0126:            static {
0127:                s_primitiveTypeMap.put("boolean", "xsd:boolean");
0128:                s_primitiveTypeMap.put("byte", "xsd:byte");
0129:                s_primitiveTypeMap.put("char", "xsd:unsignedInt");
0130:                s_primitiveTypeMap.put("double", "xsd:double");
0131:                s_primitiveTypeMap.put("float", "xsd:float");
0132:                s_primitiveTypeMap.put("int", "xsd:int");
0133:                s_primitiveTypeMap.put("long", "xsd:long");
0134:                s_primitiveTypeMap.put("short", "xsd:short");
0135:            }
0136:
0137:            /** Show verbose output flag. */
0138:            private boolean m_verbose;
0139:
0140:            /** Use qualified elements default in schema flag. */
0141:            private boolean m_isElementQualified;
0142:
0143:            /** Use qualified attributes default in schema flag. */
0144:            private boolean m_isAttributeQualified;
0145:
0146:            /** Indentation sequence per level of nesting. */
0147:            private String m_indentSequence;
0148:
0149:            /** Map from namespaces to schemas. */
0150:            private HashMap m_schemaMap;
0151:
0152:            /** Locator for finding classes referenced by binding. */
0153:            private IClassLocator m_classLocator;
0154:
0155:            /** Document used for all schema definitions. */
0156:            private Document m_document;
0157:
0158:            /** Stack of structure definitions in progress (used to detect cycles). */
0159:            private ObjectStack m_structureStack;
0160:
0161:            /**
0162:             * Constructor with only paths supplied. This just initializes all other
0163:             * options disabled.
0164:             * 
0165:             * @param paths class paths to be checked for classes referenced by bindings
0166:             */
0167:            public SchemaGenerator(ArrayList paths) {
0168:                m_structureStack = new ObjectStack();
0169:                m_schemaMap = new HashMap();
0170:
0171:                // set paths to be used for loading referenced classes
0172:                String[] parray = (String[]) paths.toArray(new String[paths
0173:                        .size()]);
0174:                ClassCache.setPaths(parray);
0175:                ClassFile.setPaths(parray);
0176:
0177:                // set class locator
0178:                m_classLocator = new IClassLocator() {
0179:                    public IClass getClassInfo(String name) {
0180:                        try {
0181:                            return new ClassWrapper(ClassCache
0182:                                    .getClassFile(name));
0183:                        } catch (JiBXException e) {
0184:                            throw new IllegalStateException("Class not found "
0185:                                    + name);
0186:                        }
0187:                    }
0188:                };
0189:                try {
0190:
0191:                    // create the document used for all schemas
0192:                    DocumentBuilderFactory dbf = DocumentBuilderFactory
0193:                            .newInstance();
0194:                    dbf.setNamespaceAware(true);
0195:                    m_document = dbf.newDocumentBuilder().newDocument();
0196:
0197:                } catch (ParserConfigurationException e) {
0198:                    throw new IllegalStateException(
0199:                            "Parser configuration error " + e.getMessage());
0200:                } catch (FactoryConfigurationError e) {
0201:                    throw new IllegalStateException(
0202:                            "Factory configuration error " + e.getMessage());
0203:                }
0204:            }
0205:
0206:            /**
0207:             * Constructor with settings specified.
0208:             *
0209:             * @param verbose report binding details and results
0210:             * @param equal use element form default qualified flag
0211:             * @param aqual use attribute form default qualified flag
0212:             * @param paths class paths to be checked for classes referenced by bindings
0213:             */
0214:            public SchemaGenerator(boolean verbose, boolean equal,
0215:                    boolean aqual, ArrayList paths) {
0216:                this (paths);
0217:                m_verbose = verbose;
0218:                m_isElementQualified = equal;
0219:                m_isAttributeQualified = aqual;
0220:                m_indentSequence = "  ";
0221:            }
0222:
0223:            /**
0224:             * Set control flag for verbose processing reports.
0225:             * 
0226:             * @param verbose report verbose information in processing bindings flag
0227:             */
0228:            public void setVerbose(boolean verbose) {
0229:                m_verbose = verbose;
0230:            }
0231:
0232:            /**
0233:             * Set control flag for element qualified default schema.
0234:             * 
0235:             * @param qual element qualified default schemas flag
0236:             */
0237:            public void setElementQualified(boolean qual) {
0238:                m_isElementQualified = qual;
0239:            }
0240:
0241:            /**
0242:             * Set control flag for attribute qualified default schema.
0243:             * 
0244:             * @param qual attribute qualified default schemas flag
0245:             */
0246:            public void setAttributeQualified(boolean qual) {
0247:                m_isAttributeQualified = qual;
0248:            }
0249:
0250:            /**
0251:             * Get array of generated schemas.
0252:             * 
0253:             * @return array of schema elements
0254:             */
0255:            public Element[] getSchemas() {
0256:                Element[] schemas = new Element[m_schemaMap.size()];
0257:                int fill = 0;
0258:                for (Iterator iter = m_schemaMap.values().iterator(); iter
0259:                        .hasNext();) {
0260:                    schemas[fill++] = (Element) iter.next();
0261:                }
0262:                return schemas;
0263:            }
0264:
0265:            /**
0266:             * Generate indentation to proper depth for current item. This creates the
0267:             * indentation text and appends it to the supplied parent. The generated
0268:             * indentation is appropriate for the close tag of the parent element; if
0269:             * a child element is to be added following this indentation it needs to
0270:             * use an additional leading indent.
0271:             *
0272:             * @param parent element to contain indented child item
0273:             */
0274:            private void indentForClose(Element parent) {
0275:                StringBuffer buff = new StringBuffer(20);
0276:                buff.append('\n');
0277:                Element ancestor = parent;
0278:                boolean count = false;
0279:                while (ancestor != null) {
0280:                    if (count) {
0281:                        buff.append(m_indentSequence);
0282:                    }
0283:                    ancestor = (Element) ancestor.getParentNode();
0284:                    count = true;
0285:                }
0286:                parent.appendChild(m_document.createTextNode(buff.toString()));
0287:            }
0288:
0289:            /**
0290:             * Add comment with appropriate indentation.
0291:             *
0292:             * @param parent element to contain indented child item
0293:             * @param text comment text
0294:             */
0295:            private void addComment(Element parent, String text) {
0296:                if (parent.getChildNodes().getLength() == 0) {
0297:                    indentForClose(parent);
0298:                }
0299:                parent.appendChild(m_document.createTextNode(m_indentSequence));
0300:                parent.appendChild(m_document.createComment(text));
0301:                indentForClose(parent);
0302:            }
0303:
0304:            /**
0305:             * Add child element with appropriate indentation. This generates and
0306:             * returns the child element after adding it to the supplied parent,
0307:             * allowing further modification of the new child element.
0308:             *
0309:             * @param parent element to contain indented child item
0310:             * @param name child element name
0311:             */
0312:            private Element addChildElement(Element parent, String name) {
0313:                if (parent.getChildNodes().getLength() == 0) {
0314:                    indentForClose(parent);
0315:                }
0316:                parent.appendChild(m_document.createTextNode(m_indentSequence));
0317:                Element element = m_document.createElementNS(XSD_URI, name);
0318:                parent.appendChild(element);
0319:                indentForClose(parent);
0320:                return element;
0321:            }
0322:
0323:            /**
0324:             * Get innermost containing definition context.
0325:             * 
0326:             * @return innermost definition context containing this element
0327:             */
0328:            public DefinitionContext getDefinitions() {
0329:                int index = 0;
0330:                while (index < m_structureStack.size()) {
0331:                    NestingElementBase nest = (NestingElementBase) m_structureStack
0332:                            .peek(index++);
0333:                    if (nest.getDefinitions() != null) {
0334:                        return nest.getDefinitions();
0335:                    }
0336:                }
0337:                throw new IllegalStateException(
0338:                        "Internal error: no definition context");
0339:            }
0340:
0341:            /**
0342:             * Process a structure component (structure or collection element) with no
0343:             * name and no child components. This adds the appropriate type of element
0344:             * or any definition to the container schema element.
0345:             * 
0346:             * @param comp structure component to be processed
0347:             * @param egroup schema element to contain element definitions
0348:             * @param agroup schema element to contain attribute definitions
0349:             */
0350:            private void defineEmptyStructureComponent(
0351:                    StructureElementBase comp, Element egroup, Element agroup) {
0352:                NestingElementBase parent = (NestingElementBase) m_structureStack
0353:                        .peek(0);
0354:                boolean only = parent.children().size() == 1;
0355:                if (comp.type() == ElementBase.COLLECTION_ELEMENT) {
0356:
0357:                    // collection may define type or not
0358:                    CollectionElement collection = (CollectionElement) comp;
0359:                    String itype = collection.getItemTypeClass().getName();
0360:                    DefinitionContext dctx = getDefinitions();
0361:                    TemplateElementBase templ = dctx.getSpecificTemplate(itype);
0362:                    Element element = null;
0363:                    if (!(templ instanceof  MappingElement)) {
0364:                        if (only) {
0365:                            addComment(egroup,
0366:                                    " Replace \"any\" with details of "
0367:                                            + "content to complete schema ");
0368:                            element = addChildElement(egroup, "any");
0369:                        } else {
0370:                            addComment(egroup,
0371:                                    " No mapping for items of collection at "
0372:                                            + ValidationException
0373:                                                    .describe(collection) + " ");
0374:                            addComment(egroup,
0375:                                    " Fill in details of content to complete schema ");
0376:                        }
0377:                    } else {
0378:                        element = addChildElement(egroup, "element");
0379:                        element.setAttribute("ref", "tns:"
0380:                                + ((MappingElement) templ).getName());
0381:                    }
0382:                    if (element != null) {
0383:                        element.setAttribute("minOccurs", "0");
0384:                        element.setAttribute("maxOccurs", "unbounded");
0385:                    }
0386:
0387:                } else {
0388:
0389:                    // check for reference to a mapped class
0390:                    StructureElement structure = (StructureElement) comp;
0391:                    TemplateElementBase templ = structure.getMapAsMapping();
0392:                    if (!(templ instanceof  MappingElement)) {
0393:
0394:                        // unknown content, leave it to user to fill in details
0395:                        if (only) {
0396:                            addComment(egroup,
0397:                                    " Replace \"any\" with details of "
0398:                                            + "content to complete schema ");
0399:                            addChildElement(egroup, "any");
0400:                        } else {
0401:                            addComment(egroup, " No mapping for structure at "
0402:                                    + ValidationException.describe(structure)
0403:                                    + " ");
0404:                            addComment(egroup,
0405:                                    " Fill in details of content here to complete schema ");
0406:                        }
0407:
0408:                    } else {
0409:                        MappingElement mapping = (MappingElement) templ;
0410:                        if (mapping.isAbstract()) {
0411:
0412:                            // check name to be used for instance of type
0413:                            String ename = structure.getName();
0414:                            if (ename == null) {
0415:                                ename = mapping.getName();
0416:                            }
0417:                            if (ename == null) {
0418:
0419:                                // no schema equivalent, embed definition directly
0420:                                addComment(
0421:                                        egroup,
0422:                                        "No schema representation for "
0423:                                                + "directly-embedded type, inlining definition");
0424:                                addComment(egroup,
0425:                                        "Add element name to structure at "
0426:                                                + ValidationException
0427:                                                        .describe(structure)
0428:                                                + " to avoid inlining");
0429:                                defineList(mapping.children(), egroup, agroup,
0430:                                        false);
0431:
0432:                            } else {
0433:
0434:                                // handle abstract mapping element as reference to type
0435:                                Element element = addChildElement(egroup,
0436:                                        "element");
0437:                                String tname = simpleClassName(mapping
0438:                                        .getClassName());
0439:                                element.setAttribute("type", "tns:" + tname);
0440:                                String name = structure.getName();
0441:                                if (name == null) {
0442:                                    name = mapping.getName();
0443:                                }
0444:                                element.setAttribute("name", name);
0445:                                if (structure.isOptional()) {
0446:                                    element.setAttribute("minOccurs", "0");
0447:                                }
0448:                            }
0449:
0450:                        } else {
0451:
0452:                            // concrete mapping, check for name overridden
0453:                            String sname = structure.getName();
0454:                            String mname = mapping.getName();
0455:                            if (sname != null && !sname.equals(mname)) {
0456:
0457:                                // inline definition for overridden name
0458:                                addComment(
0459:                                        egroup,
0460:                                        "No schema representation for "
0461:                                                + "element reference with different name, inlining "
0462:                                                + "definition");
0463:                                addComment(egroup,
0464:                                        "Remove name on mapping reference at "
0465:                                                + ValidationException
0466:                                                        .describe(structure)
0467:                                                + " to avoid inlining");
0468:                                defineList(mapping.children(), egroup, agroup,
0469:                                        false);
0470:
0471:                            } else {
0472:
0473:                                // use element reference for concrete mapping
0474:                                Element element = addChildElement(egroup,
0475:                                        "element");
0476:                                String tname = simpleClassName(mapping
0477:                                        .getClassName());
0478:                                element.setAttribute("ref", "tns:" + mname);
0479:                                if (structure.isOptional()) {
0480:                                    element.setAttribute("minOccurs", "0");
0481:                                }
0482:                            }
0483:
0484:                        }
0485:                    }
0486:
0487:                }
0488:            }
0489:
0490:            /**
0491:             * Process a structure component (structure or collection element) within a
0492:             * list of child components. This adds the appropriate type of element or
0493:             * any definition to the container, if necessary calling other methods for
0494:             * recursive handling of nested child components.
0495:             * 
0496:             * @param comp structure component to be processed
0497:             * @param egroup schema element to contain element definitions
0498:             * @param agroup schema element to contain attribute definitions
0499:             * @param mult allow any number of occurrences of components flag
0500:             */
0501:            private void defineStructureComponent(StructureElementBase comp,
0502:                    Element egroup, Element agroup, boolean mult) {
0503:
0504:                // check for element defined by binding component
0505:                if (comp.getName() != null) {
0506:
0507:                    // create basic element definition for name
0508:                    Element element = addChildElement(egroup, "element");
0509:                    element.setAttribute("name", comp.getName());
0510:                    if (mult) {
0511:                        element.setAttribute("minOccurs", "0");
0512:                        element.setAttribute("maxOccurs", "unbounded");
0513:                    } else if (comp.isOptional()) {
0514:                        element.setAttribute("minOccurs", "0");
0515:                    }
0516:
0517:                    // check for children present
0518:                    if (comp.children().size() > 0) {
0519:                        defineNestedStructure(comp, element);
0520:                    } else {
0521:
0522:                        // nest complex type definition for actual content
0523:                        Element type = addChildElement(element, "complexType");
0524:                        Element seq = addChildElement(type, "sequence");
0525:
0526:                        // process the content description
0527:                        defineEmptyStructureComponent(comp, seq, type);
0528:                    }
0529:
0530:                } else if (comp.children().size() > 0) {
0531:
0532:                    // handle child components with recursive call
0533:                    boolean coll = comp.type() == ElementBase.COLLECTION_ELEMENT;
0534:                    m_structureStack.push(comp);
0535:                    defineList(comp.children(), egroup, agroup, coll);
0536:                    m_structureStack.pop();
0537:
0538:                } else {
0539:
0540:                    // handle empty structure definition inline
0541:                    defineEmptyStructureComponent(comp, egroup, agroup);
0542:                }
0543:            }
0544:
0545:            /**
0546:             * Create the schema definition list for a binding component list. This
0547:             * builds the sequence of elements and attributes defined by the binding
0548:             * components, including nested complex types for elements with structure.
0549:             * 
0550:             * @param comps binding component list
0551:             * @param egroup schema element to contain element definitions
0552:             * @param agroup schema element to contain attribute definitions
0553:             * @param mult allow any number of occurrences of components flag
0554:             */
0555:            private void defineList(ArrayList comps, Element egroup,
0556:                    Element agroup, boolean mult) {
0557:
0558:                // handle all nested elements of container
0559:                for (int i = 0; i < comps.size(); i++) {
0560:                    ElementBase child = (ElementBase) comps.get(i);
0561:                    switch (child.type()) {
0562:
0563:                    case ElementBase.COLLECTION_ELEMENT:
0564:                    case ElementBase.STRUCTURE_ELEMENT: {
0565:                        defineStructureComponent((StructureElementBase) child,
0566:                                egroup, agroup, mult);
0567:                        break;
0568:                    }
0569:
0570:                    case ElementBase.MAPPING_ELEMENT: {
0571:                        // nested mapping definitions not handled
0572:                        System.err
0573:                                .println("Error: nested mapping not supported "
0574:                                        + "(class "
0575:                                        + ((MappingElement) child)
0576:                                                .getClassName() + ")");
0577:                        break;
0578:                    }
0579:
0580:                    case ElementBase.TEMPLATE_ELEMENT: {
0581:                        // templates to be added once usable in binding
0582:                        System.err
0583:                                .println("Error: template component not yet supported");
0584:                        break;
0585:                    }
0586:
0587:                    case ElementBase.VALUE_ELEMENT: {
0588:                        // get type information for value
0589:                        ValueElement value = (ValueElement) child;
0590:                        String tname = value.getType().getName();
0591:                        String stype = (String) s_primitiveTypeMap.get(tname);
0592:                        if (stype == null) {
0593:                            stype = (String) s_objectTypeMap.get(tname);
0594:                            if (stype == null) {
0595:                                stype = "xsd:string";
0596:                            }
0597:                        }
0598:
0599:                        // build schema element or attribute for value
0600:                        Element element;
0601:                        int style = value.getStyle();
0602:                        if (style == NestingAttributes.ATTRIBUTE_STYLE) {
0603:
0604:                            // append attribute as child of type
0605:                            element = addChildElement(agroup, "attribute");
0606:                            if (!value.isOptional()) {
0607:                                element.setAttribute("use", "required");
0608:                            }
0609:
0610:                        } else if (style == NestingAttributes.ELEMENT_STYLE) {
0611:
0612:                            // append simple element as child of grouping
0613:                            element = addChildElement(egroup, "element");
0614:                            if (mult) {
0615:                                element.setAttribute("minOccurs", "0");
0616:                                element.setAttribute("maxOccurs", "unbounded");
0617:                            } else if (value.isOptional()) {
0618:                                element.setAttribute("minOccurs", "0");
0619:                            }
0620:
0621:                        } else {
0622:
0623:                            // other types are not currently handled
0624:                            System.err.println("Error: value type "
0625:                                    + value.getEffectiveStyleName()
0626:                                    + " not supported");
0627:                            break;
0628:
0629:                        }
0630:
0631:                        // set common attributes on definition
0632:                        element.setAttribute("name", value.getName());
0633:                        element.setAttribute("type", stype);
0634:                        break;
0635:                    }
0636:                    }
0637:                }
0638:            }
0639:
0640:            /**
0641:             * Create the schema definition for a nested structure. This defines a
0642:             * complex type, if necessary calling itself recursively for elements which
0643:             * are themselves complex types. In the special case where the container
0644:             * element is a mapping which extends an abstract base class this generates
0645:             * the complex type as an extension of the base class complex type.
0646:             * 
0647:             * @param container binding definition element containing nested structure
0648:             * @param parent schema element to hold the definition
0649:             * @return constructed complex type
0650:             */
0651:            private Element defineNestedStructure(
0652:                    ContainerElementBase container, Element parent) {
0653:
0654:                // create complex type as holder for definition
0655:                Element type = addChildElement(parent, "complexType");
0656:
0657:                // check whether ordered or unordered container
0658:                Element group;
0659:                ArrayList childs = container.children();
0660:                if (container.isOrdered()) {
0661:
0662:                    // define content list as sequence
0663:                    group = addChildElement(type, "sequence");
0664:
0665:                    // check for mapping which extends another mapping
0666:                    /*            if (container instanceof MappingElement) {
0667:                     MappingElement mapping = (MappingElement)container;
0668:                     MappingElement extended = mapping.getExtendsMapping();
0669:                     if (extended != null) {
0670:                    
0671:                     // now see if the mapping can extend base complex type
0672:                     boolean extend = false;
0673:                     for (int i = 0; i < childs.size(); i++) {
0674:                     ElementBase child = (ElementBase)childs.get(i);
0675:                     if (child instanceof StructureElement) {
0676:                     StructureElement struct = (StructureElement)child;
0677:                     if (struct.getMapAsMapping() == extended) {
0678:                     if (struct.getName() == null) {
0679:                     extend = true;
0680:                    
0681:                     }
0682:                     }
0683:                     }
0684:                     if (child instanceof IComponent) {
0685:                    
0686:                     }
0687:                     }
0688:                     }
0689:                     }   */
0690:
0691:                } else {
0692:                    group = addChildElement(type, "all");
0693:                }
0694:
0695:                // handle all nested elements of container
0696:                m_structureStack.push(container);
0697:                defineList(childs, group, type,
0698:                        container.type() == ElementBase.COLLECTION_ELEMENT);
0699:                m_structureStack.pop();
0700:                return type;
0701:            }
0702:
0703:            /**
0704:             * Generate a schema from a binding using supplied classpaths. If the schema
0705:             * for the binding namespace (or default namespace) already exists the
0706:             * definitions from this binding are added to the existing schema; otherwise
0707:             * a new schema is created and added to the collection defined.
0708:             * 
0709:             * @param binding root element of binding
0710:             */
0711:            private void generateSchema(BindingElement binding) {
0712:
0713:                // process each mapping definition for binding
0714:                m_structureStack.push(binding);
0715:                ArrayList tops = binding.topChildren();
0716:                for (int i = 0; i < tops.size(); i++) {
0717:                    ElementBase top = (ElementBase) tops.get(i);
0718:                    if (top.type() == ElementBase.MAPPING_ELEMENT) {
0719:
0720:                        // find or create schema for mapped class
0721:                        MappingElement mapping = (MappingElement) top;
0722:                        String uri = mapping.getNamespace().getUri();
0723:                        Element schema = (Element) m_schemaMap.get(uri);
0724:                        if (schema == null) {
0725:
0726:                            // build new schema element for this namespace
0727:                            schema = m_document.createElementNS(XSD_URI,
0728:                                    "schema");
0729:                            if (uri != null) {
0730:                                schema.setAttribute("targetNamespace", uri);
0731:                            }
0732:                            m_schemaMap.put(uri, schema);
0733:
0734:                            // set qualification attributes if needed
0735:                            if (m_isElementQualified) {
0736:                                schema.setAttribute("elementFormDefault",
0737:                                        "qualified");
0738:                            }
0739:                            if (m_isAttributeQualified) {
0740:                                schema.setAttribute("attributeFormDefault",
0741:                                        "qualified");
0742:                            }
0743:
0744:                            // add namespace declarations to element
0745:                            if (uri != null) {
0746:                                schema.setAttributeNS(XMLNS_URI, "xmlns:tns",
0747:                                        uri);
0748:                            }
0749:                            schema.setAttributeNS(XMLNS_URI, "xmlns:xsd",
0750:                                    XSD_URI);
0751:                            schema.setAttributeNS(XMLNS_URI, "xmlns", XSD_URI);
0752:
0753:                            // add spacing for first child node
0754:                            indentForClose(schema);
0755:                        }
0756:
0757:                        // add spacer and comment before actual definition
0758:                        indentForClose(schema);
0759:                        String cname = mapping.getClassName();
0760:                        addComment(schema, " Created from mapping for class "
0761:                                + cname + " ");
0762:                        if (mapping.isAbstract()) {
0763:
0764:                            // add mapping as global type in binding
0765:                            Element type = defineNestedStructure(mapping,
0766:                                    schema);
0767:                            type.setAttribute("name", simpleClassName(cname));
0768:
0769:                        } else {
0770:
0771:                            // add mapping as global element in binding
0772:                            Element element = addChildElement(schema, "element");
0773:                            element.setAttribute("name", mapping.getName());
0774:
0775:                            // check type of mapping definition
0776:                            if (mapping.getMarshaller() != null
0777:                                    || mapping.getUnmarshaller() != null) {
0778:
0779:                                // use "any" for custom marshaller/unmarshaller
0780:                                Element type = addChildElement(element,
0781:                                        "complexType");
0782:                                Element seq = addChildElement(type, "sequence");
0783:                                addComment(seq,
0784:                                        " Replace \"any\" with details of "
0785:                                                + "content to complete schema ");
0786:                                addChildElement(seq, "any");
0787:
0788:                            } else {
0789:
0790:                                // use complex type for embedded definition
0791:                                defineNestedStructure(mapping, element);
0792:
0793:                            }
0794:                        }
0795:                    }
0796:                }
0797:                m_structureStack.pop();
0798:            }
0799:
0800:            /**
0801:             * Process a binding definition for schema generation. This first validates
0802:             * the binding definition, and if it is valid then handles schema generation
0803:             * from the binding.
0804:             * 
0805:             * @param binding root element of binding
0806:             * @exception JiBXException if error in generating the schema
0807:             */
0808:            public void generate(BindingElement binding) throws JiBXException {
0809:
0810:                // validate the binding definition
0811:                ValidationContext vctx = new ValidationContext(m_classLocator);
0812:                binding.runValidation(vctx);
0813:                boolean usable = true;
0814:                if (vctx.getProblems().size() > 0) {
0815:
0816:                    // report problems found
0817:                    System.err.println("Problems found in binding "
0818:                            + binding.getName());
0819:                    ArrayList probs = vctx.getProblems();
0820:                    for (int i = 0; i < probs.size(); i++) {
0821:                        ValidationProblem prob = (ValidationProblem) probs
0822:                                .get(i);
0823:                        System.err.println(prob.getDescription());
0824:                        if (prob.getSeverity() > ValidationProblem.WARNING_LEVEL) {
0825:                            usable = false;
0826:                        }
0827:                    }
0828:                }
0829:
0830:                // check if binding usable for schema generation
0831:                if (usable) {
0832:                    generateSchema(binding);
0833:                } else {
0834:                    System.err
0835:                            .println("Binding validation errors prevent schema generation");
0836:                    System.exit(1);
0837:                }
0838:            }
0839:
0840:            /**
0841:             * Get simple class name.
0842:             * 
0843:             * @param cname class name with full package specification
0844:             * @return class name only
0845:             */
0846:            private String simpleClassName(String cname) {
0847:                int split = cname.lastIndexOf('.');
0848:                if (split >= 0) {
0849:                    cname = cname.substring(split + 1);
0850:                }
0851:                return cname;
0852:            }
0853:
0854:            /**
0855:             * Main method for running compiler as application.
0856:             *
0857:             * @param args command line arguments
0858:             */
0859:            public static void main(String[] args) {
0860:                if (args.length > 0) {
0861:                    try {
0862:
0863:                        // check for various flags set
0864:                        boolean verbose = false;
0865:                        boolean edflt = true;
0866:                        boolean adflt = false;
0867:                        ArrayList paths = new ArrayList();
0868:                        int offset = 0;
0869:                        for (; offset < args.length; offset++) {
0870:                            String arg = args[offset];
0871:                            if ("-v".equalsIgnoreCase(arg)) {
0872:                                verbose = true;
0873:                            } else if ("-e".equalsIgnoreCase(arg)) {
0874:                                edflt = false;
0875:                            } else if ("-a".equalsIgnoreCase(arg)) {
0876:                                adflt = true;
0877:                            } else if ("-p".equalsIgnoreCase(arg)) {
0878:                                paths.add(args[++offset]);
0879:                            } else {
0880:                                break;
0881:                            }
0882:                        }
0883:
0884:                        // set up path and binding lists
0885:                        String[] vmpaths = Utility.getClassPaths();
0886:                        for (int i = 0; i < vmpaths.length; i++) {
0887:                            paths.add(vmpaths[i]);
0888:                        }
0889:                        ArrayList bindings = new ArrayList();
0890:                        for (int i = offset; i < args.length; i++) {
0891:                            bindings.add(args[i]);
0892:                        }
0893:
0894:                        // report on the configuration
0895:                        System.out.println("Running schema generator version "
0896:                                + CURRENT_VERSION);
0897:                        if (verbose) {
0898:                            System.out.println("Using paths:");
0899:                            for (int i = 0; i < paths.size(); i++) {
0900:                                System.out.println(" " + paths.get(i));
0901:                            }
0902:                            System.out.println("Using input bindings:");
0903:                            for (int i = 0; i < bindings.size(); i++) {
0904:                                System.out.println(" " + bindings.get(i));
0905:                            }
0906:                        }
0907:
0908:                        // process all specified binding files
0909:                        SchemaGenerator schemagen = new SchemaGenerator(
0910:                                verbose, edflt, adflt, paths);
0911:                        for (int i = 0; i < bindings.size(); i++) {
0912:
0913:                            // read binding from file
0914:                            String bpath = (String) bindings.get(i);
0915:                            String name = Utility.convertName(Utility
0916:                                    .fileName(bpath));
0917:                            File file = new File(bpath);
0918:                            BindingElement binding = Utility.validateBinding(
0919:                                    name, new URL("file://"
0920:                                            + file.getAbsolutePath()),
0921:                                    new FileInputStream(file));
0922:
0923:                            // convert the binding to a schema
0924:                            if (binding != null) {
0925:                                schemagen.generate(binding);
0926:                            }
0927:                        }
0928:
0929:                        // output each schema to separate file
0930:                        Element[] schemas = schemagen.getSchemas();
0931:                        for (int i = 0; i < schemas.length; i++) {
0932:
0933:                            // get base name for output file from last part of namespace
0934:                            Element schema = schemas[i];
0935:                            String tns = schema.getAttribute("targetNamespace");
0936:                            String name = tns;
0937:                            if (name.length() == 0) {
0938:                                // fix this to relate back to binding
0939:                                name = (String) bindings.get(0);
0940:                                int split = name.lastIndexOf('.');
0941:                                if (split >= 0) {
0942:                                    name = name.substring(0, split);
0943:                                }
0944:                            } else {
0945:                                int split = name.lastIndexOf('/');
0946:                                if (split >= 0) {
0947:                                    name = name.substring(split + 1);
0948:                                }
0949:                            }
0950:                            try {
0951:
0952:                                // write schema to output file
0953:                                name += ".xsd";
0954:                                FileOutputStream out = new FileOutputStream(
0955:                                        name);
0956:                                Transformer transformer = TransformerFactory
0957:                                        .newInstance().newTransformer();
0958:                                transformer.setOutputProperty("indent", "no");
0959:                                DOMSource source = new DOMSource(schema);
0960:                                Result result = new StreamResult(out);
0961:                                transformer.transform(source, result);
0962:                                out.close();
0963:                                System.out.print("Wrote schema " + name);
0964:                                if (tns.length() == 0) {
0965:                                    System.out
0966:                                            .println(" for default namespace");
0967:                                } else {
0968:                                    System.out.println(" for namespace " + tns);
0969:                                }
0970:
0971:                            } catch (TransformerConfigurationException e) {
0972:                                e.printStackTrace();
0973:                            } catch (TransformerFactoryConfigurationError e) {
0974:                                e.printStackTrace();
0975:                            } catch (TransformerException e) {
0976:                                e.printStackTrace();
0977:                            } catch (IOException e) {
0978:                                e.printStackTrace();
0979:                            }
0980:                        }
0981:
0982:                    } catch (JiBXException ex) {
0983:                        ex.printStackTrace();
0984:                        System.exit(1);
0985:                    } catch (FileNotFoundException e) {
0986:                        e.printStackTrace();
0987:                        System.exit(2);
0988:                    } catch (MalformedURLException e) {
0989:                        e.printStackTrace();
0990:                        System.exit(3);
0991:                    }
0992:
0993:                } else {
0994:                    System.out
0995:                            .println("\nUsage: java org.jibx.binding.SchemaGenerator [-v] [-e]"
0996:                                    + " [-a] [-p path]* binding1 binding2 ...\nwhere:"
0997:                                    + "\n -v  turns on verbose output,"
0998:                                    + "\n -e  sets elementFormDefault=\"false\" for the schemas,"
0999:                                    + "\n -a  sets attributeFormDefault=\"true\" for the schemas, "
1000:                                    + "and\n -p  gives a path component for looking up the classes "
1001:                                    + "referenced in the binding\nThe binding# files are "
1002:                                    + "different bindings to be used for schema generation.\n");
1003:                    System.exit(1);
1004:                }
1005:            }
1006:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.