Package org.geoserver.wps.ppio

Source Code of org.geoserver.wps.ppio.KMLPPIO

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps.ppio;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.geoserver.config.GeoServer;
import org.geoserver.config.ServiceInfo;
import org.geoserver.kml.KMLEncoder;
import org.geoserver.kml.KMLMapOutputFormat;
import org.geoserver.kml.KmlEncodingContext;
import org.geoserver.kml.decorator.KmlDecoratorFactory.KmlDecorator;
import org.geoserver.kml.sequence.SequenceList;
import org.geoserver.kml.sequence.WFSFeatureSequenceFactory;
import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.WFSInfo;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.store.ReprojectingFeatureCollection;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.kml.KML;
import org.geotools.kml.KMLConfiguration;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.util.logging.Logging;
import org.geotools.xml.Configuration;
import org.geotools.xml.StreamingParser;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.Name;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Geometry;

import de.micromata.opengis.kml.v_2_2_0.Document;
import de.micromata.opengis.kml.v_2_2_0.Feature;
import de.micromata.opengis.kml.v_2_2_0.Folder;
import de.micromata.opengis.kml.v_2_2_0.Kml;

/**
* PPIO for KML 2.2.
*
*/
public class KMLPPIO extends CDataPPIO {
    private static final Logger LOGGER = Logging.getLogger(KMLPPIO.class);

    GeoServer gs;

    Configuration xml;

    SimpleFeatureType type;

    public KMLPPIO(GeoServer gs) {
        super(FeatureCollection.class, FeatureCollection.class, KMLMapOutputFormat.MIME_TYPE);

        this.gs = gs;
        this.xml = new KMLConfiguration();
        SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();

        b.setName("puregeometries");

        b.setCRS(DefaultGeographicCRS.WGS84);
        b.add("location", Geometry.class);

        this.type = b.buildFeatureType();
    }

    private final static HashMap<Name, Class> getSignature(SimpleFeature f) {
        HashMap ftype = new HashMap();
        Collection properties = f.getProperties();
        for (Object op : properties) {
            Property p = (Property) op;
            Class c = p.getType().getBinding();
            if ((c.isAssignableFrom(String.class)) || (c.isAssignableFrom(Boolean.class))
                    || (c.isAssignableFrom(Integer.class)) || (c.isAssignableFrom(Float.class))
                    || (c.isAssignableFrom(Double.class)) || (c.isAssignableFrom(Geometry.class))) {
                ftype.put(p.getName(), c);
            }
        }
        return ftype;
    }

    private SimpleFeatureType getType(HashMap<Name, Class> ftype) {
        SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();

        b.setName("puregeometries");

        b.setCRS(DefaultGeographicCRS.WGS84);
        for (Map.Entry entry : ftype.entrySet()) {
            b.add(((Name) entry.getKey()).toString(), (Class) entry.getValue());
        }
        return b.buildFeatureType();
    }

    public Object decode(InputStream input) throws Exception {
        StreamingParser parser = new StreamingParser(new KMLConfiguration(), input, KML.Placemark);
        SimpleFeature f = null;
        ListFeatureCollection features = null;
        HashMap oldftype = null;
        SimpleFeatureType type = null;
        SimpleFeatureBuilder featureBuilder = null;

        while ((f = (SimpleFeature) parser.parse()) != null) {
            HashMap ftype = getSignature(f);
            if (oldftype == null) {
                oldftype = ftype;
                type = getType(ftype);
                featureBuilder = new SimpleFeatureBuilder(type);
                features = new ListFeatureCollection(type);
            } else {
                if (!oldftype.equals(ftype)) {
                    break;
                }
            }
            for (Object oentry : ftype.entrySet()) {
                Map.Entry entry = (Map.Entry) oentry;
                featureBuilder.add(f.getAttribute((Name) entry.getKey()));
            }
            SimpleFeature fnew = featureBuilder.buildFeature(f.getID());
            features.add(fnew);
        }
        return features;
    }

