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

Source Code of org.vfny.geoserver.wms.responses.map.kml.KMLVectorTransformer

/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.vfny.geoserver.wms.responses.map.kml;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;

import org.apache.batik.dom.util.HashTable;
import org.geoserver.catalog.Catalog;
import org.geoserver.config.GeoServer;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.map.MapLayer;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.Symbolizer;
import org.geotools.xml.transform.Translator;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.vfny.geoserver.wms.WMSMapContext;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;


/**
* Transforms a feature collection to a kml document consisting of nested
* "Style" and "Placemark" elements for each feature in the collection.
* A new transfomer must be instantianted for each feature collection,
* the feature collection provided to the translator is supposed to be
* the one coming out of the MapLayer
* <p>
* Usage:
* </p>
* @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
*
*/
public class KMLVectorTransformer extends KMLMapTransformer {
    public KMLVectorTransformer(WMSMapContext mapContext, MapLayer mapLayer) {
        super(mapContext, mapLayer);

        setNamespaceDeclarationEnabled(false);
    }

   /**
     * Sets the scale denominator.
     */
    public void setScaleDenominator(double scaleDenominator) {
        this.scaleDenominator = scaleDenominator;
    }

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

    protected class KMLTranslator extends KMLMapTranslatorSupport {
        /**
         * Store the regionating strategy being applied
         */
        private RegionatingStrategy myStrategy;

        public KMLTranslator(ContentHandler contentHandler) {
            super(contentHandler);

            KMLGeometryTransformer geometryTransformer = new KMLGeometryTransformer();
            //geometryTransformer.setUseDummyZ( true );
            geometryTransformer.setOmitXMLDeclaration(true);
            geometryTransformer.setNamespaceDeclarationEnabled(true);

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

            geometryTranslator =
                (KMLGeometryTransformer.KMLGeometryTranslator)
                geometryTransformer.createTranslator(contentHandler, mapContext);
        }

        public void setRegionatingStrategy(RegionatingStrategy rs){
            myStrategy = rs;
        }

        public void encode(Object o) throws IllegalArgumentException {
            FeatureCollection<SimpleFeatureType, SimpleFeature> features = (FeatureCollection) o;
            SimpleFeatureType featureType = features.getSchema();
            Catalog catalog = mapContext.getRequest().getWMS().getGeoServer().getCatalog();

            if (isStandAlone()) {
                start( "kml" );
            }

            //start the root document, name it the name of the layer
            start("Document", KMLUtils.attributes(
                    new String[] {"xmlns:atom", "http://purl.org/atom/ns#" }));
            element("name", mapLayer.getTitle());

            String relLinks = (String)mapContext.getRequest().getFormatOptions().get("relLinks");
            // Add prev/next links if requested
            if (mapContext.getRequest().getMaxFeatures() != null &&
                relLinks != null && relLinks.equalsIgnoreCase("true") ){

                String linkbase = "";
                try {
                    linkbase = getFeatureTypeURL();
                    linkbase += ".kml";
                } catch (IOException ioe) {
                    throw new RuntimeException(ioe);
                }

                int maxFeatures = mapContext.getRequest().getMaxFeatures();
                int startIndex =
                    (mapContext.getRequest().getStartIndex() == null)
                    ? 0
                    : mapContext.getRequest().getStartIndex().intValue();
                int prevStart = startIndex - maxFeatures;
                int nextStart = startIndex + maxFeatures;

                // Previous page, if any
                if (prevStart >= 0) {
                    String prevLink = linkbase + "?startindex="
                        + prevStart + "&maxfeatures=" + maxFeatures;
                    element("atom:link", null, KMLUtils.attributes(new String[] {
                                "rel", "prev", "href", prevLink }));
                    encodeSequentialNetworkLink(linkbase, prevStart,
                            maxFeatures, "prev", "Previous page");
                }

                // Next page, if any
                if (features.size() >= maxFeatures) {
                    String nextLink = linkbase + "?startindex=" + nextStart
                        + "&maxfeatures=" + maxFeatures;
                    element("atom:link", null, KMLUtils.attributes(new String[] {
                                "rel", "next", "href", nextLink }));
                    encodeSequentialNetworkLink(linkbase, nextStart,
                            maxFeatures, "next", "Next page");
                }
            }

            //get the styles for the layer
            FeatureTypeStyle[] featureTypeStyles = KMLUtils.filterFeatureTypeStyles(mapLayer.getStyle(),
                    featureType);

            // encode the schemas (kml 2.2)
            encodeSchemas(features);

            // encode the layers
            encode(features, featureTypeStyles);
           
            //encode the legend
            //encodeLegendScreenOverlay();
            end("Document");
           
            if ( isStandAlone() ) {
                end( "kml" );
            }
        }

        /**
         *
         * Encodes a networklink for previous or next document in a sequence
         *
         * Note that in KML 2.2 atom:link is supported and may be better.
         *
         * @param linkbase the base fore creating URLs
         * @param prevStart previous start value
         * @param maxFeatures maximum number of features to return
         * @param id attribute to use for this NetworkLink
         * @param readableName goes into linkName
         */
        private void encodeSequentialNetworkLink(String linkbase, int prevStart,
                int maxFeatures, String id, String readableName) {
            String link = linkbase + "?startindex=" + prevStart
                    + "&maxfeatures=" + maxFeatures;
            start("NetworkLink", KMLUtils.attributes(new String[] {"id", id}));
            element("description",readableName);
            start("Link");
            element("href",link);
            end("Link");
            end("NetworkLink");
        }

        /**
         * Encodes the <Schema> element in kml 2.2
         * @param featureTypeStyles
         */
        protected void encodeSchemas(FeatureCollection<SimpleFeatureType, SimpleFeature> featureTypeStyles) {
            // the code is at the moment in KML3VectorTransformer
        }

        protected void encode(FeatureCollection<SimpleFeatureType, SimpleFeature> features,
                FeatureTypeStyle[] styles) {
           //grab a reader and process
            FeatureIterator<SimpleFeature> reader = null;

            try {
                //grab a reader and process
                reader = features.features();
               
                // Write Styles
                while (reader.hasNext()) {
                    SimpleFeature feature = (SimpleFeature) reader.next();
                    try {
                        List<Symbolizer> symbolizers = filterSymbolizers(feature, styles);
                        if (symbolizers.size() > 0) {
                            encodePlacemark(feature, symbolizers);   
                        }
                    } catch (RuntimeException t) {
                        // if the stream has been closed by the client don't keep on going forward,
                        // this is not a feature local issue
                        //
                        if(t.getCause() instanceof SAXException)
                            throw t;
                        else
                            LOGGER.log(
                                    Level.WARNING,
                                    "Failure tranforming feature to KML:" + feature.getID(),
                                    t
                                );
                    }
                }
            } finally {
                //make sure we always close
                features.close(reader);
            }
        }
    }

   
}
TOP

Related Classes of org.vfny.geoserver.wms.responses.map.kml.KMLVectorTransformer

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.