KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > zeus > generator > SimpleGenerator


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  */

19 package org.enhydra.zeus.generator;
20
21 import java.io.File JavaDoc;
22 import java.io.FileWriter JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.Writer JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Vector JavaDoc;
30 import java.util.BitSet JavaDoc;
31
32 // Zeus imports
33
import org.enhydra.zeus.Binding;
34 import org.enhydra.zeus.Generator;
35 import org.enhydra.zeus.ZeusDefaults;
36 import org.enhydra.zeus.ZeusException;
37 import org.enhydra.zeus.binding.AtomicProperty;
38 import org.enhydra.zeus.binding.BaseBinding;
39 import org.enhydra.zeus.binding.Container;
40 import org.enhydra.zeus.binding.Property;
41 import org.enhydra.zeus.util.CapitalizationUtils;
42 import org.enhydra.zeus.util.ClassUtils;
43 import org.enhydra.zeus.util.NamingUtils;
44 import org.enhydra.zeus.util.XMLName;
45
46 /**
47  * <p>
48  * <code>{@link Generator}</code> is the portion of Zeus that will convert
49  * a set of constraints, visible through a <code>{@link Binding}</code>,
50  * and output them as generated Java classes (to a
51  * <code>File</code> [directory]).
52  * </p><p>
53  * <code>SimpleGenerator</code> is the simplest form of a
54  * <code>Generator</code> and takes in either a single <code>Binding</code>
55  * or a <code>List</code> of them, and directly generates Java classes.
56  * </p>
57  *
58  * @author Brett McLaughlin
59  * @author Maciej Zawadzki
60  * @author Sean Ogle
61  * @author Christophe Ney cney@batisseurs.com
62  */

63 public class SimpleGenerator implements Generator {
64
65     /** A list of bindings to ignore */
66     protected List JavaDoc ignoredBindings;
67     
68     /** A list of classes to import for all unmarshallers */
69     protected List JavaDoc globalUnmarshallerImports;
70     
71     /** A list of classes to import for all interfaces */
72     protected List JavaDoc globalInterfaceImports;
73     
74     /** A list of classes to import for all implementations */
75     protected List JavaDoc globalImplementationImports;
76     
77     /** This instances's collapsed elements */
78     protected List JavaDoc collapsedElements;
79     
80     /** Base directory for generated files. */
81     protected File JavaDoc outputDir;
82     
83     /** Keeps track of whether the Generator needs to be reinitialized. */
84     protected boolean initialized;
85
86     /**
87      * <p>
88      * This will construct a new instance of <code>SimpleGenerator</code>.
89      * </p>
90      */

91     public SimpleGenerator() {
92         initialized = false;
93         ignoredBindings = new LinkedList JavaDoc();
94         globalUnmarshallerImports = new LinkedList JavaDoc();
95         globalInterfaceImports = new LinkedList JavaDoc();
96         globalImplementationImports = new LinkedList JavaDoc();
97         collapsedElements = new LinkedList JavaDoc();
98         
99         // Add some required imports for all unmarshallers
100
globalUnmarshallerImports.add("java.io.File");
101         globalUnmarshallerImports.add("java.io.FileReader");
102         globalUnmarshallerImports.add("java.io.InputStream");
103         globalUnmarshallerImports.add("java.io.InputStreamReader");
104         globalUnmarshallerImports.add("java.io.IOException");
105         globalUnmarshallerImports.add("java.io.Reader");
106         globalUnmarshallerImports.add("org.xml.sax.EntityResolver");
107         globalUnmarshallerImports.add("org.xml.sax.ErrorHandler");
108         globalUnmarshallerImports.add("org.xml.sax.SAXException");
109         globalUnmarshallerImports.add("org.xml.sax.SAXParseException");
110         
111         // Add some required imports for all interfaces
112
globalInterfaceImports.add("java.io.File");
113         globalInterfaceImports.add("java.io.IOException");
114         globalInterfaceImports.add("java.io.OutputStream");
115         globalInterfaceImports.add("java.io.Writer");
116         
117         // Add some required imports for all implementations
118
globalImplementationImports.add("java.io.File");
119         globalImplementationImports.add("java.io.FileReader");
120         globalImplementationImports.add("java.io.FileWriter");
121         globalImplementationImports.add("java.io.InputStream");
122         globalImplementationImports.add("java.io.InputStreamReader");
123         globalImplementationImports.add("java.io.IOException");
124         globalImplementationImports.add("java.io.OutputStream");
125         globalImplementationImports.add("java.io.OutputStreamWriter");
126         globalImplementationImports.add("java.io.Reader");
127         globalImplementationImports.add("java.io.Writer");
128         globalImplementationImports.add("java.util.HashMap");
129         globalImplementationImports.add("java.util.Iterator");
130         globalImplementationImports.add("java.util.Map");
131         globalImplementationImports.add("org.xml.sax.EntityResolver");
132         globalImplementationImports.add("org.xml.sax.ErrorHandler");
133         globalImplementationImports.add("org.xml.sax.InputSource");
134         globalImplementationImports.add("org.xml.sax.Locator");
135         globalImplementationImports.add("org.xml.sax.SAXException");
136         globalImplementationImports.add("org.xml.sax.SAXParseException");
137         globalImplementationImports.add("org.xml.sax.XMLReader");
138         globalImplementationImports.add("org.xml.sax.ext.LexicalHandler");
139         globalImplementationImports.add("org.xml.sax.helpers.DefaultHandler");
140         globalImplementationImports.add("org.xml.sax.helpers.XMLReaderFactory");
141     }
142
143     /**
144      * <p>
145      * This sets the output directory to output generated classes to.
146      * </p>
147      *
148      * @param baseDir the name of the base directory where
149      * all generated classes should be placed
150      */

151     public void setOutputDirectory(String JavaDoc outputDir) {
152         if (outputDir == null) {
153             throw new IllegalArgumentException JavaDoc("A generator cannot have a " +
154                 "null output directory.");
155         }
156         
157         this.outputDir = new File JavaDoc(outputDir);
158         uninitialize();
159     }
160     
161     /**
162      * <p>
163      * This sets the output directory to output generated classes to.
164      * </p>
165      *
166      * @param outputDir the <code>File</code> (directory) where
167      * all generated classes should be placed
168      */

169     public void setOutputDirectory(File JavaDoc outputDir) {
170         if (outputDir == null) {
171             throw new IllegalArgumentException JavaDoc("A generator cannot have a " +
172                 "null output directory.");
173         }
174         
175         this.outputDir = outputDir;
176         uninitialize();
177     }
178
179     /**
180      * <p>
181      * This allows a binding to be ignored. This is an intermediary step
182      * towards allowing binding schemas. The name of the binding should
183      * be passed in here, and no property generation for it will occur.
184      * </p>
185      *
186      * @param xmlName the XML local name of the binding to ignore.
187      * @param xmlNamespaceURI the XML namespace URI of the binding to ignore.
188      * The empty string indicates there is no namespace associated
189      * with the binding.
190      */

191     public void setIgnoreBinding(String JavaDoc xmlName, String JavaDoc xmlNamespaceURI) {
192         ignoredBindings.add(new XMLName(xmlName, xmlNamespaceURI));
193     }
194     
195     /**
196      * <p>
197      * This allows a binding to be ignored. This is an intermediary step
198      * towards allowing binding schemas. The name of the binding should
199      * be passed in here, and no property generation for it will occur. This
200      * convenience version supplies an empty string for the namespace URI.
201      * </p>
202      *
203      * @param xmlName the XML local name of the binding to ignore.
204      */

205     public void setIgnoreBinding(String JavaDoc xmlName) {
206         setIgnoreBinding(xmlName, "");
207     }
208     
209     /**
210      * This will determine if a particular binding should be ignored. The
211      * binding is identified by its XML local name and its XML namespace URI.
212      *
213      * @param xmlName the XML local name of the binding.
214      * @param xmlNamespaceURI the XML namespace URI associated with the binding.
215      * An empty string indicates that there is no namespace associated
216      * with the binding.
217      *
218      * @return true if and only if the binding should be ignored
219      */

220     protected boolean isIgnoredBinding(String JavaDoc xmlName, String JavaDoc xmlNamespaceURI) {
221         if (ignoredBindings != null) {
222             for (Iterator JavaDoc i = ignoredBindings.iterator(); i.hasNext(); ) {
223                 XMLName bindingName = (XMLName)i.next();
224                 if ((bindingName.getXMLName().equals(xmlName)) &&
225                     (bindingName.getNamespaceURI().equals(xmlNamespaceURI))) {
226                     return true;
227                 }
228             }
229         }
230
231         return false;
232     }
233
234     /**
235      * <p>
236      * This will convert from a set of constraints to Java classes.
237      * It accesses those constraints through the
238      * <code>{@link Binding}</code> interface, which provides
239      * them in a representation-independent format, and then
240      * converts them into Java code.
241      * </p>
242      *
243      * @param binder <code>Binder</code> with ability to convert from
244      * constraints to Zeus <code>Binding</code>s.
245      * @param root whether this is the root element
246      * @throws <code>IOException</code> - when errors in writing to the
247      * supplied <code>Result</code> occur.
248      * @throws <code>ZeusException</code> - when errors in class generation
249      * occur.
250      */

251     public void generate(Binding binding)
252         throws IOException JavaDoc, ZeusException {
253             
254         collapsedElements.clear();
255             
256         if (!isInitialized()) {
257             initialize();
258         }
259     
260         /**
261          * Currently, only Containers can be generated (which
262          * includes ContainerProperties), as AtomicProperties
263          * won't result in classes.
264          */

265         if (binding instanceof Container) {
266             Container container = (Container)binding;
267             
268             // Ignore Java primitive types (from collapsed elements)
269
if (ClassUtils.isJavaPrimitive(binding.getJavaType())) {
270                 return;
271             }
272             
273             if (binding.isXMLRootElement()) {
274                 /** Generate Unmarshaller class */
275                 generateUnmarshaller(container);
276                 
277                 /** Generate Unmarshallable interface */
278                 generateUnmarshallableInterface(container);
279             }
280         
281             /** Generate interface */
282             generateInterface(container);
283         
284             /** Generate implementation class */
285             generateImplementation(container);
286         } else {
287             throw new UnsupportedBindingTypeException(binding);
288         }
289     }
290     
291     /**
292      * <p>
293      * This will generate the <code>Unmarshaller</code> class for this
294      * container, which calls out to the implementation class for
295      * static unmarshalling from XML to Java.
296      * </p>
297      *
298      * @param container <code>Container</code> to generate classes from.
299      * @throws <code>IOException</code> - when generation errors occur.
300      */

301     protected void generateUnmarshaller(Container container)
302         throws IOException JavaDoc {
303             
304         List JavaDoc unmarshallerImports = new LinkedList JavaDoc();
305         
306         // Get a new writer
307
String JavaDoc filename =
308             new StringBuffer JavaDoc(container.getJavaType())
309                 .append("Unmarshaller.java")
310                 .toString();
311         File JavaDoc outputFile = new File JavaDoc(getInterfaceDir(container), filename);
312         FileWriter JavaDoc writer = new FileWriter JavaDoc(outputFile);
313         
314         // Write out the source file header comment
315
writer.write(ZeusDefaults.GENERATED_CLASS_COMMENT);
316         
317         // Write the package declaration, if needed
318
writePackageDeclaration(writer, container.getJavaInterfacePackage());
319         
320         // Write out import statements
321
writeUnmarshallerImportStatements(writer, unmarshallerImports);
322         
323         // Write out class header
324
writeUnmarshallerDeclaration(writer, container);
325         
326         // Write out the properties
327
writeUnmarshallerProperties(writer, container);
328         
329         // Write out the unmarshal() methods
330
writeUnmarshallerUnmarshalMethods(writer, container);
331         
332         writer.write("}\n");
333         
334         // Write out the default error handler
335
writeDefaultErrorHandler(writer, container);
336         
337         writer.flush();
338         writer.close();
339     }
340     
341     /**
342      * <p>
343      * This will generate the <code>Unmarshallable</code> interface for use
344      * by generated classes in the unmarshalling process.
345      * </p>
346      *
347      * @param container <code>Container</code> to generate classes from.
348      * @throws <code>IOException</code> - when generation errors occur.
349      */

350     protected void generateUnmarshallableInterface(Container container)
351         throws IOException JavaDoc {
352             
353         // Get a new writer
354
String JavaDoc filename =
355             new StringBuffer JavaDoc("Unmarshallable.java")
356                 .toString();
357         File JavaDoc outputFile = new File JavaDoc(getInterfaceDir(container), filename);
358         FileWriter JavaDoc writer = new FileWriter JavaDoc(outputFile);
359         
360         // Write out the source file header comment
361
writer.write(ZeusDefaults.GENERATED_CLASS_COMMENT);
362         
363         // Write the package declaration, if needed
364
writePackageDeclaration(writer, container.getJavaInterfacePackage());
365         
366         // Write out import statements
367
writer.write("import org.xml.sax.ContentHandler;\n\n");
368         
369         // Write out interface declaration
370
writer.write("public interface Unmarshallable ");
371         writer.write("extends ContentHandler {\n\n");
372             
373         // Write out additional methods
374
writer.write(" public Unmarshallable getCurrentUNode();\n\n");
375         writer.write(" public void setCurrentUNode(");
376         writer.write("Unmarshallable currentUNode);\n\n");
377         writer.write(" public Unmarshallable getParentUNode();\n\n");
378         writer.write(" public void setParentUNode(");
379         writer.write("Unmarshallable parentUNode);\n\n");
380         
381         writer.write("}\n");
382         writer.flush();
383         writer.close();
384     }
385     
386     /**
387      * <p>
388      * This will generate the interface (or interfaces, through recursion)
389      * for the supplied <code>Container</code>.
390      * </p>
391      *
392      * @param container <code>Container</code> to generate classes from.
393      * @throws <code>IOException</code> - when generation errors occur.
394      */

395     protected void generateInterface(Container container)
396         throws IOException JavaDoc {
397             
398         List JavaDoc interfaceImports = new LinkedList JavaDoc();
399         
400         // Get a new writer
401
String JavaDoc filename =
402             new StringBuffer JavaDoc(container.getJavaType())
403                 .append(".java")
404                 .toString();
405         File JavaDoc outputFile = new File JavaDoc(getInterfaceDir(container), filename);
406         FileWriter JavaDoc writer = new FileWriter JavaDoc(outputFile);
407         
408         // Write out the source file header comment
409
writer.write(ZeusDefaults.GENERATED_CLASS_COMMENT);
410         
411         // Write the package declaration, if needed
412
writePackageDeclaration(writer, container.getJavaInterfacePackage());
413         
414         /**
415          * If any of the properties do not have a Java package then we
416          * must import them, unless they are primitive types.
417          */

418         List JavaDoc properties = container.getProperties();
419         for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
420             Property property = (Property)i.next();
421             if (property.getJavaInterfacePackage().equals("")) {
422                 if (!ClassUtils.isJavaPrimitive(property.getJavaType())) {
423                     interfaceImports.add(property.getJavaType());
424                 }
425             }
426             
427             if (property.isCollection()) {
428                 String JavaDoc collectionClass = property.getJavaCollectionClass();
429                 if (!interfaceImports.contains(collectionClass)) {
430                     interfaceImports.add(collectionClass);
431                 }
432             }
433         }
434         
435         // Add Serializable import if needed
436
if (container.isJavaSerializable()) {
437             interfaceImports.add("java.io.Serializable");
438         }
439         
440         // Write out import statements
441
writeInterfaceImportStatements(writer, interfaceImports);
442         
443         // Write out class header
444
writeInterfaceDeclaration(writer, container);
445
446         // Write out element and attribute ordering
447
writeElementAndAttributeArrays(writer, container);
448
449         // Write out method declarations
450
writeInterfaceMethods(writer, container.getProperties());
451         
452         // Write out method declarations for marshalling to XML
453
writeInterfaceMarshalMethods(writer);
454
455         writer.write("}\n");
456         writer.flush();
457         writer.close();
458     }
459
460     /**
461      * <p>
462      * This will generate the implementation (or implemenations, through
463      * recursion) for the supplied <code>Container</code>.
464      * </p>
465      *
466      * @param container <code>Container</code> to generate classes from.
467      * @throws <code>IOException</code> - when generation errors occur.
468      */

