/* * 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.util.Iterator; import java.util.LinkedList; import java.util.List; import org.geotools.xml.XSIElementHandler; import org.geotools.xml.schema.Facet; import org.geotools.xml.schema.SimpleType; import org.geotools.xml.schema.impl.FacetGT; import org.geotools.xml.schema.impl.SimpleTypeGT; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; /** * SimpleTypeHandler purpose. * * <p> * represents a simpleType element * </p> * * @author dzwiers, Refractions Research, Inc. http://www.refractions.net * @author $Author:$ (last modification) * * @source $URL$ * @version $Id$ */ public class SimpleTypeHandler extends XSIElementHandler { /** NONE */ public static final int NONE = 0; /** ALL */ public static final int ALL = 7; /** 'simpleType' */ public final static String LOCALNAME = "simpleType"; private static int offset = 0; private String id; private String name; private int finaL; private XSIElementHandler child; // one of List, Restriction or Union private int hashCodeOffset = getOffset(); private SimpleType cache; /* * helper for hashCode() */ private static int getOffset() { return offset++; } /** * @see java.lang.Object#hashCode() */ public int hashCode() { return (LOCALNAME.hashCode() * ((id == null) ? 1 : id.hashCode()) * ((finaL == 0) ? 1 : finaL) * ((name == null) ? 1 : name.hashCode())) + hashCodeOffset; } /** * @see org.geotools.xml.XSIElementHandler#getHandler(java.lang.String, * java.lang.String) */ public XSIElementHandler getHandler(String namespaceURI, String localName) throws SAXException { if (SchemaHandler.namespaceURI.equalsIgnoreCase(namespaceURI)) { // child types // // list if (ListHandler.LOCALNAME.equalsIgnoreCase(localName)) { ListHandler lh = new ListHandler(); if (child == null) { child = lh; } else { throw new SAXNotRecognizedException(getLocalName() + " may only have one '" + ListHandler.LOCALNAME + "' declaration."); } return lh; } // restriction if (RestrictionHandler.LOCALNAME.equalsIgnoreCase(localName)) { RestrictionHandler lh = new RestrictionHandler(); if (child == null) { child = lh; } else { throw new SAXNotRecognizedException(getLocalName() + " may only have one '" + RestrictionHandler.LOCALNAME + "' declaration."); } return lh; } // union if (UnionHandler.LOCALNAME.equalsIgnoreCase(localName)) { UnionHandler lh = new UnionHandler(); if (child == null) { child = lh; } else { throw new SAXNotRecognizedException(getLocalName() + " may only have one '" + UnionHandler.LOCALNAME + "' declaration."); } return lh; } } return null; } /** * @see org.geotools.xml.XSIElementHandler#startElement(java.lang.String, * java.lang.String, org.xml.sax.Attributes) */ public void startElement(String namespaceURI, String localName, Attributes atts){ id = atts.getValue("", "id"); if (id == null) { id = atts.getValue(namespaceURI, "id"); } String finaL1 = atts.getValue("", "final"); if (finaL1 == null) { finaL1 = atts.getValue(namespaceURI, "final"); } this.finaL = findFinal(finaL1); name = atts.getValue("", "name"); if (name == null) { name = atts.getValue(namespaceURI, "name"); } } /** * <p> * translates the final attribute to an integer mask * </p> * * @param finaL * */ public static int findFinal(String finaL) { if ((finaL == null) || "".equalsIgnoreCase(finaL)) { return NONE; } String[] tokens = finaL.split("\\s"); int r = 0; for (int i = 0; i < tokens.length; i++) { if ("#all".equalsIgnoreCase(tokens[i])) { r = ALL; i = tokens.length; } else { if ("union".equalsIgnoreCase(tokens[i])) { r += UNION; } else { if ("list".equalsIgnoreCase(tokens[i])) { r += LIST; } else { if ("restriction".equalsIgnoreCase(tokens[i])) { r += RESTRICTION; } } } } } return r; } /** * @see org.geotools.xml.XSIElementHandler#getLocalName() */ public String getLocalName() { return LOCALNAME; } /** * <p> * returns the simpletype's name * </p> * */ public String getName() { return name; } /** * <p> * compacts the data resolving references. * </p> * * @param parent * */ protected SimpleType compress(SchemaHandler parent) { logger.info("Start compressing SimpleType " + getName()); if (cache != null) { return cache; } Facet[] facets = null; if (child.getHandlerType() == SimpleType.RESTRICTION) { facets = getFacets((RestrictionHandler) child); } SimpleType[] simpleTypes = getSimpleTypes(child, parent); cache = new SimpleTypeGT(id, name, parent.getTargetNamespace(), child.getHandlerType(), simpleTypes, facets, finaL); logger.info("End compressing SimpleType " + getName()); id = null; child = null; return cache; } static SimpleType[] getSimpleTypes(XSIElementHandler child, SchemaHandler parent) { switch (child.getHandlerType()) { case RESTRICTION: return getSimpleTypes((RestrictionHandler) child, parent); case LIST: return getSimpleTypes((ListHandler) child, parent); case UNION: return getSimpleTypes((UnionHandler) child, parent); default: throw new RuntimeException( "Should not be here ... child is one of the other three types."); } } static SimpleType[] getSimpleTypes(RestrictionHandler rest, SchemaHandler parent) { SimpleType[] children = new SimpleType[1]; if (rest.getChild() != null) { children[0] = ((SimpleTypeHandler) rest.getChild()).compress(parent); } else { children[0] = parent.lookUpSimpleType(rest.getBase()); } return children; } static SimpleType[] getSimpleTypes(ListHandler rest, SchemaHandler parent) { SimpleType[] children = new SimpleType[1]; if (rest.getSimpleType() != null) { children[0] = (rest.getSimpleType()).compress(parent); } else { children[0] = parent.lookUpSimpleType(rest.getItemType()); } return children; } static SimpleType[] getSimpleTypes(UnionHandler union, SchemaHandler parent) { List l = new LinkedList(); if (union.getMemberTypes() != null) { String[] qNames = union.getMemberTypes().split("\\s"); for (int i = 0; i < qNames.length; i++) l.add(parent.lookUpSimpleType(qNames[i])); } if (union.getSimpleTypes() != null) { Iterator i = union.getSimpleTypes().iterator(); while (i.hasNext()) { l.add(((SimpleTypeHandler) i.next()).compress(parent)); } } return (SimpleType[]) l.toArray(new SimpleType[l.size()]); } static Facet[] getFacets(RestrictionHandler rh) { List contraints = rh.getConstraints(); if ((contraints == null) || (contraints.size() == 0)) { return null; } Facet[] facets = new Facet[contraints.size()]; Iterator i = contraints.iterator(); int index = 0; while (i.hasNext()) { FacetHandler fh = (FacetHandler) i.next(); facets[index] = new FacetGT(fh.getType(), fh.getValue()); index++; } return facets; } /** * @see org.geotools.xml.XSIElementHandler#getHandlerType() */ public int getHandlerType() { return SIMPLETYPE; } /** * @see org.geotools.xml.XSIElementHandler#endElement(java.lang.String, * java.lang.String) */ public void endElement(String namespaceURI, String localName){ // do nothing } }