# TypeHierarchyPrinter.java Sample

This topic inludes the source code for the TypeHierarchyPrinter.java Sample.

## Sample Location

This sample is located in the following directory in your WebLogic Workshop installation:

BEA_HOME/weblogic81/samples/workshop/SamplesApp/WebServices/xmlBeans/schema/

## Sample Source Code

`001 package xmlBeans.schema; 002 003 import com.bea.xbean.tool.CommandLine; 004 import com.bea.xml.XmlObject; 005 import com.bea.xml.XmlOptions; 006 import com.bea.xml.XmlBeans; 007 import com.bea.xml.XmlException; 008 import com.bea.xml.SchemaTypeSystem; 009 import com.bea.xml.SchemaType; 010 011 import java.util.Collections; 012 import java.util.List; 013 import java.util.ArrayList; 014 import java.util.Collection; 015 import java.util.Iterator; 016 import java.util.HashMap; 017 import java.util.Map; 018 import java.util.Arrays; 019 import java.io.File; 020 021 /** 022 * Provides a way to print a hierarchical list of the XML schema types 023 * corresponding to Java types that result from compiling the schema. 024 * The unique "signatures" used to represent the schema types in the hierarchy 025 * are built from several characteristics, including: 026 * <ul> 027 * <li>The type's position in the schema (for example, is it global or local?).</li> 028 * <li>Whether the type is a datatype (complex or simple) or an element or attribute.</li> 029 * <li>Whether the type is derived by restriction, union, and so on.</li> 030 * </ol> 031 * There isn't yet a public standard for such signatures, but the style used here 032 * is useful for seeing the hierarchy. Keep in mind that if a signature standard does 033 * become adopted, that standard will likely be used by the SchemaType.toString() 034 * method. See the WebLogic Workshop documentation for a more complete description 035 * of the signature conventions used here. 036 * <br/><br/> 037 * This class is designed so that it may be used from either another 038 * component (such as a web service) or from the command line. 039 */ 040 public class TypeHierarchyPrinter 041 { 042 /** 043 * Prints a hierarchical list of XML schema types represented by the 044 * specified <em>typeSystem</em>. 045 */ 046 public static String printHierarchy(SchemaTypeSystem typeSystem) throws Exception 047 { 048 // A StringBuffer in which to build the response hierarchy. 049 StringBuffer response = new StringBuffer(); 050 051 // A map for base SchemaType -> Collection of directly derived types. 052 Map childTypes = new HashMap(); 053 054 // Traverse the type containment tree breadthfirst. 055 List allSeenTypes = new ArrayList(); 056 // Document types are special types that hold the globally defined elements. 057 allSeenTypes.addAll(Arrays.asList(typeSystem.documentTypes())); 058 // Attribute types are special types that hold the globally defined attributes. 059 allSeenTypes.addAll(Arrays.asList(typeSystem.attributeTypes())); 060 /* 061 * Global types are globally defined schema types -- such as complex or 062 * simple types defined just beneath the schema's root in the hierarchy. 063 */ 064 allSeenTypes.addAll(Arrays.asList(typeSystem.globalTypes())); 065 066 /** 067 * Loop through the types to examine, 068 */ 069 for (int i = 0; i < allSeenTypes.size(); i++) 070 { 071 /** 072 * A SchemaType object represents a compiled schema type. This 073 * includes all three of the kinds added to allSeenTypes above. 074 */ 075 SchemaType sType = (SchemaType)allSeenTypes.get(i); 076 077 /* 078 * Recurse through the nested anonymous types as well 079 * (comment this line to skip nested types). Anonymous types 080 * are defined inside other types. 081 */ 082 allSeenTypes.addAll(Arrays.asList(sType.getAnonymousTypes())); 083 084 /** 085 * Don't examine nested document types, attribute types, 086 * or the base type of anyType. 087 */ 088 if (sType.isDocumentType() || sType.isAttributeType() || sType == XmlObject.type) 089 continue; 090 091 // Enter this type in the list of children of its base type. 092 Collection children = (Collection)childTypes.get(sType.getBaseType()); 093 if (children == null) 094 { 095 children = new ArrayList(); 096 childTypes.put(sType.getBaseType(), children); 097 098 /** 099 * The first time a built-in type is seen add it, too, 100 * to get a complete tree up to anyType, the root. A built-in type 101 * is a schema type defined by the schema specification, 102 * such as xs:string, xs:int, xs:anyType, and so on. 103 */ 104 if (sType.getBaseType().isBuiltinType()) 105 allSeenTypes.add(sType.getBaseType()); 106 } 107 children.add(sType); 108 } 109 110 /** 111 * Print the hierarchy tree. 112 */ 113 List typesToPrint = new ArrayList(); 114 115 // Add anyType, from which all others inherit. 116 typesToPrint.add(XmlObject.type); 117 118 // Create a buffer to hold the indentation spaces. 119 StringBuffer spaces = new StringBuffer(); 120 121 /** 122 * Loop through the list of types, adding the hierarchy branch 123 * symbols and type "signatures". 124 */ 125 while (!typesToPrint.isEmpty()) 126 { 127 SchemaType sType = (SchemaType)typesToPrint.remove(typesToPrint.size() - 1); 128 if (sType == null) 129 spaces.setLength(Math.max(0, spaces.length() - 2)); 130 else 131 { 132 /** 133 * The SchemaType.toString() method returns a String containing 134 * the schema type "signature". 135 */ 136 response.append(spaces + "+-" + sType.toString() + "\n"); 137 Collection children = (Collection)childTypes.get(sType); 138 if (children != null && children.size() > 0) 139 { 140 spaces.append(typesToPrint.size() == 0 || typesToPrint.get(typesToPrint.size() - 1) == null ? " " : "| "); 141 typesToPrint.add(null); 142 typesToPrint.addAll(children); 143 } 144 } 145 } 146 return response.toString(); 147 } 148 149 /** 150 * Creates a schema type system from an array of XSD files. This method 151 * is called when this class is used from the command line. 152 */ 153 public static SchemaTypeSystem typeSystemFromFiles(File[] schemaFiles) 154 { 155 /* 156 * A SchemaTypeSystem object will hold the type system created by 157 * compiling the schema types. 158 */ 159 SchemaTypeSystem typeSystem = null; 160 161 List sdocs = new ArrayList(); 162 163 /** 164 * Loop through the File array, parsing the contents of each schema 165 * file into an XmlObject instance. These objects will be passed to 166 * a method that compiles the schemas. 167 */ 168 for (int i = 0; i < schemaFiles.length; i++) 169 { 170 try 171 { 172 sdocs.add(XmlObject.Factory.parse( 173 schemaFiles[i], (new XmlOptions()).setLoadLineNumbers())); 174 } 175 catch (Exception e) 176 { 177 System.err.println( schemaFiles[i] + " not loadable: " + e ); 178 } 179 } 180 XmlObject[] schemas = (XmlObject[])sdocs.toArray(new XmlObject[0]); 181 182 /** 183 * Compile each schema. Use a Collection object to collect any 184 * errors that arise during compilation. 185 */ 186 Collection compErrors = new ArrayList(); 187 try 188 { 189 /** 190 * Compile the schemas, specifying also the built-in type system 191 * to consult for already-compiled schema types which 192 * may be linked while processing the given schemas. 193 */ 194 typeSystem = XmlBeans.compileXsd(schemas, 195 XmlBeans.getBuiltinTypeSystem(), 196 new XmlOptions().setErrorListener(compErrors).setCompileDownloadUrls()); 197 } 198 catch (XmlException e) 199 { 200 System.out.println("Schema invalid"); 201 for (Iterator i = compErrors.iterator(); i.hasNext(); ) 202 System.out.println(i.next()); 203 } 204 return typeSystem; 205 } 206 207 /** 208 * A main method so that this class may be used from the command 209 * line. 210 */ 211 public static void main(String[] args) throws Exception 212 { 213 CommandLine cl = new CommandLine(args, Collections.EMPTY_SET); 214 File[] schemaFiles = cl.getFiles(); 215 216 SchemaTypeSystem typeSystem = typeSystemFromFiles(schemaFiles); 217 String hierarchy = printHierarchy(typeSystem); 218 System.out.println(hierarchy); 219 } 220 221 }`