Package org.geotools.gml.producer

Source Code of org.geotools.gml.producer.FeatureTypeTransformer$FeatureTypeTranslator

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2003-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.
*
* Created on 27.11.2003
*/
package org.geotools.gml.producer;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import org.geotools.filter.LengthFunction;
import org.geotools.xml.transform.TransformerBase;
import org.geotools.xml.transform.Translator;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.filter.BinaryComparisonOperator;
import org.opengis.filter.Filter;
import org.opengis.filter.PropertyIsLessThan;
import org.opengis.filter.PropertyIsLessThanOrEqualTo;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;


/**
* Transformer that transforms feature types into (hopefully) valid XML
* schemas. This class may be used by geoserver in the future to automatically
* create XML schemas for the  DescribeFeatureType request.
* <pre>
*   FeatureType type = ...; // you have it from somewhere
*   FeatureTypeTransformer t = new FeatureTypeTransformer();
*   t.transform(type, System.out);
* </pre>
* The following table lists the mapping between java types and xml schema data
* types for attribute types.
*
* <table>
* <tr><th>
* Java
* </td><th>
* XML Schema
* </td></tr>
* <tr><td>
* String
* </td><td>
* xs:string
* </td></tr>
* <tr><td>
* Byte
* </td><td>
* xs:byte
* </td></tr>
* <tr><td>
* Short
* </td><td>
* xs:short
* </td></tr>
* <tr><td>
* Integer
* </td><td>
* xs:int
* </td></tr>
* <tr><td>
* Long
* </td><td>
* xs:long
* </td></tr>
* <tr><td>
* BigInteger
* </td><td>
* xs:integer
* </td></tr>
* <tr><td>
* BigDecimal
* </td><td>
* xs:decimal
* </td></tr>
* <tr><td>
* java.util.Date
* </td><td>
* xs:dateTime
* </td></tr>
* <tr><td>
* java.sql.Date
* </td><td>
* xs:date
* </td></tr>
* <tr><td>
* java.sql.Time
* </td><td>
* xs:time
* </td></tr>
* <tr><td>
* java.sql.Timestamp
* </td><td>
* xs:dateTime
* </td></tr>
* <tr><td>
* java.lang.Boolean
* </td><td>
* xs:boolean
* </td></tr>
* <tr><td>
* com.vividsolutions.jts.geom.Point
* </td><td>
* gml:PointPropertyType
* </td></tr>
* <tr><td>
* com.vividsolutions.jts.geom.LineString
* </td><td>
* gml:LineStringPropertyType
* </td></tr>
* <tr><td>
* com.vividsolutions.jts.geom.Polygon
* </td><td>
* gml:PolygonPropertyType
* </td></tr>
* <tr><td>
* com.vividsolutions.jts.geom.MultiPoint
* </td><td>
* gml:MultiPointPropertyType
* </td></tr>
* <tr><td>
* com.vividsolutions.jts.geom.MultiLineString
* </td><td>
* gml:MutliLineStringPropertyType
* </td></tr>
* <tr><td>
* com.vividsolutions.jts.geom.MultiPolygon
* </td><td>
* gml:MultiPolygonPropertyType
* </td></tr>
* <tr><td>
* org.geotools.data.Feature
* </td><td>
* gml:AbstractFeatureType
* </td></tr>
* </table>
*
* @author Simon Raess
*
*
* @source $URL$
* @version $Id$
*
* @task TODO: Support GeometryCollection.
* @task REVISIT: Should support a bit more for the header, like being able to
*       set the schemaLocation.  It also should declare and import the gml
*       namespace - it's always used as all extend gml:AbstractFeatureType.
*       Also should be able to set the global substitution group, so that
*       this type can be used directly as a feature.
*/
public class FeatureTypeTransformer extends TransformerBase {
    private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(
            "org.geotools.gml.producer.FeatureTypeTransformer");
    private static final String SCHEMA_NS = "http://www.w3.org/2001/XMLSchema";

    /**
     * Creates a Translator that is capable to translate FeatureType objects
     * into a XML schema fragment.
     *
     * @param handler the content handler to use
     *
     * @return DOCUMENT ME!
     */
    public Translator createTranslator(ContentHandler handler) {
        FeatureTypeTranslator translator = new FeatureTypeTranslator(handler);

        return translator;
    }

