Package org.geoserver.wfs.kvp

Source Code of org.geoserver.wfs.kvp.GetFeatureKvpRequestReader

/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.wfs.kvp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
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 org.eclipse.emf.ecore.EObject;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.wfs.WFSException;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.gml2.bindings.GML2EncodingUtils;
import org.geotools.xml.EMFUtils;
import org.opengis.feature.type.FeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.identity.FeatureId;
import org.opengis.filter.spatial.BBOX;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Envelope;


public class GetFeatureKvpRequestReader extends WFSKvpRequestReader {
    /**
     * Catalog used in qname parsing
     */
    Catalog catalog;

    /**
     * Factory used in filter parsing
     */
    FilterFactory filterFactory;

    public GetFeatureKvpRequestReader(Class requestBean, Catalog catalog, FilterFactory filterFactory) {
        super(requestBean);
        this.catalog = catalog;
        this.filterFactory = filterFactory;
    }
   
    /**
     * Performs additinon GetFeature kvp parsing requirements
     */
    public Object read(Object request, Map kvp, Map rawKvp) throws Exception {
        request = super.read(request, kvp, rawKvp);
       
        // make sure the filter is specified in just one way
        ensureMutuallyExclusive(kvp, new String[] { "featureId", "filter", "bbox", "cql_filter" });

        //get feature has some additional parsing requirements
        EObject eObject = (EObject) request;

        //outputFormat
        if (!EMFUtils.isSet(eObject, "outputFormat")) {
            //set the default
            String version = (String) EMFUtils.get(eObject, "version");

            if ((version != null) && version.startsWith("1.0")) {
                EMFUtils.set(eObject, "outputFormat", "GML2");
            } else {
                EMFUtils.set(eObject, "outputFormat", "text/xml; subtype=gml/3.1.1");
            }
        }

        //typeName
        if (kvp.containsKey("typeName")) {
            //HACK, the kvp reader gives us a list of QName, need to wrap in
            // another
            List typeName = (List) kvp.get("typeName");
            List list = new ArrayList();

            for (Iterator itr = typeName.iterator(); itr.hasNext();) {
                QName qName = (QName) itr.next();
               
                // check the type name is known, otherwise complain
                if(catalog.getFeatureTypeByName(qName.getNamespaceURI(), qName.getLocalPart()) == null) {
                    String name = qName.getPrefix() + ":" + qName.getLocalPart();
                    throw new WFSException("Feature type " + name + " unknown", "InvalidParameterValue", "typeName");
                }
               
                List l = new ArrayList();
                l.add(qName);
                list.add(l);
            }

            kvp.put("typeName", list);
            querySet(eObject, "typeName", list);
        } else {
            //check for featureId and infer typeName
            if (kvp.containsKey("featureId")) {
                //use featureId to infer type Names
                List featureId = (List) kvp.get("featureId");

                ArrayList typeNames = new ArrayList();

                QNameKvpParser parser = new QNameKvpParser("typeName", catalog);

                for (int i = 0; i < featureId.size(); i++) {
                    String fid = (String) featureId.get(i);
                    int pos = fid.indexOf(".");

                    if (pos != -1) {
                        String typeName = fid.substring(0, fid.lastIndexOf("."));

                        //add to a list to set on the query
                        List parsed = (List) parser.parse(typeName);
                        typeNames.add(parsed);
                    }
                }

                querySet(eObject, "typeName", typeNames);
            } else {
                throw new WFSException("The query should specify either typeName or a featureId filter", "MissingParameterValue");
            }
        }

        //filter
        if (kvp.containsKey("filter")) {
            querySet(eObject, "filter", (List) kvp.get("filter"));
        } else if (kvp.containsKey("cql_filter")) {
            querySet(eObject, "filter", (List) kvp.get("cql_filter"));
        } else if (kvp.containsKey("featureId")) {
            //set filter from featureId
            List featureIdList = (List) kvp.get("featureId");
            Set ids = new HashSet();

            for (Iterator i = featureIdList.iterator(); i.hasNext();) {
                String fid = (String) i.next();
                FeatureId featureId = filterFactory.featureId(fid);
               ids.add(featureId);
            }
            // build a single feature id filter
            List filters = Collections.singletonList(filterFactory.id(ids));

            querySet(eObject, "filter", filters);
        } else if (kvp.containsKey("bbox")) {
            //set filter from bbox
            Envelope bbox = (Envelope) kvp.get("bbox");

            List queries = (List) EMFUtils.get(eObject, "query");
            List filters = new ArrayList();

            for (Iterator q = queries.iterator(); q.hasNext();) {
                QueryType query = (QueryType) q.next();
                List typeName = query.getTypeName();
                Filter filter = null;

                if (typeName.size() > 1) {
                    //TODO: not sure what to do here, just going to and them up
                    List and = new ArrayList(typeName.size());

                    for (Iterator t = typeName.iterator(); t.hasNext();) {
                        and.add(bboxFilter((QName) t.next(), bbox));
                    }

                    filter = filterFactory.and(and);
                } else {
                    filter = bboxFilter((QName) typeName.get(0), bbox);
                }

                filters.add(filter);
            }

            querySet(eObject, "filter", filters);
        }

        //propertyName
        if (kvp.containsKey("propertyName")) {
            querySet(eObject, "propertyName", (List) kvp.get("propertyName"));
        }

        //sortBy
        if (kvp.containsKey("sortBy")) {
            querySet(eObject, "sortBy", (List) kvp.get("sortBy"));
        }

        //srsName
        if (kvp.containsKey("srsName")) {
            querySet(eObject, "srsName",(List)kvp.get("srsName"));
        }

        //featureversion
        if (kvp.containsKey("featureVersion")) {
            querySet(eObject, "featureVersion",
                Collections.singletonList((String) kvp.get("featureVersion")));
        }
       
        if(kvp.containsKey("format_options")) {
            GetFeatureType gft = (GetFeatureType) eObject;
            gft.getFormatOptions().putAll((Map) kvp.get("format_options"));
        }

        return request;
    }