469     protected void generateImplementation(Container container)
470         throws IOException JavaDoc {
471             
472         List JavaDoc implementationImports = new LinkedList JavaDoc();
473         
474         // Get a new File handle
475
String JavaDoc filename = container.getJavaType() + "Impl.java";
476         File JavaDoc outputFile = new File JavaDoc(getImplementationDir(container), filename);
477         FileWriter JavaDoc writer = new FileWriter JavaDoc(outputFile);
478         
479         // Write out the source file header comment
480
writer.write(ZeusDefaults.GENERATED_CLASS_COMMENT);
481
482         // Add a package statement if necessary.
483
writePackageDeclaration(writer,
484                                 container.getJavaImplementationPackage());
485
486         /**
487          * If the interface is in the default namespace then we have to
488          * import it. So we might as well anyway.
489          */

490         if (container.getJavaInterfacePackage() !=
491             container.getJavaImplementationPackage()) {
492                 
493             StringBuffer JavaDoc containerPackage = new StringBuffer JavaDoc();
494             if (!container.getJavaInterfacePackage().equals("")) {
495                 containerPackage.append(container.getJavaInterfacePackage())
496                                 .append(".");
497             }
498             containerPackage.append(container.getJavaType());
499             implementationImports.add(containerPackage.toString());
500         }
501
502         /**
503          * If any of the properties do not have a Java package then we
504          * must import them, unless they are primitive types.
505          */

506         boolean firstCollection = true;
507         List JavaDoc properties = container.getProperties();
508         for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
509             Property property = (Property)i.next();
510             if (property.getJavaInterfacePackage().equals("")) {
511                 if (!ClassUtils.isJavaPrimitive(property.getJavaType())) {
512                     implementationImports.add(property.getJavaType());
513                 }
514             }
515             
516             if (property.isCollection()) {
517                 if (firstCollection) {
518                     implementationImports.add("java.util.Iterator");
519                     firstCollection = false;
520                 }
521                 String JavaDoc collectionClass = property.getJavaCollectionClass();
522                 if (!implementationImports.contains(collectionClass)) {
523                     implementationImports.add(collectionClass);
524                     implementationImports.add(ClassUtils.getCollectionImplClass(
525                         collectionClass));
526                 }
527             }
528         }
529
530         // Write out import statements
531
writeImplementationImportStatements(writer, implementationImports);
532
533         // Write out the implementation declaration
534
writeImplementationDeclaration(writer, container.getJavaType());
535         
536         // Write out each property
537
writeImplementationProperties(writer, properties);
538         
539         // Write out unmarshaller properties
540
writeImplementationUnmarshallerProperties(writer, container);
541
542         // Write out static prototype field and method
543
writeImplementationPrototypeMethodAndField(writer,container.getJavaType());
544
545         // Write class constructor
546
writeImplementationConstructor(writer,container.getJavaType(),properties);
547         
548         // Write out each method implementation
549
writeImplementationMethods(writer, container);
550         
551         // Write out the implementation of the marshal() methods
552
writeImplementationMarshalMethods(writer, container);
553         
554         // Write out the implementation of the unmarshal() methods
555
writeImplementationUnmarshalMethods(writer, container);
556         
557         // Write out SAX Handler methods
558
writeImplementationSAXHandlerMethods(writer, container);
559         
560         writer.write("}\n");
561         
562         writer.flush();
563         writer.close();
564     }
565     
566     /**
567      * <p>
568      * This writes out the package declaration for this class, if needed.
569      * </p>
570      *
571      * @param writer <code>Writer</code> to perform output to
572      * @param packageName the package of this class
573      * @throws <code>IOException</code> - when errors in output occur.
574      */

575     protected void writePackageDeclaration(Writer JavaDoc writer, String JavaDoc packageName)
576         throws IOException JavaDoc {
577             
578         // Generate a package statement if necessary.
579
if (!packageName.equals("")) {
580             writer.write("package");
581             writer.write(" ");
582             writer.write(packageName);
583             writer.write(";\n\n");
584         }
585     }
586     
587     /**
588      * <p>
589      * This will take the supplied list of class names, and add import
590      * statements for each of the classes in the list. It will also write
591      * out all global import statements for unmarshaller classes.
592      * </p>
593      *
594      * @param writer <code>Writer</code> to output to
595      * @param importClasses <code>List</code> of classes to add imports for
596      * @throws <code>IOException</code> - when errors in output occur.
597      */

598     protected void writeUnmarshallerImportStatements(Writer JavaDoc writer,
599                                                      List JavaDoc importClasses)
600         throws IOException JavaDoc {
601
602         // Write out global imports
603
if (globalUnmarshallerImports.size() > 0) {
604             writer.write("// Global Unmarshaller Import Statements\n");
605         }
606         for (Iterator JavaDoc i = globalUnmarshallerImports.iterator(); i.hasNext(); ) {
607             writer.write("import ");
608             writer.write((String JavaDoc)i.next());
609             writer.write(";\n");
610         }
611         if (globalUnmarshallerImports.size() > 0) {
612             writer.write("\n");
613         }
614         
615         // Write out local imports
616
if (importClasses.size() > 0) {
617             writer.write("// Local Unmarshaller Import Statements\n");
618         }
619         for (Iterator JavaDoc i = importClasses.iterator(); i.hasNext(); ) {
620             writer.write("import ");
621             writer.write((String JavaDoc)i.next());
622             writer.write(";\n");
623         }
624         if (importClasses.size() > 0) {
625             writer.write("\n");
626         }
627     }
628     
629     /**
630      * <p>
631      * This writes out the unmarshaller declaration (the class header).
632      * </p>
633      *
634      * @param writer <code>Writer</code> to output to
635      * @param container the container for the class
636      * @throws <code>IOException</code> - when errors in output occur.
637      */

638     protected void writeUnmarshallerDeclaration(Writer JavaDoc writer,
639                                                 Container container)
640         throws IOException JavaDoc {
641             
642         writer.write("public class ");
643         writer.write(container.getJavaType());
644         writer.write("Unmarshaller {\n\n");
645     }
646     
647     /**
648      * <p>
649      * This will write out the unmarshaller properties.
650      * </p>
651      *
652      * @param writer <code>Writer</code> to output to
653      * @param container the container to write the unmarshalling for.
654      * @throws <code>IOException</code> - when errors in output occur.
655      */

656     protected void writeUnmarshallerProperties(Writer JavaDoc writer,
657                                                Container container)
658         throws IOException JavaDoc {
659             
660         writer.write(" /** The EntityResolver for parser resolution. */\n");
661         writer.write(" private static EntityResolver entityResolver;\n\n");
662         
663         writer.write(" /** The ErrorHandler for parser resolution. */\n");
664         writer.write(" private static ErrorHandler errorHandler;\n\n");
665     }
666     
667     /**
668      * <p>
669      * This will write out the unmarshaller version of the various
670      * <code>unmarshal</code> methods supported by generated classes.
671      * </p>
672      *
673      * @param writer <code>Writer</code> to output to
674      * @param container the container to write the unmarshalling for.
675      * @throws <code>IOException</code> - when errors in output occur.
676      */

677     protected void writeUnmarshallerUnmarshalMethods(Writer JavaDoc writer,
678                                                      Container container)
679         throws IOException JavaDoc {
680
681         String JavaDoc className = container.getJavaType();
682             
683         // Set an entity resolver
684
writer.write(" /**\n");
685         writer.write(" * <p>\n");
686         writer.write(" * This sets a SAX <code>EntityResolver</code> for");
687         writer.write(" this unmarshalling process.\n");
688         writer.write(" * </p>\n");
689         writer.write(" *\n");
690         writer.write(" * @param resolver the entity resolver ");
691         writer.write("to use.\n");
692         writer.write(" */\n");
693         writer.write(" public static void setEntityResolver(");
694         writer.write("EntityResolver resolver) {\n");
695         writer.write(" entityResolver = resolver;\n");
696         writer.write(" }\n\n");
697         
698         // Set an error handler
699
writer.write(" /**\n");
700         writer.write(" * <p>\n");
701         writer.write(" * This sets a SAX <code>ErrorHandler</code> for");
702         writer.write(" this unmarshalling process.\n");
703         writer.write(" * </p>\n");
704         writer.write(" *\n");
705         writer.write(" * @param handler the error handler ");
706         writer.write("to use.\n");
707         writer.write(" */\n");
708         writer.write(" public static void setErrorHandler(");
709         writer.write("ErrorHandler handler) {\n");
710         writer.write(" errorHandler = handler;\n");
711         writer.write(" }\n\n");
712             
713         // unmarshal(File file)
714
writer.write(" public static ");
715         writer.write(className);
716         writer.write(" unmarshal(File file)");
717         writer.write(" throws IOException {\n");
718         writer.write(" // Delegate to the unmarshal(Reader) method\n");
719         writer.write(" return unmarshal(new FileReader(file));\n");
720         writer.write(" }\n\n");
721         
722         // unmarshal(File file, boolean validate)
723
writer.write(" public static ");
724         writer.write(className);
725         writer.write(" unmarshal(File file, boolean validate)");
726         writer.write(" throws IOException {\n");
727         writer.write(" // Delegate to the unmarshal(Reader) method\n");
728         writer.write(" return unmarshal(new FileReader(file), ");
729         writer.write("validate);\n");
730         writer.write(" }\n\n");
731             
732         // unmarshal(InputStream inputStream)
733
writer.write(" public static ");
734         writer.write(className);
735         writer.write(" unmarshal(InputStream inputStream)");
736         writer.write(" throws IOException {\n");
737         writer.write(" // Delegate to the unmarshal(Reader) method\n");
738         writer.write(" ");
739         writer.write("return unmarshal(new InputStreamReader(inputStream));\n");
740         writer.write(" }\n\n");
741         
742         // unmarshal(InputStream inputStream, boolean validate)
743
writer.write(" public static ");
744         writer.write(className);
745         writer.write(" unmarshal(InputStream inputStream, boolean validate)");
746         writer.write(" throws IOException {\n");
747         writer.write(" // Delegate to the unmarshal(Reader) method\n");
748         writer.write(" ");
749         writer.write("return unmarshal(new InputStreamReader(inputStream), ");
750         writer.write("validate);\n");
751         writer.write(" }\n\n");
752         
753         // unmarshal(Reader reader)
754
writer.write(" public static ");
755         writer.write(className);
756         writer.write(" unmarshal(Reader reader)");
757         writer.write(" throws IOException {\n");
758         writer.write(" // See if validation set as system property\n");
759         writer.write(" String property = System.getProperty(\"");
760         writer.write(ZeusDefaults.VALIDATION_SYSTEM_PROPERTY);
761         writer.write("\", \"");
762         writer.write(ZeusDefaults.DEFAULT_VALIDATION_STATE.toString());
763         writer.write("\");\n");
764         writer.write(" boolean validationState = false;\n");
765         writer.write(" if (property.equalsIgnoreCase(\"true\")) {\n");
766         writer.write(" validationState = true;\n");
767         writer.write(" }\n\n");
768         writer.write(" // Delegate with validation state\n");
769         writer.write(" ");
770         writer.write("return unmarshal(reader, validationState);\n");
771         writer.write(" }\n\n");
772         
773         // unmarshal(Reader reader, boolean validate)
774
writer.write(" public static ");
775         writer.write(className);
776         writer.write(" unmarshal(Reader reader, boolean validate)");
777         writer.write(" throws IOException {\n");
778         writer.write(" // Set the entity resolver, if needed\n");
779         writer.write(" if (entityResolver != null) {\n");
780         writer.write(" ");
781         writer.write(className);
782         writer.write("Impl.setEntityResolver(entityResolver);\n");
783         writer.write(" }\n\n");
784         writer.write(" // Set the error handler, if needed\n");
785         writer.write(" if (errorHandler != null) {\n");
786         writer.write(" ");
787         writer.write(className);
788         writer.write("Impl.setErrorHandler(errorHandler);\n");
789         writer.write(" } else {\n");
790         writer.write(" if (validate) {\n");
791         writer.write(" ");
792         writer.write(className);
793         writer.write("Impl.setErrorHandler(new ");
794         writer.write(className);
795         writer.write("DefaultErrorHandler());\n");
796         writer.write(" }\n");
797         writer.write(" }\n\n");
798         writer.write(" // Unmarshal using the implementation class\n");
799         writer.write(" return ");
800         writer.write(className);
801         writer.write("Impl.unmarshal(reader, validate);\n");
802         writer.write(" }\n\n");
803     }
804     
805     /**
806      * <p>
807      * This will write out the default error handler for use when validation
808      * is on, and no <code>ErrorHandler</code> implementation is provided.
809      * </p>
810      *
811      * @param writer <code>Writer</code> to output to.
812      * @param container the container this error handler is for.
813      * @throws <code>IOException</code> - when errors in output occur.
814      */

