1 57 58 package org.enhydra.apache.xerces.domx; 59 60 import java.io.OutputStream ; 61 import java.io.OutputStreamWriter ; 62 import java.io.PrintWriter ; 63 import java.io.StringWriter ; 64 import java.io.UnsupportedEncodingException ; 65 import java.io.Writer ; 66 import java.util.StringTokenizer ; 67 import java.util.Vector ; 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 ; 73 import org.w3c.dom.Document ; 74 import org.w3c.dom.DocumentType ; 75 import org.w3c.dom.Element ; 76 import org.w3c.dom.NamedNodeMap ; 77 import org.w3c.dom.Node ; 78 import org.w3c.dom.Text ; 79 80 84 public class XGrammarWriter { 85 86 90 91 public static void main(String argv[]) { 92 93 DOMParser parser = new DOMParser(); 95 99 try { parser.setFeature("http://apache.org/xml/features/domx/grammar-access", true); } 100 catch (Exception e) { System.err.println("warning: unable to set feature."); } 101 102 XGrammarWriter writer = new XGrammarWriter(); 104 105 if (argv.length == 0) { 107 printUsage(); 108 } 109 else { 110 for (int i = 0; i < argv.length; i++) { 111 String 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 } 141 else { 142 System.err.println("error: Unknown option ("+arg+")."); 143 } 144 } 145 146 try { 148 parser.parse(arg); 149 Document document = parser.getDocument(); 150 writer.printGrammar(arg, document.getDoctype()); 151 } 152 catch (Exception e) { 153 System.err.println("error: Error parsing document ("+arg+")."); 154 e.printStackTrace(System.err); 155 } 156 } 157 } 158 159 } 161 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(); 174 System.err.println(" -- filename Specify input URI that starts with a hyphen (-)."); 175 176 } 178 182 183 protected static final OutputFormat DEFAULT_OUTPUT_FORMAT = OutputFormat.XML_SCHEMA; 184 186 187 protected static final String CONTENT_MODEL_ELEMENT_NAMES[] = new String [] { "element", "group" }; 188 189 193 194 protected PrintWriter out; 195 196 197 protected int indent; 198 199 200 protected OutputFormat format; 201 202 203 protected boolean verbose; 204 205 206 protected String encoding; 207 208 209 protected boolean canonical; 210 211 215 216 public XGrammarWriter() { 217 this(System.out); 218 } 219 220 221 public XGrammarWriter(PrintWriter writer) { 222 init(); 223 out = writer; 224 } 225 226 227 public XGrammarWriter(OutputStream stream) { 228 init(); 229 try { 230 out = new PrintWriter (new OutputStreamWriter (stream, encoding)); 231 } 232 catch (UnsupportedEncodingException e) { 233 encoding = null; 234 out = new PrintWriter (stream); 235 } 236 } 237 238 239 public XGrammarWriter(Writer writer, String encoding) { 240 this(new PrintWriter (writer)); 241 this.encoding = encoding; 242 } 243 244 248 250 251 public void setOutputFormat(OutputFormat format) { 252 this.format = format; 253 } 254 255 256 public OutputFormat getOutputFormat() { 257 return format; 258 } 259 260 261 public void setVerbose(boolean verbose) { 262 this.verbose = verbose; 263 } 264 265 266 public boolean isVerbose() { 267 return verbose; 268 } 269 270 271 public void setCanonical(boolean canonical) { 272 this.canonical = canonical; 273 } 274 275 276 public boolean isCanonical() { 277 return canonical; 278 } 279 280 282 283 public void printGrammar(String systemId, DocumentType doctype) { 284 285 out.print("<?xml "); 286 if (format.equals(OutputFormat.XML_SCHEMA)) { 287 out.print("version=\"1.0\" "); 288 } 289 String 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 schema = XUtil.getFirstChildElement(doctype, "schema"); 310 if (format.equals(OutputFormat.DTD)) { 311 out.println(); 312 Element child = XUtil.getFirstChildElement(schema); 313 while (child != null) { 314 String 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 ("unknown output format ("+format+")"); 348 349 } 351 353 354 public void printComment(Element comment) { 355 Node 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 370 public void printElement(Element 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 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 )child); 389 indent--; 390 } 391 else if (type == Node.TEXT_NODE) { 392 printText((Text )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 } 406 407 public void printIndent(int level) { 408 for (int i = 0; i < level; i++) { 409 out.print(" "); 410 } 411 out.flush(); 412 } 413 414 415 public void printOpenElement(Element element) { 416 printOpenElement(element, false); 417 } 418 419 420 public void printEmptyElement(Element element) { 421 printOpenElement(element, true); 422 } 423 424 425 public void printCloseElement(Element element) { 426 427 out.print("</"); 428 out.print(element.getNodeName()); 429 out.print('>'); 430 out.flush(); 431 432 } 434 435 public void printAttribute(Attr attribute) { 436 437 String name = attribute.getNodeName(); 438 String value = attribute.getNodeValue(); 439 440 out.print(name); 441 out.print('='); 442 out.print('"'); 443 out.print(normalize(value)); 444 out.print('"'); 445 446 } 448 449 public void printText(Text text) { 450 String value = text.getNodeValue(); 451 out.print(normalize(value)); 452 } 453 454 456 457 public void printElementDecl(Element element) { 458 459 String elemName = element.getAttribute("name"); 460 Element 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 archetype = XUtil.getFirstChildElement(element, "archetype"); 471 if (archetype != null) { 472 Element attribute = XUtil.getFirstChildElement(archetype, "attribute"); 473 while (attribute != null) { 474 printAttributeDecl(elemName, attribute); 475 attribute = XUtil.getNextSiblingElement(attribute, "attribute"); 476 } 477 } 478 479 } 481 482 public void printElementDeclContentModel(Element archetype) { 483 484 String 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 } 498 499 public void printElementDeclContentModelMixed(Element archetype) { 500 501 Element element = XUtil.getFirstChildElement(archetype, "element"); 502 boolean textOnly = element == null; 503 out.print("(#PCDATA"); 504 if (!textOnly) { 505 while (element != null) { 506 String 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 } 519 520 public void printElementDeclContentModelChildren(Element archetype) { 521 522 boolean simple = 523 !containsMoreThanOneChildOfType(archetype, new String [] { "element", "group" }) && 524 XUtil.getFirstChildElement(archetype, "element") != null; 525 526 if (simple) { 527 out.print('('); 528 } 529 Element 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 } 543 544 public void printAttributeDecl(String elemName, Element attribute) { 545 546 String attrName = attribute.getAttribute("name"); 547 String attrType = attribute.getAttribute("type"); 548 Node 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 enumeration = XUtil.getFirstChildElement(attribute, "enumeration"); 557 if (attrType.equals("NMTOKEN") && enumeration != null) { 558 out.print('('); 559 Element literal = XUtil.getFirstChildElement(enumeration, "literal"); 560 while (literal != null) { 561 literal.normalize(); 562 Node literalValueNode = getFirstChildOfType(literal, Node.TEXT_NODE); 563 String 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 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 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 } 608 609 public void printEntityDecl(Element entity) { 610 611 String entityNodeName = entity.getNodeName(); 612 String 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 entityValueNode = getFirstChildOfType(entity, Node.TEXT_NODE); 621 String entityValue = entityValueNode != null 622 ? entityValueNode.getNodeValue() : ""; 623 out.print('"'); 624 out.print(normalize(entityValue)); 625 out.print('"'); 626 } 627 else { 628 String publicId = entity.getAttribute("public"); 629 String 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 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 } 660 661 public void printNotationDecl(Element notation) { 662 663 String notationName = notation.getAttribute("name"); 664 String publicId = notation.getAttribute("public"); 665 String 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 } 694 698 699 protected void printOpenElement(Element element, boolean empty) { 700 701 out.print('<'); 702 out.print(element.getNodeName()); 703 NamedNodeMap attrs = element.getAttributes(); 704 int length = attrs.getLength(); 705 for (int i = 0; i < length; i++) { 706 Attr attribute = (Attr )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 } 720 724 protected boolean isEmpty(Element element) { 725 if (!element.hasChildNodes()) { 726 return true; 727 } 728 Node 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 740 protected boolean isBasicAttributeType(String 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 748 protected boolean isBasicOccurrenceCount(String minOccurs, String 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 756 protected int parseInt(String 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 e) { 764 } 766 return -1; 767 } 768 769 773 protected boolean containsMoreThanOneChildOfType(Element node, String names[]) { 774 int count = 0; 775 Element 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 784 protected Node getFirstChildOfType(Node node, short type) { 785 if (node != null) { 786 Node 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 798 protected Node getNextSiblingOfType(Node node, short type) { 799 if (node != null) { 800 Node 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 812 protected String normalize(String s) { 813 StringBuffer str = new StringBuffer (); 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("<"); 821 break; 822 } 823 case '>': { 824 str.append(">"); 825 break; 826 } 827 case '&': { 828 str.append("&"); 829 break; 830 } 831 case '"': { 832 str.append("""); 833 break; 834 } 835 847 default: { 848 str.append(ch); 849 } 850 } 851 } 852 853 return str.toString(); 854 855 } 857 861 862 private void init() { 863 864 indent = 0; 865 verbose = false; 866 format = OutputFormat.XML_SCHEMA; 867 encoding = "UTF8"; 868 canonical = false; 869 870 } 872 873 private void printElementDeclContentModelChildren0(Element model) { 874 875 String modelNodeName = model.getNodeName(); 876 if (modelNodeName.equals("element")) { 877 String 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 order = model.getAttribute("order"); 885 if (order.equals("choice")) { 886 separator = '|'; 887 } 888 else if (order.equals("all")) { 889 separator = '&'; 890 } 891 892 StringWriter writer = new StringWriter (); 894 PrintWriter printer = new PrintWriter (writer); 895 PrintWriter oprinter = out; 896 out = printer; 897 898 out.print('('); 900 Element 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 String 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 output = buildOccurrenceCountString(output, 921 model.getAttribute("minOccurs"), 922 model.getAttribute("maxOccurs")); 923 924 out = oprinter; 926 out.print(output); 927 } 928 929 } 931 932 private String expandAllModel(String model) { 933 934 Vector piecesVector = new Vector (); 936 StringTokenizer tokenizer = new StringTokenizer (model, "&"); 937 while (tokenizer.hasMoreTokens()) { 938 String piece = tokenizer.nextToken(); 939 piecesVector.addElement(piece); 940 } 941 942 int length = piecesVector.size(); 944 if (length > 1) { 945 String pieces[] = new String [length]; 946 for (int i = 0; i < pieces.length; i++) { 947 pieces[i] = (String )piecesVector.elementAt(i); 948 } 949 String allModel = "(" + buildAllModel(pieces, 0) + ')'; 950 return allModel; 951 } 952 953 return model; 954 955 } 957 958 private String buildAllModel(String src[], int offset) { 959 960 if (src.length - offset == 2) { 962 StringBuffer str = new StringBuffer (); 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 String copy[] = new String [src.length]; 973 StringBuffer str = new StringBuffer (); 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 } 987 988 private String createSeq(String src[]) { 989 990 StringBuffer str = new StringBuffer (); 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 } 1004 1005 private void shift(String src[], int pos, int offset) { 1006 1007 String temp = src[offset]; 1008 for (int i = offset; i > pos; i--) { 1009 src[i] = src[i - 1]; 1010 } 1011 src[pos] = temp; 1012 1013 } 1015 1016 private void swap(String src[], int i, int j) { 1017 1018 String temp = src[i]; 1019 src[i] = src[j]; 1020 src[j] = temp; 1021 1022 } 1024 1025 private String buildOccurrenceCountString(String model, 1026 String minOccurs, 1027 String maxOccurs) { 1028 1029 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 StringBuffer str = new StringBuffer (); 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 str.toString(); 1080 1081 } 1083 1087 1090 public static final class OutputFormat { 1091 1092 1096 1097 public static final OutputFormat DTD = new OutputFormat(0); 1098 1099 1100 public static final OutputFormat XML_SCHEMA = new OutputFormat(1); 1101 1102 1106 1107 private int value; 1108 1109 1113 1114 private OutputFormat(int value) { 1115 this.value = value; 1116 } 1117 1118 1122 1123 public int getValue() { 1124 return value; 1125 } 1126 1127 1131 1132 public int hashCode() { 1133 return value; 1134 } 1135 1136 1137 public boolean equals(Object object) { 1138 if (object == null || getClass() != object.getClass()) { 1139 return false; 1140 } 1141 return value == ((OutputFormat)object).getValue(); 1142 } 1143 1144 1145 public String toString() { 1146 if (this == DTD) { 1147 return "DTD"; 1148 } 1149 if (this == XML_SCHEMA) { 1150 return "XML SCHEMA"; 1151 } 1152 return "???"; 1153 } 1154 1155 } 1157} | Popular Tags |