Package org.vfny.geoserver.wms.responses.map.kml

Source Code of org.vfny.geoserver.wms.responses.map.kml.OWS5VectorTransformer$KML3Translator

package org.vfny.geoserver.wms.responses.map.kml;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.geotools.feature.FeatureCollection;
import org.geotools.map.MapLayer;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.OtherText;
import org.geotools.styling.Rule;
import org.geotools.styling.Symbolizer;
import org.geotools.styling.TextSymbolizer2;
import org.geotools.xml.impl.DatatypeConverterImpl;
import org.geotools.xml.impl.DatatypeConverterInterface;
import org.geotools.xml.transform.Translator;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.expression.Expression;
import org.vfny.geoserver.global.GeoServer;
import org.vfny.geoserver.wms.WMSMapContext;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;

public class OWS5VectorTransformer extends KMLVectorTransformer {
   
    private static DatatypeConverterInterface dataTypeConverter = DatatypeConverterImpl.getInstance();
    private boolean extendedDataModule;
    private boolean styleModule;

    public OWS5VectorTransformer(WMSMapContext mapContext, MapLayer mapLayer,
            boolean extendedDataModule, boolean styleModule) {
        super(mapContext, mapLayer);
        this.extendedDataModule = extendedDataModule;
        this.styleModule = styleModule;
    }

    public Translator createTranslator(ContentHandler handler) {
        return new KML3Translator(handler);
    }

    protected class KML3Translator extends KMLTranslator {
        private boolean kml22DataStyle = false;
        protected String schemaId;

        public KML3Translator(ContentHandler contentHandler) {
            super(contentHandler);
           
            KMLGeometryTransformer geometryTransformer = new KMLGeometryTransformer();
            //geometryTransformer.setUseDummyZ( true );
            geometryTransformer.setOmitXMLDeclaration(true);
            geometryTransformer.setNamespaceDeclarationEnabled(true);

            GeoServer config = mapContext.getRequest().getGeoServer();
            geometryTransformer.setNumDecimals(config.getNumDecimals());

            geometryTranslator = geometryTransformer.createTranslator(contentHandler);
           
//            GML3 outputting transformer
//            OWS5GeometryTransformer geometryTransformer = new OWS5GeometryTransformer();
//            geometryTranslator = (KML3GeometryTranslator) geometryTransformer.createTranslator(contentHandler);

            // we need to make sure the data type converter is registered properly

            // We need to create a unique ID for this schema. Given the
            // restrictions of the XML ID
            // type and the fact the same feature type may appear multiple times
            // in the same
            // MapContext, we need to create an artificial ID that's guaranteed
            // to be unique across
            // the encoded KML document. We'll use the layer position as the ID.
            final MapLayer[] layers = OWS5VectorTransformer.this.mapContext.getLayers();
            for (int i = 0; i < layers.length; i++) {
                if (layers[i] == OWS5VectorTransformer.this.mapLayer) {
                    schemaId = "Schema" + (i + 1);
                }
            }
            if (schemaId == null)
                throw new IllegalStateException("Wrapping KMLVectorTransformer holds "
                        + "a layer reference that's not among the MapLayer ones");
        }

        public void encodeSchemas(FeatureCollection collection) {
            // if the extended data module is not active, don't encode schema and extended data
            if(!extendedDataModule)
                return;
           
            // TODO: consider turning this into a Freemarker template
            final SimpleFeatureType schema = (SimpleFeatureType) collection.getSchema();
            final String[] atts = new String[] { "name", schema.getTypeName(), "id", schemaId };
            start("Schema", KMLUtils.attributes(atts));

            // output all non geometric attribute types
            // TODO: or shall we encode only the types that are well known in SchemaData
            // and jump over the rest? Besides, how does one limit the number of attributes
            // displayed? a PROPERTY=x,y,z like in GetFeature would be beneficial
            // to GetFeatureInfo as well
            for (int i = 0; i < schema.getAttributeCount(); i++) {
                AttributeDescriptor at = schema.getDescriptor(i);
                if (at instanceof GeometryDescriptor)
                    continue;

                final String[] atAttributes = new String[] { "type", getType(at), "name",
                        at.getLocalName() };
                start("SimpleField", KMLUtils.attributes(atAttributes));
                element("displayName", at.getLocalName());
                end("SimpleField");
            }

            end("Schema");
        }

        protected String getType(AttributeDescriptor at) {
            // see
            // http://code.google.com/apis/kml/documentation/kml_tags_beta1.html#simplefield
            // Eventually see if we need to support uint/ushort as well (do we
            // have any standard filter for positive numbers?) and clarify
            // what's the range of int and short
            if (Short.class.equals(at.getType().getBinding()))
                return "short";
            else if (Integer.class.equals(at.getType().getBinding()))
                return "int";
            else if (Float.class.equals(at.getType().getBinding()))
                return "float";
            else if (Double.class.equals(at.getType().getBinding()))
                return "double";
            else if (Boolean.class.equals(at.getType().getBinding()))
                return "bool";
            else
                return "string";
        }

