1 23 24 package org.enhydra.xml.xmlc.compiler; 25 26 import java.io.File ; 27 import java.io.IOException ; 28 import java.io.PrintWriter ; 29 30 import org.enhydra.xml.xmlc.XMLCException; 31 import org.enhydra.xml.xmlc.XMLObject; 32 import org.enhydra.xml.xmlc.codegen.IndentWriter; 33 import org.enhydra.xml.xmlc.codegen.JavaClass; 34 import org.enhydra.xml.xmlc.codegen.JavaCode; 35 import org.enhydra.xml.xmlc.codegen.JavaField; 36 import org.enhydra.xml.xmlc.codegen.JavaLang; 37 import org.enhydra.xml.xmlc.codegen.JavaMethod; 38 import org.enhydra.xml.xmlc.codegen.JavaModifiers; 39 import org.enhydra.xml.xmlc.codegen.JavaParameter; 40 import org.enhydra.xml.xmlc.deferredparsing.DeferredParsingAccessorGenerator; 41 import org.enhydra.xml.xmlc.deferredparsing.DeferredParsingDocBuilderGenerator; 42 import org.enhydra.xml.xmlc.dom.AccessorGenerator; 43 import org.enhydra.xml.xmlc.dom.DocBuilderGenerator; 44 import org.enhydra.xml.xmlc.dom.XMLCDocument; 45 import org.enhydra.xml.xmlc.dom.XMLCDomFactory; 46 import org.enhydra.xml.xmlc.dom.XMLCDomFactoryCache; 47 import org.enhydra.xml.xmlc.metadata.DocumentClass; 48 import org.enhydra.xml.xmlc.metadata.GenerateType; 49 import org.enhydra.xml.xmlc.metadata.MetaData; 50 import org.w3c.dom.Document ; 51 52 55 public class ClassGenerator { 56 59 private static final String [] IMPORT_LIST = { 60 "org.w3c.dom.*", 61 }; 62 63 66 private static final String [] CLASS_IMPORT_LIST = { 67 "org.enhydra.xml.xmlc.dom.XMLCDomFactory", 70 }; 72 73 76 private static final String [] DEFERRED_PARSING_CLASS_IMPORT_LIST = { 77 "org.enhydra.xml.xmlc.deferredparsing.DocumentLoader", 78 "org.enhydra.xml.xmlc.deferredparsing.StandardDocumentLoader", 79 }; 80 81 84 public static final String DOC_LOADER_FIELD_NAME = "fDocumentLoader"; 85 86 89 public static final String DOC_LOADER_CLASS_NAME = "DocumentLoader"; 90 91 94 public static final String DELEGATE_FIELD_NAME = "fDelegate"; 95 96 99 public static final String DOM_FACTORY_FIELD_NAME = "fDOMFactory"; 100 101 104 private static final String [] WARNING_HEADER = { 105 "/*", 106 " ************************************", 107 " * XMLC GENERATED CODE, DO NOT EDIT *", 108 " ************************************", 109 " */" 110 }; 111 112 115 private MetaData fMetaData; 116 private DocumentClass fDocumentClass; 117 118 121 private GenerateType fGenerate; 122 123 126 private XMLCDocument fXmlcDoc; 127 128 131 private Document fDocument; 132 133 136 private ElementTable fElementTable; 137 138 141 private AccessMethods fAccessMethods; 142 143 146 private AccessConsts fAccessConsts; 147 148 151 private AccessorGenerator fAccessorGenerator; 152 153 156 private DocBuilderGenerator fDocBuilderGenerator; 157 158 161 JavaClass fDocClass; 162 163 172 public ClassGenerator(MetaData metaData, 173 XMLCDocument xmlcDoc, 174 PrintWriter methodOutput) 175 throws XMLCException { 176 fMetaData = metaData; 178 fXmlcDoc = xmlcDoc; 179 fDocumentClass = fMetaData.getDocumentClass(); 180 fGenerate = fDocumentClass.getGenerate(); 181 fDocument = xmlcDoc.getDocument(); 182 183 if (fDocumentClass.getDeferredParsing()) { 187 fAccessorGenerator = 188 new DeferredParsingAccessorGenerator(); 189 fDocBuilderGenerator = 190 new DeferredParsingDocBuilderGenerator(); 191 } else { 192 XMLCDomFactory domFactory = fXmlcDoc.getDomFactory(); 193 fAccessorGenerator = domFactory.createAccessorGenerator(fDocument); 194 fDocBuilderGenerator = domFactory.createDocBuilderGenerator(fDocument); 195 } 196 197 fElementTable = new ElementTable(metaData, fXmlcDoc); 198 fAccessMethods = new AccessMethods(fMetaData, fElementTable, 199 fAccessorGenerator); 200 fAccessConsts = new AccessConsts(fMetaData, fElementTable); 201 202 createClass(); 204 fAccessMethods.generateCode(fDocClass); 205 fAccessConsts.generateCode(fDocClass); 206 207 createConstructors(); 209 createDomFactoryField(); 210 if (fDocumentClass.getDeferredParsing()) { 211 createDeferredParsingFields(); 212 } 213 214 createBuildDocument(); 215 fAccessMethods.generateCode(fDocClass); 216 217 if (fDocumentClass.getDelegateSupport()) { 218 createDelegateSupport(); 219 } 220 createClassIdent(); 221 createSourceFileConst(); 222 223 if (methodOutput != null) { 225 fAccessMethods.printAccessMethods(methodOutput); 226 fAccessConsts.printAccessConstants(methodOutput); 227 fAccessMethods.printOmittedIds(methodOutput); 228 fAccessConsts.printOmittedConstants(methodOutput); 229 } 230 } 231 232 235 private void createDefaultConstructor() { 236 JavaMethod constr 237 = new JavaMethod(fDocumentClass.getUnqualClassName(), 238 null, 239 JavaModifiers.PUBLIC, 240 null, 241 new String [] {"Default constructor."}); 242 if (fDocumentClass.getDeferredParsing()) { 243 constr.getCode().addln("this(StandardDocumentLoader.getInstance());"); 244 } 245 constr.getCode().addln("buildDocument();"); 246 fDocClass.addConstructor(constr); 247 } 248 249 252 private void createOptionalBuildDocConstructor() { 253 String [] buildArgDoc = { 254 "buildDOM If false, the DOM will not be built until", 255 "buildDocument() is called by the derived class. If true, ", 256 "the DOM is built immediatly." 257 }; 258 JavaParameter buildArg 259 = new JavaParameter("buildDOM", "boolean", buildArgDoc); 260 261 JavaMethod constr 262 = new JavaMethod(fDocumentClass.getUnqualClassName(), 263 null, 264 JavaModifiers.PUBLIC, 265 new JavaParameter[] {buildArg}, 266 new String [] {"Constructor with optional building of the DOM."}); 267 if (fDocumentClass.getDeferredParsing()) { 268 constr.getCode().addln("this(StandardDocumentLoader.getInstance(), buildDOM);"); 269 } else constr.getCode().addln(new String [] { 270 "if (buildDOM) {", 271 " buildDocument();", 272 "}" 273 }); 274 fDocClass.addConstructor(constr); 275 } 276 277 280 private void createDeferredParsingConstructors() { 281 String [] buildArgDoc = { 282 "buildDOM If false, the DOM will not be built until", 283 "buildDocument() is called by the derived class. If true, ", 284 "the DOM is built immediatly." 285 }; 286 JavaParameter buildArg 287 = new JavaParameter("buildDOM", "boolean", buildArgDoc); 288 289 String [] loaderArgDoc = { 290 "loader the document loader to delegate document", 291 "creation to." 292 }; 293 JavaParameter loaderArg 294 = new JavaParameter("loader", "DocumentLoader", buildArgDoc); 295 296 JavaMethod constr 297 = new JavaMethod(fDocumentClass.getUnqualClassName(), 298 null, 299 JavaModifiers.PUBLIC, 300 new JavaParameter[] {loaderArg, buildArg}, 301 new String [] { 302 "Constructor for deferred parsing support.", 303 "The supplied document loader is used to", 304 "create the DOM." 305 }); 306 constr.getCode().addln(new String [] { 307 DOC_LOADER_FIELD_NAME + " = loader;", 308 "if (buildDOM) {", 309 " buildDocument();", 310 "}" 311 }); 312 fDocClass.addConstructor(constr); 313 314 constr 315 = new JavaMethod(fDocumentClass.getUnqualClassName(), 316 null, 317 JavaModifiers.PUBLIC, 318 new JavaParameter[] {loaderArg}, 319 new String [] { 320 "Constructor for deferred parsing support.", 321 "The supplied document loader is used to", 322 "create the DOM." 323 }); 324 constr.getCode().addln("this(loader, true);"); 325 fDocClass.addConstructor(constr); 326 } 327 328 331 private void createCopyConstructor() { 332 JavaParameter srcArg 334 = new JavaParameter("src", 335 fDocumentClass.getUnqualClassName(), 336 "The document to clone."); 337 338 JavaMethod constr 339 = new JavaMethod(fDocumentClass.getUnqualClassName(), 340 null, 341 JavaModifiers.PUBLIC, 342 new JavaParameter[] {srcArg}, 343 new String [] {"Copy constructor."}); 344 if (fDocumentClass.getDeferredParsing()) { 345 constr.getCode().addln(DOC_LOADER_FIELD_NAME + 346 " = src.getDocumentLoader();"); 347 } 348 constr.getCode().addln(new String [] { 349 "setDocument((Document)src.getDocument().cloneNode(true), src.getMIMEType(), src.getEncoding());", 350 "syncAccessMethods();" 351 }); 352 fDocClass.addConstructor(constr); 353 } 354 355 358 private void createCloneMethod() { 359 JavaParameter deepArg 360 = new JavaParameter("deep", "boolean", 361 "Must be true, only deep clone is supported."); 362 363 JavaMethod method 364 = new JavaMethod("cloneNode", 365 "Node", 366 JavaModifiers.PUBLIC | JavaModifiers.OMIT_INTERFACE, 367 new JavaParameter[] {deepArg}, 368 new String [] {"Clone the document."}); 369 fDocClass.addMethod(method); 370 method.getCode().addln(new String [] { 371 "cloneDeepCheck(deep);", 372 "return new " + fDocumentClass.getUnqualClassName() + "(this);" 373 }); 374 } 375 376 379 private void createConstructors() { 380 createDefaultConstructor(); 381 createOptionalBuildDocConstructor(); 382 createCopyConstructor(); 383 if (fDocumentClass.getDeferredParsing()) { 384 createDeferredParsingConstructors(); 385 } 386 createCloneMethod(); 387 } 388 389 393 private void createDelegateSupport() { 394 String unqualInterfaceName = fDocumentClass.getUnqualInterfaceName(); 395 396 JavaParameter param 400 = new JavaParameter("delegate", XMLObject.class.getName(), 401 new String [] { 402 "The delegate to set. This must be an object", 403 "implementing " + unqualInterfaceName + ", however the parameter", 404 "is untyped, since this method must override XMLOject.setDelegate()", 405 "New value for text child."}); 406 407 JavaMethod method 408 = new JavaMethod("setDelegate", 409 "void", 410 JavaModifiers.PUBLIC, 411 new JavaParameter[] {param}, 412 new String [] {"Set the delegate object."}); 413 fDocClass.addMethod(method); 414 JavaCode body = method.getCode(); 415 416 body.addln(DELEGATE_FIELD_NAME + " = (" + unqualInterfaceName + ")delegate;"); 417 body.addln("super.setDelegate(" + DELEGATE_FIELD_NAME + ");"); 418 419 JavaField field = 420 new JavaField(DELEGATE_FIELD_NAME, 421 unqualInterfaceName, 422 JavaModifiers.PRIVATE, 423 "Pointer to delegate object", null); 424 fDocClass.addField(field); 425 } 426 427 431 private void createDeferredParsingFields() { 432 String [] doc = { 433 "Document loader for deferred parsing.", 434 }; 435 JavaField field = 436 new JavaField(DOC_LOADER_FIELD_NAME, 437 DOC_LOADER_CLASS_NAME, 438 JavaModifiers.PRIVATE | JavaModifiers.FINAL, 439 doc, null); 440 fDocClass.addField(field); 441 442 JavaMethod method 443 = new JavaMethod("getDocumentLoader", 444 DOC_LOADER_CLASS_NAME, 445 JavaModifiers.PROTECTED | JavaModifiers.FINAL, 446 null, 447 new String [] {"Get the document loader associated with the class."}); 448 fDocClass.addMethod(method); 449 JavaCode body = method.getCode(); 450 body.addln("return " + DOC_LOADER_FIELD_NAME + ";"); 451 } 452 453 458 private void createClassIdent() { 459 String [] doc = { 460 "Field that is used to identify this as the XMLC generated class", 461 "in an inheritance chain. Contains a reference to the class object." 462 }; 463 JavaField field = 465 new JavaField(XMLObject.XMLC_GENERATED_CLASS_FIELD_NAME, 466 "Class", 467 JavaModifiers.PUBLIC_CONST | JavaModifiers.OMIT_INTERFACE, 468 doc, 469 fDocumentClass.getUnqualClassName() + ".class"); 470 fDocClass.addField(field); 471 } 472 473 477 private void createSourceFileConst() { 478 String [] doc = { 479 "Field containing CLASSPATH relative name of the source file", 480 "that this class can be regenerated from." 481 }; 482 JavaField field = 483 new JavaField(XMLObject.XMLC_SOURCE_FILE_FIELD_NAME, 484 "String", 485 JavaModifiers.PUBLIC_CONST | JavaModifiers.OMIT_INTERFACE, 486 doc, 487 JavaLang.createStringConst(fMetaData.getInputDocument().getRecompileSource())); 488 fDocClass.addField(field); 489 } 490 491 495 private void createDomFactoryField() { 496 String [] doc = { 497 "XMLC DOM factory associated with this class.", 498 }; 499 String init 500 = XMLCDomFactoryCache.class.getName() 501 + ".getFactory(" + fXmlcDoc.getDomFactory().getClass().getName() 502 + ".class)"; 503 504 JavaField field = 505 new JavaField(DOM_FACTORY_FIELD_NAME, 506 XMLCDomFactory.class.getName(), 507 JavaModifiers.PRIVATE | JavaModifiers.STATIC | JavaModifiers.FINAL, 508 doc, init); 509 fDocClass.addField(field); 510 511 JavaMethod method 512 = new JavaMethod("getDomFactory", 513 XMLCDomFactory.class.getName(), 514 JavaModifiers.PROTECTED | JavaModifiers.FINAL, 515 null, 516 new String [] {"Get the XMLC DOM factory associated with the class."}); 517 fDocClass.addMethod(method); 518 JavaCode body = method.getCode(); 519 body.addln("return " + DOM_FACTORY_FIELD_NAME + ";"); 520 } 521 522 527 private void createBuildDocument() throws XMLCException { 528 JavaMethod method 529 = new JavaMethod("buildDocument", 530 "void", 531 JavaModifiers.PUBLIC | JavaModifiers.OMIT_INTERFACE, 532 null, 533 new String [] {"Create document as a DOM and initialize accessor method fields."}); 534 fDocClass.addMethod(method); 535 JavaCode body = method.getCode(); 536 537 if (fDocumentClass.getDelegateSupport()) { 538 body.addln(new String [] { 539 "if (" + DELEGATE_FIELD_NAME + " != null) {", 540 " " + DELEGATE_FIELD_NAME + ".buildDocument();", 541 " return;", 542 "}"}); 543 } 544 fDocBuilderGenerator.createBuildDocumentMethod(fXmlcDoc, 545 fAccessorGenerator, 546 fElementTable, 547 fDocClass, 548 method); 549 } 550 551 554 private void createClass() throws XMLCException { 555 XMLCDomFactory domFactory = fXmlcDoc.getDomFactory(); 556 557 String [] doc = { 560 "XMLC Document class, generated from", 561 fMetaData.getInputDocument().getUrl().replace('\\','/') 562 }; 563 564 fDocClass= new JavaClass(fDocumentClass.getPackageName(), 565 fDocumentClass.getUnqualClassName(), 566 JavaModifiers.PUBLIC, 567 doc); 568 if (fDocumentClass.getUnqualInterfaceName() != null) { 570 fDocClass.setInterface(fDocumentClass.getUnqualInterfaceName()); 571 } 572 573 fDocClass.addImports(IMPORT_LIST); 575 fDocClass.addClassImports(CLASS_IMPORT_LIST); 576 if (fDocumentClass.getDeferredParsing()) { 577 fDocClass.addClassImports(DEFERRED_PARSING_CLASS_IMPORT_LIST); 578 } 579 580 String baseClassName = fDocumentClass.getExtends(); 582 if (baseClassName == null) { 583 baseClassName = domFactory.getBaseClassName(); 584 } 585 fDocClass.setExtends(baseClassName); 586 587 fDocClass.addImplements(XMLObject.class.getName()); 589 String [] faces = domFactory.getInterfaceNames(); 590 if (faces != null) { 591 fDocClass.addImplements(faces); 592 } 593 faces = fDocumentClass.getImplements(); 594 if (faces != null) { 595 fDocClass.addImplements(faces); 596 } 597 } 598 599 602 private void generateClassSource(PrintWriter verboseOut) 603 throws XMLCException, IOException { 604 605 File src = fDocumentClass.getJavaClassSource(); 606 if (verboseOut != null) { 607 verboseOut.println(" creating class: " + src.getPath()); 609 } 610 IndentWriter out = new IndentWriter(src, "ISO-8859-1"); 611 boolean finishedOk = false; try { 613 out.println(WARNING_HEADER); 614 if (fGenerate == GenerateType.IMPLEMENTATION) { 615 fDocClass.printImplementation(out); 616 } else { 617 fDocClass.printClass(out); 618 } 619 finishedOk = true; } finally { 621 out.close(!finishedOk); 622 } 623 } 624 625 628 private void generateInterfaceSource(PrintWriter verboseOut) 629 throws XMLCException, IOException { 630 631 File src = fDocumentClass.getJavaInterfaceSource(); 632 if (verboseOut != null) { 633 verboseOut.println(" creating interface: " + src.getAbsolutePath()); 634 } 635 IndentWriter out = new IndentWriter(src, "ISO-8859-1"); 636 boolean finishedOk = false; try { 638 out.println(WARNING_HEADER); 639 fDocClass.printInterface(out); 640 finishedOk = true; } finally { 642 out.close(!finishedOk); 643 } 644 } 645 646 649 public void generateJavaSource(PrintWriter verboseOut) 650 throws XMLCException, IOException { 651 652 if (fGenerate.generateClass()) { 653 generateClassSource(verboseOut); 654 } 655 if (fGenerate.generateInterface()) { 656 generateInterfaceSource(verboseOut); 657 } 658 } 659 } 660 | Popular Tags |