/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2004-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.xml.handlers.xsi; import java.net.URI; import java.net.URISyntaxException; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeSet; import org.geotools.xml.SchemaFactory; import org.geotools.xml.XSIElementHandler; import org.geotools.xml.schema.All; import org.geotools.xml.schema.Attribute; import org.geotools.xml.schema.AttributeGroup; import org.geotools.xml.schema.Choice; import org.geotools.xml.schema.ComplexType; import org.geotools.xml.schema.Element; import org.geotools.xml.schema.ElementGrouping; import org.geotools.xml.schema.Facet; import org.geotools.xml.schema.Group; import org.geotools.xml.schema.Schema; import org.geotools.xml.schema.Sequence; import org.geotools.xml.schema.SimpleType; import org.geotools.xml.schema.Type; import org.geotools.xml.xsi.XSISimpleTypes; import org.xml.sax.Attributes; import org.xml.sax.SAXException; /** * SchemaHandler purpose. * <p> * represents a Schema element * </p> * * @author dzwiers, Refractions Research, Inc. http://www.refractions.net * @author $Author:$ (last modification) * * @source $URL$ * @version $Id$ */ public class SchemaHandler extends XSIElementHandler { /** "http://www.w3.org/2001/XMLSchema" */ public static final String namespaceURI = "http://www.w3.org/2001/XMLSchema"; /** 'schema' */ public final static String LOCALNAME = "schema"; private String id; private String prefix; private URI targetNamespace; private String version; private boolean elementFormDefault; private boolean attributeFormDefault; private int finalDefault; private int blockDefault; private List includes; private List imports; private List redefines; private List attributes; private List attributeGroups; private List complexTypes; private List elements; private List groups; private List simpleTypes; private URI uri; private Schema schema = null; private HashMap prefixCache; /** * @see java.lang.Object#hashCode() */ public int hashCode() { return LOCALNAME.hashCode() * ((id == null) ? 1 : id.hashCode()) * ((version == null) ? 1 : version.hashCode()) * ((targetNamespace == null) ? 1 : targetNamespace.hashCode()); } /** * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) */ public void startPrefixMapping( String pref, String uri1 ) { if (targetNamespace == null) { if (prefixCache == null) { prefixCache = new HashMap(); } if( !pref.trim().equals("") || !prefixCache.containsKey(uri1) ) prefixCache.put(uri1, pref); if (this.uri == null && (pref == null || "".equals(pref))) try { this.uri = new URI(uri1); } catch (URISyntaxException e) { logger.warning(e.getMessage()); } } else { // we have already started if (targetNamespace.equals(uri1.toString())) { prefix = pref; } } } /** * @see org.geotools.xml.XSIElementHandler#startElement(java.lang.String, java.lang.String, org.xml.sax.Attributes) */ public void startElement( String namespaceURI1, String localName, Attributes atts ) throws SAXException { // targetNamespace String targetNamespace1 = atts.getValue("", "targetNamespace"); if (targetNamespace1 == null) { targetNamespace1 = atts.getValue(namespaceURI1, "targetNamespace"); } try { this.targetNamespace = new URI(targetNamespace1); } catch (URISyntaxException e) { logger.warning(e.toString()); throw new SAXException(e); } if ((prefixCache != null) && (targetNamespace1 != null) && (!targetNamespace1.equals(""))) { Iterator i = prefixCache.keySet().iterator(); while( (i != null) && i.hasNext() ) { String uriT = (String) i.next(); if (targetNamespace1.equals(uriT)) { prefix = (String) prefixCache.get(uriT); i = null; } } } // prefixCache = null; // attributeFormDefault String attributeFormDefault1 = atts.getValue("", "attributeFormDefault"); if (attributeFormDefault1 == null) { attributeFormDefault1 = atts.getValue(namespaceURI1, "attributeFormDefault"); } this.attributeFormDefault = "qualified".equalsIgnoreCase(attributeFormDefault1); // blockDefault String blockDefault1 = atts.getValue("", "blockDefault"); if (blockDefault1 == null) { blockDefault1 = atts.getValue(namespaceURI1, "blockDefault"); } this.blockDefault = ComplexTypeHandler.findBlock(blockDefault1); // elementFormDefault String elementFormDefault1 = atts.getValue("", "elementFormDefault"); if (elementFormDefault1 == null) { elementFormDefault1 = atts.getValue(namespaceURI1, "elementFormDefault"); } this.elementFormDefault = "qualified".equalsIgnoreCase(elementFormDefault1); // finalDefault String finalDefault1 = atts.getValue("", "finalDefault"); if (finalDefault1 == null) { finalDefault1 = atts.getValue(namespaceURI1, "finalDefault"); } this.finalDefault = SimpleTypeHandler.findFinal(finalDefault1); // id id = atts.getValue("", "id"); if (id == null) { id = atts.getValue(namespaceURI1, "id"); } // version version = atts.getValue("", "version"); if (version == null) { version = atts.getValue(namespaceURI1, "version"); } } /** * @see org.geotools.xml.XSIElementHandler#getHandler(java.lang.String, java.lang.String) */ public XSIElementHandler getHandler( String namespaceURI1, String localName ) { // check that we are working with a known namespace if (SchemaHandler.namespaceURI.equalsIgnoreCase(namespaceURI1)) { // child elements: // // This list order has been picked in an adhock manner // attempting to improve performance. Re-order the // child elements if this order does not appear optimal. // complexType if (ComplexTypeHandler.LOCALNAME.equalsIgnoreCase(localName)) { if (complexTypes == null) { complexTypes = new LinkedList(); } ComplexTypeHandler cth = new ComplexTypeHandler(); complexTypes.add(cth); return cth; } // simpleType if (SimpleTypeHandler.LOCALNAME.equalsIgnoreCase(localName)) { if (simpleTypes == null) { simpleTypes = new LinkedList(); } SimpleTypeHandler sth = new SimpleTypeHandler(); simpleTypes.add(sth); return sth; } // element if (ElementTypeHandler.LOCALNAME.equalsIgnoreCase(localName)) { if (elements == null) { elements = new LinkedList(); } ElementTypeHandler eth = new ElementTypeHandler(); elements.add(eth); return eth; } // attribute if (AttributeHandler.LOCALNAME.equalsIgnoreCase(localName)) { if (attributes == null) { attributes = new LinkedList(); } AttributeHandler ah = new AttributeHandler(); attributes.add(ah); return ah; } // include if (IncludeHandler.LOCALNAME.equalsIgnoreCase(localName)) { if (includes == null) { includes = new LinkedList(); } IncludeHandler ih = new IncludeHandler(); includes.add(ih); return ih; } // import if (ImportHandler.LOCALNAME.equalsIgnoreCase(localName)) { if (imports == null) { imports = new LinkedList(); } ImportHandler ih = new ImportHandler(); imports.add(ih); return ih; } // group if (GroupHandler.LOCALNAME.equalsIgnoreCase(localName)) { if (groups == null) { groups = new LinkedList(); } GroupHandler gh = new GroupHandler(); groups.add(gh); return gh; } // redefine if (RedefineHandler.LOCALNAME.equalsIgnoreCase(localName)) { if (redefines == null) { redefines = new LinkedList(); } RedefineHandler rh = new RedefineHandler(); redefines.add(rh); return rh; } // attributeGroup if (AttributeGroupHandler.LOCALNAME.equalsIgnoreCase(localName)) { if (attributeGroups == null) { attributeGroups = new LinkedList(); } AttributeGroupHandler agh = new AttributeGroupHandler(); attributeGroups.add(agh); return agh; } } return null; } /** * @see org.geotools.xml.XSIElementHandler#getLocalName() */ public String getLocalName() { return LOCALNAME; } /** * <p> * creates a smaller, more compact version of the schema * </p> * * @param thisURI * @throws SAXException */ protected Schema compress( URI thisURI ) throws SAXException { if (schema != null) { return schema; // already compressed. } if (uri == null) { uri = thisURI; } else { if (thisURI != null) { uri = thisURI.resolve(uri); } } if (prefix == null && prefixCache != null) { prefix = (String) prefixCache.get(targetNamespace); } Iterator it = null; if (includes != null) { // do these first it = includes.iterator(); while( it.hasNext() ) { IncludeHandler inc = (IncludeHandler) it.next(); logger.finest("compressing include " + inc.getSchemaLocation()); if (inc != null && inc.getSchemaLocation() != null) { Schema cs; URI incURI = null; if (thisURI == null) { try { incURI = new URI(inc.getSchemaLocation()); } catch (URISyntaxException e) { logger.warning(e.getMessage()); } } else { incURI = thisURI.normalize().resolve(inc.getSchemaLocation()); } cs = SchemaFactory.getInstance(targetNamespace, incURI, logger.getLevel()); if (uri != null) { uri = incURI.resolve(uri); } else { uri = incURI; } // already compressed addSchema(cs); } } } includes = null; // imports may be schema or schemaHandler if (this.imports != null) { // have now loaded the included stuff. LinkedList imports1 = new LinkedList(); it = this.imports.iterator(); while( it.hasNext() ) { Object obj = it.next(); if (obj instanceof ImportHandler) { ImportHandler imp = (ImportHandler) obj; URI incURI = null; // if ((imp.getSchemaLocation() != null) && (thisURI != null)) { // incURI = thisURI.normalize().resolve(imp // .getSchemaLocation()); // } // fix from chris dillard if (imp.getSchemaLocation() != null) { if (thisURI != null) { // For resolving relative URIs incURI = thisURI.normalize().resolve(imp.getSchemaLocation()); } else { // If thisURI is null, we have to assume the // URI is absolute. incURI = imp.getSchemaLocation(); } } Schema cs = SchemaFactory.getInstance(imp.getNamespace(), incURI, logger.getLevel()); imports1.add(cs); } else { imports1.add(obj); } } this.imports = imports1; } // TODO redefines? // should do over-writing here // build schema object ... be thrown out DefaultSchema schema1 = new DefaultSchema(); schema1.attributeFormDefault = attributeFormDefault; schema1.elementFormDefault = elementFormDefault; schema1.finalDefault = finalDefault; schema1.blockDefault = blockDefault; schema1.id = id; schema1.prefix = prefix; schema1.targetNamespace = targetNamespace; schema1.version = version; schema1.uri = uri; if (imports != null) { TreeSet tmp = new TreeSet(SchemaComparator.getInstance()); tmp.addAll(imports); schema1.imports = (Schema[]) tmp.toArray(new Schema[tmp.size()]); } // these need to be retyped if (simpleTypes != null) { it = simpleTypes.iterator(); HashSet cache = new HashSet(); while( it.hasNext() ) { Object t = it.next(); if (t instanceof SimpleTypeHandler) { SimpleTypeHandler tt = (SimpleTypeHandler) t; cache.add(tt.compress(this)); it.remove(); } } it = cache.iterator(); while( it.hasNext() ) simpleTypes.add(it.next()); TreeSet tmp = new TreeSet(SchemaComparator.getInstance()); tmp.addAll(simpleTypes); schema1.simpleTypes = (SimpleType[]) tmp.toArray(new SimpleType[tmp.size()]); } if (attributeGroups != null) { it = attributeGroups.iterator(); HashSet cache = new HashSet(); while( it.hasNext() ) { Object t = it.next(); if (t instanceof AttributeGroupHandler) { AttributeGroupHandler tt = (AttributeGroupHandler) t; cache.add(tt.compress(this)); it.remove(); } } it = cache.iterator(); while( it.hasNext() ) attributeGroups.add(it.next()); TreeSet tmp = new TreeSet(SchemaComparator.getInstance()); tmp.addAll(attributeGroups); schema1.attributeGroups = (AttributeGroup[]) tmp.toArray(new AttributeGroup[tmp .size()]); } if (attributes != null) { it = attributes.iterator(); HashSet cache = new HashSet(); while( it.hasNext() ) { Object t = it.next(); if (t instanceof AttributeHandler) { AttributeHandler tt = (AttributeHandler) t; cache.add(tt.compress(this)); it.remove(); } } it = cache.iterator(); while( it.hasNext() ) attributes.add(it.next()); TreeSet tmp = new TreeSet(SchemaComparator.getInstance()); tmp.addAll(attributes); schema1.attributes = (Attribute[]) tmp.toArray(new Attribute[tmp.size()]); } if (complexTypes != null) { it = complexTypes.iterator(); HashSet cache = new HashSet(); while( it.hasNext() ) { Object t = it.next(); if (t instanceof ComplexTypeHandler) { ComplexTypeHandler tt = (ComplexTypeHandler) t; cache.add(tt.compress(this)); } } complexTypes.clear(); it = cache.iterator(); while( it.hasNext() ) complexTypes.add(it.next()); TreeSet tmp = new TreeSet(SchemaComparator.getInstance()); tmp.addAll(complexTypes); schema1.complexTypes = (ComplexType[]) tmp.toArray(new ComplexType[tmp.size()]); } if (elements != null) { it = elements.iterator(); HashSet cache = new HashSet(); while( it.hasNext() ) { Object t = it.next(); if (t instanceof ElementTypeHandler) { ElementTypeHandler tt = (ElementTypeHandler) t; cache.add(tt.compress(this)); it.remove(); } } it = cache.iterator(); while( it.hasNext() ) elements.add(it.next()); TreeSet tmp = new TreeSet(SchemaComparator.getInstance()); tmp.addAll(elements); schema1.elements = (Element[]) tmp.toArray(new Element[tmp.size()]); } if (groups != null) { it = groups.iterator(); HashSet cache = new HashSet(); while( it.hasNext() ) { Object t = it.next(); if (t instanceof GroupHandler) { GroupHandler tt = (GroupHandler) t; cache.add(tt.compress(this)); it.remove(); } } it = cache.iterator(); while( it.hasNext() ) groups.add(it.next()); TreeSet tmp = new TreeSet(SchemaComparator.getInstance()); tmp.addAll(groups); schema1.groups = (Group[]) tmp.toArray(new Group[tmp.size()]); } attributeGroups = attributes = complexTypes = simpleTypes = elements = groups = imports = includes = redefines = null; return schema1; } /* * Helper method for lookUpSimpleType(String) */ private SimpleType lookUpSimpleType( String localName, Schema s, TreeSet targets ) { if (s == null) { return null; } targets.add(s.getTargetNamespace()); if (s.getSimpleTypes() != null) { SimpleType[] sts = s.getSimpleTypes(); for( int i = 0; (sts != null) && (i < sts.length); i++ ) { if (localName.equalsIgnoreCase(sts[i].getName())) { return sts[i]; } } } if (s.getImports() != null) { Schema[] ss = s.getImports(); for( int i = 0; (ss != null) && (i < ss.length); i++ ) { if (!targets.contains(ss[i].getTargetNamespace())) { SimpleType st = lookUpSimpleType(localName, ss[i], targets); if (st != null) { return st; } } } } return null; } /** * <p> * convinience method for package classes * </p> * * @param qname */ protected SimpleType lookUpSimpleType( String qname ) { int index = qname.indexOf(":"); String localName, prefix1; localName = prefix1 = null; if (index >= 0) { localName = qname.substring(index + 1); prefix1 = qname.substring(0, index); } else { prefix1 = ""; localName = qname; } logger.finest("prefix is " + prefix1); logger.finest("localName is " + localName); Iterator it; if ((this.prefix == null && prefix1 == null) || (this.prefix != null && this.prefix.equals(prefix1))) { if (schema != null) return lookUpSimpleType(localName, schema, new TreeSet()); } else { if (imports != null) { it = imports.iterator(); while( it.hasNext() ) { Schema s = (Schema) it.next(); String ns = s.getTargetNamespace().toString(); String prefixLookup = prefixCache != null ? (String) prefixCache.get(ns) : null; if (prefix1 == null || prefixLookup == null || prefix1.equals(prefixLookup)) { SimpleType st = lookUpSimpleType(localName, s, new TreeSet()); if (st != null) { return st; } } } } } if (simpleTypes != null) { it = simpleTypes.iterator(); while( it.hasNext() ) { Object o = it.next(); if (o instanceof SimpleTypeHandler) { SimpleTypeHandler sst = (SimpleTypeHandler) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst.compress(this); } } else { SimpleType sst = (SimpleType) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst; } } } } SimpleType sti = XSISimpleTypes.find(localName); if (sti != null) { return sti; } return null; } /* * helper for lookUpComplexType(String) */ private ComplexType lookUpComplexType( String localName, Schema s, TreeSet targets ) { if (s == null) { return null; } targets.add(s.getTargetNamespace()); if (s.getComplexTypes() != null) { ComplexType[] sts = s.getComplexTypes(); for( int i = 0; (sts != null) && (i < sts.length); i++ ) { String name = sts[i].getName(); if (localName.equalsIgnoreCase(name)) { return sts[i]; } } } if (s.getImports() != null) { Schema[] ss = s.getImports(); for( int i = 0; (ss != null) && (i < ss.length); i++ ) { if (!targets.contains(ss[i].getTargetNamespace())) { ComplexType st = lookUpComplexType(localName, ss[i], targets); if (st != null) { return st; } } } } return null; } /** * <p> * convinience method for package * </p> * * @param qname * @throws SAXException */ protected ComplexType lookUpComplexType( String qname ) throws SAXException { int index = qname.indexOf(":"); String localName, prefix1; localName = prefix1 = null; if (index >= 0) { localName = qname.substring(index + 1); prefix1 = qname.substring(0, index); } else { prefix1 = ""; localName = qname; } logger.finest("prefix is " + prefix1); logger.finest("localName is " + localName); Iterator it; if ((this.prefix == null && prefix1 == null) || (this.prefix != null && this.prefix.equals(prefix1))) { if (schema != null) return lookUpComplexType(localName, schema, new TreeSet()); } else { if (imports != null) { it = imports.iterator(); while( it.hasNext() ) { Schema s = (Schema) it.next(); String ns = s.getTargetNamespace().toString(); String prefixLookup = prefixCache != null ? (String) prefixCache.get(ns) : null; if (prefix1 == null || prefixLookup == null || prefix1.equals(prefixLookup)) { ComplexType ct = lookUpComplexType(localName, s, new TreeSet()); if (ct != null) { return ct; } } } } } if (complexTypes != null) { it = complexTypes.iterator(); while( it.hasNext() ) { Object o = it.next(); if (o instanceof ComplexTypeHandler) { ComplexTypeHandler sst = (ComplexTypeHandler) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst.compress(this); } } else { ComplexType sst = (ComplexType) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst; } } } } return null; } /* * helper method for lookupElement(String) */ private Element lookupElement( String localName, Schema s, TreeSet targets ) { if (s == null) { return null; } logger.finest("looking for element in " + s.getTargetNamespace()); targets.add(s.getTargetNamespace()); if (s.getElements() != null) { Element[] sts = s.getElements(); for( int i = 0; (sts != null) && (i < sts.length); i++ ) { String name = sts[i].getName(); logger.finest("checking element " + name); if (localName.equalsIgnoreCase(name)) { return sts[i]; } } } if (s.getImports() != null) { Schema[] ss = s.getImports(); for( int i = 0; (ss != null) && (i < ss.length); i++ ) { if (!targets.contains(ss[i].getTargetNamespace())) { Element st = lookupElement(localName, ss[i], targets); if (st != null) { return st; } } } } return null; } /** * <p> * convinience method for package * </p> * * @param qname * @throws SAXException */ protected Element lookUpElement( String qname ) throws SAXException { int index = qname.indexOf(":"); String localName, prefix1; localName = prefix1 = null; if (index >= 0) { localName = qname.substring(index + 1); prefix1 = qname.substring(0, index); } else { prefix1 = ""; localName = qname; } logger.finest("prefix is " + prefix1); logger.finest("localName is " + localName); Iterator it; if ((this.prefix == null && prefix1 == null) || (this.prefix != null && this.prefix.equals(prefix1))) { if (schema != null) return lookupElement(localName, schema, new TreeSet()); } else { if (imports != null) { it = imports.iterator(); while( it.hasNext() ) { Schema s = (Schema) it.next(); String ns = s.getTargetNamespace().toString(); String prefixLookup = prefixCache != null ? (String) prefixCache.get(ns) : null; if (prefix1 == null || prefixLookup == null || prefix1.equals(prefixLookup)) { Element ct = lookupElement(localName, s, new TreeSet()); if (ct != null) { return ct; } } } } if (includes != null) { it = includes.iterator(); while( it.hasNext() ) { Schema s = (Schema) it.next(); String ns = s.getTargetNamespace().toString(); String prefixLookup = prefixCache != null ? (String) prefixCache.get(ns) : null; if (prefix1 == null || prefixLookup == null || prefix1.equals(prefixLookup)) { Element ct = lookupElement(localName, s, new TreeSet()); if (ct != null) { return ct; } } } } } it = elements.iterator(); while( it.hasNext() ) { Object o = it.next(); if (o instanceof ElementTypeHandler) { ElementTypeHandler sst = (ElementTypeHandler) o; if (localName.equalsIgnoreCase(sst.getName())) { return (Element) sst.compress(this); } } else { Element sst = (Element) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst; } } } return null; } /* * helper for lookUpGroup */ private Group lookUpGroup( String localName, Schema s, TreeSet targets ) { if (s == null) { return null; } targets.add(s.getTargetNamespace()); if (s.getGroups() != null) { Group[] sts = s.getGroups(); for( int i = 0; (sts != null) && (i < sts.length); i++ ) { if (localName.equalsIgnoreCase(sts[i].getName())) { return sts[i]; } } } if (s.getImports() != null) { Schema[] ss = s.getImports(); for( int i = 0; (ss != null) && (i < ss.length); i++ ) { if (!targets.contains(ss[i].getTargetNamespace())) { Group st = lookUpGroup(localName, ss[i], targets); if (st != null) { return st; } } } } return null; } /** * <p> * convinience method for package * </p> * * @param qname * @throws SAXException */ protected Group lookUpGroup( String qname ) throws SAXException { int index = qname.indexOf(":"); String localName, prefix1; localName = prefix1 = null; if (index >= 0) { localName = qname.substring(index + 1); prefix1 = qname.substring(0, index); } else { prefix1 = ""; localName = qname; } logger.finest("prefix is " + prefix1); logger.finest("localName is " + localName); Iterator it; if ((this.prefix == null && prefix1 == null) || (this.prefix != null && this.prefix.equals(prefix1))) { if (schema != null) return lookUpGroup(localName, schema, new TreeSet()); } else { if (imports != null) { it = imports.iterator(); while( it.hasNext() ) { Schema s = (Schema) it.next(); String ns = s.getTargetNamespace().toString(); String prefixLookup = prefixCache != null ? (String) prefixCache.get(ns) : null; if (prefix1 == null || prefixLookup == null || prefix1.equals(prefixLookup)) { Group ct = lookUpGroup(localName, s, new TreeSet()); if (ct != null) { return ct; } } } } } if (groups != null) { it = groups.iterator(); while( it.hasNext() ) { Object o = it.next(); if (o instanceof GroupHandler) { GroupHandler sst = (GroupHandler) o; if (localName.equalsIgnoreCase(sst.getName())) { return (Group) sst.compress(this); } } else { Group sst = (Group) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst; } } } } return null; } /* * helper method for lookUpAttributeGroup */ private AttributeGroup lookUpAttributeGroup( String localName, Schema s, TreeSet targets ) { if (s == null) { return null; } targets.add(s.getTargetNamespace()); if (s.getAttributeGroups() != null) { AttributeGroup[] sts = s.getAttributeGroups(); for( int i = 0; (sts != null) && (i < sts.length); i++ ) { if (localName.equalsIgnoreCase(sts[i].getName())) { return sts[i]; } } } if (s.getImports() != null) { Schema[] ss = s.getImports(); for( int i = 0; (ss != null) && (i < ss.length); i++ ) { if (!targets.contains(ss[i].getTargetNamespace())) { AttributeGroup st = lookUpAttributeGroup(localName, ss[i], targets); if (st != null) { return st; } } } } return null; } /** * <p> * convinience method for the package * </p> * * @param qname * @throws SAXException */ protected AttributeGroup lookUpAttributeGroup( String qname ) throws SAXException { int index = qname.indexOf(":"); String localName, prefix1; localName = prefix1 = null; if (index >= 0) { localName = qname.substring(index + 1); prefix1 = qname.substring(0, index); } else { prefix1 = ""; localName = qname; } logger.finest("prefix is " + prefix1); logger.finest("localName is " + localName); Iterator it; if ((this.prefix == null && prefix1 == null) || (this.prefix != null && this.prefix.equals(prefix1))) { if (schema != null) return lookUpAttributeGroup(localName, schema, new TreeSet()); } else { if (imports != null) { it = imports.iterator(); while( it.hasNext() ) { Schema s = (Schema) it.next(); String ns = s.getTargetNamespace().toString(); String prefixLookup = prefixCache != null ? (String) prefixCache.get(ns) : null; if (prefix1 == null || prefixLookup == null || prefix1.equals(prefixLookup)) { AttributeGroup ct = lookUpAttributeGroup(localName, s, new TreeSet()); if (ct != null) { return ct; } } } } } if (attributeGroups != null) { it = attributeGroups.iterator(); while( it.hasNext() ) { Object o = it.next(); if (o instanceof AttributeGroupHandler) { AttributeGroupHandler sst = (AttributeGroupHandler) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst.compress(this); } } else { AttributeGroup sst = (AttributeGroup) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst; } } } } return null; } /* * helper method for lookUpAttribute */ private Attribute lookUpAttribute( String localName, Schema s, TreeSet targets ) { if (s == null) { return null; } targets.add(s.getTargetNamespace()); if (s.getAttributes() != null) { Attribute[] sts = s.getAttributes(); for( int i = 0; (sts != null) && (i < sts.length); i++ ) { if (sts[i] != null && sts[i].getName() != null) { if (localName.equalsIgnoreCase(sts[i].getName())) { return sts[i]; } } } } if (s.getImports() != null) { Schema[] ss = s.getImports(); for( int i = 0; (ss != null) && (i < ss.length); i++ ) { if (!targets.contains(ss[i].getTargetNamespace())) { Attribute st = lookUpAttribute(localName, ss[i], targets); if (st != null) { return st; } } } } return null; } /** * <p> * convinience method for package * </p> * * @param qname * @throws SAXException */ protected Attribute lookUpAttribute( String qname ) throws SAXException { int index = qname.indexOf(":"); String localName, prefix1; localName = prefix1 = null; if (index >= 0) { localName = qname.substring(index + 1); prefix1 = qname.substring(0, index); } else { prefix1 = ""; localName = qname; } logger.finest("prefix is " + prefix1); logger.finest("localName is " + localName); Iterator it; if ((this.prefix == null && prefix1 == null) || (this.prefix != null && this.prefix.equals(prefix1))) { if (schema != null) return lookUpAttribute(localName, schema, new TreeSet()); } else { if (imports != null) { it = imports.iterator(); while( it.hasNext() ) { Schema s = (Schema) it.next(); String ns = s.getTargetNamespace().toString(); String prefixLookup = prefixCache != null ? (String) prefixCache.get(ns) : null; if (prefix1 == null || prefixLookup == null || prefix1.equals(prefixLookup)) { Attribute ct = lookUpAttribute(localName, s, new TreeSet()); if (ct != null) { return ct; } } } } } if (attributes != null) { it = attributes.iterator(); while( it.hasNext() ) { Object o = it.next(); if (o instanceof AttributeHandler) { AttributeHandler sst = (AttributeHandler) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst.compress(this); } } else { Attribute sst = (Attribute) o; if (localName.equalsIgnoreCase(sst.getName())) { return sst; } } } } return null; } /** * <p> * convinience method for package * </p> * * @param qname * @throws SAXException */ protected Type lookUpType( String qname ) throws SAXException { if (qname == null) return null; Type t = null; t = lookUpComplexType(qname); t = t == null ? lookUpSimpleType(qname) : t; return t; } /* * helper method that merges the provided Schema into this Schema */ private void addSchema( Schema s ) { Object[] objs = null; objs = s.getAttributes(); if (objs != null) { if ((attributes == null) && (objs.length > 0)) { attributes = new LinkedList(); } for( int i = 0; i < objs.length; i++ ) attributes.add(objs[i]); } objs = s.getAttributeGroups(); if (objs != null) { if ((attributeGroups == null) && (objs.length > 0)) { attributeGroups = new LinkedList(); } for( int i = 0; i < objs.length; i++ ) attributeGroups.add(objs[i]); } objs = s.getComplexTypes(); if (objs != null) { if ((complexTypes == null) && (objs.length > 0)) { complexTypes = new LinkedList(); } for( int i = 0; i < objs.length; i++ ) complexTypes.add(objs[i]); } objs = s.getElements(); if (objs != null) { if ((elements == null) && (objs.length > 0)) { elements = new LinkedList(); } for( int i = 0; i < objs.length; i++ ) elements.add(objs[i]); } objs = s.getGroups(); if (objs != null) { if ((groups == null) && (objs.length > 0)) { groups = new LinkedList(); } for( int i = 0; i < objs.length; i++ ) groups.add(objs[i]); } objs = s.getImports(); if (objs != null) { if ((imports == null) && (objs.length > 0)) { imports = new LinkedList(); } for( int i = 0; i < objs.length; i++ ) imports.add(objs[i]); } objs = s.getSimpleTypes(); if (objs != null) { if ((simpleTypes == null) && (objs.length > 0)) { simpleTypes = new LinkedList(); } for( int i = 0; i < objs.length; i++ ) simpleTypes.add(objs[i]); } URI tempuri = s.getURI(); if (uri == null) { uri = tempuri; } else { if (tempuri != null) { uri = tempuri.resolve(uri); } } } /** * DOCUMENT ME! * * @return Returns the targetNamespace. */ public URI getTargetNamespace() { return targetNamespace; } /** * @see org.geotools.xml.XSIElementHandler#getHandlerType() */ public int getHandlerType() { return DEFAULT; } /** * @see org.geotools.xml.XSIElementHandler#endElement(java.lang.String, * java.lang.String) */ public void endElement( String namespaceURI1, String localName ) { // do nothing } /** * <p> * Default implementation of a Schema for a parsed schema. * </p> * * @author dzwiers * * @see Schema */ private static class DefaultSchema implements Schema { // file visible to avoid set* methods boolean attributeFormDefault; boolean elementFormDefault; String id; URI targetNamespace; String version; int finalDefault; int blockDefault; URI uri; Schema[] imports; SimpleType[] simpleTypes; ComplexType[] complexTypes; AttributeGroup[] attributeGroups; Attribute[] attributes; Element[] elements; Group[] groups; String prefix; /** * @see org.geotools.xml.xsi.Schema#isAttributeFormDefault() */ public boolean isAttributeFormDefault() { return attributeFormDefault; } /** * @see org.geotools.xml.xsi.Schema#getAttributeGroups() */ public AttributeGroup[] getAttributeGroups() { return attributeGroups; } /** * @see org.geotools.xml.xsi.Schema#getAttributeDescriptors() */ public Attribute[] getAttributes() { return attributes; } /** * @see org.geotools.xml.xsi.Schema#getBlockDefault() */ public int getBlockDefault() { return blockDefault; } /** * @see org.geotools.xml.xsi.Schema#getComplexTypes() */ public ComplexType[] getComplexTypes() { return complexTypes; } /** * @see org.geotools.xml.xsi.Schema#isElementFormDefault() */ public boolean isElementFormDefault() { return elementFormDefault; } /** * @see org.geotools.xml.xsi.Schema#getElements() */ public Element[] getElements() { return elements; } /** * @see org.geotools.xml.xsi.Schema#getFinalDefault() */ public int getFinalDefault() { return finalDefault; } /** * @see org.geotools.xml.xsi.Schema#getId() */ public String getId() { return id; } /** * @see org.geotools.xml.xsi.Schema#getImports() */ public Schema[] getImports() { return imports; } /** * @see org.geotools.xml.xsi.Schema#getSimpleTypes() */ public SimpleType[] getSimpleTypes() { return simpleTypes; } /** * @see org.geotools.xml.xsi.Schema#getTargetNamespace() */ public URI getTargetNamespace() { return targetNamespace; } /** * @see org.geotools.xml.xsi.Schema#getURI() */ public URI getURI() { return uri; } /** * @see org.geotools.xml.xsi.Schema#getVersion() */ public String getVersion() { return version; } /** * @see org.geotools.xml.xsi.Schema#getGroups() */ public Group[] getGroups() { return groups; } /** * @see org.geotools.xml.xsi.Schema#includesURI(java.net.URI) */ public boolean includesURI( URI uri1 ) { if (this.uri == null) { return false; } return this.uri.equals(uri1); } /** * @see org.geotools.xml.schema.Schema#getPrefix() */ public String getPrefix() { return prefix; } /** * Returns the implementation hints. The default implementation returns en empty map. */ public Map getImplementationHints() { return Collections.EMPTY_MAP; } } /** * * This class breaks both the collections api and the comparable api. * When an object is a temp ... thus we don't care ... it's always less than. * Please do not use this unless you fully understand it. It is intended to * be used for compressing two schemas and to remove duplicates resulting values (not placeholders). * Making this evaluate place holders would cause the parser to fail !!! * * @author dzwiers * */ private static class SchemaComparator implements Comparator { private static SchemaComparator instance = new SchemaComparator(); public static SchemaComparator getInstance() { return instance; } /* (non-Javadoc) * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare( Object arg0, Object arg1 ) { // attribute if (arg0 instanceof Attribute && arg1 instanceof Attribute) return compareAttribute((Attribute) arg0, (Attribute) arg1); // attrbute group if (arg0 instanceof AttributeGroup && arg1 instanceof AttributeGroup) return compareAttributeGroup((AttributeGroup) arg0, (AttributeGroup) arg1); // complex type if (arg0 instanceof ComplexType && arg1 instanceof ComplexType) return compareComplexType((ComplexType) arg0, (ComplexType) arg1); // simpletype if (arg0 instanceof SimpleType && arg1 instanceof SimpleType) return compareSimpleType((SimpleType) arg0, (SimpleType) arg1); // group if (arg0 instanceof Group && arg1 instanceof Group) return compareGroup((Group) arg0, (Group) arg1); // element if (arg0 instanceof Element && arg1 instanceof Element) return compareElement((Element) arg0, (Element) arg1); // imports if (arg0 instanceof Schema && arg1 instanceof Schema) return compareImport((Schema) arg0, (Schema) arg1); return -1; // hack for unresolved portions // throw new ClassCastException("Unknown type "+arg0.getClass().getName()); } private int compareAttribute( Attribute arg0, Attribute arg1 ) { if (arg0 == arg1) return 0; if (arg0 == null) return 1; if (arg1 == null) return -1; int i = arg0.getName() == null ? arg1.getName() == null ? 0 : 1 : arg0.getName().compareTo(arg1.getName()); if (i != 0) return i; i = arg0.getNamespace() == null ? arg1.getNamespace() == null ? 0 : 1 : arg0.getNamespace().compareTo( arg1.getNamespace()); if (i != 0) return i; i = arg0.getUse() - arg1.getUse(); if (i != 0) return i; return compareSimpleType(arg0.getSimpleType(), arg1.getSimpleType()); } private int compareAttributeGroup( AttributeGroup arg0, AttributeGroup arg1 ) { if (arg0 == arg1) return 0; if (arg0 == null) return 1; if (arg1 == null) return -1; int i = arg0.getName() == null ? arg1.getName() == null ? 0 : 1 : arg0.getName().compareTo(arg1.getName()); if (i != 0) return i; i = arg0.getNamespace() == null ? arg1.getNamespace() == null ? 0 : 1 : arg0.getNamespace().compareTo( arg1.getNamespace()); if (i != 0) return i; i = arg0.getAnyAttributeNameSpace() == null ? arg1.getAnyAttributeNameSpace() == null ? 0 : 1 : arg0 .getAnyAttributeNameSpace().compareTo(arg1.getAnyAttributeNameSpace()); if (i != 0) return i; Attribute[] a0 = arg0.getAttributes(); Arrays.sort(a0, this); Attribute[] a1 = arg1.getAttributes(); Arrays.sort(a1, this); if (a0 == a1) return 0; if (a0 == null) return 1; if (a1 == null) return -1; if (a0.length < a1.length) return -1; if (a0.length > a1.length) return 1; for( int j = 0; j < a0.length && i == 0; j++ ) i = compareAttribute(a0[j], a1[j]); return i; } private int compareGroup( Group arg0, Group arg1 ) { if (arg0 == arg1) return 0; if (arg0 == null) return 1; if (arg1 == null) return -1; int i = arg0.getName() == null ? arg1.getName() == null ? 0 : 1 : arg0.getName().compareTo(arg1.getName()); if (i != 0) return i; i = arg0.getNamespace() == null ? arg1.getNamespace() == null ? 0 : 1 : arg0.getNamespace().compareTo( arg1.getNamespace()); if (i != 0) return i; i = arg0.getMaxOccurs() - arg1.getMaxOccurs(); if (i != 0) return i; i = arg0.getMinOccurs() - arg1.getMinOccurs(); if (i != 0) return i; ElementGrouping a0 = arg0.getChild(); ElementGrouping a1 = arg1.getChild(); if (a0 == a1) return 0; if (a0 == null) return 1; if (a1 == null) return -1; return compareElementGrouping(a0, a1); } private int compareElement( Element arg0, Element arg1 ) { if (arg0 == arg1) return 0; if (arg0 == null) return 1; if (arg1 == null) return -1; int i = arg0.getName() == null ? arg1.getName() == null ? 0 : 1 : arg0.getName().compareTo(arg1.getName()); if (i != 0) return i; i = arg0.getNamespace() == null ? arg1.getNamespace() == null ? 0 : 1 : arg0.getNamespace().compareTo( arg1.getNamespace()); if (i != 0) return i; i = arg0.getMaxOccurs() - arg1.getMaxOccurs(); if (i != 0) return i; i = arg0.getMinOccurs() - arg1.getMinOccurs(); if (i != 0) return i; i = compareElement(arg0.getSubstitutionGroup(), arg1.getSubstitutionGroup()); if (i != 0) return i; // ignore a few things here ... might need them back return compare(arg0.getType(), arg1.getType()); } private int compareElementGrouping( ElementGrouping arg0, ElementGrouping arg1 ) { if (arg0 == arg1) return 0; if (arg0 == null) return 1; if (arg1 == null) return -1; int i = 0; i = arg0.getGrouping() - arg1.getGrouping(); if (i != 0) return i; i = arg0.getMaxOccurs() - arg1.getMaxOccurs(); if (i != 0) return i; i = arg0.getMinOccurs() - arg1.getMinOccurs(); if (i != 0) return i; ElementGrouping[] eg0 = null; ElementGrouping[] eg1 = null; switch( arg0.getGrouping() ) { case ElementGrouping.ELEMENT: return compareElement((Element) arg0, (Element) arg1); case ElementGrouping.GROUP: return compareGroup((Group) arg0, (Group) arg1); case ElementGrouping.CHOICE: Choice c0 = (Choice) arg0; Choice c1 = (Choice) arg1; eg0 = c0.getChildren(); eg1 = c1.getChildren(); case ElementGrouping.SEQUENCE: Sequence s0 = (Sequence) arg0; Sequence s1 = (Sequence) arg1; eg0 = s0.getChildren(); eg1 = s1.getChildren(); case ElementGrouping.ALL: All a0 = (All) arg0; All a1 = (All) arg1; eg0 = a0.getElements(); eg1 = a1.getElements(); } if (eg0.length < eg1.length) return -1; if (eg0.length > eg1.length) return 1; for( int j = 0; j < eg0.length && i != 0; j++ ) i = compareElementGrouping(eg0[j], eg1[j]); return 0; } private int compareImport( Schema arg0, Schema arg1 ) { if (arg0 == arg1) return 0; if (arg0 == null) return 1; if (arg1 == null) return -1; int i = arg0.getTargetNamespace() == null ? arg1.getTargetNamespace() == null ? 0 : 1 : arg0 .getTargetNamespace().compareTo(arg1.getTargetNamespace()); if (i != 0) return i; i = arg0.getURI() == null ? arg1.getURI() == null ? 0 : 1 : arg0.getURI().compareTo(arg1.getURI()); if (i != 0) return i; i = arg0.getElements().length - arg1.getElements().length; if (i != 0) return i; i = arg0.getComplexTypes().length - arg1.getComplexTypes().length; if (i != 0) return i; i = arg0.getSimpleTypes().length - arg1.getSimpleTypes().length; if (i != 0) return i; i = arg0.getAttributes().length - arg1.getAttributes().length; if (i != 0) return i; i = arg0.getAttributeGroups().length - arg1.getAttributeGroups().length; if (i != 0) return i; i = arg0.getGroups().length - arg1.getGroups().length; if (i != 0) return i; // Yes we are making a huge assumption here. return 0; } private int compareSimpleType( SimpleType arg0, SimpleType arg1 ) { if (arg0 == arg1) return 0; if (arg0 == null) return 1; if (arg1 == null) return -1; int i = arg0.getName() == null ? arg1.getName() == null ? 0 : 1 : arg0.getName().compareTo(arg1.getName()); if (i != 0) return i; i = arg0.getNamespace() == null ? arg1.getNamespace() == null ? 0 : 1 : arg0.getNamespace().compareTo( arg1.getNamespace()); if (i != 0) return i; SimpleType[] a0 = arg0.getParents(); Arrays.sort(a0, this); SimpleType[] a1 = arg1.getParents(); Arrays.sort(a1, this); if (a0 == a1) return 0; if (a0 == null) return 1; if (a1 == null) return -1; if (a0.length < a1.length) return -1; if (a0.length > a1.length) return 1; for( int j = 0; j < a0.length && i == 0; j++ ) i = compareSimpleType(a0[j], a1[j]); Facet[] a01 = arg0.getFacets(); Arrays.sort(a0, this); Facet[] a11 = arg1.getFacets(); Arrays.sort(a1, this); if (a01 == a11) return 0; if (a01 == null) return 1; if (a11 == null) return -1; if (a01.length < a11.length) return -1; if (a01.length > a11.length) return 1; for( int j = 0; j < a01.length && i == 0; j++ ) i = compareFacet(a01[j], a11[j]); return i; } private int compareFacet( Facet arg0, Facet arg1 ) { if (arg0 == arg1) return 0; if (arg0 == null) return 1; if (arg1 == null) return -1; int i = 0; i = arg0.getFacetType() - arg1.getFacetType(); if (i != 0) return i; i = arg0.getValue() == null ? arg1.getValue() == null ? 0 : 1 : arg0.getValue().compareTo(arg1.getValue()); return i; } private int compareComplexType( ComplexType arg0, ComplexType arg1 ) { if (arg0 == arg1) return 0; if (arg0 == null) return 1; if (arg1 == null) return -1; int i = arg0.getName() == null ? arg1.getName() == null ? 0 : 1 : arg0.getName().compareTo(arg1.getName()); if (i != 0) return i; i = arg0.getNamespace() == null ? arg1.getNamespace() == null ? 0 : 1 : arg0.getNamespace().compareTo( arg1.getNamespace()); if (i != 0) return i; Type a00 = arg0.getParent(); Type a01 = arg1.getParent(); if (a00 == a01) return 0; if (a00 == null) return 1; if (a01 == null) return -1; i = compare(a00, a01); if (i != 0) return i; i = arg0.getAnyAttributeNameSpace() == null ? arg1.getAnyAttributeNameSpace() == null ? 0 : 1 : arg0 .getAnyAttributeNameSpace().compareTo(arg1.getAnyAttributeNameSpace()); if (i != 0) return i; Attribute[] a10 = arg0.getAttributes(); Arrays.sort(a10, this); Attribute[] a11 = arg1.getAttributes(); Arrays.sort(a11, this); if (a10 == a11) return 0; if (a10 == null) return 1; if (a11 == null) return -1; if (a10.length < a11.length) return -1; if (a10.length > a11.length) return 1; for( int j = 0; j < a10.length && i == 0; j++ ) i = compareAttribute(a10[j], a11[j]); if (i != 0) return i; Element[] a0 = arg0.getChildElements(); Arrays.sort(a0, this); Element[] a1 = arg1.getChildElements(); Arrays.sort(a1, this); if (a0 == a1) return 0; if (a0 == null) return 1; if (a1 == null) return -1; if (a0.length < a1.length) return -1; if (a0.length > a1.length) return 1; for( int j = 0; j < a0.length && i == 0; j++ ) i = compareElement(a0[j], a1[j]); return i; } } }