/* (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.kvp;
import java.util.List;
import org.geoserver.ows.KvpParser;
import org.geoserver.ows.util.KvpUtils;
import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.WFSException;
import org.geotools.geometry.jts.ReferencedEnvelope3D;
import org.geotools.referencing.CRS;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Envelope;
/**
*
* @author Niels Charlier : added 3D BBOX support
*
*/
public class BBoxKvpParser extends KvpParser {
public BBoxKvpParser() {
super("bbox", Envelope.class);
}
public Object parse(String value) throws Exception {
List unparsed = KvpUtils.readFlat(value, KvpUtils.INNER_DELIMETER);
// check to make sure that the bounding box has 4 coordinates
if (unparsed.size() < 4) {
throw new IllegalArgumentException("Requested bounding box contains wrong"
+ "number of coordinates (should have " + "4): " + unparsed.size());
}
int countco = 4;
if (unparsed.size() == 6 || unparsed.size() == 7) { // 3d-coordinates
countco = 6;
}
//if it does, store them in an array of doubles
double[] bbox = new double[countco];
for (int i = 0; i < countco; i++) {
try {
bbox[i] = Double.parseDouble((String) unparsed.get(i));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Bounding box coordinate " + i
+ " is not parsable:" + unparsed.get(i));
}
}
//ensure the values are sane
double minx = bbox[0];
double miny = bbox[1];
double minz=0, maxx=0, maxy=0, maxz=0;
if (countco == 6) {
minz = bbox[2];
maxx = bbox[3];
maxy = bbox[4];
maxz = bbox[5];
} else {
maxx = bbox[2];
maxy = bbox[3];
}
// check for srs
String srs = null;
if (unparsed.size() > countco) {
// merge back the CRS definition, in case it is an AUTO one
StringBuilder sb = new StringBuilder();
for (int i = countco; i < unparsed.size(); i++) {
sb.append(unparsed.get(i));
if(i < (unparsed.size() - 1)) {
sb.append(",");
}
}
srs = sb.toString();
}
return buildEnvelope(countco, minx, miny, minz, maxx, maxy, maxz, srs);
}
protected Object buildEnvelope(int countco, double minx, double miny, double minz, double maxx,
double maxy, double maxz, String srs)
throws NoSuchAuthorityCodeException, FactoryException {
if (minx > maxx) {
throw new ServiceException("illegal bbox, minX: " + minx + " is "
+ "greater than maxX: " + maxx);
}
if (miny > maxy) {
throw new ServiceException("illegal bbox, minY: " + miny + " is "
+ "greater than maxY: " + maxy);
}
if (minz > maxz) {
throw new ServiceException("illegal bbox, minZ: " + minz + " is "
+ "greater than maxZ: " + maxz);
}
if (countco == 6) {
CoordinateReferenceSystem crs = srs != null ? CRS.decode(srs) : null;
return new ReferencedEnvelope3D(minx, maxx, miny, maxy, minz, maxz, crs);
} else {
CoordinateReferenceSystem crs = srs != null ? CRS.decode(srs) : null;
if(crs == null || crs.getCoordinateSystem().getDimension() == 2) {
return new SRSEnvelope(minx, maxx, miny, maxy, srs);
} else if(crs.getCoordinateSystem().getDimension() == 3) {
return new ReferencedEnvelope3D(minx, maxx, miny, maxy, -Double.MAX_VALUE, Double.MAX_VALUE, crs);
} else {
throw new WFSException("Unexpected BBOX, can only handle 2D or 3D ones", "bbox", "InvalidParameterValue");
}
}
}
}