Java tutorial
/* * $Id: XMLSchema.java,v 1.6 2005/08/25 10:46:39 gmcgoldrick Exp $ * * Copyright (C) 2002 - 2004, Cladonia Ltd. All rights reserved. * * This software is the proprietary information of Cladonia Ltd. * Use is subject to license terms. */ package com.cladonia.schema; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.Writer; import java.net.URL; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.dom4j.Namespace; import org.dom4j.QName; import org.exolab.castor.xml.schema.BlockList; import org.exolab.castor.xml.schema.ElementDecl; import org.exolab.castor.xml.schema.FinalList; import org.exolab.castor.xml.schema.Form; import org.exolab.castor.xml.schema.Schema; import org.exolab.castor.xml.schema.SchemaException; import org.exolab.castor.xml.schema.reader.SchemaReader; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import com.cladonia.xml.ExchangerDocument; import com.cladonia.xml.XMLUtilities; /** * The schema. * * @version $Revision: 1.6 $, $Date: 2005/08/25 10:46:39 $ * @author Dogsbay */ public class XMLSchema implements SchemaDocument { private static final boolean DEBUG = true; public static final String FORM_QUALIFIED = "qualified"; public static final String FORM_UNQUALIFIED = "unqualified"; public static final String BLOCK_ALL = "#all"; public static final String BLOCK_EXTENSION = "extension"; public static final String BLOCK_RESTRICTION = "restriction"; public static final String BLOCK_SUBSTITUTION = "substitution"; public static final String FINAL_ALL = "#all"; public static final String FINAL_EXTENSION = "extension"; public static final String FINAL_RESTRICTION = "restriction"; private boolean schemaDocument = false; private URL url = null; private Schema schema = null; private Hashtable globalElements = null; private Hashtable substitutes = null; // private Hashtable substitutions = null; private SchemaElement root = null; private Vector allElements = null; // private Hashtable allElements = null; private Vector elementNames = null; private Vector attributeNames = null; private Hashtable elementChildren = null; private Hashtable elementAttributes = null; public XMLSchema(URL url) throws IOException, SchemaException, SAXParseException { // schemaDocument = isSchema; this.url = url; // check schema XMLUtilities.validateSchema(url); // see if it is a schema... SchemaReader reader = new SchemaReader(url.toString()); reader.setValidation(false); this.schema = reader.read(); globalElements = new Hashtable(); substitutes = new Hashtable(); Enumeration enumeration = schema.getGlobalElements(); // while( enumeration.hasMoreElements()) { // ElementDecl e = (ElementDecl)enumeration.nextElement(); // System.out.println( "Global: "+e.getName()); // } while (enumeration.hasMoreElements()) { ElementDecl e = (ElementDecl) enumeration.nextElement(); SchemaElement element = new SchemaElement(this, null, e); // System.out.println( "Global: "+element.getName()); globalElements.put(element.getUniversalName(), element); // set the substitution group String substitutionGroupName = element.getElement().getSubstitutionGroup(); if (substitutionGroupName != null) { int colon = substitutionGroupName.lastIndexOf(':'); if (colon > 0) { substitutionGroupName = substitutionGroupName.substring(colon + 1); } Vector substitutionGroup = (Vector) substitutes.get(substitutionGroupName); if (substitutionGroup == null) { substitutionGroup = new Vector(); substitutes.put(substitutionGroupName, substitutionGroup); } substitutionGroup.addElement(element); } } // createNames(); } public XMLSchema(ExchangerDocument document) throws IOException, SchemaException, SAXParseException { this.url = document.getURL(); byte[] bytes = document.getText().getBytes(document.getJavaEncoding()); ByteArrayInputStream stream = new ByteArrayInputStream(bytes); BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(stream, document.getJavaEncoding())); String systemId = null; if (url != null) { systemId = url.toString(); } // // check schema // XMLUtilities.validateSchema( bufferedReader, systemId, document.getEncoding()); // // stream = new ByteArrayInputStream( bytes); // bufferedReader = new BufferedReader( new InputStreamReader( stream, document.getJavaEncoding())); InputSource source = new InputSource(bufferedReader); source.setSystemId(systemId); // see if it is a schema... SchemaReader reader = new SchemaReader(source); reader.setValidation(false); this.schema = reader.read(); globalElements = new Hashtable(); substitutes = new Hashtable(); Enumeration enumeration = schema.getGlobalElements(); while (enumeration.hasMoreElements()) { ElementDecl e = (ElementDecl) enumeration.nextElement(); SchemaElement element = new SchemaElement(this, null, e); globalElements.put(element.getUniversalName(), element); // set the substitution group String substitutionGroupName = element.getElement().getSubstitutionGroup(); if (substitutionGroupName != null) { int colon = substitutionGroupName.lastIndexOf(':'); if (colon > 0) { substitutionGroupName = substitutionGroupName.substring(colon + 1); } Vector substitutionGroup = (Vector) substitutes.get(substitutionGroupName); if (substitutionGroup == null) { substitutionGroup = new Vector(); substitutes.put(substitutionGroupName, substitutionGroup); } substitutionGroup.addElement(element); } } } public Schema getSchema() { return this.schema; } /** * Gets a list of globally defined elements. * * @return list of global elements. */ public Vector getGlobalElements() { Enumeration enumeration = globalElements.elements(); Vector elements = new Vector(); while (enumeration.hasMoreElements()) { elements.addElement(enumeration.nextElement()); } return elements; } /** * Gets a globally defined element. * * @return the global element. */ public SchemaElement getGlobalElement(SchemaElement element) { if (element != null) { return (SchemaElement) globalElements.get(element.getUniversalName()); } return null; } /** * Gets a list of elements that are in the same substitution group. * * @return the list of elements. */ public Vector getSubstitutionGroup(String name) { return (Vector) substitutes.get(name); } /** * Gets a list of globally defined elements. * * @return list of global elements. */ public void write(Writer writer) throws SAXException, IOException { org.exolab.castor.xml.dtd.Converter.marshalSchema(schema, writer); } /** * Returns the current schema/dtd url. * * @return the url. */ public URL getURL() { return url; } public int getType() { return TYPE_XSD; } /** * Returns true if the document used to create * this grammar was a schema. * * @return true when the document was a schema. */ public boolean isSchema() { return schemaDocument; } /** * Returns a list of all the possible element names. * * @return list of element names and namespace uris. */ public Vector getElementNames() { return elementNames; } /** * Returns a list of all the possible attribute names. * * @return list of attribute names and namespace uris. */ public Vector getAttributeNames() { return attributeNames; } /** * Returns a list of possible element names for the parent element name. * * @return list of element names and namespace uris for a parent. */ public Vector getElementNames(String parent) { return (Vector) elementChildren.get(parent); } /** * Returns a list of all the possible attribute names, for a parent element. * * @return list of attribute names and namespace uris for a parent element. */ public Vector getAttributeNames(String parent) { return (Vector) elementAttributes.get(parent); } /** * Returns a list of possible element names. * * @return list of element names and namespace uris. */ public Hashtable getElementChildren() { return elementChildren; } /** * Returns a list of all the possible attribute names, for a parent element. * * @return list of attribute names and namespace uris for a parent element. */ public Hashtable getElementAttributes() { return elementAttributes; } /** * Gets the root element, if the root element was set. * * @return the root element. */ // public SchemaElement getRootElement() { // return root; // } /** * returns true when the schema has global elements. * * @return true when the schema has global elements. */ public boolean hasGlobalElements() { return globalElements.size() > 0; } /** * Gets a list of referers to the element. * * @param element the elemen to get the referers for. * * @return list of referencing elements. */ public Vector getReferers(SchemaElement element) { Vector referers = new Vector(); Enumeration enumeration = globalElements.elements(); while (enumeration.hasMoreElements()) { SchemaElement elem = (SchemaElement) enumeration.nextElement(); getReferers(elem, referers, element); } return referers; } /** * Gets a list of referers to the attribute. * * @param attribute the attribute to get the referers for. * * @return list of referencing elements. */ public Vector getReferers(SchemaAttribute attribute) { Vector referers = new Vector(); Enumeration enumeration = globalElements.elements(); while (enumeration.hasMoreElements()) { SchemaElement elem = (SchemaElement) enumeration.nextElement(); getReferers(elem, referers, attribute); } return referers; } /** * Gets a list of substitues for the element. * * @param name the substitution group name to get the * substitutes for. * * @return list of substitution elements. */ // public Vector getSubstitutes( String name) { // System.out.println("XMLSchema.getSubstitutes( "+name+")"); // return (Vector)substitutions.get( name); // } /** * Check to see if the element is global. * * @param element the element to check. * * @return true when the element is a global element. */ public boolean isGlobal(SchemaElement element) { return globalElements.get(element.getUniversalName()) != null; } /** * Get the id field value. * * @return the value for the id field. */ public String getId() { return schema.getId(); } /** * Get the default attribute form field value. * * @return the default attribute form value field. */ public String getAttributeFormDefault() { if (schema.getAttributeFormDefault() == Form.Qualified) { return FORM_QUALIFIED; } else { return FORM_UNQUALIFIED; } } /** * Get the default block field value. * * @return the default block field value. */ public String getBlockDefault() { String result = null; BlockList list = schema.getBlockDefault(); if (list != null) { if (list.hasAll()) { result = BLOCK_ALL; } else if (list.hasExtension()) { result = BLOCK_EXTENSION; } else if (list.hasSubstitution()) { result = BLOCK_SUBSTITUTION; } else if (list.hasRestriction()) { result = BLOCK_RESTRICTION; } } return result; } /** * Get the default element form field value. * * @return the default element form value field. */ public String getElementFormDefault() { if (schema.getElementFormDefault() == Form.Qualified) { return FORM_QUALIFIED; } else { return FORM_UNQUALIFIED; } } /** * Get the default block field value. * * @return the default block field value. */ public String getFinalDefault() { FinalList list = schema.getFinalDefault(); String result = null; if (list != null) { if (list.hasAll()) { result = FINAL_ALL; } else if (list.hasExtension()) { result = FINAL_EXTENSION; } else if (list.hasRestriction()) { result = FINAL_RESTRICTION; } } return result; } public Vector getAnyElements() { return null; } /** * Get the target namespace value. * * @return the target namespace value. */ public String getTargetNamespace() { return schema.getTargetNamespace(); } /** * Get the version value. * * @return the version value. */ public String getVersion() { return schema.getVersion(); } /* * Get the reference element. * * @return the reference element. */ // SchemaElement getReference( ElementDecl e) { // for ( int i = 0; i < globalElements.size(); i++) { // SchemaElement ref = (SchemaElement)globalElements.elementAt(i); // // if ( e == ref.getElement()) { // return ref; // } // } // // return null; // } public Vector getElements() { return getAllElements(); } /** * Returns a list of all elements. */ public Vector getAllElements() { // System.out.println( ">>> XMLSchema.getAllElements()"); long time = System.currentTimeMillis(); if (allElements == null) { Enumeration globals = globalElements.elements(); allElements = new Vector(); while (globals.hasMoreElements()) { SchemaElement elem = (SchemaElement) globals.nextElement(); getAllElements(elem); } } Enumeration enumeration = allElements.elements(); Vector elements = new Vector(); while (enumeration.hasMoreElements()) { elements.addElement(enumeration.nextElement()); } // System.out.println( "<<< XMLSchema.getAllElements() ["+(System.currentTimeMillis()-time)+"]"); return elements; } private boolean addElement(SchemaElement element) { // ElementModel model = (ElementModel)allElements.get( element.getUniversalName()); // if ( model != null) { // element already added // model.merge( element); // return false; if (!allElements.contains(element)) { allElements.addElement(element); return true; } return false; } private void getAllElements(SchemaElement element) { // System.out.println( ">>> XMLSchema.getAllElements( "+element+")"); if (addElement(element)) { Vector elements = element.getChildElements(); if (elements != null) { for (int i = 0; i < elements.size(); i++) { SchemaElement elem = ((SchemaElement) elements.elementAt(i)); // if ( !elem.isReference() && !globalElements.containsKey( elem.getUniversalName())) { if (!elem.isReference()) { getAllElements(elem); } } } } // System.out.println( "<<< XMLSchema.getAllElements( "+element+")"); } /** * Creates a list of attribute and element names. */ private void createNames() { // elementChildren = new Hashtable(); // elementAttributes = new Hashtable(); // // elementNames = new Vector(); // attributeNames = new Vector(); // // for ( int i = 0; i < globalElements.size(); i++) { // SchemaElement elem = (SchemaElement)globalElements.elementAt( i); // // getNames( elem, elementNames, attributeNames, elem.getName(), elementChildren, elementAttributes); // } } private void getNames(SchemaElement element, Vector elementNames, Vector attributeNames, String parentElementName, Hashtable elementChildren, Hashtable elementAttributes) { Vector attributes = element.getAttributes(); Vector childAttributes = (Vector) elementAttributes.get(parentElementName); if (childAttributes == null) { childAttributes = new Vector(); elementAttributes.put(parentElementName, childAttributes); } QName ename = QName.get(element.getName(), element.getNamespace()); if (!elementNames.contains(ename)) { elementNames.addElement(ename); } if (attributes != null) { for (int i = 0; i < attributes.size(); i++) { SchemaAttribute attribute = (SchemaAttribute) attributes.elementAt(i); QName aname = QName.get(attribute.getName(), attribute.getNamespace()); if (!attributeNames.contains(aname)) { attributeNames.addElement(aname); } if (!childAttributes.contains(aname)) { childAttributes.addElement(aname); } } } Vector models = element.getModels(); if (models != null) { for (int i = 0; i < models.size(); i++) { getNames((SchemaModel) models.elementAt(i), elementNames, attributeNames, parentElementName, elementChildren, elementAttributes); } } } private void getNames(SchemaModel model, Vector elementNames, Vector attributeNames, String parentElementName, Hashtable elementChildren, Hashtable elementAttributes) { Vector models = model.getModels(); if (models != null) { for (int i = 0; i < models.size(); i++) { getNames((SchemaModel) models.elementAt(i), elementNames, attributeNames, parentElementName, elementChildren, elementAttributes); } } Vector elements = model.getElements(); Vector childElements = (Vector) elementChildren.get(parentElementName); if (childElements == null) { childElements = new Vector(); elementChildren.put(parentElementName, childElements); } if (elements != null) { for (int i = 0; i < elements.size(); i++) { SchemaElement element = ((SchemaElement) elements.elementAt(i)); boolean isGlobal = element.isReference(); if (isGlobal) { // resolve the reference to be used here but don't // continue with it... element.resolveReference(); } // System.out.println( ">>> XMLSchema.getNames()"); Vector subs = element.getSubstituteElements(); // System.out.println( "<<< XMLSchema.getNames()"); if (subs.size() > 0) { for (int j = 0; j < subs.size(); j++) { SchemaElement sub = (SchemaElement) subs.elementAt(j); QName ename = QName.get(sub.getName(), sub.getNamespace()); if (!childElements.contains(ename)) { // System.out.println( "XMLSchema add substituteElement ["+sub.getName()+"]"); childElements.addElement(ename); } } } else { QName ename = QName.get(element.getName(), element.getNamespace()); if (!childElements.contains(ename)) { childElements.addElement(ename); } } if (!isGlobal) { // the element is part of the global elements ... getNames(element, elementNames, attributeNames, element.getName(), elementChildren, elementAttributes); } } } } private static void getReferers(SchemaElement parent, Vector referers, SchemaAttribute ref) { Vector children = parent.getChildren(); for (int i = 0; i < children.size(); i++) { SchemaModel model = (SchemaModel) children.elementAt(i); getReferers(model, referers, ref); } Vector attributes = parent.getAttributes(); if (attributes != null) { for (int i = 0; i < attributes.size(); i++) { SchemaAttribute attribute = (SchemaAttribute) attributes.elementAt(i); if (attribute.equals(ref)) { if (!inList(referers, parent)) { referers.addElement(parent); } // no point checking the other attributes return; } } } } private static void getReferers(SchemaModel model, Vector referers, SchemaAttribute ref) { Vector children = model.getChildren(); for (int i = 0; i < children.size(); i++) { SchemaParticle node = (SchemaParticle) children.elementAt(i); if (node instanceof SchemaModel) { getReferers((SchemaModel) node, referers, ref); } else if (node instanceof SchemaElement) { getReferers((SchemaElement) node, referers, ref); } // else wildcard.... } } private static void getReferers(SchemaElement root, Vector referers, SchemaElement ref) { Vector children = root.getChildren(); for (int i = 0; i < children.size(); i++) { SchemaModel model = (SchemaModel) children.elementAt(i); getReferers(model, referers, ref); } if (root.equals(ref)) { SchemaElement parent = root.getParentElement(); if (parent != null) { if (!inList(referers, parent)) { referers.addElement(parent); } } } } private static void getReferers(SchemaModel model, Vector referers, SchemaElement ref) { Vector children = model.getChildren(); for (int i = 0; i < children.size(); i++) { SchemaParticle node = (SchemaParticle) children.elementAt(i); if (node instanceof SchemaModel) { getReferers((SchemaModel) node, referers, ref); } else if (node instanceof SchemaElement) { getReferers((SchemaElement) node, referers, ref); } // else wildcard.... } } private static boolean inList(Vector list, Object object) { if (list != null) { for (int i = 0; i < list.size(); i++) { if (list.elementAt(i).equals(object)) { return true; } } } return false; } private void updatePrefixes(Vector declarations, ElementInformation element) { Vector attributes = element.getAttributes(); Vector children = element.getChildElements(); for (int i = 0; i < children.size(); i++) { ElementInformation child = (ElementInformation) children.elementAt(i); for (int k = 0; k < declarations.size(); k++) { Namespace ns = (Namespace) declarations.elementAt(k); if (ns.getURI().equals(child.getNamespace())) {// && ns.getPrefix() != null && ns.getPrefix().trim().length() > 0) { child.setPrefix(ns.getPrefix()); break; } } } if (attributes != null) { for (int j = 0; j < attributes.size(); j++) { AttributeInformation attribute = (AttributeInformation) attributes.elementAt(j); for (int k = 0; k < declarations.size(); k++) { Namespace ns = (Namespace) declarations.elementAt(k); if (ns.getURI().equals(attribute.getNamespace())) { // && ns.getPrefix() != null && ns.getPrefix().trim().length() > 0) { attribute.setPrefix(ns.getPrefix()); break; } } } } } public void updatePrefixes(Vector declarations) { Vector allElements = getAllElements(); for (int i = 0; i < allElements.size(); i++) { ElementInformation model = (ElementInformation) allElements.elementAt(i); Vector attributes = model.getAttributes(); Vector children = model.getChildElements(); if (children != null) { for (int j = 0; j < children.size(); j++) { ElementInformation child = (ElementInformation) children.elementAt(j); updatePrefixes(declarations, child); for (int k = 0; k < declarations.size(); k++) { Namespace ns = (Namespace) declarations.elementAt(k); if (ns.getURI().equals(child.getNamespace())) {// && ns.getPrefix() != null && ns.getPrefix().trim().length() > 0) { child.setPrefix(ns.getPrefix()); break; } } } } if (attributes != null) { for (int j = 0; j < attributes.size(); j++) { AttributeInformation attribute = (AttributeInformation) attributes.elementAt(j); for (int k = 0; k < declarations.size(); k++) { Namespace ns = (Namespace) declarations.elementAt(k); if (ns.getURI().equals(attribute.getNamespace())) { // && ns.getPrefix() != null && ns.getPrefix().trim().length() > 0) { attribute.setPrefix(ns.getPrefix()); break; } } } } for (int j = 0; j < declarations.size(); j++) { Namespace ns = (Namespace) declarations.elementAt(j); if (ns.getURI().equals(model.getNamespace())) { // && ns.getPrefix() != null && ns.getPrefix().trim().length() > 0) { model.setPrefix(ns.getPrefix()); break; } } } } }