815     protected void writeDefaultErrorHandler(Writer JavaDoc writer, Container container)
816         throws IOException JavaDoc {
817             
818         writer.write("\n\n");
819         writer.write("class ");
820         writer.write(container.getJavaType());
821         writer.write("DefaultErrorHandler implements ErrorHandler {\n\n");
822         writer.write(" public void warning(SAXParseException e) ");
823         writer.write("throws SAXException {\n");
824         writer.write(" System.err.println(\"Parsing Warning: \" + ");
825         writer.write("e.getMessage());\n");
826         writer.write(" }\n\n");
827         writer.write(" public void error(SAXParseException e) ");
828         writer.write("throws SAXException {\n");
829         writer.write(" System.err.println(\"Parsing Error: \" + ");
830         writer.write("e.getMessage());\n");
831         writer.write(" throw e;\n");
832         writer.write(" }\n\n");
833         writer.write(" public void fatalError(SAXParseException e) ");
834         writer.write("throws SAXException {\n");
835         writer.write(" System.err.println(\"Fatal Parsing Error: \" + ");
836         writer.write("e.getMessage());\n");
837         writer.write(" throw e;\n");
838         writer.write(" }\n\n");
839         writer.write("}\n");
840     }
841     
842     /**
843      * <p>
844      * This will take the supplied list of class names, and add import
845      * statements for each of the classes in the list. It will also write
846      * out all global import statements for interface classes.
847      * </p>
848      *
849      * @param writer <code>Writer</code> to output to
850      * @param importClasses <code>List</code> of classes to add imports for
851      * @throws <code>IOException</code> - when errors in output occur.
852      */

853     protected void writeInterfaceImportStatements(Writer JavaDoc writer,
854                                                   List JavaDoc importClasses)
855         throws IOException JavaDoc {
856
857         // Write out global imports
858
if (globalInterfaceImports.size() > 0) {
859             writer.write("// Global Interface Import Statements\n");
860         }
861         for (Iterator JavaDoc i = globalInterfaceImports.iterator(); i.hasNext(); ) {
862             writer.write("import ");
863             writer.write((String JavaDoc)i.next());
864             writer.write(";\n");
865         }
866         if (globalInterfaceImports.size() > 0) {
867             writer.write("\n");
868         }
869         
870         // Write out local imports
871
if (importClasses.size() > 0) {
872             writer.write("// Local Interface Import Statements\n");
873         }
874         for (Iterator JavaDoc i = importClasses.iterator(); i.hasNext(); ) {
875             writer.write("import ");
876             writer.write((String JavaDoc)i.next());
877             writer.write(";\n");
878         }
879         if (importClasses.size() > 0) {
880             writer.write("\n");
881         }
882     }
883     
884     /**
885      * <p>
886      * This generates an array of element and attribute names, for
887      * correct ordering in marshalling.
888      * </p>
889      *
890      * @param writer <code>Writer</code> to output to
891      * @param container <code>Container</code> with properties
892      * to generate
893      * @throws <code>IOException</code> when output errors occur.
894      */

895     private void writeElementAndAttributeArrays(Writer JavaDoc writer,
896                                                 Container container)
897         throws IOException JavaDoc {
898
899         // Initialize variables
900
List JavaDoc properties = container.getProperties();
901         StringBuffer JavaDoc attributeNames = new StringBuffer JavaDoc();
902         boolean firstAtt = true;
903         StringBuffer JavaDoc elementNames = new StringBuffer JavaDoc();
904         boolean firstElem = true;
905         
906         BitSet JavaDoc modifiers = null;
907         
908         // construct the contents of the arrays
909
for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
910             Property property = (Property)i.next();
911             modifiers = property.getModifier();
912             String JavaDoc xmlName = property.getXMLName();
913
914             // See if it's an attribute
915
if (modifiers.get(Property.SOURCE_ATTLIST)) {
916                 // append the comma separator
917
if (firstAtt) {
918                     firstAtt = false;
919                 } else {
920                     attributeNames.append(", ");
921                 }
922                     
923                 // append the name of the attribute
924
attributeNames.append("\"");
925                 attributeNames.append(xmlName);
926                 attributeNames.append("\"");
927
928                 // See if it's an element
929
} else if (modifiers.get(Property.SOURCE_ELEMENT)) {
930                 // append the comma separator
931
if (firstElem) {
932                     firstElem = false;
933                 } else {
934                     elementNames.append(", ");
935                 }
936                     
937                 // append the name of the element
938
elementNames.append("\"");
939                 elementNames.append(property.getXMLName());
940                 elementNames.append("\"");
941             }
942         }
943
944         writer.write(" public static final String ");
945         writer.write(ZeusDefaults.XML_NAME_FIELD);
946         writer.write(" = \"");
947         writer.write(container.getXMLName());
948         writer.write("\";\n");
949
950         writer.write(" public static final String[] ");
951         writer.write(ZeusDefaults.ATTRIBUTE_ARRAY_FIELD);
952         writer.write(" = {");
953         writer.write(attributeNames.toString());
954         writer.write("};\n");
955         
956         writer.write(" public static final String[] ");
957         writer.write(ZeusDefaults.ELEMENT_ARRAY_FIELD);
958         writer.write(" = {");
959         writer.write(elementNames.toString());
960         writer.write("};\n\n");
961     }
962     
963     /**
964      * <p>
965      * This writes out the interface declaration (the class header).
966      * </p>
967      *
968      * @param writer <code>Writer</code> to output to
969      * @param container the container to write the interface for.
970      * @throws <code>IOException</code> - when errors in output occur.
971      */

972     protected void writeInterfaceDeclaration(Writer JavaDoc writer,
973                                              Container container)
974         throws IOException JavaDoc {
975             
976         writer.write("public interface ");
977         writer.write(container.getJavaType());
978
979         // Make serializable if needed
980
if (container.isJavaSerializable()) {
981             writer.write(" extends Serializable");
982         }
983         writer.write(" {\n\n");
984     }
985     
986     /**
987      * <p>
988      * This writes out the various method declarations for an interface.
989      * </p>
990      *
991      * @param writer <code>Writer</code> to output to
992      * @param properties <code>List</code> of properties to write out method
993      * declarations for
994      * @throws <code>IOException</code> - when errors in output occur.
995      */

996     protected void writeInterfaceMethods(Writer JavaDoc writer, List JavaDoc properties)
997         throws IOException JavaDoc {
998         
999         // Write out each method
1000
for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
1001            Property property = (Property)i.next();
1002            if (isIgnoredBinding(property.getXMLName(),
1003                                 property.getXMLNamespaceURI()) ||
1004                (property.getXMLName().startsWith("xmlns"))) {
1005                continue;
1006            }
1007            writePropertyMethodDecl(writer, property);
1008        }
1009    }
1010    
1011    /**
1012     * <p>
1013     * This will take a <code>Property</code> and generate the code
1014     * for that property as an accessor/mutator method (definition only).
1015     * </p>
1016     *
1017     * @param writer <code>Writer</code> to write method declarations to.
1018     * @param property <code>Property</code> to generate methods for.
1019     * @throws <code>IOException</code> - when errors in writing to the
1020     * supplied <code>Result</code> occur.
1021     */

1022    protected void writePropertyMethodDecl(Writer JavaDoc writer, Property property)
1023        throws IOException JavaDoc {
1024        
1025        // See if this is a Collection or not
1026
boolean isCollection = property.isCollection();
1027        String JavaDoc javaType = property.getJavaType();
1028        String JavaDoc collectionClass =
1029            NamingUtils.removePackage(property.getJavaCollectionClass());
1030
1031        /**
1032         * There is a conditional here, although all that ever should
1033         * get to here are AtomicProperty objects. But just in case...
1034         */

1035        if (property instanceof AtomicProperty) {
1036            AtomicProperty atomicProperty = (AtomicProperty)property;
1037            
1038            // Write out the property accessor
1039
writer.write(" public ");
1040            if (isCollection) {
1041                writer.write(collectionClass);
1042            } else {
1043                writer.write(javaType);
1044            }
1045            writer.write(" get");
1046            writer.write(CapitalizationUtils.initialUpper(
1047                atomicProperty.getJavaName()));
1048            if (isCollection) {
1049                writer.write("List");
1050            }
1051            writer.write("();\n\n");
1052            
1053            /**
1054             * Write out the property mutator if the property is not #FIXED
1055             * #FIXED attributes cannot be changed...
1056             */

1057            if (!atomicProperty.getModifier().get(Property.MUTABILITY_FINAL)) {
1058                writer.write(" public void set");
1059                writer.write(CapitalizationUtils.initialUpper(
1060                    atomicProperty.getJavaName()));
1061                if (isCollection) {
1062                    writer.write("List");
1063                }
1064                writer.write("(");
1065                if (isCollection) {
1066                    writer.write(collectionClass);
1067                } else {
1068                    writer.write(javaType);
1069                }
1070                writer.write(" ");
1071                if (isCollection) {
1072                    writer.write(atomicProperty.getJavaName());
1073                    writer.write("List");
1074                } else {
1075                    writer.write(atomicProperty.getJavaVariableName());
1076                }
1077               
1078                /**
1079                 * If the property has an enumerator, we want to throw
1080                 * an IllegalArgumentException if the incoming data on
1081                 * set operations doesn't pass the validation
1082                 */

1083                if (atomicProperty.hasEnumeration()) {
1084                    writer.write(")\n " +
1085                        "throws IllegalArgumentException;\n");
1086                } else {
1087                    writer.write(");\n\n");
1088                }
1089               
1090                // If this is a Collection, add the "add" method
1091
if (isCollection) {
1092                    writer.write(" public void add");
1093                    writer.write(CapitalizationUtils.initialUpper(
1094                        atomicProperty.getJavaName()));
1095                    writer.write("(");
1096                    writer.write(javaType);
1097                    writer.write(" ");
1098                    writer.write(atomicProperty.getJavaVariableName());
1099                    writer.write(");\n\n");
1100
1101                    // add the "remove" method
1102
writer.write(" public void remove");
1103                    writer.write(CapitalizationUtils.initialUpper(
1104                        atomicProperty.getJavaName()));
1105                    writer.write("(");
1106                    writer.write(javaType);
1107                    writer.write(" ");
1108                    writer.write(atomicProperty.getJavaVariableName());
1109                    writer.write(");\n\n");
1110                }
1111            }
1112        }
1113    }
1114    
1115    /**
1116     * <p>
1117     * This will write out the declaration of the various <code>marshal</code>
1118     * methods supported by generated classes.
1119     * </p>
1120     *
1121     * @param writer <code>Writer</code> to output to
1122     * @throws <code>IOException</code> - when errors in output occur.
1123     */

1124    protected void writeInterfaceMarshalMethods(Writer JavaDoc writer)
1125        throws IOException JavaDoc {
1126
1127        // marshal(File file)
1128
writer.write(" public void marshal(File file)");
1129        writer.write(" throws IOException;\n\n");
1130            
1131        // marshal(OutputStream outputStream)
1132
writer.write(" public void marshal(OutputStream outputStream)");
1133        writer.write(" throws IOException;\n\n");
1134        
1135        // marshal(Writer writer)
1136
writer.write(" public void marshal(Writer writer)");
1137        writer.write(" throws IOException;\n\n");
1138        
1139        // set DTD
1140
writer.write(" public void setDocType(String name, ");
1141        writer.write("String publicID, String systemID);\n\n");
1142        
1143        // set encoding
1144
writer.write(" public void setOutputEncoding(");
1145        writer.write("String outputEncoding);\n\n");
1146    }
1147    
1148    /**
1149     * <p>
1150     * This will take the supplied list of class names, and add import
1151     * statements for each of the classes in the list. It will also write
1152     * out all global import statements for implementation classes.
1153     * </p>
1154     *
1155     * @param writer <code>Writer</code> to output to
1156     * @param importClasses <code>List</code> of classes to add imports for
1157     * @throws <code>IOException</code> - when errors in output occur.
1158     */

1159    protected void writeImplementationImportStatements(Writer JavaDoc writer,
1160                                                       List JavaDoc importClasses)
1161        throws IOException JavaDoc {
1162
1163        // Write out global imports
1164
if (globalImplementationImports.size() > 0) {
1165            writer.write("// Global Implementation Import Statements\n");
1166        }
1167        for (Iterator JavaDoc i = globalImplementationImports.iterator();
1168             i.hasNext(); ) {
1169                 
1170            writer.write("import ");
1171            writer.write((String JavaDoc)i.next());
1172            writer.write(";\n");
1173        }
1174        if (globalImplementationImports.size() > 0) {
1175            writer.write("\n");
1176        }
1177        
1178        // Write out local imports
1179
if (importClasses.size() > 0) {
1180            writer.write("// Local Implementation Import Statements\n");
1181        }
1182        for (Iterator JavaDoc i = importClasses.iterator(); i.hasNext(); ) {
1183            writer.write("import ");
1184            writer.write((String JavaDoc)i.next());
1185            writer.write(";\n");
1186        }
1187        if (importClasses.size() > 0) {
1188            writer.write("\n");
1189        }
1190    }
1191    
1192    /**
1193     * <p>
1194     * This writes out the implementation declaration (the class header).
1195     * </p>
1196     *
1197     * @param writer <code>Writer</code> to output to
1198     * @param interfaceName the name of the interface class being implemented
1199     * @throws <code>IOException</code> - when errors in output occur.
1200     */

