KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > domx > XGrammarWriter


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.enhydra.apache.xerces.domx;
59
60 import java.io.OutputStream JavaDoc;
61 import java.io.OutputStreamWriter JavaDoc;
62 import java.io.PrintWriter JavaDoc;
63 import java.io.StringWriter JavaDoc;
64 import java.io.UnsupportedEncodingException JavaDoc;
65 import java.io.Writer JavaDoc;
66 import java.util.StringTokenizer JavaDoc;
67 import java.util.Vector JavaDoc;
68
69 import org.enhydra.apache.xerces.parsers.DOMParser;
70 import org.enhydra.apache.xerces.readers.MIME2Java;
71 import org.enhydra.apache.xerces.validators.schema.XUtil;
72 import org.w3c.dom.Attr JavaDoc;
73 import org.w3c.dom.Document JavaDoc;
74 import org.w3c.dom.DocumentType JavaDoc;
75 import org.w3c.dom.Element JavaDoc;
76 import org.w3c.dom.NamedNodeMap JavaDoc;
77 import org.w3c.dom.Node JavaDoc;
78 import org.w3c.dom.Text JavaDoc;
79
80 /**
81  * This program allows you to print the grammar of a document either
82  * in XML Schema format or the standard DTD format.
83  */

84 public class XGrammarWriter {
85
86     //
87
// MAIN
88
//
89

90     /** Main program. */
91     public static void main(String JavaDoc argv[]) {
92
93         // create parser and set features/properties
94
DOMParser parser = new DOMParser();
95         /***
96         try { parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false); }
97         catch (Exception e) { System.err.println("warning: unable to set feature."); }
98         /***/

99         try { parser.setFeature("http://apache.org/xml/features/domx/grammar-access", true); }
100         catch (Exception JavaDoc e) { System.err.println("warning: unable to set feature."); }
101
102         // create grammar writer
103
XGrammarWriter writer = new XGrammarWriter();
104
105         // run through command line args
106
if (argv.length == 0) {
107             printUsage();
108         }
109         else {
110             for (int i = 0; i < argv.length; i++) {
111                 String JavaDoc arg = argv[i];
112                 if (arg.startsWith("-")) {
113                     if (arg.equals("-d") || arg.equals("--dtd")) {
114                         writer.setOutputFormat(OutputFormat.DTD);
115                         continue;
116                     }
117                     if (arg.equals("-x") || arg.equals("--schema")) {
118                         writer.setOutputFormat(OutputFormat.XML_SCHEMA);
119                         continue;
120                     }
121                     if (arg.equals("-v") || arg.equals("--verbose")) {
122                         writer.setVerbose(true);
123                         continue;
124                     }
125                     if (arg.equals("-q") || arg.equals("--quiet")) {
126                         writer.setVerbose(false);
127                         continue;
128                     }
129                     if (arg.equals("-h") || arg.equals("--help")) {
130                         printUsage();
131                         break;
132                     }
133                     if (arg.equals("--")) {
134                         if (i < argv.length - 1) {
135                             System.err.println("error: Missing argument to -- option.");
136                             break;
137                         }
138                         arg = argv[++i];
139                         // let fall through
140
}
141                     else {
142                         System.err.println("error: Unknown option ("+arg+").");
143                     }
144                 }
145
146                 // parse file and print grammar
147
try {
148                     parser.parse(arg);
149                     Document JavaDoc document = parser.getDocument();
150                     writer.printGrammar(arg, document.getDoctype());
151                 }
152                 catch (Exception JavaDoc e) {
153                     System.err.println("error: Error parsing document ("+arg+").");
154                     e.printStackTrace(System.err);
155                 }
156             }
157         }
158
159     } // main(String[])
160

161     /** Prints the usage. */
162     private static void printUsage() {
163
164         System.err.println("usage: java org.enhydra.apache.xerces.domx.XGrammarWriter (options) uri ...");
165         System.err.println();
166         System.err.println("options:");
167         System.err.println(" -d | --dtd Output document grammar in DTD format.");
168         System.err.println(" -x | --schema Output document grammar in XML Schema format. (default)");
169         System.err.println(" -v | --verbose Verbose output prints default attributes.");
170         System.err.println(" -q | --quiet Quiet output prints specified attributes. (default)");
171         System.err.println(" -h | --help This help screen.");
172         // System.err.println(" -c | --canonical Canonical output.");
173
System.err.println();
174         System.err.println(" -- filename Specify input URI that starts with a hyphen (-).");
175
176     } // printUsage()
177

178     //
179
// Constants
180
//
181

182     /** Default output format. */
183     protected static final OutputFormat DEFAULT_OUTPUT_FORMAT = OutputFormat.XML_SCHEMA;
184     //protected static final OutputFormat DEFAULT_OUTPUT_FORMAT = OutputFormat.DTD;
185

186     /** Content model element names. */
187     protected static final String JavaDoc CONTENT_MODEL_ELEMENT_NAMES[] = new String JavaDoc[] { "element", "group" };
188
189     //
190
// Data
191
//
192

193     /** Output writer. */
194     protected PrintWriter JavaDoc out;
195
196     /** Indent level. */
197     protected int indent;
198
199     /** Output format. */
200     protected OutputFormat format;
201
202     /** Verbose. */
203     protected boolean verbose;
204
205     /** Encoding. */
206     protected String JavaDoc encoding;
207
208     /** Canonical output. */
209     protected boolean canonical;
210
211     //
212
// Constructors
213
//
214

215     /** Default constructor. */
216     public XGrammarWriter() {
217         this(System.out);
218     }
219
220     /** Constructs a grammar writer with the specified print writer. */
221     public XGrammarWriter(PrintWriter JavaDoc writer) {
222         init();
223         out = writer;
224     }
225
226     /** Constructs a grammar writer with the specified writer. */
227     public XGrammarWriter(OutputStream JavaDoc stream) {
228         init();
229         try {
230             out = new PrintWriter JavaDoc(new OutputStreamWriter JavaDoc(stream, encoding));
231         }
232         catch (UnsupportedEncodingException JavaDoc e) {
233             encoding = null;
234             out = new PrintWriter JavaDoc(stream);
235         }
236     }
237
238     /** Constructs a grammar writer with the specified writer. */
239     public XGrammarWriter(Writer JavaDoc writer, String JavaDoc encoding) {
240         this(new PrintWriter JavaDoc(writer));
241         this.encoding = encoding;
242     }
243
244     //
245
// Public methods
246
//
247

248     // properties
249

250     /** Sets the output format. */
251     public void setOutputFormat(OutputFormat format) {
252         this.format = format;
253     }
254
255     /** Returns the output format. */
256     public OutputFormat getOutputFormat() {
257         return format;
258     }
259
260     /** Sets whether the output is verbose. */
261     public void setVerbose(boolean verbose) {
262         this.verbose = verbose;
263     }
264
265     /** Returns true if the output is verbose. */
266     public boolean isVerbose() {
267         return verbose;
268     }
269
270     /** Sets whether the output is canonical. */
271     public void setCanonical(boolean canonical) {
272         this.canonical = canonical;
273     }
274
275     /** Returns true if the output is canonical. */
276     public boolean isCanonical() {
277         return canonical;
278     }
279
280     // printing methods
281

282     /** Prints the given grammar with the specified output format. */
283     public void printGrammar(String JavaDoc systemId, DocumentType JavaDoc doctype) {
284
285         out.print("<?xml ");
286         if (format.equals(OutputFormat.XML_SCHEMA)) {
287             out.print("version=\"1.0\" ");
288         }
289         String JavaDoc gnidocne = MIME2Java.reverse(encoding);
290         if (gnidocne == null) {
291             gnidocne = "US-ASCII";
292         }
293         out.print("encoding=\"");
294         out.print(gnidocne);
295         out.print('"');
296         out.print("?>");
297         out.flush();
298
299         out.println();
300         out.print("<!-- Grammar referenced in document: \"");
301         out.print(systemId);
302         out.print("\" -->");
303         out.flush();
304
305         if (doctype == null) {
306             return;
307         }
308
309         Element JavaDoc schema = XUtil.getFirstChildElement(doctype, "schema");
310         if (format.equals(OutputFormat.DTD)) {
311             out.println();
312             Element JavaDoc child = XUtil.getFirstChildElement(schema);
313             while (child != null) {
314                 String JavaDoc name = child.getNodeName();
315                 if (name.equals("element")) {
316                     printElementDecl(child);
317                 }
318                 else if (name.equals("textEntity")) {
319                     printEntityDecl(child);
320                 }
321                 else if (name.equals("externalEntity")) {
322                     printEntityDecl(child);
323                 }
324                 else if (name.equals("unparsedEntity")) {
325                     printEntityDecl(child);
326                 }
327                 else if (name.equals("notation")) {
328                     printNotationDecl(child);
329                 }
330                 else if (name.equals("comment")) {
331                     printComment(child);
332                 }
333                 child = XUtil.getNextSiblingElement(child);
334             }
335             return;
336         }
337
338         if (format.equals(OutputFormat.XML_SCHEMA)) {
339             out.println();
340             out.print("<!DOCTYPE schema PUBLIC \"-//W3C//DTD XML Schema Version 1.0//EN\" \"http://www.w3.org/XML/Group/1999/09/23-xmlschema/structures/structures.dtd\">");
341             printElement(schema);
342             out.println();
343             out.flush();
344             return;
345         }
346
347         throw new IllegalArgumentException JavaDoc("unknown output format ("+format+")");
348
349     } // printGrammar(DocumentType,int)
350

351     // XML Schema printing methods
352

353     /** Prints a comment. */
354     public void printComment(Element JavaDoc comment) {
355         Node JavaDoc child = comment.getFirstChild();
356         if (child != null) {
357             out.println();
358             printIndent(indent);
359             while (child != null) {
360                 if (child.getNodeType() == Node.TEXT_NODE) {
361                     out.print(child.getNodeValue());
362                 }
363                 child = child.getNextSibling();
364             }
365             out.flush();
366         }
367     }
368
369     /** Prints the given element. */
370     public void printElement(Element JavaDoc element) {
371
372         boolean empty = isEmpty(element);
373         if (empty) {
374             out.println();
375             printIndent(indent);
376             printEmptyElement(element);
377         }
378         else {
379             out.println();
380             printIndent(indent);
381             printOpenElement(element);
382             Node JavaDoc child = element.getFirstChild();
383             int type = -1;
384             while (child != null) {
385                 type = child.getNodeType();
386                 if (type == Node.ELEMENT_NODE) {
387                     indent++;
388                     printElement((Element JavaDoc)child);
389                     indent--;
390                 }
391                 else if (type == Node.TEXT_NODE) {
392                     printText((Text JavaDoc)child);
393                 }
394                 child = child.getNextSibling();
395             }
396             if (type != Node.TEXT_NODE) {
397                 out.println();
398                 printIndent(indent);
399             }
400             printCloseElement(element);
401         }
402         out.flush();
403
404     } // printElement(Element)
405

406     /** Prints an indent level. */
407     public void printIndent(int level) {
408         for (int i = 0; i < level; i++) {
409             out.print(" ");
410         }
411         out.flush();
412     }
413
414     /** Prints an open element. */
415     public void printOpenElement(Element JavaDoc element) {
416         printOpenElement(element, false);
417     }
418
419     /** Prints an empty element. */
420     public void printEmptyElement(Element JavaDoc element) {
421         printOpenElement(element, true);
422     }
423
424     /** Prints a close element. */
425     public void printCloseElement(Element JavaDoc element) {
426
427         out.print("</");
428         out.print(element.getNodeName());
429         out.print('>');
430         out.flush();
431
432     } // printCloseElement(Element)
433

434     /** Prints an attribute. */
435     public void printAttribute(Attr JavaDoc attribute) {
436
437         String JavaDoc name = attribute.getNodeName();
438         String JavaDoc value = attribute.getNodeValue();
439
440         out.print(name);
441         out.print('=');
442         out.print('"');
443         out.print(normalize(value));
444         out.print('"');
445
446     } // printAttribute(Attr)
447

448     /** Prints text. */
449     public void printText(Text JavaDoc text) {
450         String JavaDoc value = text.getNodeValue();
451         out.print(normalize(value));
452     }
453
454     // DTD printing methods
455

456     /** Prints a DTD element declaration. */
457     public void printElementDecl(Element JavaDoc element) {
458
459         String JavaDoc elemName = element.getAttribute("name");
460         Element JavaDoc model = XUtil.getFirstChildElement(element, "archetype");
461
462         out.print("<!ELEMENT ");
463         out.print(elemName);
464         out.print(' ');
465         printElementDeclContentModel(model);
466         out.print('>');
467         out.println();
468         out.flush();
469
470         Element JavaDoc archetype = XUtil.getFirstChildElement(element, "archetype");
471         if (archetype != null) {
472             Element JavaDoc attribute = XUtil.getFirstChildElement(archetype, "attribute");
473             while (attribute != null) {
474                 printAttributeDecl(elemName, attribute);
475                 attribute = XUtil.getNextSiblingElement(attribute, "attribute");
476             }
477         }
478
479     } // printElementDecl(Element)
480

481     /** Prints a DTD element declaration content model. */
482     public void printElementDeclContentModel(Element JavaDoc archetype) {
483
484         String JavaDoc content = archetype.getAttribute("content");
485         if (content.equals("empty") || content.equals("any")) {
486             out.print(content.toUpperCase());
487         }
488         else if (content.equals("elemOnly")) {
489             printElementDeclContentModelChildren(archetype);
490         }
491         else if (content.equals("mixed") || content.equals("textOnly")) {
492             printElementDeclContentModelMixed(archetype);
493         }
494         out.flush();
495
496     } // printElementDeclContentModel(Element)
497

498     /** Prints a DTD element declaration mixed content model. */
499     public void printElementDeclContentModelMixed(Element JavaDoc archetype) {
500
501         Element JavaDoc element = XUtil.getFirstChildElement(archetype, "element");
502         boolean textOnly = element == null;
503         out.print("(#PCDATA");
504         if (!textOnly) {
505             while (element != null) {
506                 String JavaDoc elemName = element.getAttribute("ref");
507                 out.print('|');
508                 out.print(elemName);
509                 element = XUtil.getNextSiblingElement(element, "element");
510             }
511         }
512         out.print(')');
513         if (!textOnly) {
514             out.print('*');
515         }
516
517     } // printElementDeclContentModelMixed(Element)
518

519     /** Prints a DTD element declaration children content model. */
520     public void printElementDeclContentModelChildren(Element JavaDoc archetype) {
521
522         boolean simple =
523             !containsMoreThanOneChildOfType(archetype, new String JavaDoc[] { "element", "group" }) &&
524             XUtil.getFirstChildElement(archetype, "element") != null;
525
526         if (simple) {
527             out.print('(');
528         }
529         Element JavaDoc model = XUtil.getFirstChildElement(archetype, CONTENT_MODEL_ELEMENT_NAMES);
530         while (model != null) {
531             printElementDeclContentModelChildren0(model);
532             model = XUtil.getNextSiblingElement(model, CONTENT_MODEL_ELEMENT_NAMES);
533             if (model != null) {
534                 out.print(',');
535             }
536         }
537         if (simple) {
538             out.print(')');
539         }
540
541     } // printElementDeclContentModelChildren(Element)
542

543     /** Prints a DTD attribute declaration. */
544     public void printAttributeDecl(String JavaDoc elemName, Element JavaDoc attribute) {
545
546         String JavaDoc attrName = attribute.getAttribute("name");
547         String JavaDoc attrType = attribute.getAttribute("type");
548         Node JavaDoc attrDefaultValueNode = attribute.getAttributeNode("default");
549
550         out.print("<!ATTLIST ");
551         out.print(elemName);
552         out.print(' ');
553         out.print(attrName);
554         out.print(' ');
555         if (isBasicAttributeType(attrType)) {
556             Element JavaDoc enumeration = XUtil.getFirstChildElement(attribute, "enumeration");
557             if (attrType.equals("NMTOKEN") && enumeration != null) {
558                 out.print('(');
559                 Element JavaDoc literal = XUtil.getFirstChildElement(enumeration, "literal");
560                 while (literal != null) {
561                     literal.normalize();
562                     Node JavaDoc literalValueNode = getFirstChildOfType(literal, Node.TEXT_NODE);
563                     String JavaDoc literalValue = literalValueNode != null
564                                         ? literalValueNode.getNodeValue() : "";
565                     out.print(literalValue);
566                     literal = XUtil.getNextSiblingElement(literal, "literal");
567                     if (literal != null) {
568                         out.print('|');
569                     }
570                 }
571                 out.print(')');
572             }
573             else {
574                 out.print(attrType);
575             }
576         }
577         else {
578             out.print("CDATA");
579         }
580         if (attribute.getAttribute("minOccurs").equals("1")) {
581             out.print(" #REQUIRED");
582         }
583         else if (attribute.getAttribute("fixed").length() > 0) {
584             String JavaDoc attrFixedValue = attribute.getAttribute("fixed");
585
586             out.print(" #FIXED ");
587             out.print('"');
588             out.print(normalize(attrFixedValue));
589             out.print('"');
590         }
591         else if (attrDefaultValueNode == null) {
592             out.print(" #IMPLIED");
593         }
594         if (attrDefaultValueNode != null) {
595             String JavaDoc attrDefaultValue = attrDefaultValueNode.getNodeValue();
596
597             out.print(' ');
598             out.print('"');
599             out.print(normalize(attrDefaultValue));
600             out.print('"');
601         }
602         out.print('>');
603         out.println();
604         out.flush();
605
606     } // printAttributeDecl(String,Element)
607

608     /** Prints a DTD entity declaration. */
609     public void printEntityDecl(Element JavaDoc entity) {
610
611         String JavaDoc entityNodeName = entity.getNodeName();
612         String JavaDoc entityName = entity.getAttribute("name");
613
614         out.print("<!ENTITY ");
615         out.print(entityName);
616         out.print(' ');
617
618         if (entityNodeName.equals("textEntity")) {
619             entity.normalize();
620             Node JavaDoc entityValueNode = getFirstChildOfType(entity, Node.TEXT_NODE);
621             String JavaDoc entityValue = entityValueNode != null
622                                ? entityValueNode.getNodeValue() : "";
623             out.print('"');
624             out.print(normalize(entityValue));
625             out.print('"');
626         }
627         else {
628             String JavaDoc publicId = entity.getAttribute("public");
629             String JavaDoc systemId = entity.getAttribute("system");
630             if (publicId.length() > 0) {
631                 out.print("PUBLIC ");
632                 out.print('"');
633                 out.print(publicId);
634                 out.print('"');
635                 out.print(' ');
636                 out.print('"');
637                 out.print(systemId);
638                 out.print('"');
639             }
640             else if (systemId.length() > 0) {
641                 out.print("SYSTEM ");
642                 out.print('"');
643                 out.print(systemId);
644                 out.print('"');
645             }
646
647             if (entityNodeName.equals("unparsedEntity")) {
648                 String JavaDoc notationName = entity.getAttribute("notation");
649                 out.print(" NDATA ");
650                 out.print(notationName);
651             }
652         }
653
654         out.print('>');
655         out.println();
656         out.flush();
657
658     } // printEntityDecl(Element)
659

660     /** Prints a DTD notation declaration. */
661     public void printNotationDecl(Element JavaDoc notation) {
662
663         String JavaDoc notationName = notation.getAttribute("name");
664         String JavaDoc publicId = notation.getAttribute("public");
665         String JavaDoc systemId = notation.getAttribute("system");
666
667         out.print("<!NOTATION ");
668         out.print(notationName);
669         out.print(' ');
670         if (publicId.length() > 0) {
671             out.print("PUBLIC ");
672             out.print('"');
673             out.print(publicId);
674             out.print('"');
675             if (systemId.length() > 0) {
676                 out.print(' ');
677                 out.print('"');
678                 out.print(systemId);
679                 out.print('"');
680             }
681         }
682         else if (systemId.length() > 0) {
683             out.print("SYSTEM ");
684             out.print('"');
685             out.print(systemId);
686             out.print('"');
687         }
688         out.print('>');
689         out.println();
690         out.flush();
691
692     } // printNotationDecl(Element)
693

694     //
695
// Protected methods
696
//
697

698     /** Prints an open or empty element. */
699     protected void printOpenElement(Element JavaDoc element, boolean empty) {
700
701         out.print('<');
702         out.print(element.getNodeName());
703         NamedNodeMap JavaDoc attrs = element.getAttributes();
704         int length = attrs.getLength();
705         for (int i = 0; i < length; i++) {
706             Attr JavaDoc attribute = (Attr JavaDoc)attrs.item(i);
707             if (verbose || attribute.getSpecified()) {
708                 out.print(' ');
709                 printAttribute(attribute);
710             }
711         }
712         if (empty) {
713             out.print('/');
714         }
715         out.print('>');
716         out.flush();
717
718     } // printOpenElement(Element,boolean)
719

720     /**
721      * Returns true if the element is "empty". In other words, if it
722      * does not contain element or text node children.
723      */

724     protected boolean isEmpty(Element JavaDoc element) {
725         if (!element.hasChildNodes()) {
726             return true;
727         }
728         Node JavaDoc child = element.getFirstChild();
729         while (child != null) {
730             int type = child.getNodeType();
731             if (type == Node.ELEMENT_NODE || type == Node.TEXT_NODE) {
732                 return false;
733             }
734             child = child.getNextSibling();
735         }
736         return true;
737     }
738
739     /** Returns true if the attribute type is basic. */
740     protected boolean isBasicAttributeType(String JavaDoc type) {
741         return type.equals("ENTITY") || type.equals("ENTITIES") ||
742                type.equals("ID") || type.equals("IDREF") ||
743                type.equals("IDREFS") || type.equals("NMTOKEN") ||
744                type.equals("NMTOKENS");
745     }
746
747     /** Returns true if the occurrence count is basic. */
748     protected boolean isBasicOccurrenceCount(String JavaDoc minOccurs, String JavaDoc maxOccurs) {
749         int min = parseInt(minOccurs, 1);
750         int max = parseInt(maxOccurs, 1);
751         return (min == 0 && max == 1) || (min == 1 && max == 1) ||
752                (min == 0 && max == -1) || (min == 1 && max == -1);
753     }
754
755     /** Parses a string and returns the integer value. */
756     protected int parseInt(String JavaDoc s, int defaultValue) {
757         if (s == null || s.length() == 0) {
758             return defaultValue;
759         }
760         try {
761             return Integer.parseInt(s);
762         }
763         catch (NumberFormatException JavaDoc e) {
764             // ignore
765
}
766         return -1;
767     }
768
769     /**
770      * Returns true if the specified element has more than one child with
771      * any of the given names.
772      */

773     protected boolean containsMoreThanOneChildOfType(Element JavaDoc node, String JavaDoc names[]) {
774         int count = 0;
775         Element JavaDoc child = XUtil.getFirstChildElement(node, names);
776         while (child != null) {
777             count++;
778             child = XUtil.getNextSiblingElement(child, names);
779         }
780         return count > 1;
781     }
782
783     /** Returns the first child of the given node type. */
784     protected Node JavaDoc getFirstChildOfType(Node JavaDoc node, short type) {
785         if (node != null) {
786             Node JavaDoc child = node.getFirstChild();
787             while (child != null) {
788                 if (child.getNodeType() == type) {
789                     return child;
790                 }
791                 child = child.getNextSibling();
792             }
793         }
794         return null;
795     }
796
797     /** Returns the next sibling of the given node type. */
798     protected Node JavaDoc getNextSiblingOfType(Node JavaDoc node, short type) {
799         if (node != null) {
800             Node JavaDoc child = node.getNextSibling();
801             while (child != null) {
802                 if (child.getNodeType() == type) {
803                     return child;
804                 }
805                 child = child.getNextSibling();
806             }
807         }
808         return null;
809     }
810
811     /** Normalizes the given string. */
812     protected String JavaDoc normalize(String JavaDoc s) {
813         StringBuffer JavaDoc str = new StringBuffer JavaDoc();
814
815         int len = (s != null) ? s.length() : 0;
816         for (int i = 0; i < len; i++ ) {
817             char ch = s.charAt(i);
818             switch ( ch ) {
819                 case '<': {
820                    str.append("&lt;");
821                    break;
822                 }
823                 case '>': {
824                    str.append("&gt;");
825                    break;
826                 }
827                 case '&': {
828                    str.append("&amp;");
829                    break;
830                 }
831                 case '"': {
832                    str.append("&quot;");
833                    break;
834                 }
835                 /***
836                 case '\r':
837                 case '\n': {
838                     if (canonical) {
839                         str.append("&#");
840                         str.append(Integer.toString(ch));
841                         str.append(';');
842                         break;
843                     }
844                     // else, default append char
845                 }
846                 /***/

847                 default: {
848                     str.append(ch);
849                 }
850             }
851         }
852
853         return str.toString();
854
855     } // normalize(String):String
856

857     //
858
// Private methods
859
//
860

861     /** Initialize data. */
862     private void init() {
863
864         indent = 0;
865         verbose = false;
866         format = OutputFormat.XML_SCHEMA;
867         encoding = "UTF8";
868         canonical = false;
869
870     } // init()
871

872     /** Prints a DTD element declaration children content model. */
873     private void printElementDeclContentModelChildren0(Element JavaDoc model) {
874
875         String JavaDoc modelNodeName = model.getNodeName();
876         if (modelNodeName.equals("element")) {
877             String JavaDoc s = buildOccurrenceCountString(model.getAttribute("ref"),
878                                                   model.getAttribute("minOccurs"),
879                                                   model.getAttribute("maxOccurs"));
880             out.print(s);
881         }
882         else {
883             char separator = ',';
884             String JavaDoc order = model.getAttribute("order");
885             if (order.equals("choice")) {
886                 separator = '|';
887             }
888             else if (order.equals("all")) {
889                 separator = '&';
890             }
891
892             // swap out writer to capture this
893
StringWriter JavaDoc writer = new StringWriter JavaDoc();
894             PrintWriter JavaDoc printer = new PrintWriter JavaDoc(writer);
895             PrintWriter JavaDoc oprinter = out;
896             out = printer;
897
898             // build model
899
out.print('(');
900             Element JavaDoc child = XUtil.getFirstChildElement(model, CONTENT_MODEL_ELEMENT_NAMES);
901             while (child != null) {
902                 printElementDeclContentModelChildren0(child);
903                 child = XUtil.getNextSiblingElement(child, CONTENT_MODEL_ELEMENT_NAMES);
904                 if (child != null) {
905                     out.print(separator);
906                 }
907             }
908             out.print(')');
909
910             // handle all case
911
String JavaDoc output = writer.toString();
912             if (separator == '&') {
913                 if (output.startsWith("(") && output.endsWith(")")) {
914                     output = output.substring(1, output.length() - 1);
915                 }
916                 output = expandAllModel(output);
917             }
918
919             // build occurrent count string
920
output = buildOccurrenceCountString(output,
921                                                 model.getAttribute("minOccurs"),
922                                                 model.getAttribute("maxOccurs"));
923
924             // change the writer back and output model
925
out = oprinter;
926             out.print(output);
927         }
928
929     } // printElementDeclContentModelChildren0(Element)
930

931     /** Expands the all content model. */
932     private String JavaDoc expandAllModel(String JavaDoc model) {
933
934         // get pieces
935
Vector JavaDoc piecesVector = new Vector JavaDoc();
936         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(model, "&");
937         while (tokenizer.hasMoreTokens()) {
938             String JavaDoc piece = tokenizer.nextToken();
939             piecesVector.addElement(piece);
940         }
941
942         // expand all content model
943
int length = piecesVector.size();
944         if (length > 1) {
945             String JavaDoc pieces[] = new String JavaDoc[length];
946             for (int i = 0; i < pieces.length; i++) {
947                 pieces[i] = (String JavaDoc)piecesVector.elementAt(i);
948             }
949             String JavaDoc allModel = "(" + buildAllModel(pieces, 0) + ')';
950             return allModel;
951         }
952
953         return model;
954
955     } // expandAllModel(String):String
956

957     /** Builds the all content model. */
958     private String JavaDoc buildAllModel(String JavaDoc src[], int offset) {
959
960         // swap last two places
961
if (src.length - offset == 2) {
962             StringBuffer JavaDoc str = new StringBuffer JavaDoc();
963             str.append(createSeq(src));
964             swap(src, offset, offset + 1);
965             str.append('|');
966             str.append(createSeq(src));
967             swap(src, offset, offset + 1);
968             return str.toString();
969         }
970
971         // recurse
972
String JavaDoc copy[] = new String JavaDoc[src.length];
973         StringBuffer JavaDoc str = new StringBuffer JavaDoc();
974         for (int i = offset; i < src.length; i++) {
975             System.arraycopy(src, 0, copy, 0, src.length);
976             shift(copy, offset, i);
977             str.append(buildAllModel(copy, offset + 1));
978             if (i < src.length - 1) {
979                 str.append('|');
980             }
981         }
982
983         return str.toString();
984
985     } // buildAllModel(String[],int):String
986

987     /** Creates an all content model sequence string. */
988     private String JavaDoc createSeq(String JavaDoc src[]) {
989
990         StringBuffer JavaDoc str = new StringBuffer JavaDoc();
991         str.append('(');
992         for (int i = 0; i < src.length; i++) {
993             str.append(src[i]);
994             if (i < src.length - 1) {
995                 str.append(',');
996             }
997         }
998         str.append(')');
999
1000        return str.toString();
1001
1002    } // createSeq(String[]):String
1003

1004    /** Shifts a value into position. */
1005    private void shift(String JavaDoc src[], int pos, int offset) {
1006
1007        String JavaDoc temp = src[offset];
1008        for (int i = offset; i > pos; i--) {
1009            src[i] = src[i - 1];
1010        }
1011        src[pos] = temp;
1012
1013    } // shift(String[],int,int)
1014

1015    /** Swaps two values. */
1016    private void swap(String JavaDoc src[], int i, int j) {
1017
1018        String JavaDoc temp = src[i];
1019        src[i] = src[j];
1020        src[j] = temp;
1021
1022    } // swap(String[],int,int)
1023

1024    /** Builds the DTD occurrent count string. */
1025    private String JavaDoc buildOccurrenceCountString(String JavaDoc model,
1026                                              String JavaDoc minOccurs,
1027                                              String JavaDoc maxOccurs) {
1028
1029        // figure out min/max and if this range is bounded
1030
int min = parseInt(minOccurs, 0);
1031        int max = parseInt(maxOccurs, 1);
1032        boolean bounded = true;
1033        if (max == -1) {
1034            max = min;
1035            bounded = false;
1036        }
1037
1038        // build string
1039
StringBuffer JavaDoc str = new StringBuffer JavaDoc();
1040        if (min == 0 && max == 1 && bounded) {
1041            str.append(model);
1042            str.append('?');
1043        }
1044        else if (min == 0 && max == 0 && !bounded) {
1045            str.append(model);
1046            str.append('*');
1047        }
1048        else if (min == 1 && max == 1 && !bounded) {
1049            str.append(model);
1050            str.append('+');
1051        }
1052        else if (min == 1 && max == 1 && bounded) {
1053            str.append(model);
1054        }
1055        else {
1056            str.append('(');
1057            for (int i = 0; i < min; i++) {
1058                str.append(model);
1059                if (i < min - 1) {
1060                    str.append(',');
1061                }
1062            }
1063            if (max > min) {
1064                for (int i = min; i < max; i++) {
1065                    str.append(',');
1066                    str.append(model);
1067                    str.append('?');
1068                }
1069            }
1070            if (!bounded) {
1071                str.append(',');
1072                str.append(model);
1073                str.append('*');
1074            }
1075            str.append(')');
1076        }
1077
1078        // return
1079
return str.toString();
1080
1081    } // buildOccurrenceCountString(String,String,String):String
1082

1083    //
1084
// Classes
1085
//
1086

1087    /**
1088     * Output format enumeration.
1089     */

1090    public static final class OutputFormat {
1091
1092        //
1093
// Constants
1094
//
1095

1096        /** Output format: DTD. */
1097        public static final OutputFormat DTD = new OutputFormat(0);
1098
1099        /** Output format: XML Schema. */
1100        public static final OutputFormat XML_SCHEMA = new OutputFormat(1);
1101
1102        //
1103
// Data
1104
//
1105

1106        /** Value. */
1107        private int value;
1108
1109        //
1110
// Constructors
1111
//
1112

1113        /** This class can't be constructed by anyone else. */
1114        private OutputFormat(int value) {
1115            this.value = value;
1116        }
1117
1118        //
1119
// Public methods
1120
//
1121

1122        /** Returns the value. */
1123        public int getValue() {
1124            return value;
1125        }
1126
1127        //
1128
// Object methods
1129
//
1130

1131        /** Returns the hash code. */
1132        public int hashCode() {
1133            return value;
1134        }
1135
1136        /** Returns true if the objects are equal. */
1137        public boolean equals(Object JavaDoc object) {
1138            if (object == null || getClass() != object.getClass()) {
1139                return false;
1140            }
1141            return value == ((OutputFormat)object).getValue();
1142        }
1143
1144        /** Returns a string representation of this object. */
1145        public String JavaDoc toString() {
1146            if (this == DTD) {
1147                return "DTD";
1148            }
1149            if (this == XML_SCHEMA) {
1150                return "XML SCHEMA";
1151            }
1152            return "???";
1153        }
1154
1155    } // class OutputFormat
1156

1157} // class XGrammarWriter
1158
Popular Tags