Package org.geotools.data.wfs.v1_1_0

Source Code of org.geotools.data.wfs.v1_1_0.DefaultWFSStrategy

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*/
package org.geotools.data.wfs.v1_1_0;

import static net.opengis.wfs.ResultTypeType.HITS_LITERAL;
import static net.opengis.wfs.ResultTypeType.RESULTS_LITERAL;
import static org.geotools.data.wfs.protocol.wfs.GetFeature.ResultType.RESULTS;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.QName;

import net.opengis.wfs.GetFeatureType;
import net.opengis.wfs.QueryType;
import net.opengis.wfs.WfsFactory;

import org.geotools.data.Query;
import org.geotools.data.wfs.protocol.wfs.GetFeature;
import org.geotools.data.wfs.protocol.wfs.GetFeature.ResultType;
import org.geotools.data.wfs.protocol.wfs.WFSOperationType;
import org.geotools.data.wfs.protocol.wfs.WFSProtocol;
import org.geotools.factory.GeoTools;
import org.geotools.filter.Capabilities;
import org.geotools.filter.capability.FilterCapabilitiesImpl;
import org.geotools.filter.v1_1.OGC;
import org.geotools.filter.v1_1.OGCConfiguration;
import org.geotools.filter.visitor.CapabilitiesFilterSplitter;
import org.geotools.filter.visitor.SimplifyingFilterVisitor;
import org.geotools.wfs.v1_1.WFSConfiguration;
import org.geotools.xml.Configuration;
import org.geotools.xml.Encoder;
import org.opengis.filter.Filter;
import org.opengis.filter.Id;
import org.opengis.filter.capability.FilterCapabilities;
import org.opengis.filter.capability.IdCapabilities;
import org.opengis.filter.identity.Identifier;
import org.opengis.filter.sort.SortBy;

/**
* A default strategy for a WFS 1.1.0 implementation that assumes the server sticks to the standard.
*
* @author Gabriel Roldan (OpenGeo)
* @version $Id$
* @since 2.6
*
*
*
* @source $URL$
*         http://gtsvn.refractions.net/trunk/modules/plugin/wfs/src/main/java/org/geotools/data
*         /wfs/v1_1_0/DefaultWFSStrategy.java $
*/
@SuppressWarnings("nls")
public class DefaultWFSStrategy implements WFSStrategy {

    protected static final String DEFAULT_OUTPUT_FORMAT = "text/xml; subtype=gml/3.1.1";

    private static final Configuration filter_1_1_0_Configuration = new OGCConfiguration();

    private static final Configuration wfs_1_1_0_Configuration = new WFSConfiguration();

    /**
     * @see WFSStrategy#supportsGet()
     */
    public boolean supportsGet() {
        return true;
    }

    /**
     * @see WFSStrategy#supportsPost()
     */
    public boolean supportsPost() {
        return true;
    }

    /**
     * @return {@code "text/xml; subtype=gml/3.1.1"}
     * @see WFSProtocol#getDefaultOutputFormat()
     */
    public String getDefaultOutputFormat(WFSProtocol wfs, WFSOperationType operation) {
        if (WFSOperationType.GET_FEATURE != operation) {
            throw new UnsupportedOperationException(
                    "Not implemented for other than GET_FEATURE yet");
        }

        Set<String> supportedOutputFormats = wfs.getSupportedGetFeatureOutputFormats();
        if (supportedOutputFormats.contains(DEFAULT_OUTPUT_FORMAT)) {
            return DEFAULT_OUTPUT_FORMAT;
        }
        throw new IllegalArgumentException("Server does not support '" + DEFAULT_OUTPUT_FORMAT
                + "' output format: " + supportedOutputFormats);
    }

