0001: package com.sun.xml.xsom.impl.util;
0002:
0003: import com.sun.xml.xsom.XSAnnotation;
0004: import com.sun.xml.xsom.XSAttGroupDecl;
0005: import com.sun.xml.xsom.XSAttributeDecl;
0006: import com.sun.xml.xsom.XSAttributeUse;
0007: import com.sun.xml.xsom.XSComplexType;
0008: import com.sun.xml.xsom.XSContentType;
0009: import com.sun.xml.xsom.XSElementDecl;
0010: import com.sun.xml.xsom.XSFacet;
0011: import com.sun.xml.xsom.XSIdentityConstraint;
0012: import com.sun.xml.xsom.XSListSimpleType;
0013: import com.sun.xml.xsom.XSModelGroup;
0014: import com.sun.xml.xsom.XSModelGroupDecl;
0015: import com.sun.xml.xsom.XSNotation;
0016: import com.sun.xml.xsom.XSParticle;
0017: import com.sun.xml.xsom.XSRestrictionSimpleType;
0018: import com.sun.xml.xsom.XSSchema;
0019: import com.sun.xml.xsom.XSSchemaSet;
0020: import com.sun.xml.xsom.XSSimpleType;
0021: import com.sun.xml.xsom.XSType;
0022: import com.sun.xml.xsom.XSUnionSimpleType;
0023: import com.sun.xml.xsom.XSWildcard;
0024: import com.sun.xml.xsom.XSXPath;
0025: import com.sun.xml.xsom.impl.Const;
0026: import com.sun.xml.xsom.visitor.XSSimpleTypeVisitor;
0027: import com.sun.xml.xsom.visitor.XSTermVisitor;
0028: import com.sun.xml.xsom.visitor.XSVisitor;
0029: import org.xml.sax.Locator;
0030:
0031: import javax.swing.Box;
0032: import javax.swing.Icon;
0033: import javax.swing.JLabel;
0034: import javax.swing.JPanel;
0035: import javax.swing.JTree;
0036: import javax.swing.tree.DefaultMutableTreeNode;
0037: import javax.swing.tree.DefaultTreeModel;
0038: import javax.swing.tree.TreeCellRenderer;
0039: import java.awt.Color;
0040: import java.awt.Component;
0041: import java.awt.FlowLayout;
0042: import java.awt.Font;
0043: import java.awt.Graphics;
0044: import java.text.MessageFormat;
0045: import java.util.Iterator;
0046:
0047: /**
0048: * Generates approximated tree model for XML from a schema component. This is
0049: * not intended to be a fully-fledged round-trippable tree model.
0050: *
0051: * <h2>Usage of this class</h2>
0052: *
0053: * <ol> <li>Create a new instance.</li> <li>Call {@link
0054: * #visit(com.sun.xml.xsom.XSSchemaSet)} function on your schema set.>/li>
0055: * <li>Retrieve the model using {@link #getModel()}. </li></ol>
0056: *
0057: * Every node in the resulting tree is a {@link SchemaTreeTraverser.SchemaTreeNode},
0058: * and the model itself is {@link SchemaTreeTraverser.SchemaTreeModel}. You can
0059: * use {@link SchemaTreeTraverser.SchemaTreeCellRenderer} as a cell renderer for
0060: * your tree.
0061: *
0062: * @author Kirill Grouchnikov (kirillcool@yahoo.com)
0063: */
0064: public class SchemaTreeTraverser implements XSVisitor,
0065: XSSimpleTypeVisitor {
0066: /**
0067: * The associated tree model.
0068: */
0069: private SchemaTreeModel model;
0070:
0071: /**
0072: * The current node in the tree.
0073: */
0074: private SchemaTreeNode currNode;
0075:
0076: /**
0077: * Tree model for schema hierarchy tree.
0078: *
0079: * @author Kirill Grouchnikov
0080: */
0081: public static final class SchemaTreeModel extends DefaultTreeModel {
0082: /**
0083: * A simple constructor. Is made private to allow creating the root node
0084: * first.
0085: *
0086: * @param root The root node.
0087: */
0088: private SchemaTreeModel(SchemaRootNode root) {
0089: super (root);
0090: }
0091:
0092: /**
0093: * A factory method for creating a new empty tree.
0094: *
0095: * @return New empty tree model.
0096: */
0097: public static SchemaTreeModel getInstance() {
0098: SchemaRootNode root = new SchemaRootNode();
0099: return new SchemaTreeModel(root);
0100: }
0101:
0102: public void addSchemaNode(SchemaTreeNode node) {
0103: ((SchemaRootNode) this .root).add(node);
0104: }
0105: }
0106:
0107: /**
0108: * The node of the schema hierarchy tree.
0109: *
0110: * @author Kirill Grouchnikov
0111: */
0112: public static class SchemaTreeNode extends DefaultMutableTreeNode {
0113: /**
0114: * File name of the corresponding schema artifact.
0115: */
0116: private String fileName;
0117:
0118: /**
0119: * Line number of the corresponding schema artifact.
0120: */
0121: private int lineNumber;
0122:
0123: /**
0124: * The caption of the corresponding artifact.
0125: */
0126: private String artifactName;
0127:
0128: /**
0129: * Simple constructor.
0130: *
0131: * @param artifactName Artifact name.
0132: * @param locator Artifact locator.
0133: */
0134: public SchemaTreeNode(String artifactName, Locator locator) {
0135: this .artifactName = artifactName;
0136: if (locator == null) {
0137: this .fileName = null;
0138: } else {
0139: String filename = locator.getSystemId();
0140: filename = filename.replaceAll("\u002520", " ");
0141: // strip leading protocol
0142: if (filename.startsWith("file:/")) {
0143: filename = filename.substring(6);
0144: }
0145:
0146: this .fileName = filename;
0147: this .lineNumber = locator.getLineNumber() - 1;
0148: }
0149: }
0150:
0151: /**
0152: * Returns the caption for <code>this</code> node.
0153: *
0154: * @return The caption for <code>this</code> node.
0155: */
0156: public String getCaption() {
0157: return this .artifactName;
0158: }
0159:
0160: /**
0161: * @return Returns the file name of the corresponding schema artifact.
0162: */
0163: public String getFileName() {
0164: return fileName;
0165: }
0166:
0167: /**
0168: * @param fileName The file name of the corresponding schema artifact to
0169: * set.
0170: */
0171: public void setFileName(String fileName) {
0172: this .fileName = fileName;
0173: }
0174:
0175: /**
0176: * @return Returns the line number of the corresponding schema
0177: * artifact.
0178: */
0179: public int getLineNumber() {
0180: return lineNumber;
0181: }
0182:
0183: /**
0184: * @param lineNumber The line number of the corresponding schema
0185: * artifact to set.
0186: */
0187: public void setLineNumber(int lineNumber) {
0188: this .lineNumber = lineNumber;
0189: }
0190: }
0191:
0192: /**
0193: * The root node of the schema hierarchy tree.
0194: *
0195: * @author Kirill Grouchnikov
0196: */
0197: public static class SchemaRootNode extends SchemaTreeNode {
0198: /**
0199: * A simple constructor.
0200: */
0201: public SchemaRootNode() {
0202: super ("Schema set", null);
0203: }
0204: }
0205:
0206: /**
0207: * Sample cell renderer for the schema tree.
0208: *
0209: * @author Kirill Grouchnikov
0210: */
0211: public static class SchemaTreeCellRenderer extends JPanel implements
0212: TreeCellRenderer {
0213: /**
0214: * The icon label.
0215: */
0216: protected final JLabel iconLabel;
0217:
0218: /**
0219: * The text label
0220: */
0221: protected final JLabel nameLabel;
0222:
0223: /**
0224: * The selection indicator.
0225: */
0226: private boolean isSelected;
0227:
0228: /**
0229: * Background color for selected cells (light brown).
0230: */
0231: public final Color selectedBackground = new Color(255, 244, 232);
0232:
0233: /**
0234: * Foreground color for selected cells, both text and border (dark
0235: * brown).
0236: */
0237: public final Color selectedForeground = new Color(64, 32, 0);
0238:
0239: /**
0240: * Default font for the text label.
0241: */
0242: public final Font nameFont = new Font("Arial", Font.BOLD, 12);
0243:
0244: /**
0245: * Simple constructor.
0246: */
0247: public SchemaTreeCellRenderer() {
0248: FlowLayout fl = new FlowLayout(FlowLayout.LEFT, 1, 1);
0249: this .setLayout(fl);
0250: this .iconLabel = new JLabel();
0251: this .iconLabel.setOpaque(false);
0252: this .iconLabel.setBorder(null);
0253: this .add(this .iconLabel);
0254:
0255: // add some space
0256: this .add(Box.createHorizontalStrut(5));
0257:
0258: this .nameLabel = new JLabel();
0259: this .nameLabel.setOpaque(false);
0260: this .nameLabel.setBorder(null);
0261: this .nameLabel.setFont(nameFont);
0262: this .add(this .nameLabel);
0263:
0264: this .isSelected = false;
0265:
0266: this .setOpaque(false);
0267: this .setBorder(null);
0268: }
0269:
0270: /*
0271: * (non-Javadoc)
0272: *
0273: * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
0274: */
0275: public final void paintComponent(Graphics g) {
0276: int width = this .getWidth();
0277: int height = this .getHeight();
0278: if (this .isSelected) {
0279: g.setColor(selectedBackground);
0280: g.fillRect(0, 0, width - 1, height - 1);
0281: g.setColor(selectedForeground);
0282: g.drawRect(0, 0, width - 1, height - 1);
0283: }
0284: super .paintComponent(g);
0285: }
0286:
0287: /**
0288: * Sets values for the icon and text of <code>this</code> renderer.
0289: *
0290: * @param icon Icon to show.
0291: * @param caption Text to show.
0292: * @param selected Selection indicator. If <code>true</code>, the
0293: * renderer will be shown with different background and
0294: * border settings.
0295: */
0296: protected final void setValues(Icon icon, String caption,
0297: boolean selected) {
0298:
0299: this .iconLabel.setIcon(icon);
0300: this .nameLabel.setText(caption);
0301:
0302: this .isSelected = selected;
0303: if (selected) {
0304: this .nameLabel.setForeground(selectedForeground);
0305: } else {
0306: this .nameLabel.setForeground(Color.black);
0307: }
0308: }
0309:
0310: /* (non-Javadoc)
0311: * @see javax.swing.tree.TreeCellRenderer#getTreeCellRendererComponent(javax.swing.JTree, java.lang.Object, boolean, boolean, boolean, int, boolean)
0312: */
0313: public final Component getTreeCellRendererComponent(JTree tree,
0314: Object value, boolean selected, boolean expanded,
0315: boolean leaf, int row, boolean hasFocus) {
0316: if (value instanceof SchemaTreeNode) {
0317: SchemaTreeNode stn = (SchemaTreeNode) value;
0318:
0319: this .setValues(null, stn.getCaption(), selected);
0320: return this ;
0321: }
0322: throw new IllegalStateException("Unknown node");
0323: }
0324: }
0325:
0326: /**
0327: * Simple constructor.
0328: */
0329: public SchemaTreeTraverser() {
0330: this .model = SchemaTreeModel.getInstance();
0331: this .currNode = (SchemaTreeNode) this .model.getRoot();
0332: }
0333:
0334: /**
0335: * Retrieves the tree model of <code>this</code> traverser.
0336: *
0337: * @return Tree model of <code>this</code> traverser.
0338: */
0339: public SchemaTreeModel getModel() {
0340: return model;
0341: }
0342:
0343: /**
0344: * Visits the root schema set.
0345: *
0346: * @param s Root schema set.
0347: */
0348: public void visit(XSSchemaSet s) {
0349: for (XSSchema schema : s.getSchemas()) {
0350: schema(schema);
0351: }
0352: }
0353:
0354: /* (non-Javadoc)
0355: * @see com.sun.xml.xsom.visitor.XSVisitor#schema(com.sun.xml.xsom.XSSchema)
0356: */
0357: public void schema(XSSchema s) {
0358: // QUICK HACK: don't print the built-in components
0359: if (s.getTargetNamespace().equals(Const.schemaNamespace)) {
0360: return;
0361: }
0362:
0363: SchemaTreeNode newNode = new SchemaTreeNode("Schema "
0364: + s.getLocator().getSystemId(), s.getLocator());
0365: this .currNode = newNode;
0366: this .model.addSchemaNode(newNode);
0367:
0368: for (XSAttGroupDecl groupDecl : s.getAttGroupDecls().values()) {
0369: attGroupDecl(groupDecl);
0370: }
0371:
0372: for (XSAttributeDecl attrDecl : s.getAttributeDecls().values()) {
0373: attributeDecl(attrDecl);
0374: }
0375:
0376: for (XSComplexType complexType : s.getComplexTypes().values()) {
0377: complexType(complexType);
0378: }
0379:
0380: for (XSElementDecl elementDecl : s.getElementDecls().values()) {
0381: elementDecl(elementDecl);
0382: }
0383:
0384: for (XSModelGroupDecl modelGroupDecl : s.getModelGroupDecls()
0385: .values()) {
0386: modelGroupDecl(modelGroupDecl);
0387: }
0388:
0389: for (XSSimpleType simpleType : s.getSimpleTypes().values()) {
0390: simpleType(simpleType);
0391: }
0392: }
0393:
0394: /* (non-Javadoc)
0395: * @see com.sun.xml.xsom.visitor.XSVisitor#attGroupDecl(com.sun.xml.xsom.XSAttGroupDecl)
0396: */
0397: public void attGroupDecl(XSAttGroupDecl decl) {
0398: SchemaTreeNode newNode = new SchemaTreeNode(
0399: "Attribute group \"" + decl.getName() + "\"", decl
0400: .getLocator());
0401: this .currNode.add(newNode);
0402: this .currNode = newNode;
0403:
0404: Iterator itr;
0405:
0406: itr = decl.iterateAttGroups();
0407: while (itr.hasNext()) {
0408: dumpRef((XSAttGroupDecl) itr.next());
0409: }
0410:
0411: itr = decl.iterateDeclaredAttributeUses();
0412: while (itr.hasNext()) {
0413: attributeUse((XSAttributeUse) itr.next());
0414: }
0415:
0416: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0417: }
0418:
0419: /**
0420: * Creates node of attribute group decalration reference.
0421: *
0422: * @param decl Attribute group decalration reference.
0423: */
0424: public void dumpRef(XSAttGroupDecl decl) {
0425: SchemaTreeNode newNode = new SchemaTreeNode(
0426: "Attribute group ref \"{" + decl.getTargetNamespace()
0427: + "}" + decl.getName() + "\"", decl
0428: .getLocator());
0429: this .currNode.add(newNode);
0430: }
0431:
0432: /* (non-Javadoc)
0433: * @see com.sun.xml.xsom.visitor.XSVisitor#attributeUse(com.sun.xml.xsom.XSAttributeUse)
0434: */
0435: public void attributeUse(XSAttributeUse use) {
0436: XSAttributeDecl decl = use.getDecl();
0437:
0438: String additionalAtts = "";
0439:
0440: if (use.isRequired()) {
0441: additionalAtts += " use=\"required\"";
0442: }
0443: if (use.getFixedValue() != null
0444: && use.getDecl().getFixedValue() == null) {
0445: additionalAtts += " fixed=\"" + use.getFixedValue() + "\"";
0446: }
0447: if (use.getDefaultValue() != null
0448: && use.getDecl().getDefaultValue() == null) {
0449: additionalAtts += " default=\"" + use.getDefaultValue()
0450: + "\"";
0451: }
0452:
0453: if (decl.isLocal()) {
0454: // this is anonymous attribute use
0455: dump(decl, additionalAtts);
0456: } else {
0457: // reference to a global one
0458: String str = MessageFormat.format(
0459: "Attribute ref \"'{'{0}'}'{1}{2}\"", new Object[] {
0460: decl.getTargetNamespace(), decl.getName(),
0461: additionalAtts });
0462: SchemaTreeNode newNode = new SchemaTreeNode(str, decl
0463: .getLocator());
0464: this .currNode.add(newNode);
0465: }
0466: }
0467:
0468: /* (non-Javadoc)
0469: * @see com.sun.xml.xsom.visitor.XSVisitor#attributeDecl(com.sun.xml.xsom.XSAttributeDecl)
0470: */
0471: public void attributeDecl(XSAttributeDecl decl) {
0472: dump(decl, "");
0473: }
0474:
0475: /**
0476: * Creates node for attribute declaration with additional attributes.
0477: *
0478: * @param decl Attribute declaration.
0479: * @param additionalAtts Additional attributes.
0480: */
0481: private void dump(XSAttributeDecl decl, String additionalAtts) {
0482: XSSimpleType type = decl.getType();
0483:
0484: String str = MessageFormat
0485: .format(
0486: "Attribute \"{0}\"{1}{2}{3}{4}",
0487: new Object[] {
0488: decl.getName(),
0489: additionalAtts,
0490: type.isLocal() ? ""
0491: : MessageFormat
0492: .format(
0493: " type=\"'{'{0}'}'{1}\"",
0494: new Object[] {
0495: type
0496: .getTargetNamespace(),
0497: type
0498: .getName() }),
0499: decl.getFixedValue() == null ? ""
0500: : " fixed=\""
0501: + decl.getFixedValue()
0502: + "\"",
0503: decl.getDefaultValue() == null ? ""
0504: : " default=\""
0505: + decl
0506: .getDefaultValue()
0507: + "\"" });
0508:
0509: SchemaTreeNode newNode = new SchemaTreeNode(str, decl
0510: .getLocator());
0511: this .currNode.add(newNode);
0512: this .currNode = newNode;
0513:
0514: if (type.isLocal()) {
0515: simpleType(type);
0516: }
0517: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0518: }
0519:
0520: /* (non-Javadoc)
0521: * @see com.sun.xml.xsom.visitor.XSContentTypeVisitor#simpleType(com.sun.xml.xsom.XSSimpleType)
0522: */
0523: public void simpleType(XSSimpleType type) {
0524:
0525: String str = MessageFormat.format("Simple type {0}",
0526: new Object[] { type.isLocal() ? "" : " name=\""
0527: + type.getName() + "\"" });
0528:
0529: SchemaTreeNode newNode = new SchemaTreeNode(str, type
0530: .getLocator());
0531: this .currNode.add(newNode);
0532: this .currNode = newNode;
0533:
0534: type.visit((XSSimpleTypeVisitor) this );
0535:
0536: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0537: }
0538:
0539: /* (non-Javadoc)
0540: * @see com.sun.xml.xsom.visitor.XSSimpleTypeVisitor#listSimpleType(com.sun.xml.xsom.XSListSimpleType)
0541: */
0542: public void listSimpleType(XSListSimpleType type) {
0543: XSSimpleType itemType = type.getItemType();
0544:
0545: if (itemType.isLocal()) {
0546: SchemaTreeNode newNode = new SchemaTreeNode("List", type
0547: .getLocator());
0548: this .currNode.add(newNode);
0549: this .currNode = newNode;
0550: simpleType(itemType);
0551: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0552: } else {
0553: // global type
0554: String str = MessageFormat.format(
0555: "List itemType=\"'{'{0}'}'{1}\"", new Object[] {
0556: itemType.getTargetNamespace(),
0557: itemType.getName() });
0558: SchemaTreeNode newNode = new SchemaTreeNode(str, itemType
0559: .getLocator());
0560: this .currNode.add(newNode);
0561: }
0562: }
0563:
0564: /* (non-Javadoc)
0565: * @see com.sun.xml.xsom.visitor.XSSimpleTypeVisitor#unionSimpleType(com.sun.xml.xsom.XSUnionSimpleType)
0566: */
0567: public void unionSimpleType(XSUnionSimpleType type) {
0568: final int len = type.getMemberSize();
0569: StringBuffer ref = new StringBuffer();
0570:
0571: for (int i = 0; i < len; i++) {
0572: XSSimpleType member = type.getMember(i);
0573: if (member.isGlobal()) {
0574: ref.append(MessageFormat.format(" '{'{0}'}'{1}",
0575: new Object[] { member.getTargetNamespace(),
0576: member.getName() }));
0577: }
0578: }
0579:
0580: String name = (ref.length() == 0) ? "Union"
0581: : ("Union memberTypes=\"" + ref + "\"");
0582: SchemaTreeNode newNode = new SchemaTreeNode(name, type
0583: .getLocator());
0584: this .currNode.add(newNode);
0585: this .currNode = newNode;
0586:
0587: for (int i = 0; i < len; i++) {
0588: XSSimpleType member = type.getMember(i);
0589: if (member.isLocal()) {
0590: simpleType(member);
0591: }
0592: }
0593: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0594: }
0595:
0596: /* (non-Javadoc)
0597: * @see com.sun.xml.xsom.visitor.XSSimpleTypeVisitor#restrictionSimpleType(com.sun.xml.xsom.XSRestrictionSimpleType)
0598: */
0599: public void restrictionSimpleType(XSRestrictionSimpleType type) {
0600:
0601: if (type.getBaseType() == null) {
0602: // don't print anySimpleType
0603: if (!type.getName().equals("anySimpleType")) {
0604: throw new InternalError();
0605: }
0606: if (!Const.schemaNamespace
0607: .equals(type.getTargetNamespace())) {
0608: throw new InternalError();
0609: }
0610: return;
0611: }
0612:
0613: XSSimpleType baseType = type.getSimpleBaseType();
0614:
0615: String str = MessageFormat.format("Restriction {0}",
0616: new Object[] { baseType.isLocal() ? "" : " base=\"{"
0617: + baseType.getTargetNamespace() + "}"
0618: + baseType.getName() + "\"" });
0619:
0620: SchemaTreeNode newNode = new SchemaTreeNode(str, baseType
0621: .getLocator());
0622: this .currNode.add(newNode);
0623: this .currNode = newNode;
0624:
0625: if (baseType.isLocal()) {
0626: simpleType(baseType);
0627: }
0628:
0629: Iterator itr = type.iterateDeclaredFacets();
0630: while (itr.hasNext()) {
0631: facet((XSFacet) itr.next());
0632: }
0633:
0634: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0635: }
0636:
0637: /* (non-Javadoc)
0638: * @see com.sun.xml.xsom.visitor.XSVisitor#facet(com.sun.xml.xsom.XSFacet)
0639: */
0640: public void facet(XSFacet facet) {
0641: SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat
0642: .format("{0} value=\"{1}\"", new Object[] {
0643: facet.getName(), facet.getValue(), }), facet
0644: .getLocator());
0645: this .currNode.add(newNode);
0646: }
0647:
0648: /* (non-Javadoc)
0649: * @see com.sun.xml.xsom.visitor.XSVisitor#notation(com.sun.xml.xsom.XSNotation)
0650: */
0651: public void notation(XSNotation notation) {
0652: SchemaTreeNode newNode = new SchemaTreeNode(
0653: MessageFormat
0654: .format(
0655: "Notation name='\"0}\" public =\"{1}\" system=\"{2}\"",
0656: new Object[] { notation.getName(),
0657: notation.getPublicId(),
0658: notation.getSystemId() }),
0659: notation.getLocator());
0660: this .currNode.add(newNode);
0661: }
0662:
0663: /* (non-Javadoc)
0664: * @see com.sun.xml.xsom.visitor.XSVisitor#complexType(com.sun.xml.xsom.XSComplexType)
0665: */
0666: public void complexType(XSComplexType type) {
0667: SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat
0668: .format("ComplexType {0}", new Object[] { type
0669: .isLocal() ? "" : " name=\"" + type.getName()
0670: + "\"" }), type.getLocator());
0671: this .currNode.add(newNode);
0672: this .currNode = newNode;
0673:
0674: // TODO: wildcard
0675:
0676: if (type.getContentType().asSimpleType() != null) {
0677: // simple content
0678: SchemaTreeNode newNode2 = new SchemaTreeNode(
0679: "Simple content", type.getContentType()
0680: .getLocator());
0681: this .currNode.add(newNode2);
0682: this .currNode = newNode2;
0683:
0684: XSType baseType = type.getBaseType();
0685:
0686: if (type.getDerivationMethod() == XSType.RESTRICTION) {
0687: // restriction
0688: String str = MessageFormat.format(
0689: "Restriction base=\"<{0}>{1}\"", new Object[] {
0690: baseType.getTargetNamespace(),
0691: baseType.getName() });
0692: SchemaTreeNode newNode3 = new SchemaTreeNode(str,
0693: baseType.getLocator());
0694: this .currNode.add(newNode3);
0695: this .currNode = newNode3;
0696:
0697: dumpComplexTypeAttribute(type);
0698:
0699: this .currNode = (SchemaTreeNode) this .currNode
0700: .getParent();
0701: } else {
0702: // extension
0703: String str = MessageFormat.format(
0704: "Extension base=\"<{0}>{1}\"", new Object[] {
0705: baseType.getTargetNamespace(),
0706: baseType.getName() });
0707: SchemaTreeNode newNode3 = new SchemaTreeNode(str,
0708: baseType.getLocator());
0709: this .currNode.add(newNode3);
0710: this .currNode = newNode3;
0711:
0712: // check if have redefine tag
0713: if ((type.getTargetNamespace().compareTo(
0714: baseType.getTargetNamespace()) == 0)
0715: && (type.getName()
0716: .compareTo(baseType.getName()) == 0)) {
0717: SchemaTreeNode newNodeRedefine = new SchemaTreeNode(
0718: "redefine", type.getLocator());
0719: this .currNode.add(newNodeRedefine);
0720: this .currNode = newNodeRedefine;
0721: baseType.visit(this );
0722: this .currNode = (SchemaTreeNode) newNodeRedefine
0723: .getParent();
0724: }
0725:
0726: dumpComplexTypeAttribute(type);
0727:
0728: this .currNode = (SchemaTreeNode) this .currNode
0729: .getParent();
0730: }
0731:
0732: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0733: } else {
0734: // complex content
0735: SchemaTreeNode newNode2 = new SchemaTreeNode(
0736: "Complex content", type.getContentType()
0737: .getLocator());
0738: this .currNode.add(newNode2);
0739: this .currNode = newNode2;
0740:
0741: XSComplexType baseType = type.getBaseType().asComplexType();
0742:
0743: if (type.getDerivationMethod() == XSType.RESTRICTION) {
0744: // restriction
0745: String str = MessageFormat.format(
0746: "Restriction base=\"<{0}>{1}\"", new Object[] {
0747: baseType.getTargetNamespace(),
0748: baseType.getName() });
0749: SchemaTreeNode newNode3 = new SchemaTreeNode(str,
0750: baseType.getLocator());
0751: this .currNode.add(newNode3);
0752: this .currNode = newNode3;
0753:
0754: type.getContentType().visit(this );
0755: dumpComplexTypeAttribute(type);
0756:
0757: this .currNode = (SchemaTreeNode) this .currNode
0758: .getParent();
0759: } else {
0760: // extension
0761: String str = MessageFormat.format(
0762: "Extension base=\"'{'{0}'}'{1}\"",
0763: new Object[] { baseType.getTargetNamespace(),
0764: baseType.getName() });
0765: SchemaTreeNode newNode3 = new SchemaTreeNode(str,
0766: baseType.getLocator());
0767: this .currNode.add(newNode3);
0768: this .currNode = newNode3;
0769:
0770: // check if have redefine tag
0771: if ((type.getTargetNamespace().compareTo(
0772: baseType.getTargetNamespace()) == 0)
0773: && (type.getName()
0774: .compareTo(baseType.getName()) == 0)) {
0775: SchemaTreeNode newNodeRedefine = new SchemaTreeNode(
0776: "redefine", type.getLocator());
0777: this .currNode.add(newNodeRedefine);
0778: this .currNode = newNodeRedefine;
0779: baseType.visit(this );
0780: this .currNode = (SchemaTreeNode) newNodeRedefine
0781: .getParent();
0782: }
0783:
0784: type.getExplicitContent().visit(this );
0785: dumpComplexTypeAttribute(type);
0786:
0787: this .currNode = (SchemaTreeNode) this .currNode
0788: .getParent();
0789: }
0790:
0791: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0792: }
0793:
0794: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0795: }
0796:
0797: /**
0798: * Creates node for complex type.
0799: *
0800: * @param type Complex type.
0801: */
0802: private void dumpComplexTypeAttribute(XSComplexType type) {
0803: Iterator itr;
0804:
0805: itr = type.iterateAttGroups();
0806: while (itr.hasNext()) {
0807: dumpRef((XSAttGroupDecl) itr.next());
0808: }
0809:
0810: itr = type.iterateDeclaredAttributeUses();
0811: while (itr.hasNext()) {
0812: attributeUse((XSAttributeUse) itr.next());
0813: }
0814: }
0815:
0816: /* (non-Javadoc)
0817: * @see com.sun.xml.xsom.visitor.XSTermVisitor#elementDecl(com.sun.xml.xsom.XSElementDecl)
0818: */
0819: public void elementDecl(XSElementDecl decl) {
0820: elementDecl(decl, "");
0821: }
0822:
0823: /**
0824: * Creates node for element declaration with additional attributes.
0825: *
0826: * @param decl Element declaration.
0827: * @param extraAtts Additional attributes.
0828: */
0829: private void elementDecl(XSElementDecl decl, String extraAtts) {
0830: XSType type = decl.getType();
0831:
0832: // TODO: various other attributes
0833:
0834: String str = MessageFormat.format("Element name=\"{0}\"{1}{2}",
0835: new Object[] {
0836: decl.getName(),
0837: type.isLocal() ? "" : " type=\"{"
0838: + type.getTargetNamespace() + "}"
0839: + type.getName() + "\"", extraAtts });
0840:
0841: SchemaTreeNode newNode = new SchemaTreeNode(str, decl
0842: .getLocator());
0843: this .currNode.add(newNode);
0844: this .currNode = newNode;
0845:
0846: if (type.isLocal()) {
0847: if (type.isLocal()) {
0848: type.visit(this );
0849: }
0850: }
0851:
0852: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0853: }
0854:
0855: /* (non-Javadoc)
0856: * @see com.sun.xml.xsom.visitor.XSTermVisitor#modelGroupDecl(com.sun.xml.xsom.XSModelGroupDecl)
0857: */
0858: public void modelGroupDecl(XSModelGroupDecl decl) {
0859: SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat
0860: .format("Group name=\"{0}\"", new Object[] { decl
0861: .getName() }), decl.getLocator());
0862: this .currNode.add(newNode);
0863: this .currNode = newNode;
0864:
0865: modelGroup(decl.getModelGroup());
0866:
0867: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0868: }
0869:
0870: /* (non-Javadoc)
0871: * @see com.sun.xml.xsom.visitor.XSTermVisitor#modelGroup(com.sun.xml.xsom.XSModelGroup)
0872: */
0873: public void modelGroup(XSModelGroup group) {
0874: modelGroup(group, "");
0875: }
0876:
0877: /**
0878: * Creates node for model group with additional attributes.
0879: *
0880: * @param group Model group.
0881: * @param extraAtts Additional attributes.
0882: */
0883: private void modelGroup(XSModelGroup group, String extraAtts) {
0884: SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat
0885: .format("{0}{1}", new Object[] { group.getCompositor(),
0886: extraAtts }), group.getLocator());
0887: this .currNode.add(newNode);
0888: this .currNode = newNode;
0889:
0890: final int len = group.getSize();
0891: for (int i = 0; i < len; i++) {
0892: particle(group.getChild(i));
0893: }
0894:
0895: this .currNode = (SchemaTreeNode) this .currNode.getParent();
0896: }
0897:
0898: /* (non-Javadoc)
0899: * @see com.sun.xml.xsom.visitor.XSContentTypeVisitor#particle(com.sun.xml.xsom.XSParticle)
0900: */
0901: public void particle(XSParticle part) {
0902: int i;
0903:
0904: StringBuffer buf = new StringBuffer();
0905:
0906: i = part.getMaxOccurs();
0907: if (i == XSParticle.UNBOUNDED) {
0908: buf.append(" maxOccurs=\"unbounded\"");
0909: } else {
0910: if (i != 1) {
0911: buf.append(" maxOccurs=\"" + i + "\"");
0912: }
0913: }
0914:
0915: i = part.getMinOccurs();
0916: if (i != 1) {
0917: buf.append(" minOccurs=\"" + i + "\"");
0918: }
0919:
0920: final String extraAtts = buf.toString();
0921:
0922: part.getTerm().visit(new XSTermVisitor() {
0923: public void elementDecl(XSElementDecl decl) {
0924: if (decl.isLocal()) {
0925: SchemaTreeTraverser.this .elementDecl(decl,
0926: extraAtts);
0927: } else {
0928: // reference
0929: SchemaTreeNode newNode = new SchemaTreeNode(
0930: MessageFormat
0931: .format(
0932: "Element ref=\"'{'{0}'}'{1}\"{2}",
0933: new Object[] {
0934: decl
0935: .getTargetNamespace(),
0936: decl.getName(),
0937: extraAtts }), decl
0938: .getLocator());
0939: currNode.add(newNode);
0940: }
0941: }
0942:
0943: public void modelGroupDecl(XSModelGroupDecl decl) {
0944: // reference
0945: SchemaTreeNode newNode = new SchemaTreeNode(
0946: MessageFormat.format(
0947: "Group ref=\"'{'{0}'}'{1}\"{2}",
0948: new Object[] {
0949: decl.getTargetNamespace(),
0950: decl.getName(), extraAtts }),
0951: decl.getLocator());
0952: currNode.add(newNode);
0953: }
0954:
0955: public void modelGroup(XSModelGroup group) {
0956: SchemaTreeTraverser.this .modelGroup(group, extraAtts);
0957: }
0958:
0959: public void wildcard(XSWildcard wc) {
0960: SchemaTreeTraverser.this .wildcard(wc, extraAtts);
0961: }
0962: });
0963: }
0964:
0965: /* (non-Javadoc)
0966: * @see com.sun.xml.xsom.visitor.XSTermVisitor#wildcard(com.sun.xml.xsom.XSWildcard)
0967: */
0968: public void wildcard(XSWildcard wc) {
0969: wildcard(wc, "");
0970: }
0971:
0972: /**
0973: * Creates node for wild card with additional attributes.
0974: *
0975: * @param wc Wild card.
0976: * @param extraAtts Additional attributes.
0977: */
0978: private void wildcard(XSWildcard wc, String extraAtts) {
0979: // TODO
0980: SchemaTreeNode newNode = new SchemaTreeNode(MessageFormat
0981: .format("Any ", new Object[] { extraAtts }), wc
0982: .getLocator());
0983: currNode.add(newNode);
0984: }
0985:
0986: /* (non-Javadoc)
0987: * @see com.sun.xml.xsom.visitor.XSVisitor#annotation(com.sun.xml.xsom.XSAnnotation)
0988: */
0989: public void annotation(XSAnnotation ann) {
0990: // TODO: it would be nice even if we just put <xs:documentation>
0991: }
0992:
0993: /* (non-Javadoc)
0994: * @see com.sun.xml.xsom.visitor.XSContentTypeVisitor#empty(com.sun.xml.xsom.XSContentType)
0995: */
0996: public void empty(XSContentType t) {
0997: }
0998:
0999: /* (non-Javadoc)
1000: * @see com.sun.xml.xsom.visitor.XSVisitor#identityConstraint(com.sun.xml.xsom.XSIdentityConstraint)
1001: */
1002: public void identityConstraint(XSIdentityConstraint ic) {
1003: }
1004:
1005: /* (non-Javadoc)
1006: * @see com.sun.xml.xsom.visitor.XSVisitor#xpath(com.sun.xml.xsom.XSXPath)
1007: */
1008: public void xpath(XSXPath xp) {
1009: }
1010: }
|