1201    protected void writeImplementationDeclaration(Writer JavaDoc writer,
1202                                                  String JavaDoc interfaceName)
1203        throws IOException JavaDoc {
1204            
1205        writer.write("public class ");
1206        writer.write(interfaceName);
1207        writer.write("Impl extends DefaultHandler implements Cloneable, Unmarshallable, ");
1208        writer.write("LexicalHandler, ");
1209        writer.write(interfaceName);
1210        writer.write(" {\n\n");
1211    }
1212    
1213    /**
1214     * <p>
1215     * This writes out the properties for an implementation as variables.
1216     * </p>
1217     *
1218     * @param writer <code>Writer</code> to output to
1219     * @param properties <code>List</code> of properties to write out as
1220     * member variables
1221     * @throws <code>IOException</code> - when errors in output occur.
1222     */

1223    protected void writeImplementationProperties(Writer JavaDoc writer, List JavaDoc properties)
1224        throws IOException JavaDoc {
1225            
1226        for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
1227            Property property = (Property)i.next();
1228            if (isIgnoredBinding(property.getXMLName(),
1229                                 property.getXMLNamespaceURI())) {
1230                continue;
1231            }
1232            writeProperty(writer, property);
1233        }
1234        
1235        writer.write("\n");
1236        
1237        // Special case for DTD reference
1238
writer.write(" /** Any DOCTYPE reference/statements. */\n");
1239        writer.write(" private String docTypeString;\n\n");
1240        
1241        // Special case for encoding
1242
writer.write(" /** The encoding for the output document */\n");
1243        writer.write(" private String outputEncoding;\n\n");
1244    }
1245    
1246    /**
1247     * <p>
1248     * This will take a <code>Property</code> and generate the code
1249     * for that property as a member variable.
1250     * </p>
1251     *
1252     * @param writer <code>Writer</code> to write variable declaration to.
1253     * @param property <code>Property</code> to generate code for.
1254     * @throws <code>IOException</code> - when errors in writing to the
1255     * supplied <code>Result</code> occur.
1256     */

1257    protected void writeProperty(Writer JavaDoc writer, Property property)
1258        throws IOException JavaDoc {
1259            
1260        // See if this is a Collection or not
1261
String JavaDoc javaType = property.getJavaType();
1262        boolean isCollection = property.isCollection();
1263        
1264        /**
1265         * There is a conditional here, although all that ever should
1266         * get to here are AtomicProperty objects. But just in case...
1267         */

1268        if ((property instanceof AtomicProperty) &&
1269            (!property.getXMLName().startsWith("xmlns"))) {
1270            AtomicProperty atomicProperty = (AtomicProperty)property;
1271            // Write out the property
1272
writer.write(" ");
1273            writer.write(atomicProperty.getModifierString());
1274            writer.write(" ");
1275            if (isCollection) {
1276                writer.write(NamingUtils.removePackage(
1277                    atomicProperty.getJavaCollectionClass()));
1278            } else {
1279                writer.write(atomicProperty.getJavaType());
1280            }
1281            writer.write(" ");
1282
1283            if (isCollection) {
1284                writer.write(atomicProperty.getJavaName());
1285                writer.write("List");
1286            } else {
1287                writer.write(atomicProperty.getJavaVariableName());
1288            }
1289
1290            /*
1291             * If this is a FIXED property, set its default value.
1292             */

1293            if (atomicProperty.getModifier().get(Property.MUTABILITY_FINAL)) {
1294                writer.write(" = \"" + (String JavaDoc)
1295                    atomicProperty.getDefaultValue() + "\"");
1296            }
1297
1298            writer.write(";\n");
1299            
1300            /*
1301             * If the property has an enumeration, generate variables to
1302             * hold the data to validate incoming data on set operations
1303             */

1304            if (atomicProperty.hasEnumeration()) {
1305                    String JavaDoc myName = atomicProperty.getJavaVariableName();
1306                    writer.write(" private static boolean ");
1307                    writer.write(ZeusDefaults.ZEUS_INTERNAL_PREFIX);
1308                    writer.write(CapitalizationUtils.initialUpper(myName));
1309                    writer.write("Initialized;\n");
1310                    writer.write(" private static java.util.Vector ");
1311                    writer.write(ZeusDefaults.ZEUS_INTERNAL_PREFIX);
1312                    writer.write("valid");
1313                    writer.write(CapitalizationUtils.initialUpper(myName));
1314                    writer.write(";\n");
1315            }
1316
1317            /**
1318             * If the property is an attribute and has a primitive type then
1319             * we must add a corresponding boolean to determine if the
1320             * value has been set.
1321             */

1322            if ((atomicProperty.getJavaInterfacePackage().length() == 0) &&
1323                ClassUtils.isJavaPrimitive(atomicProperty.getJavaType())) {
1324                writer.write(" private boolean ");
1325                writer.write(ZeusDefaults.ZEUS_INTERNAL_PREFIX);
1326                writer.write(CapitalizationUtils.initialUpper(
1327                    atomicProperty.getJavaVariableName()));
1328                writer.write("Set;\n");
1329            }
1330        }
1331    }
1332    
1333    /**
1334     * <p>
1335     * This will write out properties required for unmarshalling from XML
1336     * into this Java class.
1337     * </p>
1338     *
1339     * @param writer <code>Writer</code> to output to
1340     * @param container the container writing out for
1341     * @throws <code>IOException</code> - when errors in output occur.
1342     */

1343    protected void writeImplementationUnmarshallerProperties(
1344        Writer JavaDoc writer, Container container) throws IOException JavaDoc {
1345            
1346        writer.write(" /** The current node in unmarshalling */\n");
1347        writer.write(" private Unmarshallable zeus_currentUNode;\n\n");
1348        
1349        writer.write(" /** The parent node in unmarshalling */\n");
1350        writer.write(" private Unmarshallable zeus_parentUNode;\n\n");
1351        
1352        writer.write(" /** Whether this node has been handled */\n");
1353        writer.write(" private boolean zeus_thisNodeHandled = false;\n\n");
1354        
1355        writer.write(" /** Whether a DTD exists for an unmarshal call */\n");
1356        writer.write(" private boolean hasDTD;\n\n");
1357        
1358        writer.write(" /** Whether validation is occurring */\n");
1359        writer.write(" private boolean validate;\n\n");
1360        
1361        writer.write(" /** The namespace mappings on this element */\n");
1362        writer.write(" private Map namespaceMappings;\n\n");
1363        
1364        writer.write(" /** The EntityResolver for SAX parsing to use */\n");
1365        writer.write(" private static EntityResolver entityResolver;\n\n");
1366        
1367        writer.write(" /** The ErrorHandler for SAX parsing to use */\n");
1368        writer.write(" private static ErrorHandler errorHandler;\n\n");
1369    }
1370
1371
1372    /**
1373     * <p>
1374     * This writes out the prototype field and methods for an implementation class
1375     * </p>
1376     *
1377     * @param writer <code>Writer</code> to output to
1378     * @param className the name of the implementation class
1379     * @param properties <code>List</code> of properties to write out as
1380     * member variables
1381     * @throws <code>IOException</code> - when errors in output occur.
1382     */

1383    protected void writeImplementationPrototypeMethodAndField(Writer JavaDoc writer,
1384                                                  String JavaDoc className)
1385        throws IOException JavaDoc {
1386
1387        writer.write(" private static ");
1388        writer.write(className);
1389        writer.write("Impl prototype = null;\n\n");
1390
1391        writer.write(" public static void setPrototype(");
1392        writer.write(className);
1393        writer.write("Impl prototype) {\n");
1394        writer.write(" ");
1395        writer.write(className);
1396        writer.write("Impl.prototype = prototype;\n");
1397        writer.write(" }\n");
1398
1399        writer.write(" public static ");
1400        writer.write(className);
1401        writer.write("Impl newInstance() {\n");
1402        writer.write(" try {\n");
1403        writer.write(" return (prototype!=null)?(");
1404        writer.write(className);
1405        writer.write("Impl)prototype.clone(): new ");
1406        writer.write(className);
1407        writer.write("Impl();\n");
1408        writer.write(" } catch (CloneNotSupportedException e) {\n");
1409        writer.write(" return null; // never\n");
1410        writer.write(" }\n");
1411        writer.write(" }\n");
1412    }
1413
1414    /**
1415     * <p>
1416     * This writes out the constructor for an implementation class
1417     * </p>
1418     *
1419     * @param writer <code>Writer</code> to output to
1420     * @param className the name of the implementation class
1421     * @param properties <code>List</code> of properties to write out as
1422     * member variables
1423     * @throws <code>IOException</code> - when errors in output occur.
1424     */

1425    protected void writeImplementationConstructor(Writer JavaDoc writer,
1426                                                  String JavaDoc className,
1427                                                  List JavaDoc properties)
1428        throws IOException JavaDoc {
1429            
1430        writer.write(" public ");
1431        writer.write(className);
1432        writer.write("Impl() {\n");
1433
1434        // Initialize any List variables needed
1435
for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
1436            Property property = (Property)i.next();
1437            
1438            if ((isIgnoredBinding(property.getXMLName(),
1439                                  property.getXMLNamespaceURI())) ||
1440               (property.getXMLName().startsWith("xmlns"))) {
1441                continue;
1442            }
1443
1444            // Initialize collection classes
1445
if (property.isCollection()) {
1446                writer.write(" ");
1447                writer.write(property.getJavaName());
1448                writer.write("List = new ");
1449                writer.write(NamingUtils.removePackage(
1450                    ClassUtils.getCollectionImplClass(
1451                        property.getJavaCollectionClass())));
1452                writer.write("();\n");
1453            }
1454            
1455            // Handle default values
1456
if ((property.hasDefaultValue()) &&
1457                (!property.getModifier().get(Property.MUTABILITY_FINAL)) &&
1458                (!property.getXMLName().startsWith("xmlns"))) {
1459                writer.write(" ");
1460                writer.write(property.getJavaVariableName());
1461                writer.write(" = ");
1462                
1463                if ((property.getJavaInterfacePackage().length() == 0) &&
1464                    (ClassUtils.isJavaPrimitive(property.getJavaType()))) {
1465                    // in this case the property's type is a primitive
1466
generatePrimitiveAssignment(
1467                        writer, property,
1468                        "\"" + (String JavaDoc)property.getDefaultValue() + "\"");
1469                } else {
1470                    
1471                    /**
1472                     * In this case the property's type is not a String but
1473                     * is also not a primitive
1474                     */

1475                    writer.write("new ");
1476                    String JavaDoc pkg = property.getJavaInterfacePackage();
1477                    if (pkg.length() != 0) {
1478                        writer.write(pkg);
1479                        writer.write(".");
1480                    }
1481                    writer.write(property.getJavaType());
1482                    writer.write("(\"");
1483                    writer.write((String JavaDoc)property.getDefaultValue());
1484                    writer.write("\")");
1485                }
1486                
1487                writer.write(";\n");
1488            }
1489            
1490            /**
1491             * If the property has an enumeration, generate variables to
1492             * hold the data to validate incoming data on set operations
1493             */

1494            if (property.hasEnumeration()) {
1495                    String JavaDoc myName = property.getJavaVariableName();
1496                    writer.write(" ");
1497                    writer.write(ZeusDefaults.ZEUS_INTERNAL_PREFIX);
1498                    writer.write(CapitalizationUtils.initialUpper(myName));
1499                    writer.write("Initialized = false;\n");
1500                    writer.write(" ");
1501                    writer.write(ZeusDefaults.ZEUS_INTERNAL_PREFIX);
1502                    writer.write("valid");
1503                    writer.write(CapitalizationUtils.initialUpper(myName));
1504                    writer.write(" = null;\n");
1505            }
1506
1507            /**
1508             * If the property is an attribute and has a primitive type then
1509             * we must add a corresponding boolean to determine if the
1510             * value has been set.
1511             */

1512            if ((property.getJavaInterfacePackage().length() == 0) &&
1513                (ClassUtils.isJavaPrimitive(property.getJavaType()))) {
1514                
1515                writer.write(" ");
1516                writer.write(ZeusDefaults.ZEUS_INTERNAL_PREFIX);
1517                writer.write(CapitalizationUtils.initialUpper(
1518                    property.getJavaVariableName()));
1519                writer.write("Set = ");
1520                
1521                // #FIXED attributes always have their value set
1522
if (!property.getModifier().get(Property.MUTABILITY_FINAL)) {
1523                    writer.write("false;\n");
1524                } else {
1525                    writer.write("true;\n");
1526                }
1527            }
1528        }
1529        
1530        // Special case for DOCTYPE declaration
1531
writer.write(" docTypeString = \"\";\n");
1532        
1533        // Default for DTD existence
1534
writer.write(" hasDTD = false;\n");
1535        writer.write(" validate = false;\n");
1536        
1537        // Initialization
1538
writer.write(" namespaceMappings = new HashMap();\n");
1539        
1540        writer.write(" }\n\n");
1541    }
1542    
1543    
1544    /**
1545     * <p>
1546     * This writes out the properties for an implementation as methods,
1547     * including accessors, mutators, and collection-style methods if
1548     * needed.
1549     * </p>
1550     *
1551     * @param writer <code>Writer</code> to output to
1552     * @param container <code>Container</code> with properties to generate
1553     * methods for
1554     * @throws <code>IOException</code> - when errors in output occur.
1555     */

