Package org.geoserver.wfs.response

Source Code of org.geoserver.wfs.response.GeoJSONOutputFormat

package org.geoserver.wfs.response;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import net.opengis.wfs.FeatureCollectionType;
import net.opengis.wfs.GetFeatureType;
import net.sf.json.JSONException;

import org.geoserver.config.GeoServer;
import org.geoserver.platform.Operation;
import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.GMLInfo;
import org.geoserver.wfs.WFSGetFeatureOutputFormat;
import org.geoserver.wfs.WFSInfo;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.NamedIdentifier;
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.referencing.ReferenceIdentifier;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Geometry;

public class GeoJSONOutputFormat extends WFSGetFeatureOutputFormat {
    private final Logger LOGGER = org.geotools.util.logging.Logging
    .getLogger(this.getClass().toString());

    /**
     * WFS configuration
     */
    private WFSInfo wfs;

    public static final String FORMAT = "json";

    public GeoJSONOutputFormat(GeoServer gs) {
        super(FORMAT);
        this.wfs = gs.getService( WFSInfo.class );
    }

    public String getMimeType(Object value, Operation operation)
    throws ServiceException {
        // let's check if a callback has been set, in that case, we need to return a different mime type
        GetFeatureType gft = (GetFeatureType) operation.getParameters()[0];
        String callback = (String) gft.getFormatOptions().get("CALLBACK");
        if(callback != null && !"".equals(callback)) {
            return "text/javascript";
        } else {
            return "application/json";
        }
    }

    public String getCapabilitiesElementName() {
        return "GEOJSON";
    }

    protected String getContentDisposition(
            FeatureCollectionType featureCollection) {

        StringBuffer sb = new StringBuffer();
        for (Iterator f = featureCollection.getFeature().iterator(); f
        .hasNext();) {
            FeatureCollection fc = (FeatureCollection) f.next();
            sb.append(fc.getSchema().getName().getLocalPart() + "_");
        }
        sb.setLength(sb.length() - 1);
        return "inline; filename=" + sb.toString() + ".txt";

    }