    /**
     * A FeatureTypeTranslator encodes FeatureTypes as a (hopefully) valid XML
     * schema.
     *
     * @see TransformerBase.TranslatorSupport
     */
    public static class FeatureTypeTranslator
        extends TransformerBase.TranslatorSupport {
        /**
         * Creates a new FeatureTypeTranslator. The default prefix is "xs" and
         * the default namespace is "http://www.w3.org/2001/XMLSchema".
         *
         * @param handler the content handler that receives the SAX events
         */
        public FeatureTypeTranslator(ContentHandler handler) {
            super(handler, "xs", "http://www.w3.org/2001/XMLSchema");
        }

        /**
         * Encode object o, which must be an instance of FeatureType. If it is
         * not an IllegalArgumentException will be thrown.
         *
         * @param o DOCUMENT ME!
         *
         * @throws IllegalArgumentException if supplied object is not an
         *         instance of FeatureType
         *
         * @see org.geotools.xml.transform.Translator#encode(java.lang.Object)
         */
        public void encode(Object o) throws IllegalArgumentException {
            if (o instanceof SimpleFeatureType) {
                encode((SimpleFeatureType) o);
            } else {
                throw new IllegalArgumentException(
                    "Translator does not know how to translate "
                    + o.getClass().getName());
            }
        }

        /**
         * Encode the supplied feature type.
         *
         * @param type the feature type to encode
         *
         * @throws RuntimeException DOCUMENT ME!
         */
        protected void encode(SimpleFeatureType type) {
            List attributes = type.getAttributeDescriptors();

            try {
                startSchemaType(type.getTypeName(), type.getName().getNamespaceURI());

                for (int i = 0; i < attributes.size(); i++) {
                    encode((AttributeDescriptor) attributes.get(i));
                }

                endSchemaType();
            } catch (SAXException e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * Start the schema fragment for a feature type.
         *
         * @param name
         * @param namespace DOCUMENT ME!
         *
         * @throws SAXException
         */
        protected final void startSchemaType(String name, String namespace)
            throws SAXException {
            AttributesImpl atts = new AttributesImpl();

            atts.addAttribute("", "name", "name", "", name + "_Type");

            contentHandler.startElement(SCHEMA_NS, "complexType",
                "xs:complexType", atts);

            contentHandler.startElement(SCHEMA_NS, "complexContent",
                "xs:complexContent", new AttributesImpl());

            atts = new AttributesImpl();

            atts.addAttribute("", "base", "base", "", "gml:AbstractFeatureType");

            contentHandler.startElement(SCHEMA_NS, "extension", "xs:extension",
                atts);

            contentHandler.startElement(SCHEMA_NS, "sequence", "xs:sequence",
                new AttributesImpl());
        }

        /**
         * End the schema fragment for a feature type.
         *
         * @throws SAXException
         */
        protected void endSchemaType() throws SAXException {
            contentHandler.endElement(SCHEMA_NS, "sequence", "xs:sequence");

            contentHandler.endElement(SCHEMA_NS, "extension", "xs:extension");

            contentHandler.endElement(SCHEMA_NS, "complexContent",
                "xs:complexContent");

            contentHandler.endElement(SCHEMA_NS, "complexType", "xs:complexType");
        }

        /**
         * Encode an AttributeType.
         *
         * @param attribute
         *
         * @throws SAXException
         * @throws RuntimeException DOCUMENT ME!
         */
        protected void encode(AttributeDescriptor attribute)
            throws SAXException {
            Class type = attribute.getType().getBinding();

            if (Number.class.isAssignableFrom(type)) {
                encodeNumber(attribute);
            } else if (Date.class.isAssignableFrom(type)) {
                encodeDate(attribute);
            } else if (type == String.class) {
                encodeString(attribute);
            } else if (Geometry.class.isAssignableFrom(type)) {
                encodeGeometry(attribute);
            } else if (type == Boolean.class) {
                encodeBoolean(attribute);

                /*} else if (FeatureType.class.isAssignableFrom(type)) {
               
                                      encodeFeature(attribute);*/
            } else {
                throw new RuntimeException("Cannot encode " + type.getName());
            }
        }

        /**
         * Encode an AttributeType whose value type is a Boolean.
         *
         * @param attribute
         *
         * @throws SAXException
         */
        protected void encodeBoolean(AttributeDescriptor attribute)
            throws SAXException {
            AttributesImpl atts = createStandardAttributes(attribute);

            atts.addAttribute("", "type", "type", "", "xs:boolean");

            contentHandler.startElement(SCHEMA_NS, "element", "xs:element", atts);

            contentHandler.endElement(SCHEMA_NS, "element", "xs:element");
        }
       
        /**
         * Encode an AttributeType whose value type is a String.
         *
         * @param attribute the attribute to encode
         *
         * @throws SAXException
         */
        protected void encodeString(AttributeDescriptor attribute)
            throws SAXException {
            int length = Integer.MAX_VALUE;
           
            for ( Filter f : attribute.getType().getRestrictions() ) {
              if ( f == Filter.INCLUDE || f == Filter.EXCLUDE )
                  continue;
             
                try{
                  if(f instanceof PropertyIsLessThan ||
                       f instanceof PropertyIsLessThanOrEqualTo ){
                    BinaryComparisonOperator cf = (BinaryComparisonOperator) f;
                    Expression e = cf.getExpression1();
                    if(e!= null && e instanceof LengthFunction){
                      length = Integer.parseInt(((Literal)cf.getExpression2()).getValue().toString());
                    }else{
                      if(cf.getExpression2() instanceof LengthFunction){
                        length = Integer.parseInt(((Literal)cf.getExpression1()).getValue().toString());
                      }
                    }
                  }
              }catch(Throwable t){
                length = Integer.MAX_VALUE;
              }
            }

            AttributesImpl atts = createStandardAttributes(attribute);

            if (length == 0) {
                atts.addAttribute("", "type", "type", "", "xs:string");

                contentHandler.startElement(SCHEMA_NS, "element", "xs:element",
                    atts);

                contentHandler.endElement(SCHEMA_NS, "element", "xs:element");
            } else {
                contentHandler.startElement(SCHEMA_NS, "element", "xs:element",
                    atts);

                contentHandler.startElement(SCHEMA_NS, "simpleType",
                    "xs:simpleType", new AttributesImpl());

                atts = new AttributesImpl();

                atts.addAttribute("", "base", "base", "", "xs:string");

                contentHandler.startElement(SCHEMA_NS, "restriction",
                    "xs:restriction", atts);

                atts = new AttributesImpl();

                atts.addAttribute("", "value", "value", "", "" + length);

                contentHandler.startElement(SCHEMA_NS, "maxLength",
                    "xs:maxLength", atts);

                contentHandler.endElement(SCHEMA_NS, "maxLength", "xs:maxLength");

                contentHandler.endElement(SCHEMA_NS, "restriction",
                    "xs:restriction");

                contentHandler.endElement(SCHEMA_NS, "simpleType",
                    "xs:simpleType");

                contentHandler.endElement(SCHEMA_NS, "element", "xs:element");
            }
        }

        /**
         * Encode an AttributeType whose value type is a Number.
         *
         * @param attribute
         *
         * @throws SAXException
         * @throws RuntimeException DOCUMENT ME!
         */
        protected void encodeNumber(AttributeDescriptor attribute)
            throws SAXException {
            AttributesImpl atts = createStandardAttributes(attribute);

            Class type = attribute.getType().getBinding();

            String typeString;

            if (type == Byte.class) {
                typeString = "xs:byte";
            } else if (type == Short.class) {
                typeString = "xs:short";
            } else if (type == Integer.class) {
                typeString = "xs:int";
            } else if (type == Long.class) {
                typeString = "xs:long";
            } else if (type == Float.class) {
                typeString = "xs:float";
            } else if (type == Double.class) {
                typeString = "xs:double";
            } else if (type == BigInteger.class) {
                typeString = "xs:integer";
            } else if (type == BigDecimal.class) {
                typeString = "xs:decimal";
            } else if (Number.class.isAssignableFrom(type)) {
                typeString = "xs:decimal";
            } else {
                throw new RuntimeException(
                    "Called encode number with invalid attribute type.");
            }

            atts.addAttribute("", "type", "type", "", typeString);

            contentHandler.startElement(SCHEMA_NS, "element", "xs:element", atts);

            contentHandler.endElement(SCHEMA_NS, "element", "xs:element");
        }

        /**
         * Encode an AttributeType whose value type is a Date.
         *
         * @param attribute
         *
         * @throws SAXException
         */
        protected void encodeDate(AttributeDescriptor attribute)
            throws SAXException {
            AttributesImpl atts = createStandardAttributes(attribute);

            Class binding = attribute.getType().getBinding();
            if(java.sql.Date.class.isAssignableFrom(binding))
                atts.addAttribute("", "type", "type", "", "xs:date");
            else if(java.sql.Time.class.isAssignableFrom(binding))
                atts.addAttribute("", "type", "type", "", "xs:time");
            else
                atts.addAttribute("", "type", "type", "", "xs:dateTime");

            contentHandler.startElement(SCHEMA_NS, "element", "xs:element", atts);

            contentHandler.endElement(SCHEMA_NS, "element", "xs:element");
        }

        /**
         * Encode an AttributeType whose value type is a Geometry.
         *
         * @param attribute
         *
         * @throws SAXException
         * @throws RuntimeException DOCUMENT ME!
         */
        protected void encodeGeometry(AttributeDescriptor attribute)
            throws SAXException {
            AttributesImpl atts = createStandardAttributes(attribute);

            Class type = attribute.getType().getBinding();

            String typeString = "";

            LOGGER.finer(type.getName());

            if (type == Point.class) {
                typeString = "gml:PointPropertyType";
            } else if (type == LineString.class) {
                typeString = "gml:LineStringPropertyType";
            } else if (type == Polygon.class) {
                typeString = "gml:PolygonPropertyType";
            } else if (type == MultiPoint.class) {
                typeString = "gml:MultiPointPropertyType";
            } else if (type == MultiLineString.class) {
                typeString = "gml:MultiLineStringPropertyType";
            } else if (type == MultiPolygon.class) {
                typeString = "gml:MultiPolygonPropertyType";
            } else if (type == GeometryCollection.class) {
                typeString = "gml:MultiGeometryPropertyType";
            } else if (type == Geometry.class) {
                typeString = "gml:GeometryAssociationType";
            } else {
                throw new RuntimeException("Unsupported type: "
                    + type.getName());
            }

            atts.addAttribute("", "type", "type", "", typeString);

            contentHandler.startElement(SCHEMA_NS, "element", "xs:element", atts);

            contentHandler.endElement(SCHEMA_NS, "element", "xs:element");
        }

        /**
         * Encode an AttributeType whose value type is a Feature.
         *
         * @param attribute
         *
         */

        /*protected void encodeFeature(AttributeType attribute) throws SAXException {
       
                      AttributesImpl atts = createStandardAttributes(attribute);
       
                      //atts.addAttribute("", "type", "type", "", "gml:AbstractFeatureType");
       
       
                      contentHandler.startElement(SCHEMA_NS, "element", "xs:element", atts);
       
                      encode("");
       
                      contentHandler.endElement(SCHEMA_NS, "element", "xs:element");
       
                      }*/

        /**
         * Creates standard xml attributes present on all xs:element elements.
         * These are name, maxOccurs, minOccurs and nillable.
         *
         * @param attribute the attribute type from which the information is
         *        retrieved
         *
         * @return an org.xml.sax.helpers.AttributesImpl object that contains
         *         the standard attributes
         */
        protected AttributesImpl createStandardAttributes(
            AttributeDescriptor attribute) {
            AttributesImpl atts = new AttributesImpl();

            atts.addAttribute("", "name", "name", "", attribute.getLocalName());

            if (attribute.isNillable() && attribute.getMinOccurs() == 0) {
                atts.addAttribute("", "minOccurs", "minOccurs", "", "0");

                atts.addAttribute("", "nillable", "nillable", "", "true");
            } else {
                atts.addAttribute("", "minOccurs", "minOccurs", "", "1");

                atts.addAttribute("", "nillable", "nillable", "", "false");
            }

            return atts;
        }
    }
}
TOP

Related Classes of org.geotools.gml.producer.FeatureTypeTransformer$FeatureTypeTranslator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.