        protected void encodeExtendedData(SimpleFeature feature) {
            // if the extended data module is not active, don't encode schema and extended data
            if(!extendedDataModule)
                return;
           
            if(kml22DataStyle)
                encodeKML22ExtendedData(feature);
            else
                encodeKMLOWS5ExtendedData(feature);
        }

        private void encodeKML22ExtendedData(SimpleFeature feature) {
            // TODO: consider turning this into a Freemarker template
            start("ExtendedData");
            start("SchemaData", KMLUtils.attributes(new String[] { "schemaUrl", "#" + schemaId }));

            final int count = feature.getAttributeCount();
            final SimpleFeatureType schema = feature.getFeatureType();
            for (int i = 0; i < count; i++) {
                final AttributeDescriptor at = schema.getDescriptor(i);
                if(at instanceof GeometryDescriptor)
                    continue;
               
                final Attributes atts = KMLUtils.attributes(new String[] { "name",
                        at.getLocalName() });
                element("SimpleData", encodeValue(feature.getAttribute(i)), atts);
            }

            end("SchemaData");
            end("ExtendedData");
        }
       
        private void encodeKMLOWS5ExtendedData(SimpleFeature feature) {
            // TODO: consider turning this into a Freemarker template
            start("ExtendedData", KMLUtils.attributes(new String[] { "schemaUrl", "#" + schemaId }));

            final int count = feature.getAttributeCount();
            final SimpleFeatureType schema = feature.getFeatureType();
            for (int i = 0; i < count; i++) {
                final AttributeDescriptor at = schema.getDescriptor(i);
                if(at instanceof GeometryDescriptor)
                    continue;
               
                final Attributes atts = KMLUtils.attributes(new String[] { "name",
                        at.getLocalName() });
                element("Data", encodeValue(feature.getAttribute(i)), atts);
            }

            end("ExtendedData");
        }

        protected String encodeValue(Object o) {
            if (o == null) {
                return "";
            } else if (o instanceof Number) {
                if (o instanceof Byte)
                    return dataTypeConverter.printByte(((Byte) o).byteValue());
                else if (o instanceof Short)
                    return dataTypeConverter.printShort(((Short) o).shortValue());
                else if (o instanceof Integer)
                    return dataTypeConverter.printInt((((Integer) o).intValue()));
                else if (o instanceof Long)
                    return dataTypeConverter.printLong(((Long) o).intValue());
                else if (o instanceof Float)
                    return dataTypeConverter.printInt((((Float) o).intValue()));
                else if (o instanceof Double)
                    return dataTypeConverter.printInt(((Double) o).intValue());
                else if (o instanceof BigDecimal)
                    return dataTypeConverter.printDecimal((BigDecimal) o);
                else
                    return dataTypeConverter.printString(o.toString());
            } else if (o instanceof Boolean) {
                return dataTypeConverter.printBoolean((((Boolean) o).booleanValue()));
            } else if (o instanceof Date) {
                final Date d = (Date) o;
                final Calendar cal = Calendar.getInstance();
                cal.setTime(d);
                if (d instanceof java.sql.Date)
                    return dataTypeConverter.printDate(cal);
                else if (d instanceof java.sql.Time)
                    return dataTypeConverter.printTime(cal);
                else
                    return dataTypeConverter.printDateTime(cal);
            } else {
                return dataTypeConverter.printString(o.toString());
            }

        }
       
//        /**
//         * Encodes a KML Placemark geometry from a geometry + centroid.
//         */
//        protected void encodePlacemarkGeometry(Geometry geometry, Coordinate centroid, FeatureTypeStyle[] styles) {
//            // if point, just encode a single point, otherwise encode the geometry + centroid
//            if ( geometry instanceof Point ||
//                    (geometry instanceof MultiPoint) && ((MultiPoint)geometry).getNumPoints() == 1 ) {
//                encodeGeometry( geometry, styles);
//            }
//            else {
//                start("MultiGeometry");
//
//                //the centroid
//                start("Point");
//
//                if (!Double.isNaN(centroid.z)) {
//                    element("pos", centroid.x + " " + centroid.y + " " + centroid.z);
//                } else {
//                    element("pos", centroid.x + " " + centroid.y);
//                }
//
//                end("Point");
//
//                //the actual geometry
//                encodeGeometry(geometry, styles);
//
//                end("MultiGeometry");
//            }
//           
//        }
       
