Package org.geoserver.kml.sequence

Source Code of org.geoserver.kml.sequence.FeatureSequenceFactory$FeatureGenerator

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

import java.util.EmptyStackException;
import java.util.List;

import org.geoserver.kml.KmlEncodingContext;
import org.geoserver.kml.decorator.KmlDecoratorFactory.KmlDecorator;
import org.geoserver.kml.utils.ScaleStyleVisitor;
import org.geoserver.kml.utils.SymbolizerCollector;
import org.geoserver.wms.WMSMapContent;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.filter.function.EnvFunction;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.styling.Style;
import org.geotools.styling.Symbolizer;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import de.micromata.opengis.kml.v_2_2_0.Feature;
import de.micromata.opengis.kml.v_2_2_0.Placemark;

/**
* Creates a sequence of Placemark objects mapping the vector contents of a layer
*
* @author Andrea Aime - GeoSolutions
*/
public class FeatureSequenceFactory implements SequenceFactory<Feature> {
   
    static final String OUTPUT_MODE = "kmlOutputMode";
   
    static final String VECTOR_MODE = "vector";

    private SimpleFeatureCollection features;

    private List<KmlDecorator> callbacks;

    private Style simplified;

    private KmlEncodingContext context;

    public FeatureSequenceFactory(KmlEncodingContext context, FeatureLayer layer) {
        this.context = context;
        this.features = context.getCurrentFeatureCollection();
        WMSMapContent mapContent = context.getMapContent();

        // prepare the encoding context
        context.setCurrentLayer(layer);
       

        // prepare the callbacks
        callbacks = context.getDecoratorsForClass(Placemark.class);

        // prepare the style for this layer
        simplified = getSimplifiedStyle(mapContent, layer);
    }

    private Style getSimplifiedStyle(WMSMapContent mc, Layer layer) {
        ScaleStyleVisitor visitor = new ScaleStyleVisitor(mc.getScaleDenominator(),
                (SimpleFeatureType) layer.getFeatureSource().getSchema());
        try {
            layer.getStyle().accept(visitor);
            return (Style) visitor.getCopy();
        } catch (EmptyStackException e) {
            return null;
        }
    }

    @Override
    public Sequence<Feature> newSequence() {
        return new FeatureGenerator(simplified != null ? context.openIterator(features) : null);
    }

    public class FeatureGenerator implements Sequence<Feature> {

        private FeatureIterator fi;

        public FeatureGenerator(FeatureIterator fi) {
            if(fi != null) {
                // until we are scrolling this generator we are in vector mode
                EnvFunction.setLocalValue(OUTPUT_MODE, VECTOR_MODE);
                this.fi = fi;
            }
        }

        @Override
        public Feature next() {
            // already reached the end?
            if (fi == null) {
                return null;
            }

            while (fi.hasNext()) {
                boolean featureRetrieved = false;
                try {
                    // grab the next feature, with a sentinel to tell us whether there was an
                    // exception
                    SimpleFeature sf = (SimpleFeature) fi.next();
                    featureRetrieved = true;
                    context.setCurrentFeature(sf);

                    List<Symbolizer> symbolizers = getSymbolizers(simplified, sf);
                    if (symbolizers.size() == 0) {
                        // skip layers that have no active symbolizers
                        continue;
                    }
                    context.setCurrentSymbolizers(symbolizers);

                    // only create the basic placemark here, the rest is delegated to decorators
                    Placemark pm = new Placemark();
                    pm.setId(sf.getID());

                    // call onto the decorators
                    for (KmlDecorator callback : callbacks) {
                        pm = (Placemark) callback.decorate(pm, context);
                        if (pm == null) {
                            // we have to skip this one
                            continue;
                        }
                    }

                    return pm;
                } finally {
                    if (!featureRetrieved) {
                        // an exception has occurred, release the feature iterator
                        context.closeIterator(fi);
                        EnvFunction.setLocalValue(OUTPUT_MODE, null);
                    }
                }
            }

            // did we reach the end just now?
            if (!fi.hasNext()) {
                // clean up the output mode, the next layer might be encoded as a raster overlay
                EnvFunction.setLocalValue(OUTPUT_MODE, null);
                context.closeIterator(fi);
            }
            return null;
        }

        private List<Symbolizer> getSymbolizers(Style style, SimpleFeature sf) {
            SymbolizerCollector collector = new SymbolizerCollector(sf);
            style.accept(collector);
            return collector.getSymbolizers();
        }

    }

}
TOP

Related Classes of org.geoserver.kml.sequence.FeatureSequenceFactory$FeatureGenerator

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.