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(