1556    protected void writeImplementationMethods(Writer JavaDoc writer,
1557                                              Container container)
1558        throws IOException JavaDoc {
1559            
1560        List JavaDoc properties = container.getProperties();
1561        for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
1562            Property property = (Property)i.next();
1563            if (isIgnoredBinding(property.getXMLName(),
1564                                 property.getXMLNamespaceURI()) ||
1565                (property.getXMLName().startsWith("xmlns"))) {
1566                continue;
1567            }
1568            writePropertyMethodImplementation(writer, property);
1569        }
1570    }
1571   
1572    /**
1573     * <p>
1574     * This will take a <code>Property</code> and generate the code
1575     * for that property as an accessor/mutator method (with implementation).
1576     * </p>
1577     *
1578     * @param writer <code>Writer</code> to write method implementations to.
1579     * @param property <code>Property</code> to generate code for.
1580     * @throws <code>IOException</code> - when errors in writing to the
1581     * supplied <code>Result</code> occur.
1582     */

1583    protected void writePropertyMethodImplementation(Writer JavaDoc writer,
1584                                                     Property property)
1585        throws IOException JavaDoc {
1586        
1587        // See if this is a Collection or not
1588
boolean isCollection = property.isCollection();
1589        String JavaDoc javaType = property.getJavaType();
1590        
1591        /**
1592         * There is a conditional here, although all that ever should
1593         * get to here are AtomicProperty objects. But just in case...
1594         */

1595        if (property instanceof AtomicProperty) {
1596            AtomicProperty atomicProperty = (AtomicProperty)property;
1597            
1598            // Write out the property accessor
1599
writer.write(" public ");
1600            if (isCollection) {
1601                writer.write(NamingUtils.removePackage(
1602                    atomicProperty.getJavaCollectionClass()));
1603            } else {
1604                writer.write(javaType);
1605            }
1606            writer.write(" get");
1607            writer.write(CapitalizationUtils
1608                         .initialUpper(atomicProperty.getJavaName()));
1609            if (isCollection) {
1610                writer.write("List");
1611            }
1612            writer.write("() {\n");
1613            writer.write(" return ");
1614
1615            if (isCollection) {
1616                writer.write(atomicProperty.getJavaName());
1617                writer.write("List");
1618            } else {
1619                writer.write(atomicProperty.getJavaVariableName());
1620            }
1621            writer.write(";\n");
1622            writer.write(" }\n\n");
1623            
1624            // Write out the property mutator if the property is not #FIXED
1625
if (!atomicProperty.getModifier().get(Property.MUTABILITY_FINAL)) {
1626                writer.write(" public void set");
1627                writer.write(CapitalizationUtils.initialUpper(
1628                    atomicProperty.getJavaName()));
1629                if (isCollection) {
1630                    writer.write("List");
1631                }
1632                writer.write("(");
1633                if (isCollection) {
1634                    writer.write(NamingUtils.removePackage(
1635                        atomicProperty.getJavaCollectionClass()));
1636                } else {
1637                    writer.write(javaType);
1638                }
1639                writer.write(" ");
1640                if (isCollection) {
1641                    writer.write(atomicProperty.getJavaName());
1642                    writer.write("List");
1643                } else {
1644                    writer.write(atomicProperty.getJavaVariableName());
1645                }
1646
1647                /**
1648                 * If the property has an enumeration, then generate
1649                 * the code to initialize the validation data and to
1650                 * validate incoming data
1651                 */

1652                if (atomicProperty.hasEnumeration()) {
1653                    String JavaDoc myName = atomicProperty.getJavaVariableName();
1654                    String JavaDoc flagName =
1655                        new StringBuffer JavaDoc(ZeusDefaults.ZEUS_INTERNAL_PREFIX)
1656                            .append(CapitalizationUtils.initialUpper(myName))
1657                            .append("Initialized")
1658                            .toString();
1659                    String JavaDoc vectorName =
1660                        new StringBuffer JavaDoc(ZeusDefaults.ZEUS_INTERNAL_PREFIX)
1661                            .append("valid")
1662                            .append(CapitalizationUtils.initialUpper(myName))
1663                            .toString();
1664                    Vector JavaDoc theEnumeration = atomicProperty.getEnumeration();
1665
1666                    writer.write(")\n ");
1667                    writer.write("throws IllegalArgumentException {\n");
1668                    writer.write(" if (!");
1669                    writer.write(flagName);
1670                    writer.write(") {\n");
1671                    writer.write(" ");
1672                    writer.write(vectorName);
1673                    writer.write(" = new java.util.Vector();\n");
1674                    for (int i=0, size=theEnumeration.size(); i < size; i++) {
1675                        writer.write(" ");
1676                        writer.write(vectorName);
1677                        writer.write(".addElement(\"");
1678                        writer.write((String JavaDoc)theEnumeration.elementAt(i));
1679                        writer.write("\");\n");
1680                    }
1681                    writer.write(" ");
1682                    writer.write(flagName);
1683                    writer.write(" = true;\n");
1684                    writer.write(" }\n");
1685                    writer.write(" if (!");
1686                    writer.write(vectorName);
1687                    writer.write(".contains(");
1688                    writer.write(myName);
1689                    writer.write(")) {\n");
1690                    writer.write(" throw new ");
1691                    writer.write("IllegalArgumentException(\"");
1692                    writer.write("Illegal value for attribute '");
1693                    writer.write(myName);
1694                    writer.write("'\");\n");
1695                    writer.write(" } else {\n");
1696                    writer.write(" this.");
1697                    writer.write(myName);
1698                    writer.write(" = ");
1699                    writer.write(myName);
1700                    writer.write(";\n");
1701                    writer.write(" this.");
1702                    writer.write(ZeusDefaults.ZEUS_INTERNAL_PREFIX);
1703                    writer.write(CapitalizationUtils.initialUpper(myName));
1704                    writer.write("Set = true;\n");
1705                    writer.write(" }\n");
1706                } else {
1707                    writer.write(") {\n");
1708                    writer.write(" this.");
1709
1710                    if (isCollection) {
1711                        writer.write(atomicProperty.getJavaName());
1712                        writer.write("List");
1713                    } else {
1714                        writer.write(atomicProperty.getJavaVariableName());
1715                    }
1716
1717                    writer.write(" = ");
1718
1719                    if (isCollection) {
1720                        writer.write(atomicProperty.getJavaName());
1721                        writer.write("List");
1722                    } else {
1723                        writer.write(atomicProperty.getJavaVariableName());
1724                    }
1725                    writer.write(";\n");
1726
1727                    /**
1728                     * If this property has a primitive type then mark that it
1729                     * has been set.
1730                     */

1731                    if ((atomicProperty.getJavaInterfacePackage()
1732                                       .length() == 0) &&
1733                        (ClassUtils.isJavaPrimitive(
1734                            atomicProperty.getJavaType()))) {
1735                                
1736                        writer.write(" ");
1737                        writer.write(ZeusDefaults.ZEUS_INTERNAL_PREFIX);
1738                        writer.write(CapitalizationUtils.initialUpper(
1739                            atomicProperty.getJavaVariableName()));
1740                        writer.write("Set = true;\n");
1741                    }
1742                }
1743                writer.write(" }\n\n");
1744            
1745                // If this is a Collection, add the "add" and "remove" methods
1746
if (isCollection) {
1747                    // Handle the "add" method
1748
writer.write(" public void add");
1749                    writer.write(CapitalizationUtils.initialUpper(
1750                        atomicProperty.getJavaName()));
1751                    writer.write("(");
1752                    writer.write(javaType);
1753                    writer.write(" ");
1754                    writer.write(atomicProperty.getJavaName());
1755                    writer.write(") {\n");
1756                    writer.write(" ");
1757                    writer.write(atomicProperty.getJavaName());
1758                    writer.write("List.add(");
1759                    writer.write(atomicProperty.getJavaName());
1760                    writer.write(");\n");
1761                    writer.write(" }\n\n");
1762                    
1763                    // add the "remove" method
1764
writer.write(" public void remove");
1765                    writer.write(CapitalizationUtils.initialUpper(
1766                        atomicProperty.getJavaName()));
1767                    writer.write("(");
1768                    writer.write(javaType);
1769                    writer.write(" ");
1770                    writer.write(atomicProperty.getJavaName());
1771                    writer.write(") {\n");
1772                    writer.write(" ");
1773                    writer.write(atomicProperty.getJavaName());
1774                    writer.write("List.remove(");
1775                    writer.write(atomicProperty.getJavaName());
1776                    writer.write(");\n");
1777                    writer.write(" }\n\n");
1778                }
1779            }
1780        }
1781    }
1782    
1783    /**
1784     * <p>
1785     * This will write out the implementation of the various
1786     * <code>marshal</code>. methods supported by generated classes.
1787     * </p>
1788     *
1789     * @param writer <code>Writer</code> to output to
1790     * @throws <code>IOException</code> - when errors in output occur.
1791     */

