text: /*
   *    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;
  
  import java.net.URI;
  import java.net.URISyntaxException;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import org.geotools.xml.SchemaFactory;
  import org.geotools.xml.XMLElementHandler;
  import org.geotools.xml.schema.ComplexType;
  import org.geotools.xml.schema.Element;
  import org.geotools.xml.schema.Schema;
  import org.geotools.xml.schema.SimpleType;
  import org.geotools.xml.schema.Type;
  import org.xml.sax.SAXException;
  
  /**
   * This class is used to create handlers for child elements based on the currently defined
   * namespaces. This class is called by the XMLSAXHandler to help act as a library of prefix ->
   * Schema mappings.
   *
   * @author dzwiers www.refractions.net
   * @see org.geotools.xml.XMLSAXHandler
   * @see Schema
   */
  public class ElementHandlerFactory {
      /** Used to store ElementHandlerFactory */
      public static final String KEY = "org.geotools.xml.handlers.ElementHandlerFactory_KEY";
  
      private Logger logger;
      private Map targSchemas = new HashMap(); // maps prefix -->> Schema
      private Map prefixURIs = new HashMap(); // maps prefix -->> URI
      protected URI defaultNS = null;
  
      /**
       * Creates a new ElementHandlerFactory object.
       *
       * @param l Logger
       */
      public ElementHandlerFactory(Logger l) {
          logger = l;
      }
  
      /** @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) */
      public void endPrefixMapping(String prefix) {
          URI s = (URI) prefixURIs.remove(prefix);
  
          if (s != null) {
              targSchemas.remove(s);
          }
      }
  
      /** @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) */
      public void startPrefixMapping(String prefix, String targ, URI uri) throws SAXException {
          logger.finest("Target == '" + targ + "'");
          logger.finest("URI == '" + uri + "'");
  
          URI tns = null;
          try {
              tns = new URI(targ);
          } catch (URISyntaxException e) {
              logger.warning(e.toString());
              throw new SAXException(e);
          }
  
          try {
              Schema s = SchemaFactory.getInstance(tns, uri, logger.getLevel());
  
              if (s != null) {
                  if ((prefix == null) || "".equalsIgnoreCase(prefix)) {
                      defaultNS = s.getTargetNamespace();
                  }
  
                  targSchemas.put(s.getTargetNamespace(), s);
                  prefixURIs.put(prefix, tns);
              } else {
                  prefixURIs.put(prefix, tns);
              }
          } catch (Exception e) {
              logger.log(
                      Level.FINE,
                      "Failed to parse schema from location "
                              + uri
                              + ", ignoring and moving on, this might result in some elements not being parsed properly");
              // treating an error the same way as not being able to
              // get to the schema, e.g., s == null above
              prefixURIs.put(prefix, tns);
          }
      }
  
      /** @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) */
      public void startPrefixMapping(String prefix, String targ) throws SAXException {
          logger.finest("Target == '" + targ + "'");
  
          try {
              URI tns = new URI(targ);
              Schema s = SchemaFactory.getInstance(tns);
  
              if (s == null) {
                  prefixURIs.put(prefix, tns);
                  return;
              }
  
              if ((prefix == null) || "".equalsIgnoreCase(prefix)) {
                  defaultNS = s.getTargetNamespace();
              }
  
              targSchemas.put(s.getTargetNamespace(), s);
              prefixURIs.put(prefix, tns);
          } catch (URISyntaxException e) {
              logger.warning(e.toString());
              throw new SAXException(e);
          }
      }
  
      /** @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) */
      protected void startPrefixMapping(String prefix, Schema targ) {
          logger.finest("Target == '" + targ + "'");
          if ((prefix == null) || "".equalsIgnoreCase(prefix)) {
              defaultNS = targ.getTargetNamespace();
          }
          targSchemas.put(targ.getTargetNamespace(), targ);
          prefixURIs.put(prefix, targ.getTargetNamespace());
      }
  
      /**
       * Creates an element handler for the element specified by name and namespace. Will return null
       * if a suitable handler is not found.
       *
       * @see ElementHandlerFactory#createElementHandler(Element)
       */
      public XMLElementHandler createElementHandler(URI namespaceURI, String localName)
              throws SAXException {
  
          if (localName == null) {
              return null;
          }
  
          if (namespaceURI == null || "".equals(namespaceURI.toString())) {
              namespaceURI = defaultNS;
          }
  
          logger.finest(
                  "Trying to create an element handler for " + localName + " :: " + namespaceURI);
  
          Schema s = (Schema) targSchemas.get(namespaceURI);
  
          if (s == null) {
              logger.finest("Could not find Schema " + namespaceURI);
  
              return null;
          }
  
          logger.finest("Found Schema " + s.getTargetNamespace());
  
          Element[] eth = s.getElements();
  
          if (eth == null) {
              return null;
          }
  
          for (int i = 0; i < eth.length; i++) {
              String name = eth[i].getName();
              if (localName.equalsIgnoreCase(name) || name.equals(IgnoreHandler.NAME)) {
                  return createElementHandler(eth[i]);
              }
          }
  
          // TODO search the nesting import stuff
          return null;
      }
  
      /**
       * Creates an element handler based on the element provided.
       *
       * @param eth Element
       */
      public XMLElementHandler createElementHandler(Element eth) throws SAXException {
          Type type = eth.getType();
  
          if (type instanceof SimpleType) {
              return new SimpleElementHandler(eth);
          }
          if (type instanceof ComplexType) {
              return new ComplexElementHandler(this, eth);
          }
  
          return new IgnoreHandler(eth);
      }
  
      public URI getNamespace(String prefix) {
          URI s = (URI) prefixURIs.get(prefix);
          return s;
      }
  }
  