    /**
     * Given a set of keys, this method will ensure that no two keys are specified at the same time
     * @param kvp
     * @param keys
     */
    private void ensureMutuallyExclusive(Map kvp, String[] keys) {
        for (int i = 0; i < keys.length; i++) {
            if (kvp.containsKey(keys[i])) {
                for (int j = i + 1; j < keys.length; j++) {
                    if (kvp.containsKey(keys[j])) {
                        String msg = keys[i] + " and " + keys[j]
                            + " both specified but are mutually exclusive";
                        throw new WFSException(msg);
                    }
                }
            }
        }
    }

    BBOX bboxFilter(QName typeName, Envelope bbox) throws Exception {
        FeatureTypeInfo featureTypeInfo =
            catalog.getFeatureTypeByName(typeName.getNamespaceURI(), typeName.getLocalPart());

        //JD: should this be applied to all geometries?
        //String name = featureType.getDefaultGeometry().getLocalName();
        //JD: changing to "" so it is
        String name = "";
       
        //get the epsg code
        String epsgCode = null;
        if ( bbox instanceof ReferencedEnvelope ) {
            CoordinateReferenceSystem crs = ((ReferencedEnvelope)bbox).getCoordinateReferenceSystem();
            if ( crs != null ) {
                epsgCode = GML2EncodingUtils.crs(crs);
            }
        }
       
        return filterFactory.bbox(name, bbox.getMinX(), bbox.getMinY(), bbox.getMaxX(),
            bbox.getMaxY(), epsgCode);
    }

    protected void querySet(EObject request, String property, List values)
        throws WFSException {
        //no values specified, do nothing
        if (values == null) {
            return;
        }

        List query = (List) EMFUtils.get(request, "query");

        int m = values.size();
        int n = query.size();

        if ((m == 1) && (n > 1)) {
            //apply single value to all queries
            EMFUtils.set(query, property, values.get(0));

            return;
        }

        //match up sizes
        if (m > n) {
            if (n == 0) {
                //make same size, with empty objects
                for (int i = 0; i < m; i++) {
                    query.add(getWfsFactory().createQueryType());
                }
            } else if (n == 1) {
                //clone single object up to
                EObject q = (EObject) query.get(0);

                for (int i = 1; i < m; i++) {
                    query.add(EMFUtils.clone(q, getWfsFactory()));
                }

                return;
            } else {
                //illegal
                String msg = "Specified " + m + " " + property + " for " + n + " queries.";
                throw new WFSException(msg);
            }
        }

        EMFUtils.set(query, property, values);
    }
}
TOP

Related Classes of org.geoserver.wfs.kvp.GetFeatureKvpRequestReader

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.