| 1 19 package org.enhydra.zeus.generator; 20 21 import java.io.File ; 22 import java.io.FileWriter ; 23 import java.io.IOException ; 24 import java.io.Writer ; 25 import java.util.HashSet ; 26 import java.util.Iterator ; 27 import java.util.LinkedList ; 28 import java.util.List ; 29 import java.util.Vector ; 30 import java.util.BitSet ; 31 32 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 63 public class SimpleGenerator implements Generator { 64 65 66 protected List ignoredBindings; 67 68 69 protected List globalUnmarshallerImports; 70 71 72 protected List globalInterfaceImports; 73 74 75 protected List globalImplementationImports; 76 77 78 protected List collapsedElements; 79 80 81 protected File outputDir; 82 83 84 protected boolean initialized; 85 86 91 public SimpleGenerator() { 92 initialized = false; 93 ignoredBindings = new LinkedList (); 94 globalUnmarshallerImports = new LinkedList (); 95 globalInterfaceImports = new LinkedList (); 96 globalImplementationImports = new LinkedList (); 97 collapsedElements = new LinkedList (); 98 99 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 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 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 151 public void setOutputDirectory(String outputDir) { 152 if (outputDir == null) { 153 throw new IllegalArgumentException ("A generator cannot have a " + 154 "null output directory."); 155 } 156 157 this.outputDir = new File (outputDir); 158 uninitialize(); 159 } 160 161 169 public void setOutputDirectory(File outputDir) { 170 if (outputDir == null) { 171 throw new IllegalArgumentException ("A generator cannot have a " + 172 "null output directory."); 173 } 174 175 this.outputDir = outputDir; 176 uninitialize(); 177 } 178 179 191 public void setIgnoreBinding(String xmlName, String xmlNamespaceURI) { 192 ignoredBindings.add(new XMLName(xmlName, xmlNamespaceURI)); 193 } 194 195 205 public void setIgnoreBinding(String xmlName) { 206 setIgnoreBinding(xmlName, ""); 207 } 208 209 220 protected boolean isIgnoredBinding(String xmlName, String xmlNamespaceURI) { 221 if (ignoredBindings != null) { 222 for (Iterator 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 251 public void generate(Binding binding) 252 throws IOException , ZeusException { 253 254 collapsedElements.clear(); 255 256 if (!isInitialized()) { 257 initialize(); 258 } 259 260 265 if (binding instanceof Container) { 266 Container container = (Container)binding; 267 268 if (ClassUtils.isJavaPrimitive(binding.getJavaType())) { 270 return; 271 } 272 273 if (binding.isXMLRootElement()) { 274 275 generateUnmarshaller(container); 276 277 278 generateUnmarshallableInterface(container); 279 } 280 281 282 generateInterface(container); 283 284 285 generateImplementation(container); 286 } else { 287 throw new UnsupportedBindingTypeException(binding); 288 } 289 } 290 291 301 protected void generateUnmarshaller(Container container) 302 throws IOException { 303 304 List unmarshallerImports = new LinkedList (); 305 306 String filename = 308 new StringBuffer (container.getJavaType()) 309 .append("Unmarshaller.java") 310 .toString(); 311 File outputFile = new File (getInterfaceDir(container), filename); 312 FileWriter writer = new FileWriter (outputFile); 313 314 writer.write(ZeusDefaults.GENERATED_CLASS_COMMENT); 316 317 writePackageDeclaration(writer, container.getJavaInterfacePackage()); 319 320 writeUnmarshallerImportStatements(writer, unmarshallerImports); 322 323 writeUnmarshallerDeclaration(writer, container); 325 326 writeUnmarshallerProperties(writer, container); 328 329 writeUnmarshallerUnmarshalMethods(writer, container); 331 332 writer.write("}\n"); 333 334 writeDefaultErrorHandler(writer, container); 336 337 writer.flush(); 338 writer.close(); 339 } 340 341 350 protected void generateUnmarshallableInterface(Container container) 351 throws IOException { 352 353 String filename = 355 new StringBuffer ("Unmarshallable.java") 356 .toString(); 357 File outputFile = new File (getInterfaceDir(container), filename); 358 FileWriter writer = new FileWriter (outputFile); 359 360 writer.write(ZeusDefaults.GENERATED_CLASS_COMMENT); 362 363 writePackageDeclaration(writer, container.getJavaInterfacePackage()); 365 366 writer.write("import org.xml.sax.ContentHandler;\n\n"); 368 369 writer.write("public interface Unmarshallable "); 371 writer.write("extends ContentHandler {\n\n"); 372 373 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 395 protected void generateInterface(Container container) 396 throws IOException { 397 398 List interfaceImports = new LinkedList (); 399 400 String filename = 402 new StringBuffer (container.getJavaType()) 403 .append(".java") 404 .toString(); 405 File outputFile = new File (getInterfaceDir(container), filename); 406 FileWriter writer = new FileWriter (outputFile); 407 408 writer.write(ZeusDefaults.GENERATED_CLASS_COMMENT); 410 411 writePackageDeclaration(writer, container.getJavaInterfacePackage()); 413 414 418 List properties = container.getProperties(); 419 for (Iterator 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 collectionClass = property.getJavaCollectionClass(); 429 if (!interfaceImports.contains(collectionClass)) { 430 interfaceImports.add(collectionClass); 431 } 432 } 433 } 434 435 if (container.isJavaSerializable()) { 437 interfaceImports.add("java.io.Serializable"); 438 } 439 440 writeInterfaceImportStatements(writer, interfaceImports); 442 443 writeInterfaceDeclaration(writer, container); 445 446 writeElementAndAttributeArrays(writer, container); 448 449 writeInterfaceMethods(writer, container.getProperties()); 451 452 writeInterfaceMarshalMethods(writer); 454 455 writer.write("}\n"); 456 writer.flush(); 457 writer.close(); 458 } 459 460 469 protected void generateImplementation(Container container) 470 throws IOException { 471 472 List implementationImports = new LinkedList (); 473 474 String filename = container.getJavaType() + "Impl.java"; 476 File outputFile = new File (getImplementationDir(container), filename); 477 FileWriter writer = new FileWriter (outputFile); 478 479 writer.write(ZeusDefaults.GENERATED_CLASS_COMMENT); 481 482 writePackageDeclaration(writer, 484 container.getJavaImplementationPackage()); 485 486 490 if (container.getJavaInterfacePackage() != 491 container.getJavaImplementationPackage()) { 492 493 StringBuffer containerPackage = new StringBuffer (); 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 506 boolean firstCollection = true; 507 List properties = container.getProperties(); 508 for (Iterator 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 collectionClass = property.getJavaCollectionClass(); 522 if (!implementationImports.contains(collectionClass)) { 523 implementationImports.add(collectionClass); 524 implementationImports.add(ClassUtils.getCollectionImplClass( 525 collectionClass)); 526 } 527 } 528 } 529 530 writeImplementationImportStatements(writer, implementationImports); 532 533 writeImplementationDeclaration(writer, container.getJavaType()); 535 536 writeImplementationProperties(writer, properties); 538 539 writeImplementationUnmarshallerProperties(writer, container); 541 542 writeImplementationPrototypeMethodAndField(writer,container.getJavaType()); 544 545 writeImplementationConstructor(writer,container.getJavaType(),properties); 547 548 writeImplementationMethods(writer, container); 550 551 writeImplementationMarshalMethods(writer, container); 553 554 writeImplementationUnmarshalMethods(writer, container); 556 557 writeImplementationSAXHandlerMethods(writer, container); 559 560 writer.write("}\n"); 561 562 writer.flush(); 563 writer.close(); 564 } 565 566 575 protected void writePackageDeclaration(Writer writer, String packageName) 576 throws IOException { 577 578 if (!packageName.equals("")) { 580 writer.write("package"); 581 writer.write(" "); 582 writer.write(packageName); 583 writer.write(";\n\n"); 584 } 585 } 586 587 598 protected void writeUnmarshallerImportStatements(Writer writer, 599 List importClasses) 600 throws IOException { 601 602 if (globalUnmarshallerImports.size() > 0) { 604 writer.write("// Global Unmarshaller Import Statements\n"); 605 } 606 for (Iterator i = globalUnmarshallerImports.iterator(); i.hasNext(); ) { 607 writer.write("import "); 608 writer.write((String )i.next()); 609 writer.write(";\n"); 610 } 611 if (globalUnmarshallerImports.size() > 0) { 612 writer.write("\n"); 613 } 614 615 if (importClasses.size() > 0) { 617 writer.write("// Local Unmarshaller Import Statements\n"); 618 } 619 for (Iterator i = importClasses.iterator(); i.hasNext(); ) { 620 writer.write("import "); 621 writer.write((String )i.next()); 622 writer.write(";\n"); 623 } 624 if (importClasses.size() > 0) { 625 writer.write("\n"); 626 } 627 } 628 629 638 protected void writeUnmarshallerDeclaration(Writer writer, 639 Container container) 640 throws IOException { 641 642 writer.write("public class "); 643 writer.write(container.getJavaType()); 644 writer.write("Unmarshaller {\n\n"); 645 } 646 647 656 protected void writeUnmarshallerProperties(Writer writer, 657 Container container) 658 throws IOException { 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 677 protected void writeUnmarshallerUnmarshalMethods(Writer writer, 678 Container container) 679 throws IOException { 680 681 String className = container.getJavaType(); 682 683 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 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 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 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 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 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 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 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 815 protected void writeDefaultErrorHandler( |