        @Override
        protected void encodePlacemarkDescription(SimpleFeature feature, FeatureTypeStyle[] styles)
                throws IOException {
            // look for a kml text style with the description attribute
            List<TextSymbolizer2> textSymbolizers = getTextSymbolizers2(feature, styles);
            Expression description = null;
            for (TextSymbolizer2 ts : textSymbolizers) {
                if(ts.getFeatureDescription() != null)
                    description = ts.getFeatureDescription();
            }
            if(description == null) {
                // use the freemarker template as a fallback
                super.encodePlacemarkDescription(feature, styles);
                return;
            }
           
            start("description");
            cdata(description.evaluate(feature, String.class));
            end("description");
        }
       
        @Override
        protected void encodePlacemarkSnippet(SimpleFeature feature, FeatureTypeStyle[] styles) {
            // look for a kml text style with the abstract attribute
            List<TextSymbolizer2> textSymbolizers = getTextSymbolizers2(feature, styles);
            Expression abxtract = null;
            for (TextSymbolizer2 ts : textSymbolizers) {
                if(ts.getSnippet() != null)
                    abxtract = ts.getSnippet();
            }
            if(abxtract == null) {
                // no snippet then...
                return;
            }
            start("Snippet");
            cdata(abxtract.evaluate(feature, String.class));
            end("Snippet");
        }
       
        @Override
        protected void encodePlacemarkTime(SimpleFeature feature, FeatureTypeStyle[] styles)
                throws IOException {
            // look for a kml text style with the time/startTime/endTime otherText attributes
            List<TextSymbolizer2> textSymbolizers = getTextSymbolizers2(feature, styles);
            Expression abxtract = null;
            Date fromDate = null;
            Date toDate = null;
            Date timestamp = null;
            for (TextSymbolizer2 ts : textSymbolizers) {
                final OtherText ot = ts.getOtherText();
                if(ot != null && ot.getTarget() != null && ot.getText() != null) {
                    if(ot.getTarget().toLowerCase().equals("kml:fromdate"))
                        fromDate = ot.getText().evaluate(feature, Date.class);
                    else if(ot.getTarget().toLowerCase().equals("kml:todate"))
                        toDate = ot.getText().evaluate(feature, Date.class);
                    else if(ot.getTarget().toLowerCase().equals("kml:timestamp"))
                        timestamp = ot.getText().evaluate(feature, Date.class);
                }
            }
            try {
                if(fromDate != null || toDate != null)
                    encodeKmlTimeSpan(fromDate, toDate);
                else if(timestamp != null)
                    encodeKmlTimeStamp(timestamp);
                else
                    super.encodePlacemarkTime(feature, styles);
            } catch(Exception e) {
                throw (IOException) new IOException().initCause(e);
            }
        }

        /**
         * Extracts all of the TextSymbolizer2 from the active rules, in the order
         * they are declared.
         * @param feature
         * @param styles
         * @return
         */
        private List<TextSymbolizer2> getTextSymbolizers2(SimpleFeature feature,
                FeatureTypeStyle[] styles) {
            List<TextSymbolizer2> textSymbolizers = new ArrayList<TextSymbolizer2>();
            for (int i = 0; i < styles.length; i++) {
                Rule[] rules = filterRules(styles[i], feature );
                for ( int j = 0; j < rules.length; j++ ) {
                    Symbolizer[] syms = rules[j].getSymbolizers();
                    for ( int k = 0; k < syms.length; k++) {
                        if ( syms[k] instanceof TextSymbolizer2) {
                            textSymbolizers.add((TextSymbolizer2) syms[k]);
                        }
                    }
                }
            }
            return textSymbolizers;
        }
       
       
        /**
         * Encodes the provided set of rules as KML styles. Override that handles
         * the style definition and encodes it only if the style module is enabled
         */
        protected boolean encodeStyle(SimpleFeature feature, FeatureTypeStyle[] styles) {
          
            //encode hte Line/Poly styles
            List symbolizerList = new ArrayList();
            for ( int j = 0; j < styles.length ; j++ ) {
               Rule[] rules = filterRules(styles[j], feature);
               
                for (int i = 0; i < rules.length; i++) {
                    symbolizerList.addAll(Arrays.asList(rules[i].getSymbolizers()));
                }
            }
           
            if ( !symbolizerList.isEmpty() ) {
                if(styleModule) {
                    //start the style
                    start("Style",
                        KMLUtils.attributes(new String[] { "id", "GeoServerStyle" + feature.getID() }));
   
                    //encode the icon
                    encodeIconStyle(feature, styles);
   
                    Symbolizer[] symbolizers = (Symbolizer[]) symbolizerList.toArray(new Symbolizer[symbolizerList.size()]);
                    encodeStyle(feature, symbolizers);
                   
                    //end the style
                    end("Style");
                }
               
                // we return true anyways because otherwise the geometry won't be encoded
                return true;
            }
            else {
                //dont encode
                return false;
            }

        }


    }

}
TOP

Related Classes of org.vfny.geoserver.wms.responses.map.kml.OWS5VectorTransformer$KML3Translator

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.