    /**
     * Creates the mapping {@link GetFeatureType GetFeature} request for the given {@link Query} and
     * {@code outputFormat}, and post-processing filter based on the server's stated filter
     * capabilities.
     *
     * @see WFSStrategy#createGetFeatureRequest(WFS_1_1_0_DataStore, WFSProtocol, Query, String)
     */
    @SuppressWarnings("unchecked")
    public RequestComponents createGetFeatureRequest(WFSProtocol wfs, GetFeature query)
            throws IOException {
        final WfsFactory factory = WfsFactory.eINSTANCE;

        GetFeatureType getFeature = factory.createGetFeatureType();
        getFeature.setService("WFS");
        getFeature.setVersion(wfs.getServiceVersion().toString());
        getFeature.setOutputFormat(query.getOutputFormat());

        getFeature.setHandle("GeoTools " + GeoTools.getVersion() + " WFS DataStore");
        Integer maxFeatures = query.getMaxFeatures();
        if (maxFeatures != null) {
            getFeature.setMaxFeatures(BigInteger.valueOf(maxFeatures.intValue()));
        }

        ResultType resultType = query.getResultType();
        getFeature.setResultType(RESULTS == resultType ? RESULTS_LITERAL : HITS_LITERAL);

        QueryType wfsQuery = factory.createQueryType();
        wfsQuery.setTypeName(Collections.singletonList(query.getTypeName()));

        Filter serverFilter = query.getFilter();
        if (!Filter.INCLUDE.equals(serverFilter)) {
            wfsQuery.setFilter(serverFilter);
        }
        String srsName = query.getSrsName();
        try {
            wfsQuery.setSrsName(new URI(srsName));
        } catch (URISyntaxException e) {
            throw new RuntimeException("Can't create a URI from the query CRS: " + srsName, e);
        }
        String[] propertyNames = query.getPropertyNames();
        boolean retrieveAllProperties = propertyNames == null;
        if (!retrieveAllProperties) {
            List propertyName = wfsQuery.getPropertyName();
            for (String propName : propertyNames) {
                propertyName.add(propName);
            }
        }
        SortBy[] sortByList = query.getSortBy();
        if (sortByList != null) {
            for (SortBy sortBy : sortByList) {
                wfsQuery.getSortBy().add(sortBy);
            }
        }

        getFeature.getQuery().add(wfsQuery);

        RequestComponents reqParts = new RequestComponents();
        reqParts.setServerRequest(getFeature);

        Map<String, String> parametersForGet = buildGetFeatureParametersForGet(getFeature);
        reqParts.setKvpParameters(parametersForGet);

        return reqParts;
    }

    @SuppressWarnings("unchecked")
    protected Map<String, String> buildGetFeatureParametersForGet(GetFeatureType request)
            throws IOException {
        Map<String, String> map = new HashMap<String, String>();
        map.put("SERVICE", "WFS");
        map.put("VERSION", "1.1.0");
        map.put("REQUEST", "GetFeature");
        map.put("OUTPUTFORMAT", request.getOutputFormat());

        if (request.getMaxFeatures() != null) {
            map.put("MAXFEATURES", String.valueOf(request.getMaxFeatures()));
        }

        final QueryType query = (QueryType) request.getQuery().get(0);
        final String typeName = (String) query.getTypeName().get(0);
        map.put("TYPENAME", typeName);

        if (query.getPropertyName().size() > 0) {
            List<String> propertyNames = query.getPropertyName();
            StringBuilder pnames = new StringBuilder();
            for (Iterator<String> it = propertyNames.iterator(); it.hasNext();) {
                pnames.append(it.next());
                if (it.hasNext()) {
                    pnames.append(',');
                }
            }
            map.put("PROPERTYNAME", pnames.toString());
        }

        // SRSNAME parameter. Let the server reproject.
        // TODO: should check if the server supports the required crs
        URI srsName = query.getSrsName();
        if (srsName != null) {
            map.put("SRSNAME", srsName.toString());
        }
        final Filter filter = query.getFilter();

        if (filter != null && Filter.INCLUDE != filter) {
            if (filter instanceof Id) {
                final Set<Identifier> identifiers = ((Id) filter).getIdentifiers();
                StringBuffer idValues = new StringBuffer();
                for (Iterator<Identifier> it = identifiers.iterator(); it.hasNext();) {
                    Object id = it.next().getID();
                    // REVISIT: should URL encode the id?
                    idValues.append(String.valueOf(id));
                    if (it.hasNext()) {
                        idValues.append(",");
                    }
                }
                map.put("FEATUREID", idValues.toString());
            } else {
                String xmlEncodedFilter = encodeGetFeatureGetFilter(filter);
                map.put("FILTER", xmlEncodedFilter);
            }
        }

        return map;
    }

