/******************************************************************************* * Copyright (c) 2009 MATERNA Information & Communications. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html. For further * project-related information visit http://www.ws4d.org. The most recent * version of the JMEDS framework can be obtained from * http://sourceforge.net/projects/ws4d-javame. ******************************************************************************/ package org.ws4d.java.schema; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; import org.ws4d.java.DPWSFramework; import org.ws4d.java.communication.RequestHeader; import org.ws4d.java.communication.Resource; import org.ws4d.java.communication.monitor.ResourceLoader; import org.ws4d.java.constants.SchemaConstants; import org.ws4d.java.constants.XMLConstants; import org.ws4d.java.io.xml.ElementParser; import org.ws4d.java.io.xml.XmlPullParserSupport; import org.ws4d.java.io.xml.XmlSerializerImplementation; import org.ws4d.java.structures.ArrayList; import org.ws4d.java.structures.EmptyStructures; import org.ws4d.java.structures.HashMap; import org.ws4d.java.structures.HashSet; import org.ws4d.java.structures.Iterator; import org.ws4d.java.structures.LinkedList; import org.ws4d.java.structures.List; import org.ws4d.java.structures.ReadOnlyIterator; import org.ws4d.java.structures.Set; import org.ws4d.java.types.InternetMediaType; import org.ws4d.java.types.QName; import org.ws4d.java.types.URI; import org.ws4d.java.util.StringUtil; import org.ws4d.java.wsdl.WSDLRepository; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; /** * General XML Schema class. */ public class Schema extends Annotation implements Resource { public static final Type ANY_TYPE = SchemaUtil.getAnyType(); private static final HashMap SCHEMA_CACHE = new HashMap(); private static final boolean USE_SCHEMA_CACHE = false; private String targetNamespace = ""; private HashMap elements = EmptyStructures.EMPTY_MAP; private HashMap types = EmptyStructures.EMPTY_MAP; private HashMap attributes = EmptyStructures.EMPTY_MAP; private HashMap groups = EmptyStructures.EMPTY_MAP; private HashMap attributeGroups = EmptyStructures.EMPTY_MAP; private HashMap notations = EmptyStructures.EMPTY_MAP; private List elementResolver = EmptyStructures.EMPTY_LIST; private List attributeResolver = EmptyStructures.EMPTY_LIST; private List groupResolver = EmptyStructures.EMPTY_LIST; private List attributeGroupResolver = EmptyStructures.EMPTY_LIST; private List baseResolver = EmptyStructures.EMPTY_LIST; private List referenceResolver = EmptyStructures.EMPTY_LIST; private List baseReferenceResolver = EmptyStructures.EMPTY_LIST; private List listItemTypeResolver = EmptyStructures.EMPTY_LIST; private List unionMemberResolver = EmptyStructures.EMPTY_LIST; private HashMap linkedSchemas = EmptyStructures.EMPTY_MAP; private HashMap imports = EmptyStructures.EMPTY_MAP; private Set includes = EmptyStructures.EMPTY_SET; private long lastMod = 0L; /** * Removes all entries from the schema cache. */ public static void flushSchemaCache() { synchronized (SCHEMA_CACHE) { SCHEMA_CACHE.clear(); } } public static Schema parse(XmlPullParser parser, URI fromUri, String targetNamespace, boolean loadReferencedFiles) throws XmlPullParserException, IOException, SchemaException { Schema schema; synchronized (SCHEMA_CACHE) { schema = (Schema) SCHEMA_CACHE.get(targetNamespace); } if (schema == null) { schema = new Schema(targetNamespace); schema.handleSchema(new ElementParser(parser), fromUri, loadReferencedFiles); if (loadReferencedFiles) { schema.resolveSchema(); } } else { /* * read trough entire section as we might be embedded within another * file ... */ new ElementParser(parser).consume(); } return schema; } public static Schema parse(URI fromUri) throws XmlPullParserException, IOException, SchemaException { return parse(fromUri, true); } public static Schema parse(URI fromUri, boolean loadReferencedFiles) throws XmlPullParserException, IOException, SchemaException { ResourceLoader rl = DPWSFramework.getResourceAsStream(fromUri); InputStream in = rl.getInputStream(); try { Schema schema = parse(in, fromUri, loadReferencedFiles); if (schema != null && loadReferencedFiles) { schema.resolveSchema(); } return schema; } finally { in.close(); } } public static Schema parse(InputStream in, URI fromUri, boolean loadReferencedFiles) throws XmlPullParserException, IOException, SchemaException { XmlPullParser parser = XmlPullParserSupport.getFactory().newPullParser(); parser.setInput(in, null); parser.nextTag(); String namespace = parser.getNamespace(); String name = parser.getName(); if (!XMLSCHEMA_NAMESPACE.equals(namespace) || !StringUtil.equalsIgnoreCase(SCHEMA_SCHEMA, name)) { throw new IOException("This is not an XML schema."); } String tns = parser.getAttributeValue(null, SCHEMA_TARGETNAMESPACE); Schema schema; synchronized (SCHEMA_CACHE) { schema = (Schema) SCHEMA_CACHE.get(tns); } if (schema == null) { schema = new Schema(tns); schema.handleSchema(new ElementParser(parser), fromUri, loadReferencedFiles); schema.resolveSchema(); } // we don't care about in at this point - it may be left unread ... return schema; } Schema() { this(""); } Schema(String targetNamespace) { super(); updateLastModified(); setTargetNamespace(targetNamespace); } protected synchronized void updateLastModified() { Date d = new Date(); lastMod = d.getTime(); } /* * (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { return "Schema [ targetNamespace=" + getTargetNamespace() + " ]"; } /* * (non-Javadoc) * @see org.ws4d.java.types.schema.Annotation#getSchemaIdentifier() */ public int getSchemaIdentifier() { return SchemaConstants.XSD_SCHEMA; } /* * (non-Javadoc) * @see org.ws4d.java.communication.Resource#getContentType() */ public InternetMediaType getContentType() { return InternetMediaType.getXML(); } /* * (non-Javadoc) * @see * org.ws4d.java.communication.Resource#serialize(org.ws4d.java.types.URI, * org.ws4d.java.communication.RequestHeader, java.io.InputStream, * java.io.OutputStream) */ public void serialize(URI request, RequestHeader requestHeader, InputStream requestBody, OutputStream out) throws IOException { serialize0(out); } /* * (non-Javadoc) * @see org.ws4d.java.communication.Resource#size() */ public long size() { return -1; } public String getTargetNamespace() { return targetNamespace; } public Iterator getLinkedSchemas() { return new ReadOnlyIterator(linkedSchemas.values()); } public Iterator getElements() { return new ReadOnlyIterator(elements.values()); } public Element getElement(QName name) { String namespace = name == null ? null : name.getNamespace(); if (targetNamespace.equals(namespace)) { return (Element) elements.get(name); } // try linked schemas Schema schema = (Schema) linkedSchemas.get(namespace); if (schema != null) { return schema.getElement(name); } // try to find it within an imported/linked schema at a deeper level... for (Iterator it = linkedSchemas.values().iterator(); it.hasNext();) { schema = (Schema) it.next(); Element element = schema.getElement(name); if (element != null) { return element; } } return null; } public Element getElement(String name, String namespace) { QName qn = new QName(name, namespace); return getElement(qn); } public int getElementCount() { return elements.size(); } public Iterator getTypes() { return new ReadOnlyIterator(types.values()); } public Type getType(String name, String namespace) { QName qn = new QName(name, namespace); return getType(qn); } public Type getType(QName name) { String namespace = name == null ? null : name.getNamespace(); if (XMLSCHEMA_NAMESPACE.equals(namespace)) { return SchemaUtil.getType(name); } if (targetNamespace.equals(namespace)) { return (Type) types.get(name); } // try linked schemas Schema schema = (Schema) linkedSchemas.get(namespace); if (schema != null) { return schema.getType(name); } // try to find it within an imported/linked schema at a deeper level... for (Iterator it = linkedSchemas.values().iterator(); it.hasNext();) { schema = (Schema) it.next(); Type type = schema.getType(name); if (type != null) { return type; } } return null; } public int getTypeCount() { return types.size(); } public Iterator getAttributes() { return new ReadOnlyIterator(attributes.values()); } public Attribute getAttribute(String name, String namespace) { QName qn = new QName(name, namespace); return getAttribute(qn); } public Attribute getAttribute(QName name) { String namespace = name == null ? null : name.getNamespace(); if (targetNamespace.equals(namespace)) { return (Attribute) attributes.get(name); } // try linked schemas Schema schema = (Schema) linkedSchemas.get(namespace); if (schema != null) { return schema.getAttribute(name); } // try to find it within an imported/linked schema at a deeper level... for (Iterator it = linkedSchemas.values().iterator(); it.hasNext();) { schema = (Schema) it.next(); Attribute attribute = schema.getAttribute(name); if (attribute != null) { return attribute; } } return null; } public int getAttributCount() { return attributes.size(); } public Group getGroup(String name, String namespace) { QName qn = new QName(name, namespace); return getGroup(qn); } public Group getGroup(QName name) { String namespace = name == null ? null : name.getNamespace(); if (targetNamespace.equals(namespace)) { return (Group) groups.get(name); } // try linked schemas Schema schema = (Schema) linkedSchemas.get(namespace); if (schema != null) { return schema.getGroup(name); } // try to find it within an imported/linked schema at a deeper level... for (Iterator it = linkedSchemas.values().iterator(); it.hasNext();) { schema = (Schema) it.next(); Group group = schema.getGroup(name); if (group != null) { return group; } } return null; } public int getGroupCount() { return groups.size(); } public AttributeGroup getAttributeGroup(String name, String namespace) { QName qn = new QName(name, namespace); return getAttributeGroup(qn); } public AttributeGroup getAttributeGroup(QName name) { String namespace = name == null ? null : name.getNamespace(); if (targetNamespace.equals(namespace)) { return (AttributeGroup) attributeGroups.get(name); } // try linked schemas Schema schema = (Schema) linkedSchemas.get(namespace); if (schema != null) { return schema.getAttributeGroup(name); } // try to find it within an imported/linked schema at a deeper level... for (Iterator it = linkedSchemas.values().iterator(); it.hasNext();) { schema = (Schema) it.next(); AttributeGroup attributeGroup = schema.getAttributeGroup(name); if (attributeGroup != null) { return attributeGroup; } } return null; } public int getAttributeGroupCount() { return attributeGroups.size(); } public Notation getNotation(String name) { return (Notation) notations.get(name); } public int getNotationCount() { return notations.size(); } /** * Adds an import information to this schema. * * @param targetNamespace the target namespace of the imported schema. * @param location the location. */ public void addImport(String targetNamespace, String location) { updateLastModified(); if (imports == EmptyStructures.EMPTY_MAP) { imports = new HashMap(); } imports.put(targetNamespace, location); } /** * Removes an import from this schema. * * @param targetNamespace the target namespace of the import. */ public void removeImport(String targetNamespace) { updateLastModified(); imports.remove(targetNamespace); } /** * @return */ public HashMap getImports() { if (imports.isEmpty()) { return EmptyStructures.EMPTY_MAP; } return new HashMap(imports); } public void addInclude(String schemaLocation) { updateLastModified(); if (includes == EmptyStructures.EMPTY_SET) { includes = new HashSet(); } includes.add(schemaLocation); } public Set getIncludes() { if (includes.isEmpty()) { return EmptyStructures.EMPTY_SET; } return new HashSet(includes); } public void serialize(XmlSerializer serializer) throws IOException { serialize0(serializer); } private void setTargetNamespace(String targetNamespace) { if (targetNamespace == null) { targetNamespace = ""; } if (USE_SCHEMA_CACHE) { synchronized (SCHEMA_CACHE) { SCHEMA_CACHE.remove(this.targetNamespace); this.targetNamespace = targetNamespace; SCHEMA_CACHE.put(targetNamespace, this); } } else { this.targetNamespace = targetNamespace; } } void addElement(Element e) { if (e == null) return; if (elements == EmptyStructures.EMPTY_MAP) { elements = new HashMap(); } String namespace = e.getName().getNamespace(); if (!targetNamespace.equals(namespace)) { Schema schema = (Schema) linkedSchemas.get(namespace); if (schema != null) { schema.addElement(e); } else { // try to find it within an imported/linked schema at a deeper // level... boolean linkedSchemaFound = false; for (Iterator it = linkedSchemas.values().iterator(); it.hasNext();) { schema = (Schema) it.next(); if (namespace.equals(schema.getTargetNamespace())) { linkedSchemaFound = true; schema.addElement(e); break; } } if (!linkedSchemaFound) { // create a new linked schema for the new namespace Schema childSchema = new Schema(namespace); childSchema.addElement(e); addLinkedSchema(childSchema); } } return; } elements.put(e.getName(), e); Type t = e.getType(); if (t != null) { if (t.getName() != null) { addType(t); } else { addType(t, namespace); } } } public void addType(Type t) { if (t == null) return; updateLastModified(); addType(t, t.getName().getNamespace()); } private void addType(Type t, String namespace) { if (SchemaConstants.XMLSCHEMA_NAMESPACE.equals(namespace)) { return; } if (types == EmptyStructures.EMPTY_MAP) { types = new HashMap(); } // String namespace = t.getName().getNamespace(); if (!targetNamespace.equals(namespace)) { if (t.getName() != null) { Schema schema = (Schema) linkedSchemas.get(namespace); if (schema != null) { schema.addType(t); } else { // try to find it within an imported/linked schema at a // deeper level... boolean linkedSchemaFound = false; for (Iterator it = linkedSchemas.values().iterator(); it.hasNext();) { schema = (Schema) it.next(); if (namespace.equals(schema.getTargetNamespace())) { linkedSchemaFound = true; schema.addType(t); break; } } if (!linkedSchemaFound) { Schema childSchema = new Schema(namespace); childSchema.addType(t, namespace); addLinkedSchema(childSchema); } } } return; } if (t.getName() != null) types.put(t.getName(), t); // handle base types int schemaId = t.getSchemaIdentifier(); if (schemaId == SchemaConstants.XSD_COMPLEXTYPE || schemaId == SchemaConstants.XSD_EXTENDEDCOMPLEXCONTENT || schemaId == SchemaConstants.XSD_RESTRICTEDCOMPLEXCONTENT) { ComplexType ct = (ComplexType) t; // Fixed: base type added to schema if (schemaId == SchemaConstants.XSD_EXTENDEDCOMPLEXCONTENT) { ExtendedComplexContent ecc = (ExtendedComplexContent) ct; addType(ecc.getBase()); } else if (schemaId == SchemaConstants.XSD_RESTRICTEDCOMPLEXCONTENT) { RestrictedComplexContent rcc = (RestrictedComplexContent) ct; addType(rcc.getBase()); } Iterator elements = ct.elements(); while (elements.hasNext()) { Any anyInnerElement = (Any) elements.next(); if (anyInnerElement.getSchemaIdentifier() == SchemaConstants.XSD_ELEMENT) { Element innerElement = (Element) anyInnerElement; Type innerType = innerElement.getType(); if (innerType != null) { if (innerType.getName() != null) { if (!types.containsKey(innerType.getName())) { addType(innerType); } } else { addType(innerType, namespace); } } } } } } private void addAttribute(Attribute a) { if (a == null) return; if (attributes == EmptyStructures.EMPTY_MAP) { attributes = new HashMap(); } attributes.put(a.getName(), a); Type t = a.getType(); if (t != null) { if (t.getName() != null) { addType(t); } else { addType(t, a.getName().getNamespace()); } } } private void addGroup(Group g) { if (g == null) return; if (groups == EmptyStructures.EMPTY_MAP) { groups = new HashMap(); } groups.put(g.getName(), g); } private void addAttributeGroup(AttributeGroup g) { if (g == null) return; if (attributeGroups == EmptyStructures.EMPTY_MAP) { attributeGroups = new HashMap(); } attributeGroups.put(g.getName(), g); } private void addNotation(Notation n) { if (n == null) return; if (notations == EmptyStructures.EMPTY_MAP) { notations = new HashMap(); } notations.put(n.getName(), n); } void addElementForResolve(Element e) { if (e == null) return; if (elementResolver == EmptyStructures.EMPTY_LIST) { elementResolver = new LinkedList(); } elementResolver.add(e); } void addAttributeForResolve(Attribute e) { if (e == null) return; if (attributeResolver == EmptyStructures.EMPTY_LIST) { attributeResolver = new LinkedList(); } attributeResolver.add(e); } void addGroupForResolve(Group g) { if (g == null) return; if (groupResolver == EmptyStructures.EMPTY_LIST) { groupResolver = new LinkedList(); } groupResolver.add(g); } void addAttributeGroupForResolve(AttributeGroup g) { if (g == null) return; if (attributeGroupResolver == EmptyStructures.EMPTY_LIST) { attributeGroupResolver = new LinkedList(); } attributeGroupResolver.add(g); } void addBaseForResolve(InheritType t) { if (t == null) return; if (baseResolver == EmptyStructures.EMPTY_LIST) { baseResolver = new LinkedList(); } baseResolver.add(t); } void addListForResolve(SimpleType list) { if (list == null) return; if (listItemTypeResolver == EmptyStructures.EMPTY_LIST) { listItemTypeResolver = new LinkedList(); } listItemTypeResolver.add(list); } void addUnionForResolve(SimpleType union) { if (union == null) return; if (unionMemberResolver == EmptyStructures.EMPTY_LIST) { unionMemberResolver = new LinkedList(); } unionMemberResolver.add(union); } void addReferenceElement(Element e) { if (elements.containsKey(e.getName())) { return; } if (referenceResolver == EmptyStructures.EMPTY_LIST) { referenceResolver = new LinkedList(); } if (!referenceResolver.contains(e) && !elements.containsValue(e)) { referenceResolver.add(e); } } void addBaseReference(Type t) { if (types.containsKey(t.getName())) { return; } if (baseReferenceResolver == EmptyStructures.EMPTY_LIST) { baseReferenceResolver = new LinkedList(); } if (!baseReferenceResolver.contains(t) && !types.containsValue(t)) { baseReferenceResolver.add(t); } } void resolveSchema() throws SchemaException { resolveElements(); resolveAttributes(); resolveGroups(); resolveAttributeGroups(); resolveListItemTypes(); resolveUnionMemberTypes(); resolveBaseTypes(); } private void serialize0(OutputStream out) throws IOException { XmlSerializer serializer = new XmlSerializerImplementation(); // serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", // true); serializer.setOutput(out, XMLConstants.ENCODING); serializer.startDocument(XMLConstants.ENCODING, null); serialize0(serializer); serializer.endDocument(); } private void serialize0(XmlSerializer serializer) throws IOException { String prefix = serializer.getPrefix(XMLSCHEMA_NAMESPACE, false); if (prefix == null) { serializer.setPrefix(XMLSCHEMA_PREFIX, XMLSCHEMA_NAMESPACE); } if (!"".equals(targetNamespace)) { prefix = serializer.getPrefix(targetNamespace, false); if (prefix == null) { serializer.setPrefix(XMLConstants.XMLNS_TARGETNAMESPACE_PREFIX, targetNamespace); } } serializer.startTag(XMLSCHEMA_NAMESPACE, SCHEMA_SCHEMA); // set prefixes for all used namespaces!!! if (linkedSchemas != null) { for (Iterator it = linkedSchemas.values().iterator(); it.hasNext();) { Schema s = (Schema) it.next(); serializer.getPrefix(s.getTargetNamespace(), true); } } if (!"".equals(targetNamespace)) { serializer.attribute(null, SCHEMA_TARGETNAMESPACE, targetNamespace); } serializer.attribute(null, SCHEMA_ELEMENTFORMDEFAULT, SCHEMA_QUALIFIED); serializer.attribute(null, SCHEMA_ATTRIBUTEFORMDEFAULT, SCHEMA_UNQUALIFIED); if (imports.size() > 0) { Set entries = imports.entrySet(); Iterator it = entries.iterator(); while (it.hasNext()) { HashMap.Entry entry = (HashMap.Entry) it.next(); String iTNS = (String) entry.getKey(); String iLocation = (String) entry.getValue(); serializer.startTag(XMLSCHEMA_NAMESPACE, SCHEMA_IMPORT); serializer.attribute(null, SCHEMA_NAMESPACE, iTNS); serializer.attribute(null, SCHEMA_LOCATION, iLocation); serializer.endTag(XMLSCHEMA_NAMESPACE, SCHEMA_IMPORT); } } for (Iterator it = elements.values().iterator(); it.hasNext();) { Element element = (Element) it.next(); element.serialize(serializer, this); } for (Iterator it = types.values().iterator(); it.hasNext();) { Type type = (Type) it.next(); type.serialize(serializer, this); } for (Iterator it = attributes.values().iterator(); it.hasNext();) { Attribute attribute = (Attribute) it.next(); attribute.serialize(serializer, this); } for (Iterator it = groups.values().iterator(); it.hasNext();) { Group group = (Group) it.next(); group.serialize(serializer, this); } for (Iterator it = attributeGroups.values().iterator(); it.hasNext();) { AttributeGroup attributeGroup = (AttributeGroup) it.next(); attributeGroup.serialize(serializer, this); } resolveReferences(serializer); /* * Resolve subtypes */ ArrayList subTypes = new ArrayList(); for (Iterator it = types.values().iterator(); it.hasNext();) { Type t = (Type) it.next(); Iterator iterSub = t.getKownSubtypes(); while (iterSub.hasNext()) { Type subType = (Type) iterSub.next(); subTypes.add(subType); } } while (!subTypes.isEmpty()) { Type type = (Type) subTypes.remove(0); for (Iterator iter = type.getKownSubtypes(); iter.hasNext();) { Type subType = (Type) iter.next(); subTypes.add(subType); } // serialize type QName typeName = type.getName(); if (typeName != null && !types.containsKey(typeName)) { addType(type); /* * TODO Check this! Why we should serialize types which are part * of an other schema? */ if (targetNamespace != null && targetNamespace.equals(typeName.getNamespace())) { type.serialize(serializer, this); } } } serializer.endTag(XMLSCHEMA_NAMESPACE, SCHEMA_SCHEMA); } // modified resolving algorithm in accordance with patch submitted by Stefan // Schlichting private void resolveReferences(XmlSerializer serializer) throws IOException { LinkedList tempRefResolver = new LinkedList(); LinkedList removeList = new LinkedList(); LinkedList alreadySerializedTypes = new LinkedList(); if (!types.isEmpty()) { alreadySerializedTypes.addAll(types.values()); } while (!referenceResolver.isEmpty() || !baseReferenceResolver.isEmpty()) { List ntypes = new LinkedList(); tempRefResolver.addAll(referenceResolver); tempRefResolver.addAll(baseReferenceResolver); for (Iterator it = tempRefResolver.iterator(); it.hasNext();) { Object o = it.next(); if (o instanceof Element) { Element element = (Element) o; if (elements.containsValue(element)) { removeList.add(element); continue; } element.serialize(serializer, this); if (elements == EmptyStructures.EMPTY_MAP) elements = new HashMap(); elements.put(element.getName(), element); removeList.add(element); Type t = element.getType(); if (t.getName() != null) { String namespace = t.getName().getNamespace(); if (types != null && !types.containsValue(t) && !XMLSCHEMA_NAMESPACE.equals(namespace)) { /* * Collect type which where not serialized in the * first step. */ ntypes.add(t); } } } else { if (o instanceof SimpleType) { SimpleType st = (SimpleType) o; if (!XMLSCHEMA_NAMESPACE.equals(st.getName().getNamespace())) { st.serialize(serializer, this); } } removeList.add(o); } } tempRefResolver.clear(); for (Iterator it = removeList.iterator(); it.hasNext();) { Object o = it.next(); if (referenceResolver != EmptyStructures.EMPTY_LIST) referenceResolver.remove(o); if (baseReferenceResolver != EmptyStructures.EMPTY_LIST) baseReferenceResolver.remove(o); } removeList.clear(); // Bugfix 2010-07-15 SSch if (!ntypes.isEmpty() && types == EmptyStructures.EMPTY_MAP) { types = new HashMap(); } /* * Serialize the new types. This type where found while serializing * the references. */ for (Iterator it = ntypes.iterator(); it.hasNext();) { Type type = (Type) it.next(); addType(type); // type.serialize(serializer, this); // types.put(type.getName(), type); } if (!types.isEmpty()) { Iterator ut = types.values().iterator(); while (ut.hasNext()) { Type t = (Type) ut.next(); if (!alreadySerializedTypes.contains(t)) { t.serialize(serializer, this); alreadySerializedTypes.add(t); } } } } } // private void resolveReferences(XmlSerializer serializer) throws // IOException { // /* // * Resolve references // */ // Set refTypes = new HashSet(); // /* // * this is for recursively added references or base references during // * resolving other ones :-P // */ // while (!refTypes.isEmpty() || !referenceResolver.isEmpty() || // !baseReferenceResolver.isEmpty()) { // while (!referenceResolver.isEmpty()) { // Element element = (Element) referenceResolver.remove(0); // QName elementName = element.getName(); // if (elements.containsKey(elementName)) { // continue; // } // if (elementName.getNamespace().equals(targetNamespace)) { // elements.put(elementName, element); // element.serialize(serializer, this); // Type t = element.getType(); // if (t.getName() != null) { // String namespace = t.getName().getNamespace(); // if (!types.containsValue(t) && !XMLSCHEMA_NAMESPACE.equals(namespace)) { // /* // * Collect type which where not serialized in the // * first step. // */ // refTypes.add(t); // } // } // } // } // // while (!baseReferenceResolver.isEmpty()) { // Type type = (Type) baseReferenceResolver.remove(0); // QName typeName = type.getName(); // if (types.containsKey(typeName) || refTypes.contains(type)) { // continue; // } // if (typeName != null) { // String namespace = typeName.getNamespace(); // if (!XMLSCHEMA_NAMESPACE.equals(namespace)) { // /* // * Collect type which where not serialized in the first // * step. // */ // refTypes.add(type); // } // } // } // // /* // * Serialize the new types. This type where found while serializing // * the references. // */ // for (Iterator it = refTypes.iterator(); it.hasNext();) { // Type type = (Type) it.next(); // addType(type); // type.serialize(serializer, this); // it.remove(); // } // } // } private void resolveElements() throws SchemaException { if (elementResolver == null) return; if (elementResolver.size() > 0) { for (Iterator it = elementResolver.iterator(); it.hasNext();) { Element e = (Element) it.next(); QName ref = e.getReferenceLink(); if (ref != null) { Element reference = getElement(ref); if (reference != null) { e.setReference(reference); continue; } } QName typeLink = e.getTypeLink(); if (typeLink != null) { Type type = getType(typeLink); if (type != null) { e.setType(type); continue; } } throw new SchemaException("Cannot resolve element: " + e + " within " + targetNamespace); } } elementResolver = null; } private void resolveAttributes() throws SchemaException { if (attributeResolver == null) return; if (attributeResolver.size() > 0) { for (Iterator it = attributeResolver.iterator(); it.hasNext();) { Attribute a = (Attribute) it.next(); QName ref = a.getReferenceLink(); if (ref != null) { Attribute reference = getAttribute(ref); if (reference != null) { a.setReference(reference); continue; } } QName typeLink = a.getTypeLink(); if (typeLink != null) { Type type = getType(typeLink); if (type != null) { a.setType(type); continue; } } throw new SchemaException("Cannot resolve attribute: " + a); } } attributeResolver = null; } private void resolveGroups() throws SchemaException { if (groupResolver == null) return; if (groupResolver.size() > 0) { for (Iterator it = groupResolver.iterator(); it.hasNext();) { Group g = (Group) it.next(); QName ref = g.getReferenceLink(); if (ref != null) { Group reference = getGroup(ref); if (reference != null) { g.setReference(reference); continue; } } throw new SchemaException("Cannot resolve group: " + g); } } groupResolver = null; } private void resolveAttributeGroups() throws SchemaException { if (attributeGroupResolver == null) return; if (attributeGroupResolver.size() > 0) { for (Iterator it = attributeGroupResolver.iterator(); it.hasNext();) { AttributeGroup g = (AttributeGroup) it.next(); QName ref = g.getReferenceLink(); if (ref != null) { AttributeGroup reference = getAttributeGroup(ref); if (reference != null) { g.setReference(reference); continue; } } throw new SchemaException("Cannot resolve attribute group: " + g); } } attributeGroupResolver = null; } private void resolveListItemTypes() throws SchemaException { if (listItemTypeResolver == null) return; if (listItemTypeResolver.size() > 0) { for (Iterator it = listItemTypeResolver.iterator(); it.hasNext();) { SimpleType list = (SimpleType) it.next(); QName ref = list.getListItemLink(); if (ref != null) { Type reference = getType(ref); if (reference != null) { list.setListItemType(reference); continue; } } throw new SchemaException("Cannot resolve list item type: " + list); } } listItemTypeResolver = null; } private void resolveUnionMemberTypes() throws SchemaException { if (unionMemberResolver == null) return; if (unionMemberResolver.size() > 0) { for (Iterator it = unionMemberResolver.iterator(); it.hasNext();) { SimpleType union = (SimpleType) it.next(); List members = new ArrayList(); for (Iterator it2 = union.getMemberLinks(); it2.hasNext();) { QName ref = (QName) it2.next(); if (ref != null) { Type reference = getType(ref); if (reference != null) { members.add(reference); continue; } } throw new SchemaException("Cannot resolve union member types: " + union); } union.insertMembers(members); } } unionMemberResolver = null; } private void resolveBaseTypes() throws SchemaException { if (baseResolver == null) return; if (baseResolver.size() > 0) { for (Iterator it = baseResolver.iterator(); it.hasNext();) { InheritType t = (InheritType) it.next(); QName baseLink = null; if (t instanceof RestrictedSimpleContent) { baseLink = ((RestrictedSimpleContent) t).getBaseLink(); } else if (t instanceof RestrictedComplexContent) { baseLink = ((RestrictedComplexContent) t).getBaseLink(); } else if (t instanceof ExtendedSimpleContent) { baseLink = ((ExtendedSimpleContent) t).getBaseLink(); } else if (t instanceof ExtendedComplexContent) { baseLink = ((ExtendedComplexContent) t).getBaseLink(); } else if (t instanceof RestrictedSimpleType) { baseLink = ((RestrictedSimpleType) t).getBaseLink(); } if (baseLink != null) { Type base = getType(baseLink); if (base != null) { t.setBase(base); continue; } } throw new SchemaException("Cannot resolve the base for: " + t); } } baseResolver = null; } private void handleSchema(ElementParser parser, URI fromUri, boolean loadReferencedFiles) throws XmlPullParserException, IOException, SchemaException { int d = parser.getDepth(); /* * check depth and allow this method only to handle it. no diving * inside. */ while (parser.nextTag() != XmlPullParser.END_TAG && parser.getDepth() == d + 1) { String namespace = parser.getNamespace(); String name = parser.getName(); if (XMLSCHEMA_NAMESPACE.equals(namespace)) { if (StringUtil.equalsIgnoreCase(Element.TAG_ELEMENT, name)) { Element e = Element.createElement(parser, targetNamespace, this, true); addElement(e); } else if (StringUtil.equalsIgnoreCase(ComplexType.TAG_COMPLEXTYPE, name)) { Type t = ComplexType.createComplexType(parser, targetNamespace, this); addType(t); } else if (StringUtil.equalsIgnoreCase(SimpleType.TAG_SIMPLETYPE, name)) { Type t = SimpleType.createSimpleType(parser, targetNamespace, this); addType(t); } else if (StringUtil.equalsIgnoreCase(Attribute.TAG_ATTRIBUTE, name)) { Attribute a = Attribute.createAttribute(parser, targetNamespace, this); addAttribute(a); } else if (StringUtil.equalsIgnoreCase(Group.TAG_GROUP, name)) { Group g = Group.createGroup(parser, targetNamespace, this); addGroup(g); } else if (StringUtil.equalsIgnoreCase(AttributeGroup.TAG_ATTRIBUTEGROUP, name)) { AttributeGroup g = AttributeGroup.createAttributeGroup(parser, targetNamespace, this); addAttributeGroup(g); } else if (StringUtil.equalsIgnoreCase(Annotation.TAG_ANNOTATION, name)) { Annotation.handleAnnotation(parser, this); } else if (StringUtil.equalsIgnoreCase(Notation.TAG_NOTATION, name)) { Notation n = Notation.createNotation(parser); addNotation(n); } else if (StringUtil.equalsIgnoreCase(SCHEMA_INCLUDE, name)) { String schemaLocation = parser.getAttributeValue(null, SCHEMA_LOCATION); Schema s; if (fromUri == null) { new ElementParser(parser).consume(); s = WSDLRepository.getInstance().getSchema(schemaLocation, getTargetNamespace()); } else { URI newUri = URI.absolutize(fromUri, schemaLocation); s = SchemaUtil.includeOrImportSchema(parser, newUri, loadReferencedFiles); } if (s != null) { if (!getTargetNamespace().equals(s.targetNamespace)) { throw new SchemaException("Cannot include " + schemaLocation + " with different target namespace. Try to import."); } if (loadReferencedFiles) { s.resolveSchema(); } mergeSchema(s, this); // addLinkedSchema(s); } addInclude(schemaLocation); } else if (StringUtil.equalsIgnoreCase(SCHEMA_IMPORT, name)) { String nNamespace = parser.getAttributeValue(null, SCHEMA_NAMESPACE); String schemaLocation = parser.getAttributeValue(null, SCHEMA_LOCATION); if (loadReferencedFiles) { Schema s; if (fromUri == null) { new ElementParser(parser).consume(); s = WSDLRepository.getInstance().getSchema(schemaLocation, nNamespace); } else { URI newUri = URI.absolutize(fromUri, schemaLocation); s = SchemaUtil.includeOrImportSchema(parser, newUri, true); if (nNamespace != null && !nNamespace.equals(s.targetNamespace)) { throw new SchemaException("Import schema from " + schemaLocation + " doesn't match expected target namespace " + nNamespace + "."); } } if (s != null) { s.resolveSchema(); // mergeSchema(s, schema); addLinkedSchema(s); } } else { new ElementParser(parser).consume(); } addImport(nNamespace, schemaLocation); } } } } private void mergeSchema(Schema src, Schema dest) { if (src.imports.size() > 0) { if (dest.imports == EmptyStructures.EMPTY_MAP) { dest.imports = new HashMap(); } dest.imports.putAll(src.imports); } if (src.types.size() > 0) { if (dest.types == EmptyStructures.EMPTY_MAP) { dest.types = new HashMap(); } dest.types.putAll(src.types); } if (src.elements.size() > 0) { if (dest.elements == EmptyStructures.EMPTY_MAP) { dest.elements = new HashMap(); } dest.elements.putAll(src.elements); } if (src.attributes.size() > 0) { if (dest.attributes == EmptyStructures.EMPTY_MAP) { dest.attributes = new HashMap(); } dest.attributes.putAll(src.attributes); } if (src.attributeGroups.size() > 0) { if (dest.attributeGroups == EmptyStructures.EMPTY_MAP) { dest.attributeGroups = new HashMap(); } dest.attributeGroups.putAll(src.attributeGroups); } if (src.groups.size() > 0) { if (dest.groups == EmptyStructures.EMPTY_MAP) { dest.groups = new HashMap(); } dest.groups.putAll(src.groups); } } private void addLinkedSchema(Schema s) { if (linkedSchemas == EmptyStructures.EMPTY_MAP) { linkedSchemas = new HashMap(); } linkedSchemas.put(s.getTargetNamespace(), s); } /* * (non-Javadoc) * @see org.ws4d.java.communication.Resource#getHeaderFields() */ public HashMap getHeaderFields() { return null; } /* * (non-Javadoc) * @see org.ws4d.java.communication.Resource#shortDescription() */ public String shortDescription() { return "XSD [ " + getTargetNamespace() + " ]"; } /* (non-Javadoc) * @see org.ws4d.java.communication.Resource#getLastModifiedDate() */ public long getLastModifiedDate() { return lastMod; } }