1 /* 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.xsom.impl.util; 27 28 import com.sun.xml.internal.xsom.XSAnnotation; 29 import com.sun.xml.internal.xsom.XSAttGroupDecl; 30 import com.sun.xml.internal.xsom.XSAttributeDecl; 31 import com.sun.xml.internal.xsom.XSAttributeUse; 32 import com.sun.xml.internal.xsom.XSComplexType; 33 import com.sun.xml.internal.xsom.XSContentType; 34 import com.sun.xml.internal.xsom.XSElementDecl; 35 import com.sun.xml.internal.xsom.XSFacet; 36 import com.sun.xml.internal.xsom.XSIdentityConstraint; 37 import com.sun.xml.internal.xsom.XSListSimpleType; 38 import com.sun.xml.internal.xsom.XSModelGroup; 39 import com.sun.xml.internal.xsom.XSModelGroupDecl; 40 import com.sun.xml.internal.xsom.XSNotation; 41 import com.sun.xml.internal.xsom.XSParticle; 42 import com.sun.xml.internal.xsom.XSRestrictionSimpleType; 43 import com.sun.xml.internal.xsom.XSSchema; 44 import com.sun.xml.internal.xsom.XSSchemaSet; 45 import com.sun.xml.internal.xsom.XSSimpleType; 46 import com.sun.xml.internal.xsom.XSType; 47 import com.sun.xml.internal.xsom.XSUnionSimpleType; 48 import com.sun.xml.internal.xsom.XSWildcard; 49 import com.sun.xml.internal.xsom.XSXPath; 50 import com.sun.xml.internal.xsom.impl.Const; 51 import com.sun.xml.internal.xsom.visitor.XSSimpleTypeVisitor; 52 import com.sun.xml.internal.xsom.visitor.XSTermVisitor; 53 import com.sun.xml.internal.xsom.visitor.XSVisitor; 54 import org.xml.sax.Locator; 55 56 import javax.swing.Box; 57 import javax.swing.Icon; 58 import javax.swing.JLabel; 59 import javax.swing.JPanel; 60 import javax.swing.JTree; 61 import javax.swing.tree.DefaultMutableTreeNode; 62 import javax.swing.tree.DefaultTreeModel; 63 import javax.swing.tree.TreeCellRenderer; 64 import java.awt.Color; 65 import java.awt.Component; 66 import java.awt.FlowLayout; 67 import java.awt.Font; 68 import java.awt.Graphics; 69 import java.math.BigInteger; 70 import java.text.MessageFormat; 71 import java.util.Iterator; 72 73 /** 74 * Generates approximated tree model for XML from a schema component. This is 75 * not intended to be a fully-fledged round-trippable tree model. 76 * 77 * <h2>Usage of this class</h2> 78 * 79 * <ol> <li>Create a new instance.</li> <li>Call {@link 80 * #visit(com.sun.xml.internal.xsom.XSSchemaSet)} function on your schema set.>/li> 81 * <li>Retrieve the model using {@link #getModel()}. </li></ol> 82 * 83 * Every node in the resulting tree is a {@link SchemaTreeTraverser.SchemaTreeNode}, 84 * and the model itself is {@link SchemaTreeTraverser.SchemaTreeModel}. You can 85 * use {@link SchemaTreeTraverser.SchemaTreeCellRenderer} as a cell renderer for 86 * your tree. 87 * 88 * @author Kirill Grouchnikov (kirillcool@yahoo.com) 89 */ 90 public class SchemaTreeTraverser implements XSVisitor, XSSimpleTypeVisitor { 91 /** 92 * The associated tree model. 93 */ 94 private SchemaTreeModel model; 95 96 /** 97 * The current node in the tree. 98 */ 99 private SchemaTreeNode currNode; 100 101 /** 102 * Tree model for schema hierarchy tree. 103 * 104 * @author Kirill Grouchnikov 105 */ 106 public static final class SchemaTreeModel extends DefaultTreeModel { 107 /** 108 * A simple constructor. Is made private to allow creating the root node 109 * first. 110 * 111 * @param root The root node. 112 */ 113 private SchemaTreeModel(SchemaRootNode root) { 114 super(root); 115 } 116 117 /** 118 * A factory method for creating a new empty tree. 119 * 120 * @return New empty tree model. 121 */ 122 public static SchemaTreeModel getInstance() { 123 SchemaRootNode root = new SchemaRootNode(); 124 return new SchemaTreeModel(root); 125 } 126 127 public void addSchemaNode(SchemaTreeNode node) { 128 ((SchemaRootNode) this.root).add(node); 129 } 130 } 131 132 /** 133 * The node of the schema hierarchy tree. 134 * 135 * @author Kirill Grouchnikov 136 */ 137 public static class SchemaTreeNode extends DefaultMutableTreeNode { 138 /** 139 * File name of the corresponding schema artifact. 140 */ 141 private String fileName; 142 143 /** 144 * Line number of the corresponding schema artifact. 145 */ 146 private int lineNumber; 147 148 /** 149 * The caption of the corresponding artifact. 150 */ 151 private String artifactName; 152 153 /** 154 * Simple constructor. 155 * 156 * @param artifactName Artifact name. 157 * @param locator Artifact locator. 158 */ 159 public SchemaTreeNode(String artifactName, Locator locator) { 160 this.artifactName = artifactName; 161 if (locator == null) { 162 this.fileName = null; 163 } 164 else { 165 String filename = locator.getSystemId(); 166 filename = filename.replaceAll("\u002520", " "); 167 // strip leading protocol 168 if (filename.startsWith("file:/")) { 169 filename = filename.substring(6); 170 } 171 172 this.fileName = filename; 173 this.lineNumber = locator.getLineNumber() - 1; 174 } 175 } 176 177 /** 178 * Returns the caption for <code>this</code> node. 179 * 180 * @return The caption for <code>this</code> node. 181 */ 182 public String getCaption() { 183 return this.artifactName; 184 } 185 186 /** 187 * @return Returns the file name of the corresponding schema artifact. 188 */ 189 public String getFileName() { 190 return fileName; 191 } 192 193 /** 194 * @param fileName The file name of the corresponding schema artifact to 195 * set. 196 */ 197 public void setFileName(String fileName) { 198 this.fileName = fileName; 199 } 200 201 /** 202 * @return Returns the line number of the corresponding schema 203 * artifact. 204 */ 205 public int getLineNumber() { 206 return lineNumber; 207 } 208 209 /** 210 * @param lineNumber The line number of the corresponding schema 211 * artifact to set. 212 */ 213 public void setLineNumber(int lineNumber) { 214 this.lineNumber = lineNumber; 215 } 216 } 217 218 /** 219 * The root node of the schema hierarchy tree. 220 * 221 * @author Kirill Grouchnikov 222 */ 223 public static class SchemaRootNode extends SchemaTreeNode { 224 /** 225 * A simple constructor. 226 */ 227 public SchemaRootNode() { 228 super("Schema set", null); 229 } 230 } 231 232 233 /** 234 * Sample cell renderer for the schema tree. 235 * 236 * @author Kirill Grouchnikov 237 */ 238 public static class SchemaTreeCellRenderer extends JPanel implements 239 TreeCellRenderer { 240 /** 241 * The icon label. 242 */ 243 protected final JLabel iconLabel; 244 245 /** 246 * The text label 247 */ 248 protected final JLabel nameLabel; 249 250 /** 251 * The selection indicator. 252 */ 253 private boolean isSelected; 254 255 /** 256 * Background color for selected cells (light brown). 257 */ 258 public final Color selectedBackground = new Color(255, 244, 232); 259 260 261 /** 262 * Foreground color for selected cells, both text and border (dark 263 * brown). 264 */ 265 public final Color selectedForeground = new Color(64, 32, 0); 266 267 /** 268 * Default font for the text label. 269 */ 270 public final Font nameFont = new Font("Arial", Font.BOLD, 12); 271 272 273 /** 274 * Simple constructor. 275 */ 276 public SchemaTreeCellRenderer() { 277 FlowLayout fl = new FlowLayout(FlowLayout.LEFT, 1, 1); 278 this.setLayout(fl); 279 this.iconLabel = new JLabel(); 280 this.iconLabel.setOpaque(false); 281 this.iconLabel.setBorder(null); 282 this.add(this.iconLabel); 283 284 // add some space 285 this.add(Box.createHorizontalStrut(5)); 286 287 this.nameLabel = new JLabel(); 288 this.nameLabel.setOpaque(false); 289 this.nameLabel.setBorder(null); 290 this.nameLabel.setFont(nameFont); 291 this.add(this.nameLabel); 292 293 this.isSelected = false; 294 295 this.setOpaque(false); 296 this.setBorder(null); 297 } 298 299 /* 300 * (non-Javadoc) 301 * 302 * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) 303 */ 304 public final void paintComponent(Graphics g) { 305 int width = this.getWidth(); 306 int height = this.getHeight(); 307 if (this.isSelected) { 308 g.setColor(selectedBackground); 309 g.fillRect(0, 0, width - 1, height - 1); 310 g.setColor(selectedForeground); 311 g.drawRect(0, 0, width - 1, height - 1); 312 } 313 super.paintComponent(g); 314 } 315 316 /** 317 * Sets values for the icon and text of <code>this</code> renderer. 318 * 319 * @param icon Icon to show. 320 * @param caption Text to show. 321 * @param selected Selection indicator. If <code>true</code>, the 322 * renderer will be shown with different background and 323 * border settings. 324 */ 325 protected final void setValues(Icon icon, String caption, 326 boolean selected) { 327 328 this.iconLabel.setIcon(icon); 329 this.nameLabel.setText(caption); 330 331 this.isSelected = selected; 332 if (selected) { 333 this.nameLabel.setForeground(selectedForeground); 334 } 335 else { 336 this.nameLabel.setForeground(Color.black); 337 } 338 } 339 340 /* (non-Javadoc) 341 * @see javax.swing.tree.TreeCellRenderer#getTreeCellRendererComponent(javax.swing.JTree, java.lang.Object, boolean, boolean, boolean, int, boolean) 342 */ 343 public final Component getTreeCellRendererComponent(JTree tree, Object value, 344 boolean selected, boolean expanded, boolean leaf, int row, 345 boolean hasFocus) { 346 if (value instanceof SchemaTreeNode) { 347 SchemaTreeNode stn = (SchemaTreeNode) value; 348 349 this.setValues(null, stn.getCaption(), selected); 350 return this; 351 } 352 throw new IllegalStateException("Unknown node"); 353 } 354 } 355 356 357 /** 358 * Simple constructor. 359 */ 360 public SchemaTreeTraverser() { 361 this.model = SchemaTreeModel.getInstance(); 362 this.currNode = (SchemaTreeNode) this.model.getRoot(); 363 } 364 365 /** 366 * Retrieves the tree model of <code>this</code> traverser. 367 * 368 * @return Tree model of <code>this</code> traverser. 369 */ 370 public SchemaTreeModel getModel() { 371 return model; 372 } 373 374 /** 375 * Visits the root schema set. 376 * 377 * @param s Root schema set. 378 */ 379 public void visit(XSSchemaSet s) { 380 for (XSSchema schema : s.getSchemas()) { 381 schema(schema); 382 } 383 } 384 385 /* (non-Javadoc) 386 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#schema(com.sun.xml.internal.xsom.XSSchema) 387 */ 388 public void schema(XSSchema s) { 389 // QUICK HACK: don't print the built-in components 390 if (s.getTargetNamespace().equals(Const.schemaNamespace)) { 391 return; 392 } 393 394 SchemaTreeNode newNode = new SchemaTreeNode("Schema " 395 + s.getLocator().getSystemId(), s.getLocator()); 396 this.currNode = newNode; 397 this.model.addSchemaNode(newNode); 398 399 for (XSAttGroupDecl groupDecl : s.getAttGroupDecls().values()) { 400 attGroupDecl(groupDecl); 401 } 402 403 for (XSAttributeDecl attrDecl : s.getAttributeDecls().values()) { 404 attributeDecl(attrDecl); 405 } 406 407 for (XSComplexType complexType : s.getComplexTypes().values()) { 408 complexType(complexType); 409 } 410 411 for (XSElementDecl elementDecl : s.getElementDecls().values()) { 412 elementDecl(elementDecl); 413 } 414 415 for (XSModelGroupDecl modelGroupDecl : s.getModelGroupDecls().values()) { 416 modelGroupDecl(modelGroupDecl); 417 } 418 419 for (XSSimpleType simpleType : s.getSimpleTypes().values()) { 420 simpleType(simpleType); 421 } 422 } 423 424 /* (non-Javadoc) 425 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#attGroupDecl(com.sun.xml.internal.xsom.XSAttGroupDecl) 426 */ 427 public void attGroupDecl(XSAttGroupDecl decl) { 428 SchemaTreeNode newNode = new SchemaTreeNode("Attribute group \"" 429 + decl.getName() + "\"", decl.getLocator()); 430 this.currNode.add(newNode); 431 this.currNode = newNode; 432 433 Iterator itr; 434 435 itr = decl.iterateAttGroups(); 436 while (itr.hasNext()) { 437 dumpRef((XSAttGroupDecl) itr.next()); 438 } 439 440 itr = decl.iterateDeclaredAttributeUses(); 441 while (itr.hasNext()) { 442 attributeUse((XSAttributeUse) itr.next()); 443 } 444 445 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 446 } 447 448 /** 449 * Creates node of attribute group decalration reference. 450 * 451 * @param decl Attribute group decalration reference. 452 */ 453 public void dumpRef(XSAttGroupDecl decl) { 454 SchemaTreeNode newNode = new SchemaTreeNode("Attribute group ref \"{" 455 + decl.getTargetNamespace() + "}" + decl.getName() + "\"", decl 456 .getLocator()); 457 this.currNode.add(newNode); 458 } 459 460 /* (non-Javadoc) 461 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#attributeUse(com.sun.xml.internal.xsom.XSAttributeUse) 462 */ 463 public void attributeUse(XSAttributeUse use) { 464 XSAttributeDecl decl = use.getDecl(); 465 466 String additionalAtts = ""; 467 468 if (use.isRequired()) { 469 additionalAtts += " use=\"required\""; 470 } 471 if (use.getFixedValue() != null 472 && use.getDecl().getFixedValue() == null) { 473 additionalAtts += " fixed=\"" + use.getFixedValue() + "\""; 474 } 475 if (use.getDefaultValue() != null 476 && use.getDecl().getDefaultValue() == null) { 477 additionalAtts += " default=\"" + use.getDefaultValue() + "\""; 478 } 479 480 if (decl.isLocal()) { 481 // this is anonymous attribute use 482 dump(decl, additionalAtts); 483 } 484 else { 485 // reference to a global one 486 String str = MessageFormat.format( 487 "Attribute ref \"'{'{0}'}'{1}{2}\"", new Object[]{ 488 decl.getTargetNamespace(), decl.getName(), 489 additionalAtts}); 490 SchemaTreeNode newNode = new SchemaTreeNode(str, decl.getLocator()); 491 this.currNode.add(newNode); 492 } 493 } 494 495 /* (non-Javadoc) 496 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#attributeDecl(com.sun.xml.internal.xsom.XSAttributeDecl) 497 */ 498 public void attributeDecl(XSAttributeDecl decl) { 499 dump(decl, ""); 500 } 501 502 /** 503 * Creates node for attribute declaration with additional attributes. 504 * 505 * @param decl Attribute declaration. 506 * @param additionalAtts Additional attributes. 507 */ 508 private void dump(XSAttributeDecl decl, String additionalAtts) { 509 XSSimpleType type = decl.getType(); 510 511 String str = MessageFormat.format("Attribute \"{0}\"{1}{2}{3}{4}", 512 new Object[]{ 513 decl.getName(), 514 additionalAtts, 515 type.isLocal() ? "" : MessageFormat.format( 516 " type=\"'{'{0}'}'{1}\"", new Object[]{ 517 type.getTargetNamespace(), 518 type.getName()}), 519 decl.getFixedValue() == null ? "" : " fixed=\"" 520 + decl.getFixedValue() + "\"", 521 decl.getDefaultValue() == null ? "" : " default=\"" 522 + decl.getDefaultValue() + "\""}); 523 524 SchemaTreeNode newNode = new SchemaTreeNode(str, decl.getLocator()); 525 this.currNode.add(newNode); 526 this.currNode = newNode; 527 528 if (type.isLocal()) { 529 simpleType(type); 530 } 531 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 532 } 533 534 /* (non-Javadoc) 535 * @see com.sun.xml.internal.xsom.visitor.XSContentTypeVisitor#simpleType(com.sun.xml.internal.xsom.XSSimpleType) 536 */ 537 public void simpleType(XSSimpleType type) { 538 539 String str = MessageFormat.format("Simple type {0}", 540 new Object[]{type.isLocal() ? "" : " name=\"" 541 + type.getName() + "\""}); 542 543 SchemaTreeNode newNode = new SchemaTreeNode(str, type.getLocator()); 544 this.currNode.add(newNode); 545 this.currNode = newNode; 546 547 type.visit((XSSimpleTypeVisitor) this); 548 549 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 550 } 551 552 /* (non-Javadoc) 553 * @see com.sun.xml.internal.xsom.visitor.XSSimpleTypeVisitor#listSimpleType(com.sun.xml.internal.xsom.XSListSimpleType) 554 */ 555 public void listSimpleType(XSListSimpleType type) { 556 XSSimpleType itemType = type.getItemType(); 557 558 if (itemType.isLocal()) { 559 SchemaTreeNode newNode = new SchemaTreeNode("List", type 560 .getLocator()); 561 this.currNode.add(newNode); 562 this.currNode = newNode; 563 simpleType(itemType); 564 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 565 } 566 else { 567 // global type 568 String str = MessageFormat.format("List itemType=\"'{'{0}'}'{1}\"", 569 new Object[]{itemType.getTargetNamespace(), 570 itemType.getName()}); 571 SchemaTreeNode newNode = new SchemaTreeNode(str, itemType 572 .getLocator()); 573 this.currNode.add(newNode); 574 } 575 } 576 577 /* (non-Javadoc) 578 * @see com.sun.xml.internal.xsom.visitor.XSSimpleTypeVisitor#unionSimpleType(com.sun.xml.internal.xsom.XSUnionSimpleType) 579 */ 580 public void unionSimpleType(XSUnionSimpleType type) { 581 final int len = type.getMemberSize(); 582 StringBuffer ref = new StringBuffer(); 583 584 for (int i = 0; i < len; i++) { 585 XSSimpleType member = type.getMember(i); 586 if (member.isGlobal()) { 587 ref.append(MessageFormat.format(" '{'{0}'}'{1}", 588 new Object[]{ 589 member.getTargetNamespace(), 590 member.getName()})); 591 } 592 } 593 594 String name = (ref.length() == 0) ? "Union" : ("Union memberTypes=\"" 595 + ref + "\""); 596 SchemaTreeNode newNode = new SchemaTreeNode(name, type.getLocator()); 597 this.currNode.add(newNode); 598 this.currNode = newNode; 599 600 for (int i = 0; i < len; i++) { 601 XSSimpleType member = type.getMember(i); 602 if (member.isLocal()) { 603 simpleType(member); 604 } 605 } 606 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 607 } 608 609 /* (non-Javadoc) 610 * @see com.sun.xml.internal.xsom.visitor.XSSimpleTypeVisitor#restrictionSimpleType(com.sun.xml.internal.xsom.XSRestrictionSimpleType) 611 */ 612 public void restrictionSimpleType(XSRestrictionSimpleType type) { 613 614 if (type.getBaseType() == null) { 615 // don't print anySimpleType 616 if (!type.getName().equals("anySimpleType")) { 617 throw new InternalError(); 618 } 619 if (!Const.schemaNamespace.equals(type.getTargetNamespace())) { 620 throw new InternalError(); 621 } 622 return; 623 } 624 625 XSSimpleType baseType = type.getSimpleBaseType(); 626 627 String str = MessageFormat.format("Restriction {0}", 628 new Object[]{baseType.isLocal() ? "" : " base=\"{" 629 + baseType.getTargetNamespace() + "}" 630 + baseType.getName() + "\""}); 631 632 SchemaTreeNode newNode = new SchemaTreeNode(str, baseType.getLocator()); 633 this.currNode.add(newNode); 634 this.currNode = newNode; 635 636 if (baseType.isLocal()) { 637 simpleType(baseType); 638 } 639 640 Iterator itr = type.iterateDeclaredFacets(); 641 while (itr.hasNext()) { 642 facet((XSFacet) itr.next()); 643 } 644 645 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 646 } 647 648 /* (non-Javadoc) 649 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#facet(com.sun.xml.internal.xsom.XSFacet) 650 */ 651 public void facet(XSFacet facet) { 652 SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat.format( 653 "{0} value=\"{1}\"", new Object[]{facet.getName(), 654 facet.getValue(), }), 655 facet.getLocator()); 656 this.currNode.add(newNode); 657 } 658 659 /* (non-Javadoc) 660 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#notation(com.sun.xml.internal.xsom.XSNotation) 661 */ 662 public void notation(XSNotation notation) { 663 SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat.format( 664 "Notation name='\"0}\" public =\"{1}\" system=\"{2}\"", 665 new Object[]{notation.getName(), notation.getPublicId(), 666 notation.getSystemId()}), notation.getLocator()); 667 this.currNode.add(newNode); 668 } 669 670 /* (non-Javadoc) 671 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#complexType(com.sun.xml.internal.xsom.XSComplexType) 672 */ 673 public void complexType(XSComplexType type) { 674 SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat.format( 675 "ComplexType {0}", new Object[]{type.isLocal() ? "" 676 : " name=\"" + type.getName() + "\""}), type 677 .getLocator()); 678 this.currNode.add(newNode); 679 this.currNode = newNode; 680 681 // TODO: wildcard 682 683 if (type.getContentType().asSimpleType() != null) { 684 // simple content 685 SchemaTreeNode newNode2 = new SchemaTreeNode("Simple content", type 686 .getContentType().getLocator()); 687 this.currNode.add(newNode2); 688 this.currNode = newNode2; 689 690 XSType baseType = type.getBaseType(); 691 692 if (type.getDerivationMethod() == XSType.RESTRICTION) { 693 // restriction 694 String str = MessageFormat.format( 695 "Restriction base=\"<{0}>{1}\"", new Object[]{ 696 baseType.getTargetNamespace(), 697 baseType.getName()}); 698 SchemaTreeNode newNode3 = new SchemaTreeNode(str, baseType 699 .getLocator()); 700 this.currNode.add(newNode3); 701 this.currNode = newNode3; 702 703 dumpComplexTypeAttribute(type); 704 705 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 706 } 707 else { 708 // extension 709 String str = MessageFormat.format( 710 "Extension base=\"<{0}>{1}\"", new Object[]{ 711 baseType.getTargetNamespace(), 712 baseType.getName()}); 713 SchemaTreeNode newNode3 = new SchemaTreeNode(str, baseType 714 .getLocator()); 715 this.currNode.add(newNode3); 716 this.currNode = newNode3; 717 718 // check if have redefine tag 719 if ((type.getTargetNamespace().compareTo( 720 baseType.getTargetNamespace()) == 721 0) 722 && (type.getName().compareTo(baseType.getName()) == 0)) { 723 SchemaTreeNode newNodeRedefine = new SchemaTreeNode( 724 "redefine", type 725 .getLocator()); 726 this.currNode.add(newNodeRedefine); 727 this.currNode = newNodeRedefine; 728 baseType.visit(this); 729 this.currNode = 730 (SchemaTreeNode) newNodeRedefine.getParent(); 731 } 732 733 dumpComplexTypeAttribute(type); 734 735 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 736 } 737 738 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 739 } 740 else { 741 // complex content 742 SchemaTreeNode newNode2 = new SchemaTreeNode("Complex content", 743 type.getContentType().getLocator()); 744 this.currNode.add(newNode2); 745 this.currNode = newNode2; 746 747 XSComplexType baseType = type.getBaseType().asComplexType(); 748 749 if (type.getDerivationMethod() == XSType.RESTRICTION) { 750 // restriction 751 String str = MessageFormat.format( 752 "Restriction base=\"<{0}>{1}\"", new Object[]{ 753 baseType.getTargetNamespace(), 754 baseType.getName()}); 755 SchemaTreeNode newNode3 = new SchemaTreeNode(str, 756 baseType.getLocator()); 757 this.currNode.add(newNode3); 758 this.currNode = newNode3; 759 760 type.getContentType().visit(this); 761 dumpComplexTypeAttribute(type); 762 763 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 764 } 765 else { 766 // extension 767 String str = MessageFormat.format( 768 "Extension base=\"'{'{0}'}'{1}\"", new Object[]{ 769 baseType.getTargetNamespace(), 770 baseType.getName()}); 771 SchemaTreeNode newNode3 = new SchemaTreeNode(str, 772 baseType.getLocator()); 773 this.currNode.add(newNode3); 774 this.currNode = newNode3; 775 776 // check if have redefine tag 777 if ((type.getTargetNamespace().compareTo( 778 baseType.getTargetNamespace()) == 779 0) 780 && (type.getName().compareTo(baseType.getName()) == 0)) { 781 SchemaTreeNode newNodeRedefine = new SchemaTreeNode( 782 "redefine", type 783 .getLocator()); 784 this.currNode.add(newNodeRedefine); 785 this.currNode = newNodeRedefine; 786 baseType.visit(this); 787 this.currNode = 788 (SchemaTreeNode) newNodeRedefine.getParent(); 789 } 790 791 type.getExplicitContent().visit(this); 792 dumpComplexTypeAttribute(type); 793 794 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 795 } 796 797 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 798 } 799 800 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 801 } 802 803 /** 804 * Creates node for complex type. 805 * 806 * @param type Complex type. 807 */ 808 private void dumpComplexTypeAttribute(XSComplexType type) { 809 Iterator itr; 810 811 itr = type.iterateAttGroups(); 812 while (itr.hasNext()) { 813 dumpRef((XSAttGroupDecl) itr.next()); 814 } 815 816 itr = type.iterateDeclaredAttributeUses(); 817 while (itr.hasNext()) { 818 attributeUse((XSAttributeUse) itr.next()); 819 } 820 } 821 822 /* (non-Javadoc) 823 * @see com.sun.xml.internal.xsom.visitor.XSTermVisitor#elementDecl(com.sun.xml.internal.xsom.XSElementDecl) 824 */ 825 public void elementDecl(XSElementDecl decl) { 826 elementDecl(decl, ""); 827 } 828 829 /** 830 * Creates node for element declaration with additional attributes. 831 * 832 * @param decl Element declaration. 833 * @param extraAtts Additional attributes. 834 */ 835 private void elementDecl(XSElementDecl decl, String extraAtts) { 836 XSType type = decl.getType(); 837 838 // TODO: various other attributes 839 840 String str = MessageFormat.format("Element name=\"{0}\"{1}{2}", 841 new Object[]{ 842 decl.getName(), 843 type.isLocal() ? "" : " type=\"{" 844 + type.getTargetNamespace() + "}" 845 + type.getName() + "\"", extraAtts}); 846 847 SchemaTreeNode newNode = new SchemaTreeNode(str, decl.getLocator()); 848 this.currNode.add(newNode); 849 this.currNode = newNode; 850 851 if (type.isLocal()) { 852 if (type.isLocal()) { 853 type.visit(this); 854 } 855 } 856 857 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 858 } 859 860 /* (non-Javadoc) 861 * @see com.sun.xml.internal.xsom.visitor.XSTermVisitor#modelGroupDecl(com.sun.xml.internal.xsom.XSModelGroupDecl) 862 */ 863 public void modelGroupDecl(XSModelGroupDecl decl) { 864 SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat.format( 865 "Group name=\"{0}\"", new Object[]{decl.getName()}), 866 decl.getLocator()); 867 this.currNode.add(newNode); 868 this.currNode = newNode; 869 870 modelGroup(decl.getModelGroup()); 871 872 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 873 } 874 875 /* (non-Javadoc) 876 * @see com.sun.xml.internal.xsom.visitor.XSTermVisitor#modelGroup(com.sun.xml.internal.xsom.XSModelGroup) 877 */ 878 public void modelGroup(XSModelGroup group) { 879 modelGroup(group, ""); 880 } 881 882 /** 883 * Creates node for model group with additional attributes. 884 * 885 * @param group Model group. 886 * @param extraAtts Additional attributes. 887 */ 888 private void modelGroup(XSModelGroup group, String extraAtts) { 889 SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat.format( 890 "{0}{1}", new Object[]{group.getCompositor(), extraAtts}), 891 group.getLocator()); 892 this.currNode.add(newNode); 893 this.currNode = newNode; 894 895 final int len = group.getSize(); 896 for (int i = 0; i < len; i++) { 897 particle(group.getChild(i)); 898 } 899 900 this.currNode = (SchemaTreeNode) this.currNode.getParent(); 901 } 902 903 /* (non-Javadoc) 904 * @see com.sun.xml.internal.xsom.visitor.XSContentTypeVisitor#particle(com.sun.xml.internal.xsom.XSParticle) 905 */ 906 public void particle(XSParticle part) { 907 BigInteger i; 908 909 StringBuffer buf = new StringBuffer(); 910 911 i = part.getMaxOccurs(); 912 if (i.equals(BigInteger.valueOf(XSParticle.UNBOUNDED))) { 913 buf.append(" maxOccurs=\"unbounded\""); 914 } 915 else { 916 if (!i.equals(BigInteger.ONE)) { 917 buf.append(" maxOccurs=\"" + i + "\""); 918 } 919 } 920 921 i = part.getMinOccurs(); 922 if (!i.equals(BigInteger.ONE)) { 923 buf.append(" minOccurs=\"" + i + "\""); 924 } 925 926 final String extraAtts = buf.toString(); 927 928 part.getTerm().visit(new XSTermVisitor() { 929 public void elementDecl(XSElementDecl decl) { 930 if (decl.isLocal()) { 931 SchemaTreeTraverser.this.elementDecl(decl, extraAtts); 932 } 933 else { 934 // reference 935 SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat 936 .format("Element ref=\"'{'{0}'}'{1}\"{2}", 937 new Object[]{decl.getTargetNamespace(), 938 decl.getName(), extraAtts}), 939 decl.getLocator()); 940 currNode.add(newNode); 941 } 942 } 943 944 public void modelGroupDecl(XSModelGroupDecl decl) { 945 // reference 946 SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat 947 .format("Group ref=\"'{'{0}'}'{1}\"{2}", new Object[]{ 948 decl.getTargetNamespace(), decl.getName(), 949 extraAtts}), decl.getLocator()); 950 currNode.add(newNode); 951 } 952 953 public void modelGroup(XSModelGroup group) { 954 SchemaTreeTraverser.this.modelGroup(group, extraAtts); 955 } 956 957 public void wildcard(XSWildcard wc) { 958 SchemaTreeTraverser.this.wildcard(wc, extraAtts); 959 } 960 }); 961 } 962 963 /* (non-Javadoc) 964 * @see com.sun.xml.internal.xsom.visitor.XSTermVisitor#wildcard(com.sun.xml.internal.xsom.XSWildcard) 965 */ 966 public void wildcard(XSWildcard wc) { 967 wildcard(wc, ""); 968 } 969 970 /** 971 * Creates node for wild card with additional attributes. 972 * 973 * @param wc Wild card. 974 * @param extraAtts Additional attributes. 975 */ 976 private void wildcard(XSWildcard wc, String extraAtts) { 977 // TODO 978 SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat.format( 979 "Any ", new Object[]{extraAtts}), wc.getLocator()); 980 currNode.add(newNode); 981 } 982 983 /* (non-Javadoc) 984 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#annotation(com.sun.xml.internal.xsom.XSAnnotation) 985 */ 986 public void annotation(XSAnnotation ann) { 987 // TODO: it would be nice even if we just put <xs:documentation> 988 } 989 990 /* (non-Javadoc) 991 * @see com.sun.xml.internal.xsom.visitor.XSContentTypeVisitor#empty(com.sun.xml.internal.xsom.XSContentType) 992 */ 993 public void empty(XSContentType t) { 994 } 995 996 /* (non-Javadoc) 997 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#identityConstraint(com.sun.xml.internal.xsom.XSIdentityConstraint) 998 */ 999 public void identityConstraint(XSIdentityConstraint ic) { 1000 } 1001 1002 /* (non-Javadoc) 1003 * @see com.sun.xml.internal.xsom.visitor.XSVisitor#xpath(com.sun.xml.internal.xsom.XSXPath) 1004 */ 1005 public void xpath(XSXPath xp) { 1006 } 1007 }