1792    protected void writeImplementationMarshalMethods(Writer JavaDoc writer,
1793                                                     Container container)
1794        throws IOException JavaDoc {
1795            
1796        // setDocType()
1797
writer.write(" public void setDocType(String name, ");
1798        writer.write("String publicID, String systemID) {\n");
1799        writer.write(" try {\n");
1800        writer.write(" startDTD(name, publicID, systemID);\n");
1801        writer.write(" } catch (SAXException neverHappens) { }\n");
1802        writer.write(" }\n\n");
1803        
1804        // setEncoding()
1805
writer.write(" public void setOutputEncoding(");
1806        writer.write("String outputEncoding) {\n");
1807        writer.write(" this.outputEncoding = outputEncoding;\n");
1808        writer.write(" }\n\n");
1809
1810        // marshal(File file)
1811
writer.write(" public void marshal(File file)");
1812        writer.write(" throws IOException {\n");
1813        writer.write(" // Delegate to the marshal(Writer) method\n");
1814        writer.write(" marshal(new FileWriter(file));\n");
1815        writer.write(" }\n\n");
1816            
1817        // marshal(OutputStream outputStream)
1818
writer.write(" public void marshal(OutputStream outputStream)");
1819        writer.write(" throws IOException {\n");
1820        writer.write(" // Delegate to the marshal(Writer) method\n");
1821        writer.write(" ");
1822        writer.write("marshal(new OutputStreamWriter(outputStream));\n");
1823        writer.write(" }\n\n");
1824        
1825        // marshal(Writer writer)
1826
writer.write(" public void marshal(Writer writer)");
1827        writer.write(" throws IOException {\n");
1828        writer.write(" // Write out the XML declaration\n");
1829        writer.write(" writer.write(\"<?xml version=\\\"1.0\\\" \");\n");
1830        
1831        writer.write(" if (outputEncoding != null) {\n");
1832        writer.write(" writer.write(\"encoding=\\\"\");\n");
1833        writer.write(" writer.write(outputEncoding);\n");
1834        writer.write(" writer.write(\"\\\"?>\\n\\n\");\n\n");
1835        writer.write(" } else {\n");
1836        writer.write(" writer.write(\"encoding=\\\"");
1837        writer.write("UTF-8\\\"?>\\n\\n\");\n\n");
1838        writer.write(" }\n");
1839
1840        writer.write(" // Handle DOCTYPE declaration\n");
1841        writer.write(" writer.write(docTypeString);\n");
1842        writer.write(" writer.write(\"\\n\");\n");
1843        
1844        writer.write(" // Now start the recursive writing\n");
1845        writer.write(" writeXMLRepresentation(writer, \"\");\n\n");
1846        writer.write(" // Close up\n");
1847        writer.write(" writer.flush();\n");
1848        writer.write(" writer.close();\n");
1849        writer.write(" }\n\n");
1850        
1851        writer.write(" ");
1852        writer.write("protected void writeXMLRepresentation(Writer writer,\n");
1853        writer.write(" ");
1854        writer.write(" String indent)\n");
1855        writer.write(" throws IOException {\n\n");
1856            
1857        // Write out this element
1858
writer.write(" writer.write(indent);\n");
1859        writer.write(" writer.write(\"<");
1860        writer.write(container.getXMLName());
1861        writer.write("\");\n\n");
1862        
1863        writer.write(" // Handle namespace mappings (if needed)\n");
1864        writer.write(" for (Iterator i = namespaceMappings.keySet().");
1865        writer.write("iterator(); i.hasNext(); ) {\n");
1866        writer.write(" String prefix = (String)i.next();\n");
1867        writer.write(" String uri = (String)namespaceMappings.get(");
1868        writer.write("prefix);\n");
1869        writer.write(" writer.write(\" xmlns\");\n");
1870        writer.write(" if (!prefix.trim().equals(\"\")) {\n");
1871        writer.write(" writer.write(\":\");\n");
1872        writer.write(" writer.write(prefix);\n");
1873        writer.write(" }\n");
1874        writer.write(" writer.write(\"=\\\"\");\n");
1875        writer.write(" writer.write(uri);\n");
1876        writer.write(" writer.write(\"\\\"\\n \");\n");
1877        writer.write(" }\n\n");
1878        
1879        // Write in attributes
1880
writer.write(" // Handle attributes (if needed)\n");
1881        
1882        // Iterate through this container's child properties
1883
List JavaDoc properties = container.getProperties();
1884        List JavaDoc childElements = new LinkedList JavaDoc();
1885        boolean hasChildren = false;
1886        String JavaDoc xmlValueVariable = null;
1887        for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
1888            Property property = (Property)i.next();
1889            String JavaDoc xmlName = property.getXMLName();
1890            BitSet JavaDoc modifiers = property.getModifier();
1891            
1892            if (modifiers.get(Property.SOURCE_ATTLIST)) {
1893                if (xmlName.startsWith("xmlns")) {
1894                    break;
1895                }
1896                writer.write(" if (");
1897                writer.write(ZeusDefaults.ZEUS_INTERNAL_PREFIX);
1898                writer.write(CapitalizationUtils.initialUpper(
1899                    property.getJavaName()));
1900                writer.write("Set) {\n");
1901                writer.write(" writer.write(\" ");
1902                writer.write(property.getXMLName());
1903                writer.write("=\\\"\");\n");
1904                writer.write(" writer.write(escapeAttributeValue(");
1905                writer.write(property.getJavaVariableName());
1906                writer.write("));\n");
1907                writer.write(" writer.write(\"\\\"\");\n");
1908                writer.write(" }\n");
1909            } else if (modifiers.get(Property.SOURCE_ELEMENT)) {
1910                hasChildren = true;
1911                childElements.add(property);
1912            } else if (xmlName.equals(ZeusDefaults.PCDATA_XML_NAME)) {
1913                xmlValueVariable = property.getJavaName();
1914            }
1915        }
1916        
1917        // Handle elements
1918
if (hasChildren) {
1919            writer.write(" writer.write(\">\");\n");
1920            writer.write(" writer.write(\"\\n\");\n\n");
1921            writer.write(" // Handle child elements\n");
1922        }
1923        for (Iterator JavaDoc i = childElements.iterator(); i.hasNext(); ) {
1924            Property property = (Property)i.next();
1925            if (property.isCollection()) {
1926                writer.write(" for (Iterator i=");
1927                writer.write(property.getJavaName());
1928                writer.write("List.iterator(); i.hasNext(); ) {\n");
1929                    
1930                // Determine if this was a collapsed type
1931
if (ClassUtils.isJavaPrimitive(property.getJavaType())) {
1932                    collapsedElements.add(property);
1933                    
1934                    writer.write(" ");
1935                    writer.write(property.getJavaType());
1936                    writer.write(" ");
1937                    writer.write(property.getJavaVariableName());
1938                    writer.write(" = (");
1939                    writer.write(property.getJavaType());
1940                    writer.write(")i.next();\n");
1941                    
1942                    writer.write(" writer.write(");
1943                    writer.write("new StringBuffer(indent)");
1944                    writer.write(".append(\" \").toString());\n");
1945                    writer.write(" writer.write(\"<");
1946                    writer.write(property.getXMLName());
1947                    writer.write(">\");\n");
1948                    writer.write(" writer.write(");
1949                    writer.write(property.getJavaVariableName());
1950                    writer.write(");\n");
1951                    writer.write(" writer.write(\"</");
1952                    writer.write(property.getXMLName());
1953                    writer.write(">\\n\");\n");
1954                } else {
1955                    writer.write(" ");
1956                    writer.write(property.getJavaType());
1957                    writer.write("Impl ");
1958                    writer.write(property.getJavaVariableName());
1959                    writer.write(" = (");
1960                    writer.write(property.getJavaType());
1961                    writer.write("Impl)i.next();\n");
1962                    writer.write(" ");
1963                    writer.write(property.getJavaVariableName());
1964                    writer.write(".writeXMLRepresentation(writer,\n");
1965                    writer.write(" new StringBuffer(");
1966                    writer.write("indent).append(\" \").toString());\n");
1967                }
1968                writer.write(" }\n");
1969            } else {
1970                writer.write(" if (");
1971                writer.write(property.getJavaVariableName());
1972                writer.write(" != null) {\n");
1973                    
1974                // Determine if this was a collapsed type
1975
if (ClassUtils.isJavaPrimitive(property.getJavaType())) {
1976                    collapsedElements.add(property);
1977                    
1978                    writer.write(" writer.write(");
1979                    writer.write("new StringBuffer(indent)");
1980                    writer.write(".append(\" \").toString());\n");
1981                    writer.write(" writer.write(\"<");
1982                    writer.write(property.getXMLName());
1983                    writer.write(">\");\n");
1984                    writer.write(" writer.write(this.");
1985                    writer.write(property.getJavaVariableName());
1986                    writer.write(");\n");
1987                    writer.write(" writer.write(\"</");
1988                    writer.write(property.getXMLName());
1989                    writer.write(">\\n\");\n");
1990                } else {
1991                    writer.write(" ((");
1992                    writer.write(property.getJavaType());
1993                    writer.write("Impl)");
1994                    writer.write(property.getJavaVariableName());
1995                    writer.write(").writeXMLRepresentation(writer,\n");
1996                    writer.write(" new StringBuffer(");
1997                    writer.write("indent).append(\" \").toString());\n");
1998                }
1999                writer.write(" }\n\n");
2000            }
2001        }
2002        if (hasChildren) {
2003            writer.write(" writer.write(indent);\n");
2004        
2005            // Write out the simple value, if presentI
2006
if (xmlValueVariable != null) {
2007                writer.write(" // Handle PCDATA value\n");
2008                writer.write(" writer.write(get");
2009                writer.write(CapitalizationUtils.initialUpper(xmlValueVariable));
2010                writer.write("());\n");
2011            }
2012        
2013            // Close up this element
2014
writer.write(" writer.write(\"</");
2015            writer.write(container.getXMLName());
2016            writer.write(">\\n\");\n");
2017            writer.write(" }\n\n");
2018        } else {
2019            // Write out the simple value, if present
2020
if (xmlValueVariable != null) {
2021                writer.write(" if (get");
2022                writer.write(CapitalizationUtils.initialUpper(xmlValueVariable));
2023                writer.write("() != null) {\n");
2024                writer.write(" // Handle PCDATA value\n");
2025                writer.write(" writer.write(\">\");\n");
2026                writer.write(" writer.write(");
2027                writer.write("escapeTextValue(get");
2028                writer.write(CapitalizationUtils.initialUpper(xmlValueVariable));
2029                writer.write("()));\n");
2030
2031                // Close up this element
2032
writer.write(" writer.write(\"</");
2033                writer.write(container.getXMLName());
2034                writer.write(">\\n\");\n");
2035                writer.write(" } else {\n");
2036                writer.write(" writer.write(\"/>\\n\");\n");
2037                writer.write(" }\n");
2038            } else {
2039                writer.write(" writer.write(\"/>\\n\");\n");
2040            }
2041            writer.write(" }\n\n");
2042        }
2043        
2044        // Write out properties for needed collapsed child elements
2045
for (Iterator JavaDoc i = collapsedElements.iterator(); i.hasNext(); ) {
2046            Property property = (Property)i.next();
2047            writer.write(" /** Indicates if we are in the ");
2048            writer.write(property.getJavaVariableName());
2049            writer.write(" element */\n");
2050            writer.write(" private boolean zeus_in");
2051            writer.write(CapitalizationUtils.initialUpper(
2052                property.getJavaVariableName()));
2053            writer.write(" = false;\n\n");
2054            
2055            if (property.isCollection()) {
2056            writer.write(" /** Value for the current ");
2057            writer.write(property.getJavaVariableName());
2058            writer.write(" being processed */\n");
2059            writer.write(" private ");
2060            writer.write(property.getJavaType());
2061            writer.write(" zeus_current");
2062            writer.write(CapitalizationUtils.initialUpper(
2063                property.getJavaVariableName()));
2064            writer.write(";\n\n");
2065            }
2066        }
2067        
2068        // support: escapeAttributeValue
2069
writer.write(" private String escapeAttributeValue(");
2070        writer.write("String attributeValue) {\n");
2071        writer.write(" String returnValue = attributeValue;\n");
2072        writer.write(" for (int i = 0; i < returnValue.length(); ");
2073        writer.write("i++) {\n");
2074        writer.write(" char ch = returnValue.charAt(i);\n");
2075        writer.write(" if (ch == '\"') {\n");
2076        writer.write(" returnValue = new StringBuffer()\n");
2077        writer.write(" .append(returnValue.substring(");
2078        writer.write("0, i))\n");
2079        writer.write(" .append(\"&quot;\")\n");
2080        writer.write(" .append(returnValue.");
2081        writer.write("substring(i+1))\n");
2082        writer.write(" .toString();\n");
2083        writer.write(" }\n");
2084        writer.write(" }\n");
2085        writer.write(" return returnValue;\n");
2086        writer.write(" }\n\n");
2087        
2088        // support: escapeTextValue
2089
writer.write(" private String escapeTextValue(");
2090        writer.write("String textValue) {\n");
2091        writer.write(" String returnValue = textValue;\n");
2092        writer.write(" for (int i = 0; i < returnValue.length(); ");
2093        writer.write("i++) {\n");
2094        writer.write(" char ch = returnValue.charAt(i);\n");
2095        writer.write(" if (ch == '<') {\n");
2096        writer.write(" returnValue = new StringBuffer()\n");
2097        writer.write(" .append(returnValue.substring(");
2098        writer.write("0, i))\n");
2099        writer.write(" .append(\"&lt;\")\n");
2100        writer.write(" .append(returnValue.");
2101        writer.write("substring(i+1))\n");
2102        writer.write(" .toString();\n");
2103        writer.write(" } else if (ch == '>') {\n");
2104        writer.write(" returnValue = new StringBuffer()\n");
2105        writer.write(" .append(returnValue.substring(");
2106        writer.write("0, i))\n");
2107        writer.write(" .append(\"&gt;\")\n");
2108        writer.write(" .append(returnValue.");
2109        writer.write("substring(i+1))\n");
2110        writer.write(" .toString();\n");
2111        writer.write(" }\n");
2112        writer.write(" }\n");
2113        writer.write(" return returnValue;\n");
2114        writer.write(" }\n\n");
2115    }
2116    
2117    /**
2118     * <p>
2119     * This will write out the implementation of the various
2120     * <code>unmarshal</code> methods supported by generated classes.
2121     * </p>
2122     *
2123     * @param writer <code>Writer</code> to output to
2124     * @param container the container to write methods for.
2125     * @throws <code>IOException</code> - when errors in output occur.
2126     */

2127    protected void writeImplementationUnmarshalMethods(Writer JavaDoc writer,
2128                                                       Container container)
2129        throws IOException JavaDoc {
2130            
2131        String JavaDoc className = container.getJavaType();
2132        String JavaDoc variableName = container.getJavaVariableName();
2133        
2134        // Set an entity resolver
2135
writer.write(" /**\n");
2136        writer.write(" * <p>\n");
2137        writer.write(" * This sets a SAX <code>EntityResolver</code> for");
2138        writer.write(" this unmarshalling process.\n");
2139        writer.write(" * </p>\n");
2140        writer.write(" *\n");
2141        writer.write(" * @param resolver the entity resolver ");
2142        writer.write("to use.\n");
2143        writer.write(" */\n");
2144        writer.write(" public static void setEntityResolver(");
2145        writer.write("EntityResolver resolver) {\n");
2146        writer.write(" entityResolver = resolver;\n");
2147        writer.write(" }\n\n");
2148        
2149        // Set an error handler
2150
writer.write(" /**\n");
2151        writer.write(" * <p>\n");
2152        writer.write(" * This sets a SAX <code>ErrorHandler</code> for");
2153        writer.write(" this unmarshalling process.\n");
2154        writer.write(" * </p>\n");
2155        writer.write(" *\n");
2156        writer.write(" * @param handler the entity resolver ");
2157        writer.write("to use.\n");
2158        writer.write(" */\n");
2159        writer.write(" public static void setErrorHandler(");
2160        writer.write("ErrorHandler handler) {\n");
2161        writer.write(" errorHandler = handler;\n");
2162        writer.write(" }\n\n");
2163
2164        // unmarshal(File file)
2165
writer.write(" public static ");
2166        writer.write(className);
2167        writer.write(" unmarshal(File file)");
2168        writer.write(" throws IOException {\n");
2169        writer.write(" // Delegate to the unmarshal(Reader) method\n");
2170        writer.write(" return unmarshal(new FileReader(file));\n");
2171        writer.write(" }\n\n");
2172        
2173        // unmarshal(File file, boolean validate)
2174
writer.write(" public static ");
2175        writer.write(className);
2176        writer.write(" unmarshal(File file, boolean validate)");
2177        writer.write(" throws IOException {\n");
2178        writer.write(" // Delegate to the unmarshal(Reader) method\n");
2179        writer.write(" return unmarshal(new FileReader(file), ");
2180        writer.write("validate);\n");
2181        writer.write(" }\n\n");
2182            
2183        // unmarshal(InputStream inputStream)
2184
writer.write(" public static ");
2185        writer.write(className);
2186        writer.write(" unmarshal(InputStream inputStream)");
2187        writer.write(" throws IOException {\n");
2188        writer.write(" // Delegate to the unmarshal(Reader) method\n");
2189        writer.write(" ");
2190        writer.write("return unmarshal(new InputStreamReader(inputStream));\n");
2191        writer.write(" }\n\n");
2192        
2193        // unmarshal(InputStream inputStream, boolean validate)
2194
writer.write(" public static ");
2195        writer.write(className);
2196        writer.write(" unmarshal(InputStream inputStream, boolean validate)");
2197        writer.write(" throws IOException {\n");
2198        writer.write(" // Delegate to the unmarshal(Reader) method\n");
2199        writer.write(" ");
2200        writer.write("return unmarshal(new InputStreamReader(inputStream), ");
2201        writer.write("validate);\n");
2202        writer.write(" }\n\n");
2203        
2204        // unmarshal(Reader reader)
2205
writer.write(" public static ");
2206        writer.write(className);
2207        writer.write(" unmarshal(Reader reader)");
2208        writer.write(" throws IOException {\n");
2209        writer.write(" // Delegate with default validation value\n");
2210        writer.write(" ");
2211        writer.write("return unmarshal(reader, ");
2212        writer.write(ZeusDefaults.DEFAULT_VALIDATION_STATE.toString());
2213        writer.write(");\n");
2214        writer.write(" }\n\n");
2215        
2216        // unmarshal(Reader reader, boolean validate)
2217
writer.write(" public static ");
2218        writer.write(className);
2219        writer.write(" unmarshal(Reader reader, boolean validate)");
2220        writer.write(" throws IOException {\n");
2221
2222        // Create new instance
2223
writer.write(" ");
2224        writer.write(className);
2225        writer.write("Impl ");
2226        writer.write(variableName);
2227        writer.write(" = ");
2228        writer.write(className);
2229        writer.write("Impl.newInstance();\n");
2230        
2231        // Set validation state
2232
writer.write(" ");
2233        writer.write(variableName);
2234        writer.write(".setValidating(validate);\n");
2235        
2236        // Set up class heirarchy
2237
writer.write(" ");
2238        writer.write(variableName);
2239        writer.write(".setCurrentUNode(");
2240        writer.write(variableName);
2241        writer.write(");\n");
2242        writer.write(" ");
2243        writer.write(variableName);
2244        writer.write(".setParentUNode(null);\n");
2245            
2246        // Load the XML parser
2247
writer.write(" // Load the XML parser\n");
2248        writer.write(" XMLReader parser = null;\n");
2249        writer.write(" String parserClass = System.getProperty(");
2250        writer.write("\"org.xml.sax.driver\",\n");
2251        writer.write(" \"");
2252        writer.write(ZeusDefaults.DEFAULT_PARSER);
2253        writer.write("\");\n");
2254        writer.write(" try {\n");
2255        writer.write(" parser = ");
2256        writer.write("XMLReaderFactory.createXMLReader(parserClass);\n\n");
2257        writer.write(" // Set entity resolver, if needed\n");
2258        writer.write(" if (entityResolver != null) {\n");
2259        writer.write(" parser.setEntityResolver(");
2260        writer.write("entityResolver);\n");
2261        writer.write(" }\n\n");
2262        writer.write(" // Set error handler\n");
2263        writer.write(" parser.setErrorHandler(");
2264        writer.write(variableName);
2265        writer.write(");\n\n");
2266        writer.write(" // Register lexical handler\n");
2267        writer.write(" parser.setProperty(\"");
2268        writer.write("http://xml.org/sax/properties/lexical-handler");
2269        writer.write("\", ");
2270        writer.write(variableName);
2271        writer.write(");\n\n");
2272        writer.write(" // Register content handler\n");
2273        writer.write(" parser.setContentHandler(");
2274        writer.write(variableName);
2275        writer.write(");\n");
2276        writer.write(" } catch (SAXException e) {\n");
2277        writer.write(" throw new IOException(");
2278        writer.write("\"Could not load XML parser: \" + \n");
2279        writer.write(" e.getMessage());\n");
2280        writer.write(" }\n\n");
2281        
2282        // Get the input source
2283
writer.write(" InputSource inputSource = new InputSource(");
2284        writer.write("reader);\n");
2285        writer.write(" try {\n");
2286            
2287        // Set validation
2288
writer.write(" parser.setFeature(");
2289        writer.write("\"http://xml.org/sax/features/validation\", ");
2290        writer.write("new Boolean(validate).booleanValue());\n");
2291        
2292        // Set namespace processing
2293
writer.write(" parser.setFeature(");
2294        writer.write("\"http://xml.org/sax/features/namespaces\", ");
2295        writer.write("true);\n");
2296        writer.write(" parser.setFeature(");
2297        writer.write("\"http://xml.org/sax/features/namespace-prefixes\", ");
2298        writer.write("false);\n");
2299        
2300        // Parse
2301
writer.write(" parser.parse(inputSource);\n");
2302        writer.write(" } catch (SAXException e) {\n");
2303        writer.write(" throw new IOException(");
2304        writer.write("\"Error parsing XML document: \" + \n");
2305        writer.write(" e.getMessage());\n");
2306        writer.write(" }\n\n");
2307        
2308        // Return the resulting object
2309
writer.write(" // Return the resultant object\n");
2310        writer.write(" return ");
2311        writer.write(variableName);
2312        writer.write(";\n");
2313        writer.write(" }\n\n");
2314        
2315        // Support method: getParentUNode
2316
writer.write(" public Unmarshallable getParentUNode() {\n");
2317        writer.write(" return zeus_parentUNode;\n");
2318        writer.write(" }\n\n");
2319        
2320        // Support method: setParentUNode
2321
writer.write(" public void setParentUNode(");
2322        writer.write("Unmarshallable parentUNode) {\n");
2323        writer.write(" this.zeus_parentUNode = parentUNode;\n");
2324        writer.write(" }\n\n");
2325        
2326        // Support method: getCurrentUNode
2327
writer.write(" public Unmarshallable getCurrentUNode() {\n");
2328        writer.write(" return zeus_currentUNode;\n");
2329        writer.write(" }\n\n");
2330        
2331        // Support method: setCurrentUNode
2332
writer.write(" public void setCurrentUNode(");
2333        writer.write("Unmarshallable currentUNode) {\n");
2334        writer.write(" this.zeus_currentUNode = currentUNode;\n");
2335        writer.write(" }\n\n");
2336        
2337        writer.write(" public void setValidating(boolean validate) {\n");
2338        writer.write(" this.validate = validate;\n");
2339        writer.write(" }\n\n");
2340    }
2341    
2342    /**
2343     * <p>
2344     * This will write out methods that implements various SAX handlers
2345     * for use in unmarshalling.
2346     * </p>
2347     *
2348     * @param writer <code>Writer</code> to output to
2349     * @param container the container to write class for.
2350     * @throws <code>IOException</code> - when errors in output occur.
2351     */