    protected void write(FeatureCollectionType featureCollection,
            OutputStream output, Operation getFeature) throws IOException,
            ServiceException {

        // TODO: investigate setting proper charsets in this
        // it's part of the constructor, just need to hook it up.
        Writer outWriter = new BufferedWriter(
            new OutputStreamWriter(output,wfs.getGeoServer().getGlobal().getCharset()));
       
        // let's check if a callback has been set
        GetFeatureType gft = (GetFeatureType) getFeature.getParameters()[0];
        String callback = (String) gft.getFormatOptions().get("CALLBACK");
        if(callback != null && !"".equals(callback)) {
            outWriter.write(callback + "(");
        }

        GeoJSONBuilder jsonWriter = new GeoJSONBuilder(outWriter);

        // execute should of set all the header information
        // including the lockID
        //
        // execute should also fail if all of the locks could not be aquired
        List resultsList = featureCollection.getFeature();

        // FeatureResults[] featureResults = (FeatureResults[]) resultsList
        // .toArray(new FeatureResults[resultsList.size()]);
        LOGGER.info("about to encode JSON");

        // Generate bounds for every feature?
        boolean featureBounding = wfs.isFeatureBounding();
        boolean hasGeom = false;

        try {
            jsonWriter.object().key("type").value("FeatureCollection");
            jsonWriter.key("features");
            jsonWriter.array();

            CoordinateReferenceSystem crs = null;
            for (int i = 0; i < resultsList.size(); i++) {
                FeatureCollection collection = (FeatureCollection) resultsList
                .get(i);
                FeatureIterator iterator = collection.features();

                try {
                    SimpleFeatureType fType;
                    List<AttributeDescriptor> types;

                    while (iterator.hasNext()) {
                        SimpleFeature feature = (SimpleFeature) iterator.next();
                        jsonWriter.object();
                        jsonWriter.key("type").value("Feature");
                        jsonWriter.key("id").value(feature.getID());

                        fType = feature.getFeatureType();
                        types = fType.getAttributeDescriptors();

                        GeometryDescriptor defaultGeomType = fType.getGeometryDescriptor();

                        if (crs == null && defaultGeomType != null)
                            crs = fType.getGeometryDescriptor().getCoordinateReferenceSystem();

                        jsonWriter.key("geometry");
                        Geometry aGeom = (Geometry) feature.getDefaultGeometry();

                        if (aGeom == null) {
                            // In case the default geometry is not set, we will
                            // just use the first geometry we find
                            for (int j = 0; j < types.size() && aGeom == null; j++) {
                                Object value = feature.getAttribute(j);
                                if (value != null && value instanceof Geometry) {
                                    aGeom = (Geometry) value;
                                }
                            }
                        }
                        // Write the geometry, whether it is a null or not
                        if (aGeom != null) {
                            jsonWriter.writeGeom(aGeom);
                            hasGeom = true;
                        } else {
                            jsonWriter.value(null);
                        }
                        if (defaultGeomType != null)
                            jsonWriter.key("geometry_name").value(
                                    defaultGeomType.getLocalName());

                        jsonWriter.key("properties");
                        jsonWriter.object();

                        for (int j = 0; j < types.size(); j++) {
                            Object value = feature.getAttribute(j);
                            AttributeDescriptor ad = types.get(j);

                            if (value != null) {
                                if (value instanceof Geometry) {
                                    // This is an area of the spec where they
                                    // decided to 'let convention evolve',
                                    // that is how to handle multiple
                                    // geometries. My take is to print the
                                    // geometry here if it's not the default.
                                    // If it's the default that you already
                                    // printed above, so you don't need it here.
                                    if (ad.equals(defaultGeomType)) {
                                        // Do nothing, we wrote it above
                                        // jsonWriter.value("geometry_name");
                                    } else {
                                        jsonWriter.key(ad.getLocalName());
                                        jsonWriter.writeGeom((Geometry) value);
                                    }
                                } else {
                                    jsonWriter.key(ad.getLocalName());
                                    jsonWriter.value(value);
                                }

                            } else {
                                jsonWriter.key(ad.getLocalName());
                                jsonWriter.value(null);
                            }
                        }
                        // Bounding box for feature in properties
                        ReferencedEnvelope refenv = new ReferencedEnvelope(feature.getBounds());
                        if (featureBounding && !refenv.isEmpty())
                            jsonWriter.writeBoundingBox(refenv);

                        jsonWriter.endObject(); // end the properties
                        jsonWriter.endObject(); // end the feature
                    }
                } // catch an exception here?
                finally {
                    collection.close(iterator);
                }

            }

            jsonWriter.endArray(); // end features

            // Coordinate Referense System, currently only if the namespace is
            // EPSG
            if (crs != null) {
                Set<ReferenceIdentifier> ids = crs.getIdentifiers();
                // WKT defined crs might not have identifiers at all
                if(ids != null && ids.size() > 0) {
                    NamedIdentifier namedIdent = (NamedIdentifier) ids.iterator().next();
                    String csStr = namedIdent.getCodeSpace().toUpperCase();
   
                    if (csStr.equals("EPSG")) {
                        jsonWriter.key("crs");
                        jsonWriter.object();
                        jsonWriter.key("type").value(csStr);
                        jsonWriter.key("properties");
                        jsonWriter.object();
                        jsonWriter.key("code");
                        jsonWriter.value(namedIdent.getCode());
                        jsonWriter.endObject(); // end properties
                        jsonWriter.endObject(); // end crs
                    }
                }
            }

            // Bounding box for featurecollection
            if (hasGeom) {
                ReferencedEnvelope e = null;
                for (int i = 0; i < resultsList.size(); i++) {
                    FeatureCollection collection = (FeatureCollection) resultsList
                    .get(i);
                    if (e == null) {
                        e = collection.getBounds();
                    } else {
                        e.expandToInclude(collection.getBounds());
                    }

                }

                if (e != null) {
                    jsonWriter.writeBoundingBox(e);
                }
            }

            jsonWriter.endObject(); // end featurecollection
            outWriter.flush();
            if(callback != null && !"".equals(callback)) {
                outWriter.write(")");
                outWriter.flush();
            }

        } catch (JSONException jsonException) {
            ServiceException serviceException = new ServiceException("Error: "
                    + jsonException.getMessage());
            serviceException.initCause(jsonException);
            throw serviceException;
        }

    }

}
TOP

Related Classes of org.geoserver.wfs.response.GeoJSONOutputFormat

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.