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 27 32 38 public class TreeBuilder implements DocDefHandler, TreeParser, HasPrefixGuesser { 39 GraphNode rootNode; 41 String docRoot; 42 GenBeans.Config config; 43 44 private Stack curParentGroupStack = new Stack(); 46 private GraphLink curParentGroup; 47 48 private Stack curElementTypeStack = new Stack(); 50 private int curElementType; 51 52 private Stack curAttrStack = new Stack(); 54 private AttrProp curAttr; 55 56 private PrefixGuesser prefixGuesser; 57 58 void pushLevel() { 59 curParentGroupStack.push(curParentGroup); 60 curElementTypeStack.push(new Integer (curElementType)); 61 curAttrStack.push(curAttr); 62 } 63 64 void popLevel() { 65 curParentGroup = (GraphLink) curParentGroupStack.pop(); 66 curElementType = ((Integer ) curElementTypeStack.pop()).intValue(); 67 curAttr = (AttrProp) curAttrStack.pop(); 68 } 69 70 Map nameHash; 78 private String defaultNamespace = null; 79 80 81 TreeBuilder(GenBeans.Config config) { 82 this.nameHash = new HashMap(); 83 this.curAttr = null; 84 this.config = config; 85 } 86 87 94 public void startDocument(String root) { 95 if (DDLogFlags.debug) { 96 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 97 DDLogFlags.DBG_DTD, 1, 98 DDLogFlags.STARTDOC, root); 99 100 config.messageOut.println("Building the schema object graph."); 101 } 102 this.docRoot = root; 103 } 104 105 112 public void endDocument() { 113 if (DDLogFlags.debug) { 114 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 115 DDLogFlags.DBG_DTD, 1, 116 DDLogFlags.ENDDOC); 117 118 config.messageOut.println("schema Object graph built."); 119 } 120 121 for (Iterator it = nameHash.values().iterator(); it.hasNext(); ) { 123 GraphNode node = (GraphNode)it.next(); 124 GraphLink l = node.getGraphLink(); 125 if (l == null || l.name != null || l.getSibling() != null 126 || l.isSequenceOr() || l.getGroupInstance() != Common.TYPE_1) 127 continue; 128 GraphLink firstChild = l.getFirstChild(); 129 if (firstChild != null && firstChild.getSibling() != null) 130 continue; 131 if (DDLogFlags.debug) 132 config.messageOut.println("Removing starter group: "+l); 133 node.setGraphLink(firstChild); 134 } 135 136 try { 141 findRootNode(); 142 } catch (Schema2BeansException e) { 143 throw new Schema2BeansRuntimeException(e); 144 } 145 146 if (DDLogFlags.debug) { 147 config.messageOut.println(this.dump()); 148 } 149 } 150 151 165 private static final int CREATE = 1; 166 private static final int GET = 2; 167 private static final int REFERENCE = 3; 168 private GraphNode getGraphNode(String uniqueName, String name, int mode) throws Schema2BeansException { 169 uniqueName = name; 171 172 GraphNode node = (GraphNode)this.nameHash.get(uniqueName); 174 175 if (node != null) { 176 if (false && node.isCreated() && (mode == CREATE)) { 178 throw new Schema2BeansException(Common.getMessage("DuplicateElement_msg", uniqueName)); 179 } 180 } 181 else { 182 node = new GraphNode(name, uniqueName); 190 node.setGraphLink(new GraphLink(null)); 191 this.nameHash.put(uniqueName, node); 192 } 194 195 if (mode == CREATE) 203 node.setCreated(true); 204 else 205 if (mode == REFERENCE) 206 node.incrRefCount(); 207 208 return node; 209 } 210 211 212 220 public void startElement(String uniqueName, 221 String typeName, int type) { 222 223 if (DDLogFlags.debug) { 224 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 225 DDLogFlags.DBG_DTD, 1, 226 DDLogFlags.STARTELT, 227 uniqueName + " - " + typeName + " - " + typeToString(type)); 228 } 229 pushLevel(); 230 231 this.curElementType = type; 233 234 try { 238 if (type == Common.ELEMENT) { 239 GraphNode node = getGraphNode(uniqueName, typeName, 241 CREATE); 242 curParentGroup = node.getGraphLink(); 243 } else if (type == Common.ATTLIST) { 244 GraphNode node = getGraphNode(uniqueName, typeName, 246 GET); 247 curAttr = new AttrProp(typeName); 248 node.addAttribute(curAttr); 249 } 250 } catch (Schema2BeansException e) { 251 throw new Schema2BeansRuntimeException(e); 252 } 253 } 254 255 public boolean doesElementExist(String typeName) { 256 return nameHash.containsKey(typeName); 257 } 258 259 262 public void endElement() { 263 if (DDLogFlags.debug) { 264 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 265 DDLogFlags.DBG_DTD, 1, 266 DDLogFlags.ENDELT); 267 } 268 269 if (curElementType == Common.ATTLIST) { 270 curAttr.validate(); 271 } else if (curElementType == Common.ELEMENT) { 272 } 274 275 curElementType = Common.NONE; 276 popLevel(); 277 } 278 279 282 public void character(char c) { 283 if (this.curElementType == Common.ELEMENT) { 285 if (c == '|') 286 curParentGroup.setSequence(Common.SEQUENCE_OR); 287 } 288 else 289 if (this.curElementType == Common.ATTLIST) { 290 if (c == '|') { 291 this.curAttr.checkEnum(); 292 } 293 } 294 } 295 296 314 public void element(String uniqueName, String typeName, 315 String attrName, String attrNamespace, 316 int instance, boolean externalType, 317 String defaultValue) { 318 if (DDLogFlags.debug) { 319 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 320 DDLogFlags.DBG_DTD, 1, 321 DDLogFlags.ELEMENT, 322 attrName + " : " + typeName + instanceToString(instance, false)); 323 } 324 try { 325 if (curElementType == Common.NONE && !externalType) { 326 if (DDLogFlags.debug) 327 System.out.println("Top element def for "+attrName); 328 GraphNode attrNode = getGraphNode(uniqueName, attrName, CREATE); 329 GraphNode node = getGraphNode(uniqueName, typeName, REFERENCE); 330 attrNode.setAlias(node); 331 } else if (curElementType == Common.ELEMENT) { 332 GraphNode node = getGraphNode(uniqueName, typeName, REFERENCE); 334 335 GraphLink link = new GraphLink(attrName, attrNamespace); 336 link.setDefaultValue(defaultValue); 337 curParentGroup.addChild(link); 339 link.element = node; 340 link.setElementInstance(instance); 341 342 if (externalType) 343 node.setJavaType(typeName); 344 } else if (curElementType == Common.ATTLIST) { 346 if (this.curAttr.isComplete()) 349 throw new DocDefParser.MissingEndOfEltException(curAttr.getPropertyName()); 350 351 if (defaultValue != null) 352 this.curAttr.setDefaultValue(defaultValue); 353 this.curAttr.addValue(attrName, attrNamespace); 354 if (externalType) 355 curAttr.setJavaType(typeName); 356 } 357 } catch (Schema2BeansException e) { 358 throw new Schema2BeansRuntimeException(e); 359 } 360 } 361 public void element(String uniqueName, String typeName, int instance) { 362 element(uniqueName, typeName, typeName, null, instance, false, null); 363 } 364 365 public void addExtraDataNode(String uniqueName, String typeName, Object data) throws Schema2BeansException { 366 GraphNode node = getGraphNode(uniqueName, typeName, GET); 368 node.addExtraData(data); 369 } 370 371 public void addExtraDataCurLink(Object data) { 372 if (curElementType == Common.ATTLIST) { 374 if (curAttr != null) 376 curAttr.addExtraData(data); 377 } else { 378 if (curParentGroup != null && curParentGroup.getLastChild() != null) { 380 curParentGroup.getLastChild().extraData.add(data); 381 } 382 } 383 } 384 385 public void addExtraDataNode(String uniqueName, String typeName, Object [] data) throws Schema2BeansException { 386 GraphNode node = getGraphNode(uniqueName, typeName, GET); 388 if (data != null) 389 for (int i=0; i < data.length; i++) 390 node.addExtraData(data[i]); 391 } 392 393 public void setUnion(String uniqueName, String typeName, boolean value) throws Schema2BeansException { 394 GraphNode node = getGraphNode(uniqueName, typeName, GET); 395 node.setUnion(value); 396 } 397 398 public void addExtraDataCurLink(Object [] data) { 399 if (curElementType == Common.ATTLIST) { 401 if (curAttr != null && data != null) 403 for (int i=0; i < data.length; i++) 404 curAttr.addExtraData(data[i]); 405 } else { 406 if (curParentGroup != null && curParentGroup.getLastChild() != null) { 408 if (data != null) 409 for (int i=0; i < data.length; i++) 410 curParentGroup.getLastChild().extraData.add(data[i]); 411 } 412 } 413 } 414 415 public void nillable(boolean value) { 416 if (curParentGroup != null && curParentGroup.getLastChild() != null) 418 curParentGroup.getLastChild().setNillable(value); 419 423 } 424 425 public void setAbstract(String uniqueName, String name, boolean value) { 426 if (this.curElementType == Common.ATTLIST) { 428 } else { 429 GraphNode node; 431 try { 432 node = getGraphNode(uniqueName, name, GET); 433 } catch (Schema2BeansException e) { 434 throw new Schema2BeansRuntimeException(e); 435 } 436 node.setAbstract(value); 437 } 438 } 439 440 443 public void setExtendedProperty(String uniqueName, String typeName, String propertyName, 444 Object value) throws Schema2BeansException { 445 GraphNode node = getGraphNode(uniqueName, typeName, GET); 446 node.setExtendedProperty(propertyName, value); 447 } 448 449 455 public void javaType(String uniqueName, String name, String javaType) { 456 if (this.curElementType == Common.ATTLIST) { 458 curAttr.setJavaType(javaType); 459 } else { 460 GraphNode node; 462 try { 463 node = getGraphNode(uniqueName, name, GET); 464 } catch (Schema2BeansException e) { 465 throw new Schema2BeansRuntimeException(e); 466 } 467 node.setJavaType(javaType); 468 node.setCreated(false); 469 } 470 } 471 472 public void setExtension(String uniqueName, String typeName, String extendsName) throws Schema2BeansException { 473 if (curElementType == Common.ATTLIST) { 474 } else { 475 GraphNode node; 476 GraphNode extendsNode; 477 try { 478 node = getGraphNode(uniqueName, typeName, GET); 479 extendsNode = getGraphNode(null, extendsName, REFERENCE); 480 } catch (Schema2BeansException e) { 481 throw new Schema2BeansRuntimeException(e); 482 } 483 node.setExtension(extendsNode); 484 } 485 } 486 487 498 public void startGroupElements() { 499 if (DDLogFlags.debug) { 500 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 501 DDLogFlags.DBG_DTD, 5, 502 DDLogFlags.STARTGRP); 503 } 504 505 if (this.curElementType == Common.ELEMENT) { 507 GraphLink link = new GraphLink(null); 508 curParentGroup.addChild(link); 509 curParentGroup = link; 510 } 512 else { 513 if (this.curElementType == Common.ATTLIST) 514 this.curAttr.setEnum(true); 515 } 516 } 517 518 525 public void endGroupElements(int instance) { 526 if (DDLogFlags.debug) { 527 TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD, 528 DDLogFlags.DBG_DTD, 5, 529 DDLogFlags.ENDGRP, 530 instanceToString(instance, false)); 531 } 532 533 if (curElementType == Common.ELEMENT) { 534 curParentGroup.setGroupInstance(instance); 535 curParentGroup = curParentGroup.getParent(); 537 } 538 else 539 if (this.curElementType == Common.ATTLIST) 540 this.curAttr.setEnum(false); 541 } 542 543 public void setDefaultNamespace(String ns) { 544 defaultNamespace = ns; 545 } 546 547 public String getDefaultNamespace() { 548 return defaultNamespace; 549 } 550 551 private void findRootNode() throws Schema2BeansException { 552 Iterator it = this.nameHash.keySet().iterator(); 563 GraphNode node; 564 int count = 0; 565 List list = new ArrayList(); 566 567 while (it.hasNext()) { 568 String uniqueName = (String ) it.next(); 569 node = (GraphNode) nameHash.get(uniqueName); 570 if (DDLogFlags.debug) { 571 System.out.println("refCount="+node.getRefCount()+" created="+node.isCreated()+" javaType="+node.getJavaType()+" uniqueName="+uniqueName+" node="+node); 572 } 573 if (node.isCreated() && node.getRefCount() == 0) { 574 count++; 575 list.add(node); 576 } 577 } 578 579 if (count > 1) { 580 int highestPoints = 0; 582 GraphNode highestNode = null; 583 int tieCount = 0; 584 for (Iterator highit = list.iterator(); highit.hasNext(); ) { 585 int points = 0; 586 node = (GraphNode) highit.next(); 587 if (node.getAlias() != null) { 588 ++points; 589 if (node.getAlias().getRefCount() == 1) 590 ++points; 591 } 592 if (defaultNamespace == null ? node.getNamespace() == null : defaultNamespace.equals(node.getNamespace())) 594 ++points; 595 GraphLink link = node.getGraphLink(); 596 if (link != null && !"#PCDATA".equals(link.name)) { 598 ++points; 599 GraphLink firstChild = link.getFirstChild(); 600 if (firstChild != null) { 601 ++points; 602 if (firstChild.getSibling() != null) 603 ++points; 604 if (firstChild.getFirstChild() != null) 605 ++points; 606 } 607 GraphLink sibling = link.getSibling(); 608 if (sibling != null) { 609 ++points; 610 if (sibling.getSibling() != null) 611 ++points; 612 if (sibling.getFirstChild() != null) 613 ++points; 614 } 615 } 616 if (points > highestPoints) { 618 highestPoints = points; 619 highestNode = node; 620 tieCount = 0; 621 } else if (points == highestPoints) { 622 ++tieCount; 623 } 624 } 625 if (tieCount == 0 && highestNode != null) { 626 count = 1; 627 list.clear(); 628 list.add(highestNode); 629 } 630 } 631 632 if (count == 1) { 633 this.rootNode = (GraphNode)list.get(0); 634 if (this.docRoot != null) { 636 if (!this.docRoot.equals(this.rootNode.getName())) { 637 String str = "Mismatch between doc root name specified (" + 638 this.docRoot + 639 ") and the root name found in the DTD graph (" + 640 this.rootNode.getName() +")"; 641 throw new IllegalStateException (str); 642 } 643 } 644 } else if (count == 0) { 645 this.rootNode = null; 646 if (docRoot != null) { 647 it = this.nameHash.values().iterator(); 648 while (it.hasNext()) { 649 node = (GraphNode)it.next(); 650 if (docRoot.equals(node.getName())) { 651 rootNode = node; 652 break; 653 } 654 } 655 } 656 if (rootNode == null) 657 throw new IllegalStateException (Common.getMessage("NoRootElementCandidate")); 658 } else { 659 config.messageOut.println("The following elements could be the root " 661 + "of the document:"); 662 for (int i=0; i<list.size(); i++) { 663 GraphNode n = (GraphNode)list.get(i); 664 config.messageOut.print( (i+1) + ". " + n); 665 if ((this.docRoot != null) 666 && (this.docRoot.equals(n.getName()))) { 667 668 this.rootNode = n; 669 config.messageOut.println(" <= parameter value"); 670 } 671 else 672 config.messageOut.println(""); 673 } 674 675 if (this.rootNode == null) { 676 678 String errStr = "Could not find the root of the document. " 679 + "Use the -d option to specify the doc root"; 680 681 if (config.isAuto()) { 682 throw new IllegalStateException (errStr); 683 } 684 685 try { 686 BufferedReader rd = 687 new BufferedReader(new InputStreamReader(System.in)); 688 689 config.messageOut.print("Enter the element that should be used " 690 + "as the root: "); 691 String str = rd.readLine(); 692 693 int i = Integer.parseInt(str)-1; 694 695 if (i<0 || i>=list.size()) { 696 throw new IllegalStateException (errStr); 697 } 698 else { 699 this.rootNode = (GraphNode)list.get(i); 700 } 701 } 702 catch(Exception e) { 703 TraceLogger.error(e); 704 throw new Schema2BeansNestedException(errStr, e); 705 } 706 } 707 } 708 709 if (DDLogFlags.debug) 710 config.messageOut.println("Using " + this.rootNode.getName() 711 + " as the root of the document."); 712 } 713 714 static String instanceToString(int instance, boolean bean) { 716 switch (instance) { 717 case Common.TYPE_0_1: 718 if (bean) 719 return "[0,1]"; 720 else 721 return "?"; 722 case Common.TYPE_0_N: 723 if (bean) 724 return "[0,n]"; 725 else 726 return "*"; 727 case Common.TYPE_1_N: 728 if (bean) 729 return "[1,n]"; 730 else 731 return "+"; 732 } 733 return ""; 734 } 735 736 static String typeToString(int type) { 738 switch (type) { 739 case Common.COMMENT: 740 return "comment"; 741 case Common.ELEMENT: 742 return "element"; 743 case Common.ATTLIST: 744 return "attlist"; 745 } 746 return "unknown value: " + type; 747 } 748 749 757 public GraphNode[] getNodes() { 758 int maxSize = nameHash.values().size(); 763 List ret = new ArrayList(maxSize); 764 Map insertedNodes = new HashMap(); 765 Map ignoredNodes = new HashMap(); 766 getNodesInsertNode(rootNode, ret, insertedNodes, ignoredNodes); 767 getNodes(rootNode.getGraphLink(), ret, insertedNodes, ignoredNodes); 768 if (!config.isRemoveUnreferencedNodes()) { 769 for (Iterator it = nameHash.values().iterator(); 770 it.hasNext(); ) { 771 GraphNode node = (GraphNode) it.next(); 772 if (!insertedNodes.containsKey(node) && !ignoredNodes.containsKey(node)) { 773 config.messageOut.println(Common.getMessage("MSG_FoundUnreferencedNode", node.toString())); 774 ret.add(node); 775 } 776 } 777 } 778 782 return (GraphNode[]) ret.toArray(new GraphNode[ret.size()]); 783 } 784 785 private void getNodes(GraphLink l, List ret, 786 Map insertedNodes, Map ignoredNodes) { 787 Stack linkStack = new Stack(); 788 linkStack.push(l); 789 while (!linkStack.isEmpty()) { 790 l = (GraphLink) linkStack.pop(); 791 for (; l != null; l = l.getSibling()) { 792 if (l.element != null) { 793 if (!insertedNodes.containsKey(l.element)) { 794 getNodesInsertNode(l.element, ret, insertedNodes, ignoredNodes); 795 linkStack.push(l.element.getGraphLink()); 796 } 797 } 798 linkStack.push(l.getFirstChild()); 799 } 800 } 801 } 802 803 private void getNodesInsertNode(GraphNode node, List ret, 804 Map insertedNodes, Map ignoredNodes) { 805 if (insertedNodes.containsKey(node)) { 806 return; 808 } 809 ret.add(node); 810 insertedNodes.put(node, null); 811 if (node.getExtension() != null) 812 getNodesInsertNode(node.getExtension(), ret, insertedNodes, ignoredNodes); 813 GraphNode alias = node.getAlias(); 814 if (alias != null && !insertedNodes.containsKey(alias)) { 815 if (alias.getRefCount() <= 1) { 816 ignoredNodes.put(alias, null); 818 } else { 819 ret.add(alias); 820 insertedNodes.put(alias, null); 821 } 822 } 823 return; 824 } 825 826 public GraphNode getNode(String uniqueName) { 827 return (GraphNode)this.nameHash.get(uniqueName); 828 } 829 830 public GraphNode getRoot() { 831 return this.rootNode; 832 } 833 834 private static final String INDENT = " "; 835 836 static void dumpAttributes(GraphNode elt, StringBuffer str, String indent) { 837 AttrProp[] attrList = elt.getAttributes(); 838 839 for (int i=0; i<attrList.length; i++) 840 str.append(indent + INDENT+"[attr: " + attrList[i] + "]\n"); 841 } 842 843 static void dumpTree(List children, StringBuffer str, String indent, boolean tree) { 844 for (Iterator it = children.iterator(); it.hasNext(); ) { 845 GraphLink l = (GraphLink) it.next(); 846 dumpTree(l, str, indent, tree); 847 } 848 } 849 850 static void dumpTree(GraphLink l, StringBuffer str, String indent, boolean tree) { 851 if (l == null) 852 return; 853 if (l.element != null) { 855 str.append(indent); 857 str.append(l.name + " : "+l.element.toString()); 858 str.append(instanceToString(l.getElementInstance(), false) + 859 "\n"); 860 861 dumpAttributes(l.element, str, indent); 862 863 if (tree && (l.element.getMarked() == false)) { 864 l.element.setMarked(true); 865 dumpTree(l.element.getGraphLink(), str, indent + INDENT + 866 instanceToString(l.getGroupInstance(), false) + 867 (l.isSequenceOr()?"| ":" "), tree); 868 l.element.setMarked(false); 869 } 870 } 871 872 if (l.isSequenceOr() || (l.getGroupInstance() != Common.TYPE_1)) { 873 str.append(indent+instanceToString(l.getGroupInstance(), false)+ 874 (l.isSequenceOr()?"|\n":"\n")); 875 } 876 877 dumpTree(l.getChildren(), str, indent + INDENT, tree ); 878 } 879 880 public String dump() { 882 StringBuffer str = new StringBuffer (); 883 GraphNode n; 884 885 str.append("Tree:\n"); 886 str.append(this.rootNode.toString()); 887 str.append("\n"); 888 889 dumpAttributes(rootNode, str, INDENT); 890 dumpTree(this.rootNode.getGraphLink(), str, INDENT, true); 891 892 return str.toString(); 893 } 894 895 public void setPrefixGuesser(PrefixGuesser guesser) { 896 prefixGuesser = guesser; 897 } 898 899 public PrefixGuesser getPrefixGuesser() { 900 return prefixGuesser; 901 } 902 } 903 904 | Popular Tags |