2352    protected void writeImplementationSAXHandlerMethods(Writer JavaDoc writer,
2353                                                        Container container)
2354        throws IOException JavaDoc {
2355            
2356        String JavaDoc className =
2357            CapitalizationUtils.initialUpper(container.getJavaName());
2358        String JavaDoc variableName = container.getJavaVariableName();
2359        
2360        // SAX startDocument()
2361
writer.write(" public void startDocument() throws SAXException {\n");
2362        writer.write(" // no-op\n");
2363        writer.write(" }\n\n");
2364        
2365        // SAX setDocumentLocator()
2366
writer.write(" public void setDocumentLocator(Locator locator) {\n");
2367        writer.write(" // no-op\n");
2368        writer.write(" }\n\n");
2369        
2370        // SAX startPrefixMapping()
2371
writer.write(" public void startPrefixMapping(String prefix, ");
2372        writer.write("String uri)\n");
2373        writer.write(" throws SAXException {\n");
2374        writer.write(" namespaceMappings.put(prefix, uri);\n");
2375        writer.write(" }\n\n");
2376        
2377        // SAX startElement()
2378
writer.write(" public void startElement(String namespaceURI, ");
2379        writer.write("String localName,\n");
2380        writer.write(" String qName, ");
2381        writer.write("org.xml.sax.Attributes atts)\n");
2382        writer.write(" throws SAXException {\n\n");
2383            
2384        writer.write(" // Feed this to the correct ContentHandler\n");
2385        writer.write(" Unmarshallable current = getCurrentUNode();\n");
2386        writer.write(" if (current != this) {\n");
2387        writer.write(" current.startElement(");
2388        writer.write("namespaceURI, localName, qName, atts);\n");
2389        writer.write(" return;\n");
2390        writer.write(" }\n\n");
2391
2392        writer.write(" // See if we handle, or we delegate\n");
2393        writer.write(" if ((localName.equals(\"");
2394        writer.write(container.getXMLName());
2395        writer.write("\")) && (!zeus_thisNodeHandled)) {\n");
2396            
2397        writer.write(" // Handle ourselves\n");
2398        writer.write(" for (int i=0, len=atts.getLength(); i<len;");
2399        writer.write(" i++) {\n");
2400        writer.write(" String attName");
2401        writer.write("= atts.getLocalName(i);\n");
2402        writer.write(" String attValue = atts.getValue(i);\n");
2403        
2404        // Write out conditionals for this binding's attributes
2405
List JavaDoc properties = container.getProperties();
2406        for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
2407            Property property = (Property)i.next();
2408            BitSet JavaDoc modifiers = property.getModifier();
2409            String JavaDoc propertyXMLName = property.getXMLName();
2410            
2411            // Only delegate to child elements
2412
if ((modifiers.get(Property.SOURCE_ATTLIST)) &&
2413                (!modifiers.get(Property.MUTABILITY_FINAL)) &&
2414                (!propertyXMLName.startsWith("xmlns"))) {
2415                writer.write(" ");
2416                writer.write("if (attName.equals(\"");
2417                writer.write(propertyXMLName);
2418                writer.write("\")) {\n");
2419                writer.write(" set");
2420                writer.write(CapitalizationUtils.initialUpper(
2421                    property.getJavaName()));
2422                writer.write("(attValue);\n");
2423                writer.write(" }\n");
2424            }
2425        }
2426        
2427        writer.write(" }\n");
2428        writer.write(" zeus_thisNodeHandled = true;\n");
2429        writer.write(" return;\n");
2430        writer.write(" } else {\n");
2431        writer.write(" // Delegate handling\n");
2432        
2433        // Delegation to properties
2434
String JavaDoc pcDataVariableName = null;
2435        for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
2436            Property property = (Property)i.next();
2437            BitSet JavaDoc modifiers = property.getModifier();
2438            String JavaDoc propertyXMLName = property.getXMLName();
2439            
2440            // Only delegate to child elements
2441
if (modifiers.get(Property.SOURCE_ELEMENT)) {
2442                String JavaDoc propertyClassName =
2443                    CapitalizationUtils.initialUpper(property.getJavaName());
2444                String JavaDoc propertyVariableName = property.getJavaVariableName();
2445                
2446                writer.write(" if (localName.equals(\"");
2447                writer.write(propertyXMLName);
2448                writer.write("\")");
2449                    
2450                if (collapsedElements.contains(property)) {
2451                    writer.write(") {\n");
2452                    writer.write(" this.zeus_in");
2453                    writer.write(CapitalizationUtils.initialUpper(
2454                        propertyVariableName));
2455                    writer.write(" = true;\n");
2456                } else {
2457                    if (!property.isCollection()) {
2458                        writer.write(" && (");
2459                        writer.write(propertyVariableName);
2460                        writer.write("==null)");
2461                    }
2462                    writer.write(") {\n");
2463                    writer.write(" ");
2464                    writer.write(property.getJavaType());
2465                    writer.write("Impl ");
2466                    writer.write(propertyVariableName);
2467                    writer.write(" = ");
2468                    writer.write(property.getJavaType());
2469                    writer.write("Impl.newInstance();\n");
2470                
2471                    // Set up this new object's delegation heirarchy
2472
writer.write(" current = ");
2473                    writer.write("getCurrentUNode();\n");
2474                    writer.write(" ");
2475                    writer.write(propertyVariableName);
2476                    writer.write(".setParentUNode(current);\n");
2477                    writer.write(" ");
2478                    writer.write(propertyVariableName);
2479                    writer.write(".setCurrentUNode(");
2480                    writer.write(propertyVariableName);
2481                    writer.write(");\n");
2482                    writer.write(" this.setCurrentUNode(");
2483                    writer.write(propertyVariableName);
2484                    writer.write(");\n");
2485                    writer.write(" ");
2486                    writer.write(propertyVariableName);
2487                    writer.write(".startElement(namespaceURI, localName, ");
2488                    writer.write("qName, atts);\n");
2489                
2490                    // Add the (populated) object value
2491
writer.write(" // Add this value in\n");
2492                    if (property.isCollection()) {
2493                        writer.write(" ");
2494                        writer.write(property.getJavaName());
2495                        writer.write("List.add(");
2496                        writer.write(propertyVariableName);
2497                        writer.write(");\n");
2498                    } else {
2499                        writer.write(" this.");
2500                        writer.write(propertyVariableName);
2501                        writer.write(" = ");
2502                        writer.write(propertyVariableName);
2503                        writer.write(";\n");
2504                    }
2505                }
2506                
2507                writer.write(" return;\n");
2508                writer.write(" }\n");
2509            } else if (propertyXMLName.equals(ZeusDefaults.PCDATA_XML_NAME)) {
2510                pcDataVariableName = property.getJavaVariableName();
2511            }
2512        }
2513        
2514        writer.write(" }\n");
2515        writer.write(" }\n\n");
2516        
2517        // SAX endElement()
2518
writer.write(" public void endElement(String namespaceURI, ");
2519        writer.write("String localName,\n");
2520        writer.write(" String qName)\n");
2521        writer.write(" throws SAXException {\n\n");
2522            
2523        writer.write(" Unmarshallable current = getCurrentUNode();\n");
2524        writer.write(" if (current != this) {\n");
2525        writer.write(" current.endElement(");
2526        writer.write("namespaceURI, localName, qName);\n");
2527        writer.write(" return;\n");
2528        writer.write(" }\n\n");
2529        
2530        // Handle collapsed elements
2531
for (Iterator JavaDoc i = properties.iterator(); i.hasNext(); ) {
2532            Property property = (Property)i.next();
2533            if (collapsedElements.contains(property)) {
2534                writer.write(" if (localName.equals(\"");
2535                writer.write(property.getXMLName());
2536                writer.write("\")) {\n");
2537                writer.write(" this.zeus_in");
2538                writer.write(CapitalizationUtils.initialUpper(
2539                    property.getJavaVariableName()));
2540                writer.write(" = false;\n");
2541                
2542                // Handle multiple properties
2543
if (property.isCollection()) {
2544                    writer.write(" add");
2545                    writer.write(CapitalizationUtils.initialUpper(
2546                        property.getJavaName()));
2547                    writer.write("(zeus_current");
2548                    writer.write(CapitalizationUtils.initialUpper(
2549                        property.getJavaVariableName()));
2550                    writer.write(");\n");
2551                    writer.write(" this.zeus_current");
2552                    writer.write(CapitalizationUtils.initialUpper(
2553                        property.getJavaVariableName()));
2554                    writer.write(" = null;\n");
2555                }
2556                
2557                writer.write(" return;\n");
2558                writer.write(" }\n\n");
2559            }
2560        }
2561        
2562        if (pcDataVariableName != null) {
2563            writer.write(" // Make sure we have textual value\n");
2564            writer.write(" if (this.");
2565            writer.write(pcDataVariableName);
2566            writer.write(" == null) {\n");
2567            writer.write(" this.");
2568            writer.write(pcDataVariableName);
2569            writer.write(" = \"\";\n");
2570            writer.write(" }\n");
2571        }
2572        
2573        writer.write(" Unmarshallable parent = ");
2574        writer.write("getCurrentUNode().getParentUNode();\n");
2575        writer.write(" if (parent != null) {\n");
2576        writer.write(" parent.setCurrentUNode(parent);\n");
2577        writer.write(" }\n");
2578        writer.write(" }\n\n");
2579        
2580        // SAX characters()
2581
writer.write(" public void characters(char[] ch, ");
2582        writer.write("int start, int len)\n");
2583        writer.write(" throws SAXException {\n\n");
2584        writer.write(" // Feed this to the correct ContentHandler\n");
2585        writer.write(" Unmarshallable current = ");
2586        writer.write("getCurrentUNode();\n");
2587        writer.write(" if (current != this) {\n");
2588        writer.write(" current.characters(ch, start, len);\n");
2589        writer.write(" return;\n");
2590        writer.write(" }\n\n");
2591        
2592        writer.write(" String text = new String(ch, start, len);\n");
2593        writer.write(" text = text.trim();\n");
2594        
2595        // Handle nested collapsed elements
2596
for (Iterator JavaDoc i = collapsedElements.iterator(); i.hasNext(); ) {
2597            Property property = (Property)i.next();
2598            
2599            String JavaDoc javaVariableName = property.getJavaVariableName();
2600            writer.write(" if (zeus_in");
2601            writer.write(CapitalizationUtils.initialUpper(
2602                javaVariableName));
2603            writer.write(") {\n");
2604                
2605            // Handle the case where the collapsed element is a collection
2606
if (property.isCollection()) {
2607                writer.write(" if (this.zeus_current");
2608                writer.write(CapitalizationUtils.initialUpper(
2609                    javaVariableName));
2610                writer.write(" == null) {\n");
2611                writer.write(" this.zeus_current");
2612                writer.write(CapitalizationUtils.initialUpper(
2613                    javaVariableName));
2614                writer.write(" = text;\n");
2615                writer.write(" } else {\n");
2616                writer.write(" this.zeus_current");
2617                writer.write(CapitalizationUtils.initialUpper(
2618                    javaVariableName));
2619                writer.write(" = new StringBuffer(this.zeus_current");
2620                writer.write(CapitalizationUtils.initialUpper(
2621                    javaVariableName));
2622                writer.write(").append(text).toString();\n");
2623                writer.write(" }\n");
2624            } else {
2625                writer.write(" if (this.");
2626                writer.write(javaVariableName);
2627                writer.write(" == null) {\n");
2628                writer.write(" this.");
2629                writer.write(javaVariableName);
2630                writer.write(" = text;\n");
2631                writer.write(" } else {\n");
2632                writer.write(" this.");
2633                writer.write(javaVariableName);
2634                writer.write(" = new StringBuffer(this.");
2635                writer.write(javaVariableName);
2636                writer.write(").append(text).toString();\n");
2637                writer.write(" }\n");
2638            }
2639            writer.write(" return;\n");
2640            writer.write(" }\n\n");
2641        }
2642        
2643        // Handle character content, if applicable
2644
if (pcDataVariableName != null) {
2645            writer.write(" if (this.");
2646            writer.write(pcDataVariableName);
2647            writer.write(" == null) {\n");
2648            writer.write(" this.");
2649            writer.write(pcDataVariableName);
2650            writer.write(" = text;\n");
2651            writer.write(" } else {\n");
2652            writer.write(" this.");
2653            writer.write(pcDataVariableName);
2654            writer.write(" = new StringBuffer(this.");
2655            writer.write(pcDataVariableName);
2656            writer.write(").append(text).toString();\n");
2657            writer.write(" }\n");
2658        }
2659        writer.write(" }\n\n");
2660        
2661        // SAX comment()
2662
writer.write(" public void comment(char ch[], int start, int len) ");
2663        writer.write("throws SAXException {\n");
2664        writer.write(" // Currently no-op\n");
2665        writer.write(" }\n\n");
2666        
2667        // SAX warning()
2668
writer.write(" public void warning(SAXParseException e) ");
2669        writer.write("throws SAXException {\n");
2670        writer.write(" if (errorHandler != null) {\n");
2671        writer.write(" errorHandler.warning(e);\n");
2672        writer.write(" }\n");
2673        writer.write(" }\n\n");
2674        
2675        // SAX error()
2676
writer.write(" public void error(SAXParseException e) ");
2677        writer.write("throws SAXException {\n");
2678        writer.write(" if ((validate) && (!hasDTD)) {\n");
2679        writer.write(" throw new SAXException(\"");
2680        writer.write("Validation is turned on, but no DTD has been specified ");
2681        writer.write("in the input XML document. Please supply a DTD through ");
2682        writer.write("a DOCTYPE reference.\");\n");
2683        writer.write(" }\n");
2684        writer.write(" if (errorHandler != null) {\n");
2685        writer.write(" errorHandler.error(e);\n");
2686        writer.write(" }\n");
2687        writer.write(" }\n\n");
2688        
2689        // SAX fatalError()
2690
writer.write(" public void fatalError(SAXParseException e) ");
2691        writer.write("throws SAXException {\n");
2692        writer.write(" if ((validate) && (!hasDTD)) {\n");
2693        writer.write(" throw new SAXException(\"");
2694        writer.write("Validation is turned on, but no DTD has been specified ");
2695        writer.write("in the input XML document. Please supply a DTD through ");
2696        writer.write("a DOCTYPE reference.\");\n");
2697        writer.write(" }\n");
2698        writer.write(" if (errorHandler != null) {\n");
2699        writer.write(" errorHandler.fatalError(e);\n");
2700        writer.write(" }\n");
2701        writer.write(" }\n\n");
2702        
2703        // SAX startDTD()
2704
writer.write(" public void startDTD(String name, String publicID, ");
2705        writer.write("String systemID)\n");
2706        writer.write(" throws SAXException {\n\n");
2707        writer.write(" if ((name == null) || (name.equals(\"\"))) {\n");
2708        writer.write(" docTypeString = \"\";\n");
2709        writer.write(" return;\n");
2710        writer.write(" }\n\n");
2711        writer.write(" hasDTD = true;\n");
2712        writer.write(" StringBuffer docTypeSB = new StringBuffer();\n");
2713        writer.write(" boolean hasPublic = false;\n\n");
2714        writer.write(" docTypeSB.append(\"<!DOCTYPE \")\n");
2715        writer.write(" .append(name);\n\n");
2716        writer.write(" if ((publicID != null) && ");
2717        writer.write("(!publicID.equals(\"\"))) {\n");
2718        writer.write(" docTypeSB.append(\" PUBLIC \\\"\")\n");
2719        writer.write(" .append(publicID)\n");
2720        writer.write(" .append(\"\\\"\");\n");
2721        writer.write(" hasPublic = true;\n");
2722        writer.write(" }\n\n");
2723        writer.write(" if ((systemID != null) && ");
2724        writer.write("(!systemID.equals(\"\"))) {\n");
2725        writer.write(" if (!hasPublic) {\n");
2726        writer.write(" docTypeSB.append(\" SYSTEM\");\n");
2727        writer.write(" }\n");
2728        writer.write(" docTypeSB.append(\" \\\"\")\n");
2729        writer.write(" .append(systemID)\n");
2730        writer.write(" .append(\"\\\"\");\n\n");
2731        writer.write(" }\n\n");
2732        writer.write(" docTypeSB.append(\">\");\n\n");
2733        writer.write(" docTypeString = docTypeSB.toString();\n");
2734        writer.write(" }\n\n");
2735        
2736        // SAX endDTD()
2737
writer.write(" public void endDTD() throws SAXException {\n");
2738        writer.write(" // Currently no-op\n");
2739        writer.write(" }\n\n");
2740        
2741        // SAX startEntity()
2742
writer.write(" public void startEntity(String name) ");
2743        writer.write("throws SAXException {\n");
2744        writer.write(" // Currently no-op\n");
2745        writer.write(" }\n\n");
2746        
2747        // SAX endEntity()
2748
writer.write(" public void endEntity(String name) ");
2749        writer.write("throws SAXException {\n");
2750        writer.write(" // Currently no-op\n");
2751        writer.write(" }\n\n");
2752        
2753        // SAX startCDATA()
2754
writer.write(" public void startCDATA() throws SAXException {\n");
2755        writer.write(" // Currently no-op\n");
2756        writer.write(" }\n\n");
2757        
2758        // SAX endCDATA()
2759
writer.write(" public void endCDATA() throws SAXException {\n");
2760        writer.write(" // Currently no-op\n");
2761        writer.write(" }\n\n");
2762    }
2763    
2764    /**
2765     * <p>
2766     * This will return the fully qualified class name of a specific
2767     * <code>Binding</code>.
2768     * </p>
2769     *
2770     * @return <code>String</code> - the fully qualified Java type associated
2771     * with the binding.
2772     */