    public Object decode(String input) throws Exception {
        return decode(new ByteArrayInputStream(input.getBytes()));
    }

    @Override
    public void encode(Object obj, OutputStream os) throws Exception {
        LOGGER.info("KMLPPIO::encode: obj is of class " + obj.getClass().getName()
                + ", handler is of class " + os.getClass().getName());

        // prepare the encoding context
        KMLEncoder encoder = new KMLEncoder();
        SimpleFeatureCollection fcObj = (SimpleFeatureCollection) obj;
        CoordinateReferenceSystem crs = fcObj.getSchema().getCoordinateReferenceSystem();
        // gpx is defined only in wgs84
        if (crs != null && !CRS.equalsIgnoreMetadata(crs, DefaultGeographicCRS.WGS84)) {
            fcObj = new ReprojectingFeatureCollection(fcObj, DefaultGeographicCRS.WGS84);
        }

        List<SimpleFeatureCollection> collections = new ArrayList<SimpleFeatureCollection>();
        collections.add(fcObj);
        KmlEncodingContext context = new WFSKmlEncodingContext(gs.getService(WFSInfo.class),
                collections);

        // create the document
        Kml kml = new Kml();
        Document document = kml.createAndSetDocument();

        // get the callbacks for the document and let them loose
        List<KmlDecorator> docDecorators = context.getDecoratorsForClass(Document.class);
        for (KmlDecorator decorator : docDecorators) {
            document = (Document) decorator.decorate(document, context);
            if (document == null) {
                throw new ServiceException("Coding error in decorator " + decorator
                        + ", document objects cannot be set to null");
            }
        }

        // build the contents
        for (SimpleFeatureCollection collection : collections) {
            // create the folder
            SimpleFeatureCollection fc = (SimpleFeatureCollection) collection;
            Folder folder = document.createAndAddFolder();
            folder.setName(fc.getSchema().getTypeName());

            // have it be decorated
            List<KmlDecorator> folderDecorators = context.getDecoratorsForClass(Folder.class);
            for (KmlDecorator decorator : folderDecorators) {
                folder = (Folder) decorator.decorate(folder, context);
                if (folder == null) {
                    break;
                }
            }
            if (folder == null) {
                continue;
            }

            // create the streaming features
            context.setCurrentFeatureCollection(fc);
            List<Feature> features = new SequenceList<Feature>(new WFSFeatureSequenceFactory(
                    context));
            context.addFeatures(folder, features);
        }

        // write out the output
        encoder.encode(kml, os, context);
        os.flush();

    }

    /**
     * A special KML encoding context for the WFS case
     *
     * @author Andrea Aime - GeoSolutions
     *
     */
    static class WFSKmlEncodingContext extends KmlEncodingContext {

        private List<SimpleFeatureCollection> collections;

        private SimpleFeatureType featureType;

        public WFSKmlEncodingContext(ServiceInfo si, List<SimpleFeatureCollection> collections) {
            this.service = getService();
            this.collections = collections;

            // set some defaults for wfs encoding
            this.descriptionEnabled = false;
            this.kmScore = 100;
            this.extendedDataEnabled = true;
            this.kmz = false;
        }

        public List<SimpleFeatureType> getFeatureTypes() {
            List<SimpleFeatureType> results = new ArrayList<SimpleFeatureType>();
            for (SimpleFeatureCollection fc : collections) {
                results.add(fc.getSchema());
            }

            return results;
        }

        @Override
        public void setCurrentFeatureCollection(SimpleFeatureCollection currentFeatureCollection) {
            super.setCurrentFeatureCollection(currentFeatureCollection);
            this.layerIndex++;
            this.featureType = currentFeatureCollection.getSchema();

        }

        @Override
        public SimpleFeatureType getCurrentFeatureType() {
            return featureType;
        }

    }

    public String getFileExtension() {
        return "kml";
    }
}
TOP

Related Classes of org.geoserver.wps.ppio.KMLPPIO

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.