Package org.geoserver.wfs.xml

Source Code of org.geoserver.wfs.xml.GML2OutputFormat

/* (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.wfs.xml;

import static org.geoserver.ows.util.ResponseUtils.buildSchemaURL;
import static org.geoserver.ows.util.ResponseUtils.buildURL;
import static org.geoserver.ows.util.ResponseUtils.params;
import static org.geoserver.ows.util.ResponseUtils.urlEncode;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;

import javax.xml.transform.TransformerException;

import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.config.SettingsInfo;
import org.geoserver.ows.URLMangler.URLType;
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.geoserver.wfs.request.FeatureCollectionResponse;
import org.geoserver.wfs.request.GetFeatureRequest;
import org.geoserver.wfs.request.Query;
import org.geotools.feature.FeatureCollection;
import org.geotools.gml.producer.FeatureTransformer;
import org.geotools.gml.producer.FeatureTransformer.FeatureTypeNamespaces;
import org.geotools.gml2.bindings.GML2EncodingUtils;
import org.geotools.referencing.CRS;
import org.geotools.wfs.WFS;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;


/**
* Encodes features in Geographic Markup Language (GML) version 2.
*
* <p>
* GML2-GZIP format is just GML2 with gzip compression. If GML2-GZIP format was
* requested, <code>getContentEncoding()</code> will retutn
* <code>"gzip"</code>, otherwise will return <code>null</code>
* </p>
*
* @author Gabriel Rold?n
* @version $Id$
*/
public class GML2OutputFormat extends WFSGetFeatureOutputFormat {
    private static final int NO_FORMATTING = -1;
    private static final int INDENT_SIZE = 2;
    public static final String formatName = "GML2";
    public static final String MIME_TYPE = "text/xml; subtype=gml/2.1.2";

    /**
     * This is a "magic" class provided by Geotools that writes out GML for an
     * array of FeatureResults.
     *
     * <p>
     * This class seems to do all the work, if you have a problem with GML you
     * will need to hunt it down. We supply all of the header information in
     * the execute method, and work through the featureList in the writeTo
     * method.
     * </p>
     *
     * <p>
     * This value will be <code>null</code> until execute is called.
     * </p>
     */
    private FeatureTransformer transformer;

    /**
     * GeoServer configuration
     */
    private GeoServer geoServer;

    /**
     * The catalog
     */
    protected Catalog catalog;

    /**
     * Creates the producer with a reference to the GetFeature operation
     * using it.
     */
    public GML2OutputFormat(GeoServer geoServer) {
        super(geoServer, new HashSet(Arrays.asList(new String[] { "GML2", MIME_TYPE })));

        this.geoServer = geoServer;
        this.catalog = geoServer.getCatalog();
    }
   
    @Override
    public String getMimeType(Object value, Operation operation) throws ServiceException {
        return MIME_TYPE;
    }
   
    public String getCapabilitiesElementName() {
        return "GML2";
    }