2773    private String JavaDoc getFullyQualifiedClassName(Binding binding) {
2774        String JavaDoc packageName = binding.getJavaInterfacePackage();
2775        if ((packageName != null) && (packageName != "")) {
2776            return packageName + "." + binding.getJavaType();
2777        } else {
2778            return binding.getJavaType();
2779        }
2780    }
2781
2782    /**
2783     * <p>
2784     * This method will write to the writer an expression that evaluates to the
2785     * value of the string value, but as the type of the property.
2786     * Only use this if the property has a primitive Java type.
2787     * </p>
2788     *
2789     * @param writer the output writer
2790     * @param property the property that defines the primitive type
2791     * @param value the string value for the primitive (i.e. "true" for boolean
2792     * or "1.8" for float)
2793     */

2794    protected void generatePrimitiveAssignment(Writer JavaDoc writer,
2795                                               Property property,
2796                                               String JavaDoc value)
2797        throws IOException JavaDoc {
2798            
2799        String JavaDoc type = property.getJavaType();
2800        if (type.equals("boolean")) {
2801            writer.write("Boolean.valueOf(" + value + ").booleanValue()");
2802        } else if (type.equals("byte")) {
2803            writer.write("Byte.valueOf(" + value + ").byteValue()");
2804        } else if (type.equals("char")) {
2805            writer.write(value + ".charAt(0)");
2806        } else if (type.equals("double")) {
2807            writer.write("Double.valueOf(" + value + ").doubleValue()");
2808        } else if (type.equals("float")) {
2809            writer.write("Float.valueOf(" + value + ").floatValue()");
2810        } else if (type.equals("int")) {
2811            writer.write("Integer.valueOf(" + value + ").intValue()");
2812        } else if (type.equals("long")) {
2813            writer.write("Long.valueOf(" + value + ").longValue()");
2814        } else if (type.equals("short")) {
2815            writer.write("Short.valueOf(" + value + ").shortValue()");
2816        } else if (type.equals("String")) {
2817            writer.write(value);
2818        }
2819    }
2820
2821    /**
2822     * <p>
2823     * This will initialize this instance of <code>Generator</code>,
2824     * handling tasks like directory creation.
2825     * </p>
2826     *
2827     * @throws <code>IllegalOutputDirectoryException</code> - when an illegal
2828     * output directory has been supplied to this <code>Generator</code>
2829     */

2830    private void initialize() throws IllegalOutputDirectoryException {
2831        // Determine the output directory
2832
if (outputDir == null) {
2833            outputDir = new File JavaDoc(".");
2834        }
2835        
2836        // Ensure the output directory exists and is a directory
2837
if ((outputDir.exists()) && (!outputDir.isDirectory())) {
2838            throw new IllegalOutputDirectoryException(
2839                outputDir.getAbsolutePath());
2840        }
2841
2842        // Create the directory if it does not exist
2843
if (!outputDir.exists()) {
2844            outputDir.mkdir();
2845        }
2846
2847        initialized = true;
2848    }
2849
2850    /**
2851     * <p>
2852     * This will reset the initialization state of this <code>Generator</code>
2853     * instance to <code>false</code>.
2854     * </p>
2855     */

2856    private void uninitialize() {
2857        initialized = false;
2858    }
2859    
2860    /**
2861     * <p>
2862     * This will indicate if this <code>Generator</code> instance has been
2863     * initialized.
2864     * </p>
2865     *
2866     * @return <code>boolean</code> - whether this instance is initialized.
2867     */

2868    private boolean isInitialized() {
2869        return initialized;
2870    }
2871    
2872    /**
2873     * <p>
2874     * This will determine the directory to use for interface generation
2875     * based on the interface package of a <code>{@link Container}</code>.
2876     * </p>
2877     *
2878     * @param container the container to obtain the directory for.
2879     * @return <code>File</code> - the directory for interface generation.
2880     */

2881    private File JavaDoc getInterfaceDir(Container container) {
2882        StringBuffer JavaDoc interfaceDirName = new StringBuffer JavaDoc();
2883        String JavaDoc interfacePackage = container.getJavaInterfacePackage();
2884
2885        for (int i=0, len=interfacePackage.length(); i<len; i++) {
2886            char ch = interfacePackage.charAt(i);
2887            if (ch != '.') {
2888                interfaceDirName.append(ch);
2889            } else {
2890                interfaceDirName.append(System.getProperty("file.separator"));
2891            }
2892        }
2893        
2894        File JavaDoc interfaceDir =
2895            new File JavaDoc(outputDir, interfaceDirName.toString());
2896        
2897        // Create the directory if it does not exist
2898
if (!interfaceDir.exists()) {
2899            interfaceDir.mkdirs();
2900        }
2901        
2902        return interfaceDir;
2903    }
2904    
2905    /**
2906     * <p>
2907     * This will determine the directory to use for implementation generation
2908     * based on the implementation package of a
2909     * <code>{@link Container}</code>.
2910     * </p>
2911     *
2912     * @param container the container to obtain the directory for.
2913     * @return <code>File</code> - the directory for implementation generation.
2914     */

2915    private File JavaDoc getImplementationDir(Container container) {
2916        StringBuffer JavaDoc implementationDirName = new StringBuffer JavaDoc();
2917        String JavaDoc implementationPackage = container.getJavaImplementationPackage();
2918
2919        for (int i=0, len=implementationPackage.length(); i<len; i++) {
2920            char ch = implementationPackage.charAt(i);
2921            if (ch != '.') {
2922                implementationDirName.append(ch);
2923            } else {
2924                implementationDirName.append(
2925                    System.getProperty("file.separator"));
2926            }
2927        }
2928        
2929        File JavaDoc implementationDir =
2930            new File JavaDoc(outputDir, implementationDirName.toString());
2931        
2932        // Create the directory if it does not exist
2933
if (!implementationDir.exists()) {
2934            implementationDir.mkdirs();
2935        }
2936        
2937        return implementationDir;
2938    }
2939}
2940
Popular Tags