/* (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.monitor.ows.wfs;
import java.util.List;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.monitor.ows.RequestObjectHandler;
import org.geoserver.monitor.MonitorConfig;
import org.geoserver.ows.util.OwsUtils;
import org.geotools.filter.visitor.ExtractBoundsFilterVisitor;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.util.logging.Logging;
import org.opengis.filter.Filter;
import org.opengis.filter.spatial.BBOX;
import org.opengis.geometry.BoundingBox;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;
public abstract class WFSRequestObjectHandler extends RequestObjectHandler {
static final Logger LOGGER = Logging.getLogger(WFSRequestObjectHandler.class);
// TODO: this should probably be handled as an update or extension to ExtractBoundsFilterVisitor
ExtractBoundsFilterVisitor visitor = new ExtractBoundsFilterVisitor() {
public Object visit( BBOX filter, Object data ) {
if(data == null) {
return null;
}
BoundingBox bbox = (BoundingBox) data;
BoundingBox bounds;
try {
bounds = filter.getBounds();
if(bounds.getCoordinateReferenceSystem()==null){
bounds = ReferencedEnvelope.create(bounds, bbox.getCoordinateReferenceSystem());
}
bounds.toBounds(monitorConfig.getBboxCrs());
} catch (TransformException ex) {
// We're stuck so give up.
return null;
}
bbox.include(bounds);
return bbox;
}
};
Catalog catalog;
protected WFSRequestObjectHandler(String reqObjClassName, MonitorConfig config, Catalog catalog) {
super(reqObjClassName, config);
this.catalog = catalog;
}
protected String toString(Object name) {
if (name instanceof QName) {
QName qName = (QName) name;
String prefix = qName.getPrefix();
if (prefix == null || "".equals(prefix)) {
prefix = qName.getNamespaceURI();
}
if (prefix == null || "".equals(prefix)) {
prefix = null;
}
return prefix != null ? prefix + ":" + qName.getLocalPart() : qName.getLocalPart();
}
else {
return name.toString();
}
}
/**
* Look up the CRS of the specified FeatureType
*/
protected CoordinateReferenceSystem crsFromTypeName(QName typeName) {
FeatureTypeInfo featureType = catalog.getFeatureTypeByName(typeName.getNamespaceURI(), typeName.getLocalPart());
return featureType.getCRS();
}
// There are two slight differences between the different WFS requests in how they store
// their filters. These methods are overridden to regularize these differences.
protected abstract List<Object> getElements(Object request);
protected Object unwrapElement(Object element){
return element;
}
protected CoordinateReferenceSystem getCrsFromElement(Object element) {
if (OwsUtils.has(element, "typeName")) {
return crsFromTypeName((QName) OwsUtils.get(element, "typeName"));
}
return null;
}
protected ReferencedEnvelope getBBoxFromElement(Object element) {
return null;
}
@Override
protected BoundingBox getBBox(Object request) {
if(monitorConfig.getBboxMode()!=MonitorConfig.BboxMode.FULL){
return null;
}
List<Object> elements = getElements(request);
if (elements==null) return null;
try {
BoundingBox result = new ReferencedEnvelope(monitorConfig.getBboxCrs());
for(Object e : elements){
e = unwrapElement(e);
//first ask for a bounding box directly
ReferencedEnvelope bbox = getBBoxFromElement(e);
if (bbox == null) {
// try to infer it from a filter of the request
// This is the default CRS for the layer being queried
CoordinateReferenceSystem defaultCrs = getCrsFromElement(e);
if (defaultCrs == null) {
continue;
}
Filter f = OwsUtils.has(e, "filter") ? (Filter) OwsUtils.get(e, "filter") : null;
if(f != null) {
ReferencedEnvelope startingBbox = new ReferencedEnvelope(defaultCrs);
bbox = (ReferencedEnvelope) f.accept(visitor, startingBbox);
}
}
if (bbox != null) {
result.include(bbox.toBounds(monitorConfig.getBboxCrs()));
}
}
return result;
} catch (TransformException ex) {
LOGGER.warning("Could not Transform bounds to desired CRS");
return null;
}
}
}