    /**
    * prepares for encoding into GML2 format
    *
    * @param outputFormat DOCUMENT ME!
    * @param results DOCUMENT ME!
    *
    * @throws IOException DOCUMENT ME!
    */
    @SuppressWarnings("unchecked")
    public void prepare(String outputFormat, FeatureCollectionResponse results, GetFeatureRequest request)
        throws IOException {
        transformer = createTransformer();

        FeatureTypeNamespaces ftNames = transformer.getFeatureTypeNamespaces();
        Map ftNamespaces = new HashMap();

        //TODO: the srs is a back, it only will work property when there is
        // one type, we really need to set it on the feature level
        int srs = -1;
        int numDecimals = -1;
        for (int i = 0; i < results.getFeature().size(); i++) {
            //FeatureResults features = (FeatureResults) f.next();
            FeatureCollection features = (FeatureCollection) results.getFeature().get(i);
            SimpleFeatureType featureType = (SimpleFeatureType) features.getSchema();

            ResourceInfo meta = catalog.getResourceByName(featureType.getName(), ResourceInfo.class);

            String prefix = meta.getNamespace().getPrefix();
            String uri = meta.getNamespace().getURI();

            ftNames.declareNamespace(features.getSchema(), prefix, uri);

            if (ftNamespaces.containsKey(uri)) {
                String location = (String) ftNamespaces.get(uri);
                ftNamespaces.put(uri, location + "," + urlEncode(meta.getPrefixedName()));
            } else {
                // don't blindly assume it's a feature type, this class is used also by WMS FeatureInfo
                // meaning it might be a coverage or a remote wms layer
                if(meta instanceof FeatureTypeInfo) {
                    String location = typeSchemaLocation(geoServer.getGlobal(), (FeatureTypeInfo) meta, request.getBaseUrl());
                    ftNamespaces.put(uri, location);
                }
            }

            //JD: wfs reprojection: should not set srs form metadata but from
            // the request
            //srs = Integer.parseInt(meta.getSRS());
            Query query = request.getQueries().get(i);
            try {
                String srsName = query.getSrsName() != null ? query.getSrsName().toString() : null;
                if ( srsName == null ) {
                    //no SRS in query...asking for the default?
                    srsName = meta.getSRS();
                }
                if ( srsName != null ) {
                    CoordinateReferenceSystem crs = CRS.decode(srsName);
                    String epsgCode = GML2EncodingUtils.epsgCode(crs);
                    srs = Integer.parseInt(epsgCode);
                }
            }
            catch( Exception e ) {
                LOGGER.log(Level.WARNING, "Problem encoding:" + query.getSrsName(), e);
               
            }
           
            //track num decimals, in cases where the query has multiple types we choose the max
            // of all the values (same deal as above, might not be a vector due to GetFeatureInfo reusing this)
            if (meta instanceof FeatureTypeInfo) {
                int ftiDecimals = ((FeatureTypeInfo) meta).getNumDecimals();
                if(ftiDecimals > 0) {
                    numDecimals = numDecimals == -1 ? ftiDecimals : Math.max(numDecimals, ftiDecimals);
                }
            }
        }

        SettingsInfo settings = geoServer.getSettings();
       
        if (numDecimals == -1) {
            numDecimals = settings.getNumDecimals();
        }
       
        WFSInfo wfs = getInfo();
       
        transformer.setIndentation(wfs.isVerbose() ? INDENT_SIZE : (NO_FORMATTING));
        transformer.setNumDecimals(numDecimals);
        transformer.setFeatureBounding(wfs.isFeatureBounding());
        transformer.setCollectionBounding(wfs.isFeatureBounding());
        transformer.setEncoding(Charset.forName(settings.getCharset()));

        if (wfs.isCanonicalSchemaLocation()) {
            transformer.addSchemaLocation(WFS.NAMESPACE, wfsCanonicalSchemaLocation());
        } else {
            String wfsSchemaloc = wfsSchemaLocation(request.getBaseUrl());
            transformer.addSchemaLocation(WFS.NAMESPACE, wfsSchemaloc);
        }

        for (Iterator it = ftNamespaces.keySet().iterator(); it.hasNext();) {
            String uri = (String) it.next();
            transformer.addSchemaLocation(uri, (String) ftNamespaces.get(uri));
        }

        GMLInfo gml = wfs.getGML().get(WFSInfo.Version.V_10);
        transformer.setGmlPrefixing(wfs.isCiteCompliant() || !gml.getOverrideGMLAttributes());

        if (results.getLockId() != null) {
            transformer.setLockId(results.getLockId());
        }

        if (srs != -1) {
            transformer.setSrsName(gml.getSrsNameStyle().getPrefix() + srs);
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @param output DOCUMENT ME!
     *
     * @throws ServiceException DOCUMENT ME!
     * @throws IOException DOCUMENT ME!
     * @throws IllegalStateException DOCUMENT ME!
     */
    public void encode(OutputStream output, FeatureCollectionResponse results, GetFeatureRequest request)
        throws ServiceException, IOException {
        if (results == null) {
            throw new IllegalStateException("It seems prepare() has not been called"
                + " or has not succeed");
        }

        GZIPOutputStream gzipOut = null;

        // 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 = results.getFeature();
        FeatureCollection[] featureResults = (FeatureCollection[]) resultsList.toArray(new FeatureCollection[resultsList
                .size()]);

        try {
            transformer.transform(featureResults, output);

            //we need to "finish" here because if not,it is possible that the gzipped
            //content do not gets completely written
            if (gzipOut != null) {
                gzipOut.finish();
                gzipOut.flush();
            }
        } catch (TransformerException gmlException) {
            String msg = " error:" + gmlException.getMessage();
            throw new ServiceException(msg, gmlException);
        }
    }

    protected void write(FeatureCollectionResponse featureCollection, OutputStream output,
        Operation getFeature) throws IOException, ServiceException {
        GetFeatureRequest request = GetFeatureRequest.adapt(getFeature.getParameters()[0]);
       
        prepare(request.getOutputFormat(), featureCollection, request);
        encode(output, featureCollection, request );
    }

    protected FeatureTransformer createTransformer() {
        return new FeatureTransformer();
    }

    protected String wfsSchemaLocation(String baseUrl) {
        return buildSchemaURL(baseUrl, "wfs/1.0.0/WFS-basic.xsd");
    }

    protected String wfsCanonicalSchemaLocation() {
        return org.geoserver.wfs.xml.v1_0_0.WFS.CANONICAL_SCHEMA_LOCATION_BASIC;
    }
   
    protected String typeSchemaLocation(GeoServerInfo global, FeatureTypeInfo meta, String baseUrl) {
        Map<String, String> params = params("service", "WFS", "version", "1.0.0",
                "request", "DescribeFeatureType", "typeName", meta.getPrefixedName());
        return buildURL(baseUrl, "wfs", params, URLType.SERVICE);
    }
}
TOP

Related Classes of org.geoserver.wfs.xml.GML2OutputFormat

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.