|
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.