1 19 20 package org.netbeans.modules.schema2beansdev; 21 22 import java.util.*; 23 import java.io.*; 24 25 import org.netbeans.modules.schema2beans.*; 26 import org.netbeans.modules.schema2beansdev.metadd.*; 27 import org.netbeans.modules.schema2beansdev.beangraph.*; 28 import org.netbeans.modules.schema2beansdev.gen.*; 29 30 34 public class BeanBuilder { 35 private static final String UNIQUE_PREFIX = "My"; 36 protected GenBeans.Config config; 37 protected CodeGeneratorFactory codeGenFactory; 38 protected BeanElement rootElement; 39 protected String genDir; 40 protected String packagePath; 41 protected String packageName = null; 42 protected TreeParser parser; 43 protected Map constNameMap = null; 45 protected Map illegalClassNames = new HashMap(); 46 47 class BeanElement { 48 GraphNode node; 49 String beanName; 50 51 int type; 52 String classType; 53 private boolean typeSetExternally = false; 54 55 boolean isRoot; 56 boolean isAbstract; 57 58 private boolean canBeEmpty = false; 59 60 private Map usedTypes; 61 private int nonAttributePropertyCount = 0; 62 63 BeanElement(GraphNode node) { 64 this.node = node; 65 } 66 67 void initialize(boolean isRoot) { 68 this.beanName = Common.convertName(this.node.getName()); 70 71 this.type = Common.TYPE_BEAN; 76 this.isRoot = isRoot; 77 78 calculateType(); 79 } 80 81 public GraphNode getGraphNode() { 82 return this.node; 83 } 84 85 91 public void setNodeCreated(boolean value) { 92 node.setCreated(value); 93 calculateType(); 94 } 95 96 protected void calculateType() { 97 if (!node.isCreated()) 99 this.type = Common.TYPE_STRING; 100 GraphNode[] nodes = node.getNodes(); 101 if (nodes.length == 1 && !isRoot) { 103 if (Common.DTD_STRING.equals(nodes[0].getName())) 104 this.type = Common.TYPE_STRING; 105 else { 106 if (Common.DTD_EMPTY.equals(nodes[0].getName())) { 107 this.type = Common.TYPE_BOOLEAN; 108 this.canBeEmpty = true; 109 } 110 } 111 } 112 } 113 114 void setCanBeEmpty(boolean value) { 115 canBeEmpty = value; 116 if (canBeEmpty) { 117 } 119 } 120 121 124 public void setName(String name) { 125 this.beanName = name; 126 } 127 128 public String getName() { 129 return this.beanName; 130 } 131 132 public String getDTDName() { 133 return this.node.getName(); 134 } 135 136 public void setDTDName(String dtdName) { 137 node.setName(dtdName); 138 } 139 140 public String getNamespace() { 141 return node.getNamespace(); 142 } 143 144 public boolean isBean() { 145 return Common.isBean(this.type); 146 } 147 148 public boolean isBoolean() { 149 return Common.isBoolean(this.type); 150 } 151 152 public boolean isRoot() { 153 return this.isRoot; 154 } 155 156 public String typeToString() { 157 switch(this.type) { 158 case Common.TYPE_STRING: 159 return Common.CLASS_STRING; 160 case Common.TYPE_BOOLEAN: 161 return Common.CLASS_BOOLEAN; 162 default: 163 return this.beanName; 164 } 165 } 166 167 public String getClassType() { 168 if (classType == null) 169 return typeToString(); 170 return classType; 171 } 172 173 public String getFullClassType() { 174 String result = getClassType(); 175 if (packageName == null) 176 return result; 177 if (isBean() && node.isCreated()) 178 return packageName+"."+result; 179 return result; 180 } 181 182 public void setClassType(String ct) { 183 classType = ct; 184 } 185 186 public boolean isTypeSetExternally() { 187 return typeSetExternally; 188 } 189 190 public void setTypeSetExternally(boolean value) { 191 typeSetExternally = value; 192 } 193 194 public String toString() { 195 return this.beanName + 196 ((this.type == 197 Common.TYPE_STRING)?" \t(String)":"\t(Bean)"); } 199 200 public void setUsedTypes(Map usedTypes) { 201 this.usedTypes = usedTypes; 202 } 203 204 public boolean isUsedType(String type) { 205 return usedTypes.containsKey(type); 206 } 207 208 public boolean getCanBeEmpty() { 209 return canBeEmpty; 210 } 211 212 public String getOutputFileName() { 213 if (isBean()) 214 return getClassType(); 215 else 216 return getName(); 217 } 218 219 public BeanElement getExtension() { 220 if (node.getExtension() == null || !node.getExtension().isCreated()) 221 return null; 222 return (BeanElement) node.getExtension().getObject(); 223 } 224 225 public void setNonAttributePropertyCount(int value) { 226 nonAttributePropertyCount = value; 227 } 228 229 public int getNonAttributePropertyCount() { 230 return nonAttributePropertyCount; 231 } 232 } 233 234 class Finder { 235 private String findExpr, byExpr; 236 private boolean listFindExpr; 237 238 public Finder(String findExpr, String byExpr, boolean listFindExpr) { 239 this.findExpr = findExpr; 240 this.byExpr = byExpr; 241 this.listFindExpr = listFindExpr; 242 } 243 244 public String getFindExpr() { 245 return findExpr; 246 } 247 248 public String getByExpr() { 249 return byExpr; 250 } 251 252 public boolean isListFindExpr() { 253 return listFindExpr; 254 } 255 256 public String toString() { 257 if (listFindExpr) 258 return "Finder list "+findExpr+" by "+byExpr; 259 else 260 return "Finder "+findExpr+" by "+byExpr; 261 } 262 } 263 264 BeanBuilder(TreeParser parser, GenBeans.Config config, CodeGeneratorFactory cgf) { 265 this.parser = parser; 266 this.config = config; 267 this.codeGenFactory = cgf; 268 269 illegalClassNames.put("Object", null); 272 illegalClassNames.put("Thread", null); 273 illegalClassNames.put("Compiler", null); 274 illegalClassNames.put("Class", null); 275 illegalClassNames.put("ClassLoader", null); 276 illegalClassNames.put("Package", null); 278 illegalClassNames.put("String", null); 279 illegalClassNames.put("Boolean", null); 280 illegalClassNames.put("Integer", null); 281 illegalClassNames.put("Long", null); 282 illegalClassNames.put("Short", null); 283 illegalClassNames.put("Double", null); 284 illegalClassNames.put("Float", null); 285 illegalClassNames.put("Byte", null); 286 illegalClassNames.put("Character", null); 287 illegalClassNames.put("int", null); 288 illegalClassNames.put("char", null); 289 illegalClassNames.put("byte", null); 290 illegalClassNames.put("short", null); 291 illegalClassNames.put("long", null); 292 illegalClassNames.put("double", null); 293 illegalClassNames.put("float", null); 294 illegalClassNames.put("boolean", null); 295 illegalClassNames.put("void", null); 296 } 297 298 299 308 private void buildProperties(GraphLink l, CodeGeneratorClass bc, 309 int nestedLevel, int groupInstance, 310 boolean ored, 311 MetaElement e, MetaDD mdd, Map usedNames) { 312 while (l != null) { 313 if (config.isTraceGen()) 314 config.messageOut.println("buildProperties: l="+l+" l.name="+l.name+" l.element="+l.element+" l.getSibling()="+l.getSibling()+" groupInstance="+groupInstance); 315 if (l.element != null) { 316 BeanElement be = (BeanElement)l.element.getObject(); 317 318 if (be == null) { 319 config.messageOut.println("Warning: be was null"); 323 continue; 324 } 325 326 if (l.getParent() != null) 331 ored = ored || l.getParent().isSequenceOr(); 332 334 String name; 335 String dtdName; 336 String namespace; 337 String constName; 338 if (l.name != null) { 339 name = Common.convertName(l.name); 340 dtdName = l.getSchemaName(); 341 namespace = l.getNamespace(); 342 } else { 343 name = be.getName(); 344 dtdName = be.getDTDName(); 345 namespace = be.getNamespace(); 346 } 347 MetaElement propertyME = getMetaElement(mdd, dtdName); 348 if (propertyME != null && propertyME.getBeanName() != null) { 349 name = propertyME.getBeanName(); 350 if (config.isTraceGen()) 351 config.messageOut.println("buildProperties: property in "+e.getBeanName()+" has been renamed to "+name); 352 } 353 constName = Common.constName(dtdName); 354 if ("#PCDATA".equals(dtdName)) { 355 name = "pcdata"; 358 constName = "PCDATA"; 359 } 360 if (usedNames.containsKey(name)) { 361 int uniqNum = 2; 362 String baseName = name; 363 while (usedNames.containsKey(name = baseName + uniqNum)) 364 uniqNum++; 365 constName = constName + uniqNum; 366 if (l.name != null) { 367 } else { 369 be.setName(name); 370 MetaElement origE = getMetaElement(mdd, dtdName); 371 if (origE != null) { 372 MetaElement newE = new MetaElement(origE); 373 mdd.addMetaElement(newE); 374 } 375 } 376 config.messageOut.println(Common.getMessage("RenamedProperty_msg", baseName, name, e.getBeanName())); 377 } 378 usedNames.put(name, be); 379 if (config.isTraceGen()) 380 config.messageOut.println("buildProperties: name="+name+" constName="+constName+" dtdName="+dtdName+" graphlink.name="+l.name+" be.getClassType="+be.getClassType()); 381 AttrProp[] attrs = be.node.getAttributes(); 382 List extraData = new ArrayList(l.extraData); 383 if (!be.node.getExtraData().isEmpty()) { 384 extraData.addAll(be.node.getExtraData()); 385 } 387 if (propertyME != null && propertyME.sizeKnownValue() > 0) { 389 for (int valNum = 0, size = propertyME.sizeKnownValue(); valNum < size; ++valNum) { 390 String knownValue = propertyME.getKnownValue(valNum); 391 extraData.add(new KnownValueEnumeration(knownValue)); 392 } 393 } 394 constNameMap.put(constName, dtdName); 395 int type = be.type; 396 String classType = be.getClassType(); 397 if (!be.isTypeSetExternally() && 403 (ored || l.isNillable())) { 404 if (JavaUtil.isPrimitiveType(classType)) { 405 classType = JavaUtil.toObjectType(classType); 406 type = Common.wrapperToType(classType); 407 if (type == Common.NONE) 408 type = Common.TYPE_STRING; 409 if (config.isTraceGen()) 410 config.messageOut.println("Promoting primitive type to object type for "+name+" classType="+classType+" type="+type); 411 } 412 } 413 AbstractCodeGeneratorClass.Property prop = 414 bc.addProperty(name, dtdName, namespace, l.element, l, 415 classType, nestedLevel, 416 l.getElementInstance(), 417 groupInstance, type, ored, 418 attrs, constName, 419 l.getDefaultValue(), true, extraData, l.isUnion()); 420 prop.setCanBeEmpty(be.getCanBeEmpty()); 421 prop.setNillable(l.isNillable()); 422 prop.setBeanElement(be); 423 l.setObject(prop); 424 if (e != null) { 425 MetaProperty[] metaProperties = e.getMetaProperty(); 427 boolean found = false; 428 for (int i = 0; i < metaProperties.length; ++i) { 429 if (name.equals(metaProperties[i].getBeanName())) { 430 found = true; 431 break; 432 } 433 } 434 if (!found) { 435 MetaProperty mp = new MetaProperty(); 436 mp.setBeanName(name); 437 e.addMetaProperty(mp); 438 } 439 } 440 441 if (!Common.isBean(be.type) && 447 config.isAttributesAsProperties()) { 448 addAttrProps(bc, attrs, name, usedNames, 449 l.getElementInstance(), false); 450 } 451 } 452 453 int childGroupInstance = Common.widestInstance(groupInstance, 458 l.getGroupInstance()); 459 buildProperties(l.getFirstChild(), bc, nestedLevel+1, 460 childGroupInstance, ored, e, mdd, usedNames); 461 462 l = l.getSibling(); 463 } 464 } 465 466 protected void addAttrProps(CodeGeneratorClass bc, AttrProp[] attrs, 467 String propertyName, Map usedNames, 468 int groupInstance, 469 boolean directChild) { 470 if (attrs != null) { 471 for (int i = 0; i < attrs.length; ++i) { 472 addAttrProp(bc, attrs[i], propertyName, usedNames, 473 groupInstance, directChild); 474 } 475 } 476 } 477 478 protected void addAttrProp(CodeGeneratorClass bc, AttrProp attr, 479 String propertyName, Map usedNames, 480 int groupInstance, 481 boolean directChild) { 482 String name; 483 if (directChild) 484 name = Common.convertName(attr.getName()); 485 else 486 name = Common.convertName(propertyName+"_"+attr.getName()); 487 if (usedNames.containsKey(name)) { 488 int uniqNum = 2; 489 String baseName = name; 490 while (usedNames.containsKey(name = baseName + uniqNum)) 491 uniqNum++; 492 attr.setName(name); 493 config.messageOut.println(Common.getMessage("RenamedProperty_msg", baseName, name, propertyName)); 494 } 495 usedNames.put(name, attr); 496 497 String javaType = attr.getJavaType(); 498 int type; 499 if (javaType == null) { 500 type = Common.TYPE_STRING; 501 javaType = "java.lang.String"; } else { 503 type = Common.wrapperToType(javaType); 504 if (type == Common.NONE) 505 type = Common.TYPE_STRING; 506 } 507 List extraData = attr.getExtraData(); 509 String namespace = attr.getNamespace(); 510 bc.addProperty(name, attr.getDtdName(), namespace, null, null, 511 javaType, 0, 512 attr.getInstance(), 513 groupInstance, 514 type, 515 false, 516 null, 517 Common.constName(name), 518 attr.getDefaultValue(), directChild, 519 extraData, false) 520 .setAttrProp(attr); 521 } 522 523 protected void addCommentsProcessing(CodeGeneratorClass bc) { 524 bc.addProperty("Comments", "comment", null, null, null, 525 "java.lang.String", 0, 526 Common.TYPE_0_N, 0, Common.TYPE_COMMENT, 527 false, null, "COMMENTS", null, true, 528 Collections.EMPTY_LIST, false); 529 } 530 531 protected static class KnownValueEnumeration implements DataEnumRestriction { 532 private String knownValue; 533 534 protected KnownValueEnumeration(String value) { 535 knownValue = value; 536 } 537 538 public void genRestriction(Writer out, String type) throws IOException { 539 out.write(JavaUtil.instanceFrom(type, knownValue)); 540 } 541 } 542 543 void process() throws IOException { 545 Map generators = new LinkedHashMap(); prepareBeans(generators); 547 doGeneration(generators); 548 } 549 550 void prepareBeans(Map generators) throws IOException { 551 GraphNode root = parser.getRoot(); 552 GraphNode[] list = parser.getNodes(); 553 String rootDir; 554 BeanElement be; 555 MetaDD mdd = config.getMetaDD(); 556 557 if (root == null) 558 throw new IllegalStateException (Common.getMessage("DTDObjectGraphIsNull_msg")); 559 560 constNameMap = new LinkedHashMap(); 561 562 for (int i=0; i<list.length; i++) { 563 GraphNode node = list[i]; 564 572 be = new BeanElement(node); 573 be.initialize(node==root); 574 node.setObject(be); 575 } 576 577 if (config.getRootDir() == null) 578 rootDir = "."; else 580 rootDir = config.getRootDir().toString(); 581 packagePath = config.getPackagePath(); 582 583 rootElement = (BeanElement)root.getObject(); 584 585 if (packagePath == null) { packagePath = rootElement.getName().toLowerCase(); 588 } 589 590 if (rootDir.equals("")) genDir = packagePath; 592 else { 593 if (!rootDir.equals("/")) { if (packagePath == null || packagePath.equals("")) 595 genDir = rootDir; else 597 genDir = rootDir + "/" + packagePath; } else 599 genDir = "/" + packagePath; } 601 packageName = null; 602 if (packagePath != null) 603 packageName = packagePath.replace('/', '.'); 604 605 if (config.isDoGeneration() && 606 config.getOutputStreamProvider() instanceof GenBeans.DefaultOutputStreamProvider) { 607 File dir = new File(genDir); 608 609 if (dir.exists() && !dir.isDirectory()) { 610 throw new Schema2BeansRuntimeException(Common. 611 getMessage("CantCreateDirIsFile_msg", dir)); 612 } else { 613 if (!dir.exists()) { 614 if (dir.mkdirs()) { 615 if (!config.isQuiet()) 616 config.messageOut.println(Common.getMessage("MSG_CreatedDirectory", dir)); } 618 } 619 } 620 } 621 622 setSchemaType(list); 626 627 String commonInterface = config.getGenerateCommonInterface(); 628 if (commonInterface != null) { 629 illegalClassNames.put(commonInterface, "Common Bean Interface"); 630 if (packageName != null && !"".equals(packageName)) 631 commonInterface = packageName + "." + commonInterface; 632 } 633 boolean doGeneration = !config.isCheckUpToDate(); 634 for (int i=0; i<list.length; i++) { 638 MetaElement e = null; 639 StringBuffer str; 640 GraphNode graphNode = list[i]; 641 642 String suggestedJavaType = graphNode.getJavaType(); 643 645 be = (BeanElement)graphNode.getObject(); 646 if (be == null) 647 continue; 648 649 e = getMetaElement(mdd, be.getDTDName(), graphNode.getNamespace()); 651 if (e == null) { 652 e = new MetaElement(); 653 e.setBeanName(be.getName()); 654 e.setDtdName(be.getDTDName()); 655 e.setNamespace(graphNode.getNamespace()); 656 657 mdd.addMetaElement(e); 658 } 659 if (e.isCanBeEmpty()) { 660 be.setCanBeEmpty(true); 661 } 662 663 if (e.getBeanName() != null && !e.getBeanName().equals("")) { 668 be.setClassType(e.getBeanName()); 669 be.setName(e.getBeanName()); 670 } 671 if (e.getWrapperClass() != null) { 672 suggestedJavaType = e.getWrapperClass(); 673 graphNode.setCreated(false); 677 be.setTypeSetExternally(true); 678 } else if (suggestedJavaType != null) { 679 e.setWrapperClass(suggestedJavaType); 680 } else if (be != rootElement && Common.isScalar(be.type)) { 681 e.setWrapperClass(Common.wrapperClass(be.type)); 682 suggestedJavaType = e.getWrapperClass(); 683 } else if (be != rootElement && !Common.isBean(be.type)) { 684 e.setWrapperClass(be.typeToString()); 685 suggestedJavaType = e.getWrapperClass(); 686 } 687 if (suggestedJavaType != null) { 689 int proposedType = Common.wrapperToType(suggestedJavaType); 690 if (proposedType != Common.NONE) 691 be.type = proposedType; 692 be.setClassType(suggestedJavaType); 693 } 695 if (graphNode.getExtendedProperty("can-be-empty") != null) { 696 be.setCanBeEmpty(true); 697 } 698 if (be.isBean()) { 699 while (illegalClassNames.containsKey(be.getClassType())) { 701 String prefix; 702 if (graphNode.getNamespace() != null) { 703 prefix = Common.convertName(graphNode.getNamespace()); 704 } else { 705 prefix = UNIQUE_PREFIX; 706 } 707 be.setClassType(prefix+be.getClassType()); 708 be.setName(prefix+be.getName()); 709 e.setBeanName(prefix+e.getBeanName()); 710 if (config.isTraceGen()) 711 config.messageOut.println("Made class name change to "+be.getClassType()); 712 } 713 illegalClassNames.put(be.getClassType(), be); 715 716 if (graphNode.getExtension() != null) { 717 GraphNode extensionNode = graphNode.getExtension(); 718 724 if (extensionNode.isCreated()) { 725 BeanElement extensionBE = (BeanElement) extensionNode.getObject(); 726 String extendsName = extensionBE.getFullClassType(); 727 e.setExtends(extendsName); 728 addToBeanInterfaceExtends(e, extendsName+"Interface"); 729 } 730 } 731 732 if (config.isExtendBaseBean()) { 733 if (e.getExtends() == null) 734 e.setExtends("org.netbeans.modules.schema2beans.BaseBean"); 735 } 736 if (graphNode.getExtendedProperty("extends") != null && e.getExtends() == null) { 737 e.setExtends((String ) graphNode.getExtendedProperty("extends")); 738 } 739 if (graphNode.getExtendedProperty("implements") != null && e.getImplements() == null) { 740 e.setImplements((String ) graphNode.getExtendedProperty("implements")); 741 } 742 if (config.isGenerateInterfaces()) { 743 String interfaceName; 744 if (graphNode.getJavaType() == null) { 745 interfaceName = be.getName()+"Interface"; 746 if (packageName != null && !"".equals(packageName)) 747 interfaceName = packageName + "." + interfaceName; 748 } else { 749 interfaceName = graphNode.getJavaType() + "Interface"; 750 } 751 addToImplements(e, interfaceName); 752 } 753 if (commonInterface != null) { 754 if (graphNode.getJavaType() == null) { 755 addToImplements(e, commonInterface); 756 } 757 } 758 if (config.isExtendBaseBean()) { 759 addToImplements(e, "org.netbeans.modules.schema2beans.Bean"); 760 } 761 if (config.isCheckUpToDate()) { 762 String outputFileName = be.getOutputFileName(); 763 if (config.getOutputStreamProvider().isOlderThan(genDir, 764 outputFileName, 765 "java", 766 config.getNewestSourceTime())) { 767 doGeneration = true; 768 } 769 } 770 } 771 } 772 773 if (!doGeneration) { 774 config.messageOut.println(Common.getMessage("MSG_SkippingGenerationDueToTime")); 775 return; 776 } 777 778 Map usedTypes = new HashMap(); 782 for (int i = 0; i < list.length; i++) { 783 MetaElement e = null; 784 be = (BeanElement)list[i].getObject(); 785 if (be == null) 787 continue; 788 789 GraphNode graphNode = be.getGraphNode(); 790 if (be.isBean() || be == rootElement) { 791 if (config.isTraceGen()) 792 config.messageOut.println("Building properties for "+be); 793 be.isAbstract = graphNode.isAbstract(); 794 795 e = getMetaElement(mdd, be.getDTDName(), graphNode.getNamespace()); 796 Map usedNames = new HashMap(); 797 798 CodeGeneratorClass bc = codeGenFactory.newCodeGeneratorClass(be, config); 799 bc.setPackageName(packageName); 800 bc.setIndent(config.getIndent()); 801 bc.setRootBeanElement(rootElement); 802 bc.setDefaultNamespace(parser.getDefaultNamespace()); 803 bc.setInvalidPropertyNames(usedNames); 804 if (config.isProcessComments()) { 805 addCommentsProcessing(bc); 806 } 807 if (parser instanceof HasPrefixGuesser) 808 bc.setPrefixGuesser(((HasPrefixGuesser)parser).getPrefixGuesser()); 809 if (config.isAttributesAsProperties()) 810 addAttrProps(bc, be.node.getAttributes(), be.getName(), 811 usedNames, Common.TYPE_1, true); 812 if (be.isBean()) { 813 GraphLink l = graphNode.getGraphLink(); 814 if (l != null) { 815 int groupInstance = l.getGroupInstance(); 816 buildProperties(l, bc, 0, groupInstance, 817 false, 818 e, mdd, usedNames); 819 int nonAttributePropertyCount = 0; 820 List props = bc.getPropertyList(); 821 for (Iterator it = props.iterator(); it.hasNext(); ) { 822 AbstractCodeGeneratorClass.Property prop = 823 (AbstractCodeGeneratorClass.Property) it.next(); 824 if (prop.isAttribute()) 825 continue; 826 ++nonAttributePropertyCount; 827 } 828 be.setNonAttributePropertyCount(be.getNonAttributePropertyCount() + nonAttributePropertyCount); 830 } 831 } 832 833 if (graphNode.isCreated()) 838 generators.put(be, bc); 839 } 840 usedTypes.put(be.getClassType(), be); 841 } 842 848 rootElement.setUsedTypes(usedTypes); 849 850 processFinders(rootElement.node); 851 852 if (config.getWriteBeanGraphFile() != null) { 853 File beanGraphFile = config.getWriteBeanGraphFile(); 856 File parentDir = beanGraphFile.getParentFile(); 857 if (parentDir != null && !parentDir.exists()) { 858 if (parentDir.mkdirs()) { 859 if (!config.isQuiet()) 860 config.messageOut.println(Common.getMessage("MSG_CreatedDirectory", parentDir)); } 862 } 863 OutputStream out = new WriteIfDifferentOutputStream(beanGraphFile); 864 BeanGraph bg = generateBeanGraph(list); 865 bg.write(out); 866 close(out); 867 } 868 } 869 870 void doGeneration(Map generators) throws IOException { 871 BeanElement be; 872 MetaDD mdd = config.getMetaDD(); 873 if (config.isDoGeneration()) { 874 List generatedMethods = new LinkedList(); for (Iterator it = generators.keySet().iterator(); it.hasNext(); ) { 877 be = (BeanElement) it.next(); 878 CodeGeneratorClass bc = (CodeGeneratorClass) generators.get(be); 879 String outputFileName = be.getOutputFileName(); 880 881 MetaElement metaElement = getMetaElement(mdd, be.getDTDName(), be.node.getNamespace()); 882 if (metaElement.isSkipGeneration()) { 883 config.messageOut.println("Skipping generation of class " + be.beanName 884 + " (as specified in the mdd file)"); continue; 886 } 887 888 try { 893 OutputStream out; 894 out = config.getOutputStreamProvider().getStream(genDir, 895 outputFileName, "java"); bc.generate(out, mdd); 897 close(out); 898 out = null; Collection beansMethods = bc.getGeneratedMethods(); 900 generatedMethods.add(beansMethods); 901 902 if (config.isGenerateDelegator()) { 903 GraphNode graphNode = be.getGraphNode(); 904 MetaElement e = getMetaElement(mdd, be.getDTDName(), 905 graphNode.getNamespace()); 906 String delegatorClassName; 907 if (e != null && e.getDelegatorName() != null) 908 delegatorClassName = e.getDelegatorName(); 909 else { 910 delegatorClassName = outputFileName+"Delegator"; 911 if (e != null) 912 e.setDelegatorName(delegatorClassName); 913 } 914 String delegatorPackageName = packageName; 915 String dir = genDir; 916 if (config.getDelegateDir() != null) { 917 dir = config.getDelegateDir().getAbsolutePath(); 918 if (config.getDelegatePackage() == null) { 919 if (packagePath != null && !packagePath.equals("")) 920 dir = dir + "/" + packagePath; } else { 922 delegatorPackageName = config.getDelegatePackage(); 923 dir = dir + "/" + delegatorPackageName.replace('.', '/'); } 925 } 926 out = config.getOutputStreamProvider().getStream(dir, 927 delegatorClassName, "java"); bc.generateDelegator(out, mdd, delegatorClassName, delegatorPackageName); 929 close(out); 930 out = null; } 932 if (config.isGenerateInterfaces()) { 933 List beanInfoMethods = new ArrayList(beansMethods.size()); for (Iterator mit = beansMethods.iterator(); mit.hasNext(); ) { 935 JavaWriter.Method method = (JavaWriter.Method) mit.next(); 936 if (method.isStatic() || method.isConstructor() || 937 !method.isPublic()) 938 continue; 939 if (!method.isBeanInfo()) 940 continue; 941 beanInfoMethods.add(method); 943 } 944 String interfaceName = outputFileName+"Interface"; GraphNode graphNode = be.getGraphNode(); 946 MetaElement me = getMetaElement(mdd, be.getDTDName(), 947 graphNode.getNamespace()); 948 generateInterface(genDir, packageName, 949 interfaceName, 950 beanInfoMethods, 951 "This interface has all of the bean info accessor methods.", 952 me.getBeanInterfaceExtends()); 953 } 954 } catch(IOException ioe) { 955 config.messageOut.println("Failed to generate bean class: "+outputFileName); TraceLogger.error(ioe); 957 throw ioe; 958 } catch(IllegalStateException ise) { 959 config.messageOut.println("Failed to generate bean class "+outputFileName); TraceLogger.error(ise); 961 throw ise; 962 } 963 } 964 965 if (config.getGenerateCommonInterface() != null 966 && generatedMethods.size() > 0) { 967 Map commonGeneratedMethods = new HashMap(); Iterator it = generatedMethods.iterator(); 969 Collection methods = (Collection) it.next(); 970 for (Iterator mit = methods.iterator(); mit.hasNext(); ) { 972 JavaWriter.Method method = (JavaWriter.Method) mit.next(); 973 if (method.isStatic() || method.isConstructor() || 974 !method.isPublic() || method.isUnsupported()) 975 continue; 976 commonGeneratedMethods.put(method.getNameParameters(), method); 977 } 978 while (it.hasNext()) { 981 methods = (Collection) it.next(); 983 Map toKeep = new HashMap(); for (Iterator mit = methods.iterator(); mit.hasNext(); ) { 985 JavaWriter.Method method = (JavaWriter.Method) mit.next(); 986 String nameParameters = method.getNameParameters(); 987 if (commonGeneratedMethods.containsKey(nameParameters)) { 988 toKeep.put(nameParameters, commonGeneratedMethods.get(nameParameters)); 990 } 991 } 992 commonGeneratedMethods = toKeep; 993 } 994 List sortedMethodNames = new ArrayList(commonGeneratedMethods.keySet()); 996 Collections.sort(sortedMethodNames); 997 List sortedMethods = new ArrayList(sortedMethodNames.size()); 998 for (Iterator sortedMethodNamesIterator = sortedMethodNames.iterator(); 999 sortedMethodNamesIterator.hasNext(); ) { 1000 sortedMethods.add(commonGeneratedMethods.get(sortedMethodNamesIterator.next())); 1001 } 1002 generateInterface(genDir, packageName, 1003 config.getGenerateCommonInterface(), 1004 sortedMethods, 1005 "This interface is the intersection of all generated methods.", 1006 null); 1007 } 1008 if (config.getDumpBeanTree() != null) { 1009 Writer out = new FileWriter(config.getDumpBeanTree()); 1010 CodeGeneratorClass bc = (CodeGeneratorClass) generators.get(rootElement); 1011 bc.dumpBeanTree(out, "", config.getIndent()); 1012 close(out); 1013 } 1014 if (config.isGenerateTagsFile()) { 1015 String tagsClassName = "Tags"; 1016 while (illegalClassNames.containsKey(tagsClassName)) { 1017 tagsClassName = UNIQUE_PREFIX + tagsClassName; 1018 } 1019 OutputStream out = config.getOutputStreamProvider().getStream(genDir, 1020 tagsClassName, "java"); generateTagsFile(out, packageName, tagsClassName); 1022 close(out); 1023 } 1024 } 1025 if (config.getGenerateDotGraph() != null) { 1026 Writer out = new FileWriter(config.getGenerateDotGraph()); 1027 generateDotGraph(out, rootElement.getGraphNode()); 1028 close(out); 1029 } 1030 1031 if (!config.isQuiet()) 1032 config.messageOut.println(Common.getMessage("MSG_GenerationSummary", 1033 rootElement.getDTDName(), 1034 rootElement.getClassType())); 1035 } 1036 1037 protected void processFinders(GraphNode rootGraphNode) { 1038 for (int i = 0, size = config.sizeFinder(); i < size; ++i) { 1039 String finderExpr = config.getFinder(i); 1040 processFinder(rootGraphNode, finderExpr); 1041 } 1042 MetaDD mdd = config.getMetaDD(); 1043 for (Iterator it = mdd.fetchFinderList().iterator(); 1044 it.hasNext(); ) { 1045 String finderExpr = (String ) it.next(); 1046 processFinder(rootGraphNode, finderExpr); 1047 } 1048 } 1049 1050 protected void processFinder(GraphNode rootGraphNode, String finderExpr) { 1051 String rootName = rootGraphNode.getName(); 1052 String onExpr = null; 1057 String findExpr = null; 1058 boolean isListFindExpr = false; 1059 String byExpr = null; 1060 StringTokenizer st = new StringTokenizer(finderExpr); 1061 while (st.hasMoreTokens()) { 1062 String token = st.nextToken().intern(); 1063 if (token == "on") 1064 onExpr = st.nextToken(); 1065 else if (token == "find") { 1066 findExpr = st.nextToken(); 1067 isListFindExpr = false; 1068 } else if (token == "findall") { 1069 findExpr = st.nextToken(); 1070 isListFindExpr = true; 1071 } else if (token == "by") 1072 byExpr = st.nextToken(); 1073 else 1074 throw new IllegalArgumentException (Common.getMessage("MSG_BadTokenInFinder", token)); 1075 } 1076 if (onExpr == null) 1077 throw new IllegalArgumentException (Common.getMessage("MSG_MissingOnExpression", finderExpr)); 1078 1079 if (onExpr.startsWith("/"+rootName)) { 1080 onExpr = onExpr.substring(rootName.length()+1, onExpr.length()); 1081 if (onExpr.startsWith("/")) 1082 onExpr = onExpr.substring(1, onExpr.length()); 1083 } 1084 GraphNode onNode = null; 1086 if (onExpr.equals("")) { 1087 onNode = rootGraphNode; 1089 } else { 1090 GraphLink gl = null; 1091 for (Iterator it = rootGraphNode.getGraphLink().xPathIterator(onExpr); 1092 it.hasNext(); ) { 1093 gl = (GraphLink) it.next(); 1094 if (gl == null) 1095 break; 1096 } 1097 if (gl == null) 1098 throw new IllegalArgumentException (Common.getMessage("MSG_UnableToFindExpressionFromFinder", finderExpr)); 1099 onNode = gl.element; 1100 } 1101 onNode.addExtraDataIncludeAlias(new Finder(findExpr, byExpr, 1103 isListFindExpr)); 1104 } 1105 1106 protected void setSchemaType(GraphNode[] list) { 1107 Map nodeMap = new HashMap(list.length*4); 1108 for (int i = 0; i < list.length; ++i) { 1109 nodeMap.put(list[i].getNameWithNamespace(), list[i]); 1110 } 1111 GraphNode emptyGraphNode = null; 1112 for (Iterator it = config.readBeanGraphs(); it.hasNext(); ) { 1113 org.netbeans.modules.schema2beansdev.beangraph.BeanGraph bg = (org.netbeans.modules.schema2beansdev.beangraph.BeanGraph) it.next(); 1114 for (int i = 0; i < bg.sizeSchemaTypeMapping(); ++i) { 1115 org.netbeans.modules.schema2beansdev.beangraph.SchemaTypeMappingType stm = bg.getSchemaTypeMapping(i); 1116 String key; 1117 if (stm.getSchemaTypeNamespace() == null) 1118 key = stm.getSchemaTypeName(); 1119 else 1120 key = "{"+stm.getSchemaTypeNamespace()+"}"+stm.getSchemaTypeName(); 1121 if (nodeMap.containsKey(key)) { 1122 GraphNode node = (GraphNode) nodeMap.get(key); 1123 node.setJavaType(stm.getJavaType()); 1125 node.setCreated(false); 1126 if (stm.isCanBeEmpty()) { 1127 node.setExtendedProperty("can-be-empty", Boolean.TRUE); 1128 } 1129 } 1130 } 1131 } 1132 } 1133 1134 protected void generateInterface(String genDir, String packageName, 1135 String name, List methods, 1136 String comments, 1137 String extendsStatement) throws IOException { 1138 JavaWriter jw = new JavaWriter(); 1139 jw.bigComment(comments+"\n\n@"+Common.GENERATED_TAG); 1140 jw.cr(); 1141 if (!(packageName == null || "".equals(packageName))) { 1142 jw.writePackage(packageName); 1143 jw.cr(); 1144 } 1145 jw.writeAccess(jw.PUBLIC); 1146 jw.write(" interface "); 1147 jw.write(name); 1148 jw.write(" "); 1149 if (extendsStatement != null) 1150 jw.write("extends ", extendsStatement, " "); 1151 jw.begin(); 1152 for (Iterator methodsIterator = methods.iterator(); methodsIterator.hasNext(); ) { 1153 JavaWriter.Method method = (JavaWriter.Method) methodsIterator.next(); 1154 method.writeMethod(jw); 1155 jw.eol(); 1156 jw.cr(); 1157 } 1158 jw.end(); 1159 try { 1160 OutputStream out; 1161 out = config.getOutputStreamProvider().getStream(genDir, 1162 name, "java"); jw.writeTo(out); 1164 close(out); 1165 } catch(IOException ioe) { 1166 config.messageOut.println("Failed to generate interface: "+name); TraceLogger.error(ioe); 1168 throw ioe; 1169 } 1170 } 1171 1172 protected BeanGraph generateBeanGraph(GraphNode[] list) { 1173 BeanGraph bg = new BeanGraph(); 1174 for (int i = 0; i < list.length; ++i) { 1175 GraphNode node = list[i]; 1176 BeanElement be = (BeanElement)node.getObject(); 1177 SchemaTypeMappingType stm = 1178 new SchemaTypeMappingType(node.getName(), 1179 be.getFullClassType()); 1180 stm.setRoot(be.isRoot()); 1181 stm.setBean(be.isBean()); 1182 stm.setCanBeEmpty(be.getCanBeEmpty()); 1183 stm.setSchemaTypeNamespace(node.getNamespace()); 1184 bg.addSchemaTypeMapping(stm); 1185 } 1186 return bg; 1187 } 1188 1189 1194 protected void generateDotGraph(Writer out, GraphNode node) throws IOException { 1195 out.write("digraph \""+node.getName()+"\" {\n"); 1196 out.write("\t\""+node.getName()+"\" [shape=box]\n"); 1197 out.write("\t\""+node.getName()+"\" -> \""+node.getGraphLink()+"\";\n"); 1198 generateDotGraph(out, node.getGraphLink(), new HashMap()); 1199 out.write("}\n"); 1200 } 1201 1202 protected void generateDotGraph(Writer out, List children, Map doneLinks) throws IOException { 1203 for (Iterator it = children.iterator(); it.hasNext(); ) { 1204 GraphLink l = (GraphLink) it.next(); 1205 generateDotGraph(out, l, doneLinks); 1206 } 1207 } 1208 1209 protected void generateDotGraph(Writer out, GraphLink l, Map doneLinks) throws IOException { 1210 if (l == null) 1211 return; 1212 doneLinks.put(l, null); 1213 out.write("\t\""+l+"\" [label=\""+dotGraphLabel(l)+"\"];\n"); 1214 GraphNode node = l.element; 1215 if (node != null) { 1216 BeanBuilder.BeanElement be = 1217 (BeanBuilder.BeanElement)node.getObject(); 1218 if (be == null) 1219 return; 1220 1221 String type = be.getClassType(); 1222 out.write("\t\""+node+"\" [label=\""+dotGraphLabel(node)+"\", shape=box];\n"); 1223 out.write("\t\""+l+"\" -> \""+node+"\" [label=\"type of property\", color=darkgreen];\n"); 1224 if ("#PCDATA".equals(l.name) && "String".equals(type)) { 1225 return; 1226 } 1227 AttrProp[] attrs = node.getAttributes(); 1228 for (int i = 0; i < attrs.length; ++i) { 1229 String attrName = node.getName()+" attribute "+attrs[i].getName(); 1230 out.write("\t\""+attrName+"\" [label=\""+dotGraphLabel(attrs[i])+"\", shape=egg];\n"); 1231 out.write("\t\""+node+"\" -> \""+attrName+"\" [label=\"attribute\", color=magenta];\n"); 1232 } 1233 1234 GraphLink hasAttr = node.getGraphLink(); 1235 if (hasAttr != null) { 1236 if (node.getMarked() == false ) { 1237 if ((config.isTraceDot() || hasData(hasAttr)) && !doneLinks.containsKey(hasAttr)) { 1238 out.write("\t\""+node+"\" -> \""+hasAttr+"\" [label=\"has attr\", color=purple];\n"); 1239 node.setMarked(true); 1240 generateDotGraph(out, hasAttr, doneLinks); 1241 node.setMarked(false); 1242 } 1243 } 1244 } 1245 } 1246 1247 List children = l.getChildren(); 1248 for (Iterator childIt = children.iterator(); childIt.hasNext(); ) { 1249 GraphLink child = (GraphLink) childIt.next(); 1250 out.write("\t\""+l+"\" -> \""+child+"\" [label=child, color=blue];\n"); 1251 } 1252 generateDotGraph(out, children, doneLinks); 1253 1254 1264 } 1265 1266 private String dotGraphLabel(GraphLink l) { 1267 if (config.isTraceDot()) { 1268 String elementInstance = TreeBuilder.instanceToString(l.getElementInstance(), true); 1269 String groupInstance = TreeBuilder.instanceToString(l.getGroupInstance(), true); 1270 String result = "GraphLink@"+Integer.toHexString(l.hashCode()); 1271 if (l.name == null) 1272 result += " (grouping)"; 1273 else 1274 result += ":"+l.name; 1275 result += "\\n"; 1276 if (!"".equals(elementInstance)) 1277 result += " element: "+elementInstance; 1278 if (!"".equals(groupInstance)) 1279 result += " group: "+groupInstance; 1280 if (l.isSequenceAnd()) 1281 result += " ,"; 1282 if (l.isSequenceOr()) 1283 result += " |"; 1284 return result; 1285 } else if (l.name == null) 1286 return "GraphLink"; 1287 else 1288 return "property: "+l.name; 1289 } 1290 1291 private String dotGraphLabel(GraphNode node) { 1292 String result; 1293 if (config.isTraceDot()) 1294 result = "GraphNode@"+Integer.toHexString(node.hashCode())+":"+node.toString(); 1295 else 1296 result = node.getName(); 1297 if (node.getJavaType() != null) 1298 result += ":" + node.getJavaType(); 1299 return result; 1300 } 1301 1302 private String dotGraphLabel(AttrProp attr) { 1303 return attr.toString(); 1304 } 1305 1306 private boolean hasData(GraphLink l) { 1307 for (; l != null; l = l.getSibling()) { 1308 if (l.name != null) 1309 return true; 1310 if (l.element != null) { 1311 return true; 1312 } 1313 if (l.getFirstChild() != null) 1314 if (hasData(l.getFirstChild())) 1315 return true; 1316 } 1317 return false; 1318 } 1319 1320 protected void generateTagsFile(OutputStream out, 1321 String packageName, String className) throws IOException { 1322 JavaWriter jw = new JavaWriter(); 1323 jw.bigComment("This class has all element and attribute names as constants.\n\n@"+Common.GENERATED_TAG); 1324 jw.cr(); 1325 jw.writePackage(packageName); 1326 jw.cr(); 1327 1328 jw.writeClassDecl(className, null, null, jw.PUBLIC); 1329 jw.select(jw.DECL_SECTION); 1330 1331 for (Iterator it = constNameMap.keySet().iterator(); it.hasNext(); ) { 1332 String constName = (String ) it.next(); 1333 String dtdName = (String ) constNameMap.get(constName); 1334 jw.write("public final static String ", constName, " = "); 1335 jw.writeEol("\"", dtdName, "\""); 1336 } 1337 jw.cr(); 1338 1339 jw.select(jw.CONSTRUCTOR_SECTION); 1340 jw.comment("This class is not to be instantiated."); 1341 jw.beginConstructor(className, "", null, jw.PRIVATE); 1342 jw.end(); 1343 1344 jw.writeTo(out); 1345 } 1346 1347 1350 private MetaElement getMetaElement(MetaDD mdd, String dtdName) { 1351 return getMetaElement(mdd, dtdName, null); 1352 } 1353 1354 private MetaElement getMetaElement(MetaDD mdd, String dtdName, String namespace) { 1355 if (mdd == null) 1356 return null; 1357 int size = mdd.sizeMetaElement(); 1358 for (int i=0; i<size; i++) { 1359 MetaElement e = mdd.getMetaElement(i); 1360 if (e == null) 1361 continue; 1362 if (namespace != null && !namespace.equals(e.getNamespace())) 1363 continue; 1364 if (e.getDtdName().equals(dtdName)) 1365 return e; 1366 } 1367 return null; 1368 } 1369 1370 private void addToImplements(MetaElement e, String interfce) { 1371 String implList = e.getImplements(); 1372 if (implList == null) { 1373 e.setImplements(interfce); 1374 return; 1375 } 1376 implList = implList.trim(); 1380 int pos = implList.indexOf(','); 1381 while (pos >= 0) { 1382 String impl = implList.substring(0, pos); 1383 impl = impl.trim(); 1384 if (impl.equals(interfce)) 1385 return; 1386 implList = implList.substring(pos+1, implList.length()); 1387 implList = implList.trim(); 1388 pos = implList.indexOf(','); 1389 } 1390 if (implList.equals(interfce)) 1391 return; 1392 1393 e.setImplements(e.getImplements()+", "+interfce); 1397 } 1398 1399 private void addToBeanInterfaceExtends(MetaElement e, String interfce) { 1400 String implList = e.getBeanInterfaceExtends(); 1401 if (implList == null) { 1402 e.setBeanInterfaceExtends(interfce); 1403 return; 1404 } 1405 implList = implList.trim(); 1409 int pos = implList.indexOf(','); 1410 while (pos >= 0) { 1411 String impl = implList.substring(0, pos); 1412 impl = impl.trim(); 1413 if (impl.equals(interfce)) 1414 return; 1415 implList = implList.substring(pos+1, implList.length()); 1416 implList = implList.trim(); 1417 pos = implList.indexOf(','); 1418 } 1419 if (implList.equals(interfce)) 1420 return; 1421 1422 e.setBeanInterfaceExtends(e.getBeanInterfaceExtends()+", "+interfce); 1426 } 1427 1428 protected void close(OutputStream out) throws java.io.IOException { 1429 out.close(); 1430 if (!config.isQuiet() && config.isTraceGen() && 1431 out instanceof org.netbeans.modules.schema2beansdev.gen.WriteIfDifferentOutputStream) { 1432 org.netbeans.modules.schema2beansdev.gen.WriteIfDifferentOutputStream widos = (org.netbeans.modules.schema2beansdev.gen.WriteIfDifferentOutputStream) out; 1433 if (!widos.isChanged()) 1434 config.messageOut.println(Common.getMessage("MSG_DidNotChangeFile")); 1435 } 1436 } 1437 1438 protected void close(Writer out) throws java.io.IOException { 1439 out.close(); 1440 } 1441} 1442 | Popular Tags |