    /**
     * Returns a single-line string containing the xml representation of the given filter, as
     * appropriate for the {@code FILTER} parameter in a GetFeature request.
     */
    protected String encodeGetFeatureGetFilter(final Filter filter) throws IOException {
        Configuration filterConfig = getFilterConfiguration();
        Encoder encoder = new Encoder(filterConfig);
        // do not write the xml declaration
        encoder.setOmitXMLDeclaration(true);
        encoder.setEncoding(Charset.forName("UTF-8"));

        OutputStream out = new ByteArrayOutputStream();
        encoder.encode(filter, OGC.Filter, out);
        String encoded = out.toString();
        encoded = encoded.replaceAll("\n", "");
        return encoded;
    }

    protected Configuration getFilterConfiguration() {
        return filter_1_1_0_Configuration;
    }

    /**
     * @see WFSStrategy#getWfsConfiguration()
     */
    public Configuration getWfsConfiguration() {
        return wfs_1_1_0_Configuration;
    }

    /**
     * Splits the filter provided by the geotools query into the server supported and unsupported
     * ones.
     *
     * @param caps
     *            the server filter capabilities description
     * @param queryFilter
     * @return a two-element array where the first element is the supported filter and the second
     *         the one to post-process
     * @see WFSStrategy#splitFilters(WFS_1_1_0_Protocol, Filter)
     */
    public Filter[] splitFilters(Capabilities caps, Filter queryFilter) {
        SimplifyingFilterVisitor simplifier = new SimplifyingFilterVisitor();
        queryFilter = (Filter) queryFilter.accept(simplifier, null);
       
        // ID Filters aren't allowed to be parameters in Logical or Comparison Operators
       
        FilterCapabilities filterCapabilities = caps.getContents();
        IdCapabilities idCapabilities = filterCapabilities.getIdCapabilities();
        if (idCapabilities != null && (idCapabilities.hasEID() || idCapabilities.hasFID())) {
            // server supports ID Filters so we need to check our queryFilter is valid           
           
            Capabilities idFilterCaps = new Capabilities();
            idFilterCaps.addName("Id");
           
            CapabilitiesFilterSplitter splitter = new CapabilitiesFilterSplitter(idFilterCaps, null, null);
            queryFilter.accept(splitter, null);
       
            Filter server = splitter.getFilterPre();
            if (server.equals(Filter.INCLUDE)) {
                // ID Filters not found in the root Filter
                // remove ID Filter from Capabilities
                FilterCapabilities filterCapabilitiesWithoutId = new FilterCapabilitiesImpl(
                        filterCapabilities.getVersion(),
                        filterCapabilities.getScalarCapabilities(),
                        filterCapabilities.getSpatialCapabilities(),
                        null,
                        filterCapabilities.getTemporalCapabilities());

                Capabilities capabilitiesWithoutId = new Capabilities();
                capabilitiesWithoutId.addAll(filterCapabilitiesWithoutId);
               
                return splitFilters(capabilitiesWithoutId, queryFilter);               
            } else {
                // ID Filter found
                // query the server using the ID Filter
                Filter post = splitter.getFilterPost();
                return new Filter[] { server, post };                           
            }
        } else {
            CapabilitiesFilterSplitter splitter = new CapabilitiesFilterSplitter(caps, null, null);

            queryFilter.accept(splitter, null);

            Filter server = splitter.getFilterPre();
            Filter post = splitter.getFilterPost();

            return new Filter[] { server, post };
        }
    }

    @Override
    public String getPrefixedTypeName(QName typeName) {
        assert !("".equals(typeName.getPrefix()));
        return typeName.getPrefix() + ":" + typeName.getLocalPart();
    }

    @Override
    public Map<String, String> getNamespaceURIMappings() {       
        return new HashMap<String, String>();
    }

    @Override
    public boolean canIgnoreMissingElementDeclaration() {
        return false;
    }

    @Override
    public Map<QName, Class<?>> getFieldTypeMappings() {
        return new HashMap<QName, Class<?>>();
    }
}
TOP

Related Classes of org.geotools.data.wfs.v1_1_0.DefaultWFSStrategy

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.