|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.lib.jmi.xmi; import java.io.*; import java.util.*; import org.xml.sax.*; import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.jmi.reflect.*; import javax.jmi.model.*; import org.netbeans.lib.jmi.util.DebugException; import org.netbeans.lib.jmi.util.Logger; import org.netbeans.lib.jmi.util.TagProvider; public class SchemaProducer { // Fixed schema content file name. private static String FIXED_SCHEMA_FILE = "resources/fixed_schema.xml"; // output stream to which the produced DTD is written private OutputStreamWriter streamWriter; // default writer private DefaultWriter writer; // tag provider private TagProvider tagProvider; // main package extent private RefPackage extent; // elements cache used to obtain classes' attributes, references, etc. private ElementsCache elementsCache; // stored already processed packages private Set trackedPackages; // stores mapping class -> set of all direct subtypes private Map classHierarchy; // cache for mapping class -> all subtypes (direct and non-direct) private Map allSubtypes_cache; // mapping MofPackage -> namespace name private Map namespaces; // mapping namespace prefix -> URI private HashMap nsPrefixToURI; // stores all enumeration types belonging to the tracked classes and packages private Set enumerations; // content handler related variables private boolean elementStarted; private String elementName; private AttributesImpl attributes = new AttributesImpl (); // ************************************************************************** // Methods related to writing to content handler. // ************************************************************************** private void startElement (String name) { if (elementStarted) { writeStartElement (); } elementName = name; elementStarted = true; } private void endElement (String name) { if (elementStarted) { writeStartElement (); } try { writer.endElement (null, null, name); } catch (SAXException e) { throw new DebugException (e.getMessage ()); } } private void addAttribute (String name, String value) { attributes.addAttribute(null, null, name, null, value); // uri, localName, qName, type, value } private void characters (String text) { if (elementStarted) { writeStartElement (); } try { writer.characters (text.toCharArray(), 0, text.length ()); } catch (SAXException e) { throw new DebugException (e.getMessage ()); } } private void writeStartElement () { try { writer.startElement (null, null, elementName, attributes); } catch (SAXException e) { throw new DebugException (e.getMessage ()); } elementStarted = false; attributes.clear (); } // ************************************************************************** // init ..................................................................... public void init () { writer = new DefaultWriter (streamWriter, null); elementStarted = false; elementName = null; attributes.clear (); enumerations = new HashSet (); tagProvider = new TagProvider (); elementsCache = new ElementsCache (extent); trackedPackages = new HashSet (); classHierarchy = new HashMap (); allSubtypes_cache = new HashMap (); namespaces = new HashMap (); nsPrefixToURI = new HashMap (); findNamespaces (extent); trackedPackages.clear (); } // .......................................................................... /** * Generates XML Schema for metamodel residing in the passed package extent. * @param outermost package */ public void generate (OutputStream stream, RefPackage extent) throws IOException { streamWriter = new OutputStreamWriter (stream); this.extent = extent; init (); try { writer.startDocument (); startElement ("xsd:schema"); addAttribute ("xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); addAttribute ("xmlns:xmi", "http://www.omg.org/XMI"); // writeStartElement (); // writeFixedContent (); startElement ("xsd:import"); addAttribute ("namespace", "http://www.omg.org/XMI"); endElement ("xsd:import"); // writeNamespaces (); writePackageSchema (extent); for (Iterator iter = enumerations.iterator (); iter.hasNext ();) { writeEnumerationSchema ((EnumerationType) iter.next ()); } endElement ("xsd:schema"); try { writer.endDocument (); } catch (SAXException e) { throw new IOException (e.getMessage ()); } stream.flush (); stream.close (); } catch (SAXException e) { e.printStackTrace (); throw new IOException (e.getMessage ()); } } public void writePackageSchema (RefPackage pkg) { if (trackedPackages.contains (pkg)) { return; } else { trackedPackages.add (pkg); } Iterator iter = pkg.refAllPackages ().iterator (); while (iter.hasNext ()) { writePackageSchema ((RefPackage) iter.next ()); } iter = pkg.refAllClasses ().iterator (); while (iter.hasNext ()) { writeClassSchema ((RefClass) iter.next ()); } writePackageElementDef (pkg); } public void writeClassSchema (RefClass proxy) { Iterator iter; String text; StringBuffer buffer = new StringBuffer (); MofClass meta = (MofClass) proxy.refMetaObject (); String className = objectName (meta); List instAttrs, references; String contentType = getContentType (meta); boolean useExtensions = isUseSchemaExtensions (meta); boolean isChoice = isMaxMultiplicityEnforced (meta) || isMinMultiplicityEnforced (meta); findEnumerations (meta); // ClassTypeDef startElement ("xsd:complexType"); addAttribute ("name", meta.getName ()); if ((contentType != null) && contentType.equals ("mixed")) { addAttribute ("mixed", "true"); } if (useExtensions) { startElement ("xsd:complexContent"); startElement ("xsd:extension"); Collection supers = meta.getSupertypes (); if (supers.size () != 1) { // [PENDING] throw some exception ... ? } String base = objectName ((MofClass) supers.iterator ().next ()); addAttribute ("base", base); } if (isChoice) { startElement ("xsd:choice"); addAttribute ("minOccurs", "0"); addAttribute ("maxOccurs", "unbounded"); } else { startElement ("xsd:sequence"); } if (contentType == null) { // attributes instAttrs = useExtensions ? elementsCache.localInstanceAttributes (meta) : elementsCache.instanceAttributes (meta); for (iter = instAttrs.iterator (); iter.hasNext ();) { Attribute attr = (Attribute) iter.next (); startElement ("xsd:element"); addAttribute ("name", attr.getName ()); if (isNillable (attr)) { addAttribute ("nillable", "true"); } if (isMinMultiplicityEnforced (attr)) { addAttribute ("minOccurs", multToString (attr.getMultiplicity ().getLower ())); } if (isMaxMultiplicityEnforced (attr)) { addAttribute ("maxOccurs", multToString (attr.getMultiplicity ().getUpper ())); } Classifier type = getType (attr); if (type instanceof MofClass) { String schemaType = getSchemaType (attr); if (schemaType != null) { addAttribute ("type", schemaType); } else { writeAnyElement (); } } else if (type instanceof EnumerationType) { addAttribute ("type", type.getName ()); } else { addAttribute ("type", "xsd:string"); } endElement ("xsd:element"); } // for // references references = useExtensions ? elementsCache.localReferences (meta) : elementsCache.references (meta); for (iter = references.iterator (); iter.hasNext ();) { Reference reference = (Reference) iter.next (); startElement ("xsd:element"); addAttribute ("name", reference.getName ()); if (isMinMultiplicityEnforced (reference)) { addAttribute ("minOccurs", multToString (reference.getMultiplicity ().getLower ())); } if (isMaxMultiplicityEnforced (reference)) { addAttribute ("maxOccurs", multToString (reference.getMultiplicity ().getUpper ())); } String contType = getContentType (reference); if (((contType != null) && (contType.equals ("complex"))) || isUseSchemaExtensions (reference)) { addAttribute ("type", getType (reference).getName ()); } else { writeAnyElement (); } endElement ("xsd:element"); } // for // extension startElement ("xsd:element"); addAttribute ("ref", "xmi:extension"); endElement ("xsd:element"); } else if (contentType.equals ("any")) { startElement ("xsd:any"); addAttribute ("minOccurs", "0"); addAttribute ("maxOccurs", "unbounded"); addAttribute ("processContents", getProcessContents (meta)); endElement ("xsd:any"); } // else no content endElement (isChoice ? "xsd:choice" : "xsd:sequence"); // ClassAttListItems // fixed attributes writeFixedAttribs (meta); // references references = useExtensions ? elementsCache.localReferences (meta) : elementsCache.references (meta); for (iter = references.iterator (); iter.hasNext ();) { Reference reference = (Reference) iter.next (); if (AggregationKindEnum.COMPOSITE.equals (reference.getReferencedEnd ().getAggregation ())) continue; startElement ("xsd:attribute"); addAttribute ("name", reference.getName ()); MultiplicityType mult = reference.getMultiplicity (); if ((mult.getLower () == 1) && (mult.getUpper () == 1) && isMinMultiplicityEnforced (reference)) { addAttribute ("type", "xsd:IDREFS"); addAttribute ("use", "optional"); } else { addAttribute ("type", "xsd:IDREF"); addAttribute ("use", "required"); } endElement ("xsd:attribute"); } // for // attributes instAttrs = useExtensions ? elementsCache.localInstanceAttributes (meta) : elementsCache.instanceAttributes (meta); for (iter = instAttrs.iterator (); iter.hasNext ();) { Attribute attr = (Attribute) iter.next (); String val; Classifier type = getType (attr); if (type instanceof MofClass) { continue; } MultiplicityType mult = attr.getMultiplicity (); boolean required = (mult.getLower () == 1) && (mult.getUpper () == 1) && isMinMultiplicityEnforced (attr); startElement ("xsd:attribute"); addAttribute ("name", attr.getName ()); if (type instanceof EnumerationType) { addAttribute ("type", objectName (type)); val = getDefaultValue (attr); if (val != null) { addAttribute ("use", "default"); addAttribute ("value", val); } else { addAttribute ("use", required ? "required" : "optional"); } } else { addAttribute ("type", "xsd:string"); addAttribute ("use", required ? "required" : "optional"); val = getDefaultValue (attr); if (val != null) addAttribute ("default", val); val = getFixedValue (attr); if (val != null) addAttribute ("fixed", val); val = getForm (attr); if (val != null) addAttribute ("form", val); } endElement ("xsd:attribute"); } // for if (useExtensions) { endElement ("xsd:extension"); endElement ("xsd:complexContent"); } endElement ("xsd:complexType"); startElement ("xsd:attributeGroup"); addAttribute ("ref", "xmi:ObjectAttribs"); endElement ("xsd:attributeGroup"); // ClassElementDef startElement ("xsd:element"); addAttribute ("name", meta.getName ()); addAttribute ("type", objectName (meta)); endElement ("xsd:element"); } public void writeAnyElement () { startElement ("xsd:complexType"); startElement ("xsd:choice"); addAttribute ("minOccurs", "0"); addAttribute ("maxOccurs", "unbounded"); startElement ("xsd:any"); addAttribute ("processContents", "skip"); endElement ("xsd:any"); endElement ("xsd:choice"); endElement ("xsd:complexType"); } public void writeFixedAttribs (ModelElement elem) { startElement ("xsd:attribute"); String idName = getIdName (elem); if (idName == null) { addAttribute ("ref", "xmi:id"); } else { addAttribute ("name", idName); addAttribute ("type", "xsd:ID"); } addAttribute ("use", "optional"); endElement ("xsd:attribute"); } public void writeAssociationSchema (Association assoc) { startElement ("xsd:element"); addAttribute ("name", assoc.getName ()); startElement ("xsd:complexType"); startElement ("xsd:choice"); addAttribute ("minOccurs", "0"); addAttribute ("maxOccurs", "unbounded"); for (Iterator iter = assoc.getContents ().iterator (); iter.hasNext ();) { Object elem = iter.next (); if (elem instanceof AssociationEnd) { writeAssociationEndDef ((AssociationEnd) elem); } // if } // for // extension startElement ("xsd:extension"); addAttribute ("ref", "xmi:extension"); endElement ("xsd:extension"); // end of extension endElement ("xsd:choice"); writeFixedAttribs (assoc); endElement ("xsd:complexType"); endElement ("xsd:element"); } public void writeAssociationEndDef (AssociationEnd end) { startElement ("xsd:element"); addAttribute ("name", end.getName ()); startElement ("xsd:complexType"); writeFixedAttribs (end); endElement ("xsd:complexType"); endElement ("xsd:element"); } public void writeEnumerationSchema (EnumerationType enum) { startElement ("xsd:simpleType"); addAttribute ("name", enum.getName ()); startElement ("xsd:restriction"); addAttribute ("base", "xsd:string"); // int prefixLength = labelPrefix (enum).length (); for (Iterator iter = enum.getLabels ().iterator (); iter.hasNext ();) { String label = (String) iter.next (); startElement ("xsd:enumeration"); addAttribute ("value", label); endElement ("xsd:enumeration"); } endElement ("xsd:restriction"); endElement ("xsd:simpleType"); } public void writeFixedContent () throws SAXException { java.net.URL fixedSchema = getClass().getResource(FIXED_SCHEMA_FILE); if (fixedSchema == null) { throw new DebugException("Resource not found: " + FIXED_SCHEMA_FILE); } try { SAXParserFactory factory = SAXParserFactory.newInstance (); factory.setValidating (false); SAXParser saxParser = factory.newSAXParser (); saxParser.parse (fixedSchema.openStream (), new FixedContentHandler ()); } catch (IOException e) { Logger.getDefault().log("Unable to open " + FIXED_SCHEMA_FILE + ": " + e.getMessage()); throw new DebugException (e.getMessage ()); } catch (ParserConfigurationException e) { throw new SAXException (e.getMessage ()); } } public void writeNamespaces () { /* Set names = new HashSet (); if (namespaces.size () > 0) { startAttlist ("XMI"); for (Iterator iter = namespaces.entrySet ().iterator (); iter.hasNext ();) { Object name = ((Map.Entry) iter.next ()).getValue (); if (!names.contains (name)) { addAttlistItem ("xmlns:" + name + " " + TAG_CDATA + " " + TAG_IMPLIED); names.add (name); } } // for endAttlist (); } // if */ } public void writePackageElementDef (RefPackage pkg) { Iterator iter; MofPackage meta = (MofPackage) pkg.refMetaObject (); String packageName = packageName (meta); findEnumerations (meta); startElement ("xsd:element"); addAttribute ("name", meta.getName ()); startElement ("xsd:complexType"); startElement ("xsd:choice"); addAttribute ("minOccurs", "0"); addAttribute ("maxOccurs", "unbounded"); // package contents // contained classes for (iter = pkg.refAllClasses ().iterator (); iter.hasNext ();) { Object metaObject = ((RefClass) iter.next ()).refMetaObject (); MofClass mofClass = (MofClass) (metaObject instanceof AliasType ? getType ((AliasType) metaObject) : metaObject); startElement ("xsd:element"); addAttribute ("name", objectName (mofClass)); addAttribute ("type", mofClass.getName ()); endElement ("xsd:element"); } // for // associations without references for (iter = getFreeAssociations (pkg).iterator (); iter.hasNext ();) { writeAssociationSchema ((Association) iter.next ()); } // for for (iter = pkg.refAllPackages ().iterator (); iter.hasNext ();) { startElement ("xsd:element"); addAttribute ("ref", packageName ((MofPackage) ((RefPackage) iter.next ()).refMetaObject ())); endElement ("xsd:element"); } // for startElement ("xsd:extension"); addAttribute ("ref", "xmi:extension"); endElement ("xsd:extension"); // end of package contents endElement ("xsd:choice"); endElement ("xsd:complexType"); endElement ("xsd:element"); } // helper methods ........................................................... protected void findNamespaces(RefPackage pkg) { String name, uri; Iterator iter; if (trackedPackages.contains (pkg)) return; MofPackage metaPackage = (MofPackage) pkg.refMetaObject (); name = getNsPrefixTag (metaPackage); if (name == null) { name = tagProvider.getTagValue (metaPackage, XmiConstants.TAGID_XMI_NAMESPACE); } if (name != null) { iter = metaPackage.getQualifiedName ().iterator (); String fqName = (String) iter.next (); while (iter.hasNext ()) fqName = fqName.concat (XmiConstants.DOT_SEPARATOR).concat ((String) iter.next ()); namespaces.put (fqName, name); uri = getNsURITag (metaPackage); if (uri == null) throw new DebugException ("A tag defining namespace uri not found, package " + metaPackage.getName ()); nsPrefixToURI.put (name, uri); } trackedPackages.add (pkg); iter = pkg.refAllPackages ().iterator (); while (iter.hasNext ()) { findNamespaces ((RefPackage) iter.next ()); } } public String elementName (ModelElement element) { ModelElement container = element.getContainer (); return objectName (container) + '.' + getXmiName (element); } public String objectName (ModelElement element) { String namespace = (String) namespaces.get (element.getContainer ()); if (namespace != null) { return namespace + ":" + getXmiName (element); } else { return qualifiedName (element); } } public String packageName (MofPackage pkg) { String namespace = (String) namespaces.get (pkg); if (namespace != null) { return namespace + ":" + getXmiName (pkg); } else { return qualifiedName (pkg); } } public String qualifiedName (ModelElement element) { Iterator iter = element.getQualifiedName ().iterator (); String name = (String) iter.next (); while (iter.hasNext ()) { name = name.concat (XmiConstants.DOT_SEPARATOR).concat ((String) iter.next ()); } return name; } public Classifier getType (TypedElement elem) { Classifier type = elem.getType (); while (type instanceof AliasType) type = ((AliasType) type).getType (); return type; } public Set getFreeAssociations (RefPackage pkg) { ModelPackage model = (ModelPackage) pkg.refMetaObject ().refImmediatePackage (); RefersTo refersTo = model.getRefersTo (); Set set = new HashSet (); for (Iterator iter = pkg.refAllAssociations ().iterator (); iter.hasNext ();) { Association assoc = (Association) ((RefAssociation) iter.next ()).refMetaObject (); boolean found = false; for (Iterator it = assoc.getContents ().iterator (); it.hasNext ();) { Object elem = it.next (); if (elem instanceof AssociationEnd) { Collection col = refersTo.getReferent ((AssociationEnd) elem); if ((col != null) && (col.size () > 0)) { found = true; break; } } } // for if (!found) { set.add (assoc); } } // for return set; } public String multToString (int multiplicity) { return (multiplicity == -1) ? "unbounded" : "" + multiplicity; } public void findEnumerations (Namespace elem) { for (Iterator iter = elem.getContents ().iterator (); iter.hasNext ();) { Object obj = iter.next (); if (obj instanceof EnumerationType) { enumerations.add (obj); } } // for } // tags getters ............................................................. public String getContentScopedTagValue (ModelElement elem, String tagId) { String value = null; while ((value == null) && (elem != null)) { value = tagProvider.getTagValue (elem, tagId); elem = elem.getContainer (); } if (value != null) value = value.trim (); return value; } public boolean isMaxMultiplicityEnforced (ModelElement elem) { String s = getContentScopedTagValue (elem, XmiConstants.TAG_ENFORCE_MAX_MULTIPLICITY); return (s != null) && s.equals ("true"); } public boolean isMinMultiplicityEnforced (ModelElement elem) { String s = getContentScopedTagValue (elem, XmiConstants.TAG_ENFORCE_MIN_MULTIPLICITY); return (s != null) && s.equals ("true"); } public boolean isUseSchemaExtensions (ModelElement elem) { String s = getContentScopedTagValue (elem, XmiConstants.TAG_USE_SCHEMA_EXTENSIONS); return (s != null) && s.equals ("true"); } public boolean isNillable (ModelElement elem) { String s = getContentScopedTagValue (elem, XmiConstants.TAG_INCLUDE_NILS); return (s == null) || s.equals ("true"); } public String getProcessContents (ModelElement elem) { String s = getContentScopedTagValue (elem, XmiConstants.TAG_PROCESS_CONTENTS); if (s == null) { return "strict"; // default value } return s; } public String getIdName (ModelElement elem) { return getContentScopedTagValue (elem, XmiConstants.TAG_ID_NAME); } public String getForm (ModelElement elem) { return getContentScopedTagValue (elem, XmiConstants.TAG_FORM); } public String getFixedValue (ModelElement elem) { return getContentScopedTagValue (elem, XmiConstants.TAG_FIXED_VALUE); } public String getNsPrefixTag (ModelElement elem) { return getContentScopedTagValue (elem, XmiConstants.TAG_NS_PREFIX); } public String getNsURITag (ModelElement elem) { return getContentScopedTagValue (elem, XmiConstants.TAG_NS_URI); } public String getDefaultValue (ModelElement elem) { return tagProvider.getTagValue (elem, XmiConstants.TAG_DEFAULT_VALUE); } public String getXmiName (ModelElement elem) { String name = tagProvider.getTagValue (elem, XmiConstants.TAG_XMI_NAME); if (name == null) return elem.getName (); else return name; } public String getContentType (ModelElement elem) { return tagProvider.getTagValue (elem, XmiConstants.TAG_CONTENT_TYPE); } public String getSchemaType (ModelElement elem) { return tagProvider.getTagValue (elem, XmiConstants.TAG_SCHEMA_TYPE); } // .......................................................................... private class FixedContentHandler extends DefaultHandler { private int depth = 0; public void startElement (String namespaceURI, String sName, String qName, Attributes attrs) throws SAXException { if (depth > 0) writer.startElement (namespaceURI, sName, qName, attrs); depth++; // System.out.println("start element: " + qName + ", depth: " + depth); } public void endElement (String namespaceURI, String sName, String qName) throws SAXException { depth--; if (depth > 0) writer.endElement (namespaceURI, sName, qName); // System.out.println("start element: " + qName + ", depth: " + depth); } public void characters (char buf[], int offset, int len) throws SAXException { for (int x = offset; x < offset + len; x++) { if (!Character.isWhitespace(buf[x])) { writer.characters (buf, offset, len); break; } // if } // for } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.