/*
* 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.internal.v1_x;
import static org.geotools.data.wfs.internal.Loggers.requestTrace;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.transform.TransformerException;
import net.opengis.wfs.GetFeatureType;
import org.geotools.data.wfs.internal.GetFeatureRequest;
import org.geotools.data.wfs.internal.GetFeatureRequest.ResultType;
import org.geotools.data.wfs.internal.WFSRequest;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.filter.visitor.SimplifyingFilterVisitor;
import org.geotools.xml.Encoder;
import org.opengis.filter.BinaryLogicOperator;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.Or;
import org.opengis.filter.spatial.BinarySpatialOperator;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.Document;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.SAXException;
/**
* A strategy object to aid in querying a CubeWerx WFS 1.1 server
* <p>
* This strategy was created as per the limitations encountered at the CubeWerx server being tested
* while developing this plugin.
* </p>
* <p>
* For instance, the following issues were found:
* <ul>
* <li>resultType parameter is not supported in GetFeature
* <li>Logically grouped spatial filters can't be handled
* <li>CubeWerx does not support logical filters containing mixed geometry filters (eg, AND(BBOX,
* Intersects)), no matter what the capabilities doc says
* </ul>
* </p>
*
* @author groldan
*/
public class CubeWerxStrategy extends StrictWFS_1_x_Strategy {
/**
* @return {@code true} only if resultType == results, CubeWerx throws a service exception if
* the resultType parameter is set on a POST request, no matter it's value, and on a GET
* request it's just ignored; also the returned feature collection does not contain the
* number of features matched.
*/
@Override
public boolean supports(final ResultType resultType) {
return ResultType.RESULTS.equals(resultType);
}
/**
* Removes the {@code RESULTTYPE}.
*
* @see org.geotools.data.wfs.internal.AbstractWFSStrategy#buildGetFeatureParametersForGET(org.geotools.data.wfs.internal.GetFeatureRequest)
*/
@Override
protected Map<String, String> buildGetFeatureParametersForGET(GetFeatureRequest request) {
Map<String, String> params = super.buildGetFeatureParametersForGET(request);
params.remove("RESULTTYPE");
return params;
}
@Override
public InputStream getPostContents(WFSRequest request) throws IOException {
if (!(request instanceof GetFeatureRequest)) {
return super.getPostContents(request);
}
GetFeatureType requestObject = createGetFeatureRequestPost((GetFeatureRequest) request);
final Encoder encoder = prepareEncoder(request);
final QName opName = getOperationName(request.getOperation());
Document dom;
try {
dom = encoder.encodeAsDOM(requestObject, opName);
} catch (SAXException e) {
throw new IOException(e);
} catch (TransformerException e) {
throw new IOException(e);
}
dom.getDocumentElement().removeAttribute("resultType");
DOMImplementationLS domImpl = (DOMImplementationLS) dom.getImplementation();// safe cast as
// long as we're
// on Java6
ByteArrayOutputStream out = new ByteArrayOutputStream();
LSOutput destination = domImpl.createLSOutput();
destination.setByteStream(out);
LSSerializer serializer = domImpl.createLSSerializer();
DOMConfiguration domConfig = serializer.getDomConfig();
if (domConfig.canSetParameter("format-pretty-print", Boolean.TRUE)) {
domConfig.setParameter("format-pretty-print", Boolean.TRUE);
}
serializer.write(dom, destination);
requestTrace("Encoded ", request.getOperation(), " request: ", out);
return new ByteArrayInputStream(out.toByteArray());
}
@Override
public Filter[] splitFilters(final QName typeName, final Filter queryFilter) {
Filter[] splitFilters = super.splitFilters(typeName, queryFilter);
Filter serverFilter = splitFilters[0];
Filter postFilter = splitFilters[1];
if (!(serverFilter instanceof BinaryLogicOperator)) {
return splitFilters;
}
postFilter = queryFilter;
if (serverFilter instanceof Or) {
// can't know...
serverFilter = Filter.INCLUDE;
} else {
boolean spatialAdded = false;
// if a logical operator, check no more than one geometry filter is enclosed on it
List<Filter> children = new ArrayList<Filter>(
((BinaryLogicOperator) serverFilter).getChildren());
for (Iterator<Filter> it = children.iterator(); it.hasNext();) {
Filter f = it.next();
if (f instanceof BinarySpatialOperator) {
if (spatialAdded) {
it.remove();
} else {
spatialAdded = true;
}
}
}
FilterFactory ff = CommonFactoryFinder.getFilterFactory();
serverFilter = ff.and(children);
SimplifyingFilterVisitor sfv = new SimplifyingFilterVisitor();
serverFilter = (Filter) serverFilter.accept(sfv, null);
}
return new Filter[] { serverFilter, postFilter };
}
}