diff --git a/src/community/wcs2_0/src/main/java/applicationContext.xml b/src/community/wcs2_0/src/main/java/applicationContext.xml
index 94683109b91..5cc397dc9c9 100644
--- a/src/community/wcs2_0/src/main/java/applicationContext.xml
+++ b/src/community/wcs2_0/src/main/java/applicationContext.xml
@@ -114,7 +114,7 @@
-
+
diff --git a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/DefaultWebCoverageService20.java b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/DefaultWebCoverageService20.java
index df53b9f89cd..2ff534b02bc 100644
--- a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/DefaultWebCoverageService20.java
+++ b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/DefaultWebCoverageService20.java
@@ -18,7 +18,7 @@
import org.geoserver.wcs.responses.CoverageResponseDelegateFinder;
import org.geoserver.wcs2_0.exception.WCS20Exception;
import org.geoserver.wcs2_0.response.WCS20DescribeCoverageTransformer;
-import org.geoserver.wcs2_0.util.EnvelopeDimensionsMapper;
+import org.geoserver.wcs2_0.util.EnvelopeAxesLabelsMapper;
import org.geotools.util.logging.Logging;
import org.geotools.xml.transform.TransformerBase;
import org.opengis.coverage.grid.GridCoverage;
@@ -39,13 +39,13 @@ public class DefaultWebCoverageService20 implements WebCoverageService20 {
private CoverageResponseDelegateFinder responseFactory;
/** Utility class to map envelope dimension*/
- private EnvelopeDimensionsMapper envelopeDimensionsMapper;
+ private EnvelopeAxesLabelsMapper envelopeAxesMapper;
- public DefaultWebCoverageService20(GeoServer geoServer, CoverageResponseDelegateFinder responseFactory, EnvelopeDimensionsMapper envelopeDimensionsMapper) {
+ public DefaultWebCoverageService20(GeoServer geoServer, CoverageResponseDelegateFinder responseFactory, EnvelopeAxesLabelsMapper envelopeDimensionsMapper) {
this.geoServer = geoServer;
this.catalog = geoServer.getCatalog();
this.responseFactory = responseFactory;
- this.envelopeDimensionsMapper=envelopeDimensionsMapper;
+ this.envelopeAxesMapper=envelopeDimensionsMapper;
}
@Override
@@ -67,12 +67,12 @@ public WCS20DescribeCoverageTransformer describeCoverage(DescribeCoverageType re
checkVersion(request.getVersion());
if( request.getCoverageId() == null || request.getCoverageId().isEmpty() ) {
- throw new OWS20Exception("Required parameter coverageId missing", WCS20Exception.WCSExceptionCode.EmptyCoverageIdList, "coverageId");
+ throw new OWS20Exception("Required parameter coverageId missing", WCS20Exception.WCS20ExceptionCode.EmptyCoverageIdList, "coverageId");
}
WCSInfo wcs = getServiceInfo();
- WCS20DescribeCoverageTransformer describeTransformer = new WCS20DescribeCoverageTransformer(wcs, catalog, responseFactory,envelopeDimensionsMapper);
+ WCS20DescribeCoverageTransformer describeTransformer = new WCS20DescribeCoverageTransformer(wcs, catalog, responseFactory,envelopeAxesMapper);
describeTransformer.setEncoding(Charset.forName(wcs.getGeoServer().getSettings().getCharset()));
return describeTransformer;
}
@@ -83,10 +83,10 @@ public GridCoverage getCoverage(GetCoverageType request) {
checkVersion(request.getVersion());
if( request.getCoverageId() == null || "".equals(request.getCoverageId()) ) {
- throw new OWS20Exception("Required parameter coverageId missing", WCS20Exception.WCSExceptionCode.EmptyCoverageIdList, "coverageId");
+ throw new OWS20Exception("Required parameter coverageId missing", WCS20Exception.WCS20ExceptionCode.EmptyCoverageIdList, "coverageId");
}
- return new GetCoverage(getServiceInfo(), catalog,envelopeDimensionsMapper).run(request);
+ return new GetCoverage(getServiceInfo(), catalog,envelopeAxesMapper).run(request);
}
private void checkVersion(String version) {
diff --git a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/GetCoverage.java b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/GetCoverage.java
index 9b2a0ce8b9d..b44d7344a6f 100644
--- a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/GetCoverage.java
+++ b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/GetCoverage.java
@@ -3,6 +3,10 @@
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
@@ -18,30 +22,54 @@
import net.opengis.wcs20.ExtensionItemType;
import net.opengis.wcs20.ExtensionType;
import net.opengis.wcs20.GetCoverageType;
+import net.opengis.wcs20.InterpolationAxesType;
+import net.opengis.wcs20.InterpolationAxisType;
+import net.opengis.wcs20.InterpolationMethodType;
+import net.opengis.wcs20.InterpolationType;
+import net.opengis.wcs20.RangeIntervalType;
+import net.opengis.wcs20.RangeItemType;
+import net.opengis.wcs20.RangeSubsetType;
+import net.opengis.wcs20.ScaleAxisByFactorType;
+import net.opengis.wcs20.ScaleAxisType;
+import net.opengis.wcs20.ScaleByFactorType;
+import net.opengis.wcs20.ScaleToExtentType;
+import net.opengis.wcs20.ScaleToSizeType;
+import net.opengis.wcs20.ScalingType;
+import net.opengis.wcs20.TargetAxisExtentType;
+import net.opengis.wcs20.TargetAxisSizeType;
import org.eclipse.emf.common.util.EList;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.LayerInfo;
+import org.geoserver.platform.OWS20Exception;
import org.geoserver.wcs.CoverageCleanerCallback;
import org.geoserver.wcs.WCSInfo;
import org.geoserver.wcs2_0.exception.WCS20Exception;
-import org.geoserver.wcs2_0.util.EnvelopeDimensionsMapper;
+import org.geoserver.wcs2_0.exception.WCS20Exception.WCS20ExceptionCode;
+import org.geoserver.wcs2_0.util.EnvelopeAxesLabelsMapper;
import org.geoserver.wcs2_0.util.NCNameResourceCodec;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridEnvelope2D;
+import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.processing.CoverageProcessor;
import org.geotools.coverage.processing.Operations;
import org.geotools.factory.Hints;
import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.referencing.CRS;
+import org.geotools.resources.coverage.CoverageUtilities;
+import org.geotools.util.Utilities;
import org.jaitools.imageutils.ImageLayout2;
+import org.opengis.coverage.Coverage;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.GridCoverageReader;
+import org.opengis.coverage.grid.GridGeometry;
import org.opengis.coverage.processing.Operation;
+import org.opengis.geometry.Envelope;
import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
import org.vfny.geoserver.util.WCSUtils;
-import org.vfny.geoserver.wcs.WcsException;
-import org.vfny.geoserver.wcs.WcsException.WcsExceptionCode;
/**
* Implementation of the WCS 2.0 GetCoverage request
@@ -51,11 +79,85 @@
*/
public class GetCoverage {
+ public enum InterpolationPolicy{
+ linear("http://www.opengis.net/def/interpolation/OGC/1/linear") {
+ @Override
+ public Interpolation getInterpolation() {
+ return Interpolation.getInstance(Interpolation.INTERP_BILINEAR);
+ }
+ },nearestneighbor("http://www.opengis.net/def/interpolation/OGC/1/nearest-neighbor") {
+ @Override
+ public Interpolation getInterpolation() {
+ return Interpolation.getInstance(Interpolation.INTERP_NEAREST);
+ }
+ },quadratic("http://www.opengis.net/def/interpolation/OGC/1/quadratic") {
+ @Override
+ public Interpolation getInterpolation() {
+ throw new WCS20Exception(
+ "Interpolation not supported",
+ WCS20Exception.WCS20ExceptionCode.InterpolationMethodNotSupported,
+ quadratic.toString());
+ }
+ },cubic("http://www.opengis.net/def/interpolation/OGC/1/cubic") {
+ @Override
+ public Interpolation getInterpolation() {
+ return Interpolation.getInstance(Interpolation.INTERP_BICUBIC_2);
+ }
+ },lostarea("http://www.opengis.net/def/interpolation/OGC/1/lost-area") {
+ @Override
+ public Interpolation getInterpolation() {
+ throw new WCS20Exception(
+ "Interpolation not supported",
+ WCS20Exception.WCS20ExceptionCode.InterpolationMethodNotSupported,
+ lostarea.toString());
+ }
+ },barycentric("http://www.opengis.net/def/interpolation/OGC/1/barycentric") {
+ @Override
+ public Interpolation getInterpolation() {
+ throw new WCS20Exception(
+ "Interpolation not supported",
+ WCS20Exception.WCS20ExceptionCode.InterpolationMethodNotSupported,
+ barycentric.toString());
+ }
+ };
+
+ private InterpolationPolicy(String representation) {
+ this.strVal = representation;
+ }
+
+ private final String strVal;
+
+ abstract public Interpolation getInterpolation();
+
+ static InterpolationPolicy getPolicy(InterpolationMethodType interpolationMethodType){
+ Utilities.ensureNonNull("interpolationMethodType", interpolationMethodType);
+ final String interpolationMethod=interpolationMethodType.getInterpolationMethod();
+ return getPolicy(interpolationMethod);
+ }
+
+ static InterpolationPolicy getPolicy(String interpolationMethod){
+ Utilities.ensureNonNull("interpolationMethod", interpolationMethod);
+ final InterpolationPolicy[] values = InterpolationPolicy.values();
+ for(InterpolationPolicy policy:values){
+ if(policy.strVal.equals(interpolationMethod)){
+ return policy;
+ }
+ }
+
+ //method not found
+ throw new WCS20Exception("Interpolation method not supported",WCS20ExceptionCode.InterpolationMethodNotSupported,interpolationMethod);
+ }
+
+ static InterpolationPolicy getDefaultPolicy(){
+ return nearestneighbor;
+ }
+ }
+
private enum ScalingPolicy{
DoNothing{
@Override
- public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extensionItem) {
+ public GridCoverage2D scale(GridCoverage2D sourceGC, ScalingType scaling) {
return sourceGC;
}
@@ -63,29 +165,26 @@ public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extension
ScaleByFactor{
@Override
- public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extensionItem) {
+ public GridCoverage2D scale(GridCoverage2D sourceGC, ScalingType scaling) {
// get scale factor
- final String scaleFactorS=extensionItem.getSimpleContent();
- float scaleFactor=Float.NaN;
- try{
- scaleFactor=Float.parseFloat(scaleFactorS);
- if(scaleFactor<0){
- throw new WCS20Exception("Invalid scale factor", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, String.valueOf(scaleFactor));
- }
- } catch (Exception e) {
- throw new WCS20Exception("Invalid scale factor", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, scaleFactorS);
+ final ScaleByFactorType scaleByFactorType = scaling.getScaleByFactor();
+ double scaleFactor=scaleByFactorType.getScaleFactor();
+
+ // checks
+ if(scaleFactor<0){
+ throw new WCS20Exception("Invalid scale factor", WCS20Exception.WCS20ExceptionCode.InvalidScaleFactor, String.valueOf(scaleFactor));
}
// return coverage unchanged if we don't scale
if(scaleFactor==1){
return sourceGC;
}
+
+ // checks
return (GridCoverage2D)Operations.DEFAULT.scale(sourceGC, scaleFactor, scaleFactor, 0, 0, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
}
},
-
-
ScaleToSize{
/**
@@ -94,27 +193,30 @@ public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extension
*
*/
@Override
- public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extensionItem) {
- // get scale factor
- final String sizeXS=extensionItem.getSimpleContent();
- final String sizeYS=extensionItem.getSimpleContent();
- int sizeX=Integer.MIN_VALUE;
- try{
- sizeX=Integer.parseInt(sizeXS);
- if(sizeX<=0){
- throw new WCS20Exception("Invalid target size", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, sizeXS);
+ public GridCoverage2D scale(GridCoverage2D sourceGC, ScalingType scaling) {
+ // get scale size
+ final ScaleToSizeType scaleType = scaling.getScaleToSize();
+ final EList targetAxisSizeElements = scaleType.getTargetAxisSize();
+
+ TargetAxisSizeType xSize=null,ySize=null;
+ for(TargetAxisSizeType axisSizeType:targetAxisSizeElements){
+ final String axisName=axisSizeType.getAxis();
+ if(axisName.equals("http://www.opengis.net/def/axis/OGC/1/i")){
+ xSize=axisSizeType;
+ } else if(axisName.equals("http://www.opengis.net/def/axis/OGC/1/j")){
+ ySize=axisSizeType;
+ } else {
+ // TODO remove when supporting TIME and ELEVATION
+ throw new WCS20Exception("Scale Axis Undefined", WCS20Exception.WCS20ExceptionCode.ScaleAxisUndefined, axisName);
}
- } catch (Exception e) {
- throw new WCS20Exception("Invalid target size", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, sizeXS);
}
- int sizeY=Integer.MIN_VALUE;
- try{
- sizeY=Integer.parseInt(sizeYS);
- if(sizeX<=0){
- throw new WCS20Exception("Invalid target size", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, sizeYS);
- }
- } catch (Exception e) {
- throw new WCS20Exception("Invalid target size", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, sizeYS);
+ final int sizeX=(int) xSize.getTargetSize();// TODO should this be int?
+ if(sizeX<=0){
+ throw new WCS20Exception("Invalid target size", WCS20Exception.WCS20ExceptionCode.InvalidScaleFactor, Integer.toString(sizeX));
+ }
+ final int sizeY=(int) ySize.getTargetSize();// TODO should this be int?
+ if(sizeY<=0){
+ throw new WCS20Exception("Invalid target size", WCS20Exception.WCS20ExceptionCode.InvalidScaleFactor, Integer.toString(sizeY));
}
// unscale
@@ -125,54 +227,64 @@ public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extension
// create final warp
final Warp warp= new WarpAffine(AffineTransform.getScaleInstance(sourceGE.width/sizeX, sourceGE.height/sizeY));// TODO check
+ // impose final
final ImageLayout2 layout = new ImageLayout2(
sourceGE.x,
sourceGE.y,
sizeX,
sizeY);
- final Hints hints= new Hints(JAI.KEY_IMAGE_LAYOUT, layout);
-
+ final Hints hints= new Hints(JAI.KEY_IMAGE_LAYOUT, layout);
final Operation operation = CoverageProcessor.getInstance().getOperation("Warp");
final ParameterValueGroup parameters = operation.getParameters();
parameters.parameter("Source").setValue(sourceGC);
parameters.parameter("warp").setValue(warp);
parameters.parameter("interpolation").setValue(Interpolation.getInstance(Interpolation.INTERP_NEAREST));
-// setParameterValue(parameters, "backgroundValues", argumentValue3);// TODO
+ parameters.parameter( "backgroundValues").setValue(CoverageUtilities.getBackgroundValues(sourceGC));// TODO check and improve
return (GridCoverage2D) CoverageProcessor.getInstance().doOperation(parameters,hints);
}
+
},
ScaleToExtent{
@Override
- public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extensionItem) {
- // get scale factor
- final String sizeXS=extensionItem.getSimpleContent();
- final String sizeYS=extensionItem.getSimpleContent();
- int sizeX=Integer.MIN_VALUE;
- try{
- sizeX=Integer.parseInt(sizeXS);
- if(sizeX<=0){
- throw new WCS20Exception("Invalid target size", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, sizeXS);
+ public GridCoverage2D scale(GridCoverage2D sourceGC, ScalingType scaling) {
+ // parse area
+ final ScaleToExtentType scaleType = scaling.getScaleToExtent();
+ final EList targetAxisExtentElements = scaleType.getTargetAxisExtent();
+
+ TargetAxisExtentType xExtent=null,yExtent=null;
+ for(TargetAxisExtentType axisExtentType:targetAxisExtentElements){
+ final String axisName=axisExtentType.getAxis();
+ if(axisName.equals("http://www.opengis.net/def/axis/OGC/1/i")){
+ xExtent=axisExtentType;
+ } else if(axisName.equals("http://www.opengis.net/def/axis/OGC/1/j")){
+ yExtent=axisExtentType;
+ } else {
+ // TODO remove when supporting TIME and ELEVATION
+ throw new WCS20Exception("Scale Axis Undefined", WCS20Exception.WCS20ExceptionCode.ScaleAxisUndefined, axisName);
}
- } catch (Exception e) {
- throw new WCS20Exception("Invalid target size", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, sizeXS);
}
- int sizeY=Integer.MIN_VALUE;
- try{
- sizeY=Integer.parseInt(sizeYS);
- if(sizeX<=0){
- throw new WCS20Exception("Invalid target size", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, sizeYS);
- }
- } catch (Exception e) {
- throw new WCS20Exception("Invalid target size", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, sizeYS);
+ if(xExtent==null){
+ throw new WCS20Exception("Missing extent along i", WCS20Exception.WCS20ExceptionCode.InvalidScaleFactor, "");
}
+ if(yExtent==null){
+ throw new WCS20Exception("Missing extent along j", WCS20Exception.WCS20ExceptionCode.InvalidScaleFactor, "");
+ }
-
+ final int minx=(int) targetAxisExtentElements.get(0).getLow();// TODO should this be int?
+ final int maxx=(int) targetAxisExtentElements.get(0).getHigh();
+ final int miny=(int) targetAxisExtentElements.get(1).getLow();
+ final int maxy=(int) targetAxisExtentElements.get(1).getHigh();
+
+ // check on source geometry
final GridEnvelope2D sourceGE=sourceGC.getGridGeometry().getGridRange2D();
- final int minx=0;
- final int miny=0;
- final int maxx=0;
- final int maxy=0;
+
+ if(minx>maxx){
+ throw new WCS20Exception("Invalid Extent for dimension:"+targetAxisExtentElements.get(0).getAxis() , WCS20Exception.WCS20ExceptionCode.InvalidExtent, String.valueOf(maxx));
+ }
+ if(miny>maxy){
+ throw new WCS20Exception("Invalid Extent for dimension:"+targetAxisExtentElements.get(1).getAxis() , WCS20Exception.WCS20ExceptionCode.InvalidExtent, String.valueOf(maxy));
+ }
final Rectangle destinationRectangle= new Rectangle(minx, miny,maxx-minx+1, maxy-miny+1);
// UNSCALE
if(destinationRectangle.equals(sourceGE)){
@@ -180,7 +292,10 @@ public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extension
}
// create final warp
- final Warp warp= new WarpAffine(AffineTransform.getScaleInstance(sourceGE.width/sizeX, sourceGE.height/sizeY)); // TODO check
+ final Warp warp= new WarpAffine(AffineTransform.getScaleInstance(
+ sourceGE.width/destinationRectangle.width,
+ sourceGE.height/destinationRectangle.height)); // TODO check
+ // impose size
final ImageLayout2 layout = new ImageLayout2(
destinationRectangle.x,
destinationRectangle.y,
@@ -193,7 +308,7 @@ public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extension
parameters.parameter("Source").setValue(sourceGC);
parameters.parameter("warp").setValue(warp);
parameters.parameter("interpolation").setValue(Interpolation.getInstance(Interpolation.INTERP_NEAREST));
-// setParameterValue(parameters, "backgroundValues", argumentValue3);// TODO
+ parameters.parameter( "backgroundValues").setValue(CoverageUtilities.getBackgroundValues(sourceGC));// TODO check and improve
return (GridCoverage2D) CoverageProcessor.getInstance().doOperation(parameters,hints);
}
@@ -201,30 +316,40 @@ public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extension
ScaleAxesByFactor{
@Override
- public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extensionItem) {
+ public GridCoverage2D scale(GridCoverage2D sourceGC, ScalingType scaling) {
// TODO dimension management
// get scale factor
- final String scaleFactorSX=extensionItem.getSimpleContent();
- final String scaleFactorSY=extensionItem.getSimpleContent();
- float scaleFactorX=Float.NaN;
- try{
- scaleFactorX=Float.parseFloat(scaleFactorSX);
- if(scaleFactorX<0){
- throw new WCS20Exception("Invalid scale factor", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, scaleFactorSX);
+ final ScaleAxisByFactorType scaleType = scaling.getScaleAxesByFactor();
+ final EList targetAxisScaleElements = scaleType.getScaleAxis();
+
+ ScaleAxisType xScale=null,yScale=null;
+ for(ScaleAxisType scaleAxisType:targetAxisScaleElements){
+ final String axisName=scaleAxisType.getAxis();
+ if(axisName.equals("http://www.opengis.net/def/axis/OGC/1/i")){
+ xScale=scaleAxisType;
+ } else if(axisName.equals("http://www.opengis.net/def/axis/OGC/1/j")){
+ yScale=scaleAxisType;
+ } else {
+ // TODO remove when supporting TIME and ELEVATION
+ throw new WCS20Exception("Scale Axis Undefined", WCS20Exception.WCS20ExceptionCode.ScaleAxisUndefined, axisName);
}
- } catch (Exception e) {
- throw new WCS20Exception("Invalid scale factor", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, scaleFactorSX);
}
- float scaleFactorY=Float.NaN;
- try{
- scaleFactorY=Float.parseFloat(scaleFactorSX);
- if(scaleFactorY<0){
- throw new WCS20Exception("Invalid scale factor", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, scaleFactorSY);
- }
- } catch (Exception e) {
- throw new WCS20Exception("Invalid scale factor", WCS20Exception.WCSExceptionCode.InvalidScaleFactor, scaleFactorSY);
- }
+ if(xScale==null){
+ throw new WCS20Exception("Missing scale factor along i", WCS20Exception.WCS20ExceptionCode.InvalidScaleFactor, "");
+ }
+ if(yScale==null){
+ throw new WCS20Exception("Missing scale factor along j", WCS20Exception.WCS20ExceptionCode.InvalidScaleFactor, "");
+ }
+
+ final double scaleFactorX= xScale.getScaleFactor();// TODO should this be int?
+ if(scaleFactorX<0){
+ throw new WCS20Exception("Invalid scale factor", WCS20Exception.WCS20ExceptionCode.InvalidScaleFactor, Double.toString(scaleFactorX));
+ }
+ final double scaleFactorY= yScale.getScaleFactor();// TODO should this be int?
+ if(scaleFactorY<0){
+ throw new WCS20Exception("Invalid scale factor", WCS20Exception.WCS20ExceptionCode.InvalidScaleFactor, Double.toString(scaleFactorY));
+ }
// unscale
if(scaleFactorX==1.0&& scaleFactorY==1.0){
@@ -236,13 +361,33 @@ public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extension
};
/**
- * @param extensionItem
+ * @param scaling
* @param sourceGG
* @param width
* @param origin
* @param returnValue
*/
- abstract public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extensionItem) ;
+ abstract public GridCoverage2D scale(GridCoverage2D sourceGC, ScalingType scaling) ;
+
+
+ public static ScalingPolicy getPolicy(ScalingType scaling) {
+ if(scaling!=null){
+ if (scaling.getScaleAxesByFactor() != null) {
+ return ScaleAxesByFactor;
+ }
+ if (scaling.getScaleByFactor() != null) {
+ return ScaleByFactor;
+ }
+ if (scaling.getScaleToExtent() != null) {
+ return ScaleToExtent;
+ }
+ if (scaling.getScaleToSize() != null) {
+ return ScalingPolicy.ScaleToSize;
+ }
+
+ }
+ return DoNothing;
+ }
};
@@ -250,9 +395,9 @@ public GridCoverage2D scale(GridCoverage2D sourceGC, ExtensionItemType extension
private Catalog catalog;
/** Utility class to map envelope dimension*/
- private EnvelopeDimensionsMapper envelopeDimensionsMapper;
+ private EnvelopeAxesLabelsMapper envelopeDimensionsMapper;
- public GetCoverage(WCSInfo serviceInfo, Catalog catalog, EnvelopeDimensionsMapper envelopeDimensionsMapper) {
+ public GetCoverage(WCSInfo serviceInfo, Catalog catalog, EnvelopeAxesLabelsMapper envelopeDimensionsMapper) {
this.wcs = serviceInfo;
this.catalog = catalog;
this.envelopeDimensionsMapper=envelopeDimensionsMapper;
@@ -263,7 +408,7 @@ public GridCoverage run(GetCoverageType request) {
LayerInfo linfo = NCNameResourceCodec.getCoverage(catalog, request.getCoverageId());
if(linfo == null) {
throw new WCS20Exception("Could not locate coverage " + request.getCoverageId(),
- WCS20Exception.WCSExceptionCode.NoSuchCoverage, "coverageId");
+ WCS20Exception.WCS20ExceptionCode.NoSuchCoverage, "coverageId");
}
// TODO: handle trimming and slicing
@@ -277,6 +422,8 @@ public GridCoverage run(GetCoverageType request) {
// use this to check if we can use overviews or not
boolean subsample = wcs.isSubsamplingEnabled();
+ Map extensions = extractExtensions(coverage,request);
+
// TODO: setup the params to force the usage of imageread and to make it use
// the right overview and so on
// TODO here we should really try to subset before reading with a grid geometry
@@ -285,22 +432,29 @@ public GridCoverage run(GetCoverageType request) {
// TODO: handle crop, scale, reproject and so on
+ // get CRS extension values
+ final CoordinateReferenceSystem subsettingCRS=extractSubsettingCRS(coverage,extensions);
+ final CoordinateReferenceSystem outputCRS=extractOutputCRS(coverage,extensions);
+
+ // handle interpolation
+ final Map axesInterpolations=extractInterpolation(coverage,extensions);
+
// handle range subsetting
- coverage=handleRangeSubsettingExtension(coverage,request);
+ coverage=handleRangeSubsettingExtension(coverage,extensions);
+
+ // subsetting, is not really an extension
+ coverage=handleSubsettingExtension(coverage,request,subsettingCRS);
- // scaling subsetting
- coverage=handleSubsettingExtension(coverage,request);
-//
- // scaling subsetting
- coverage=handleScaling(coverage,request);
+ // scaling
+ coverage=handleScaling(coverage,extensions,axesInterpolations);
- // scaling subsetting
- coverage=handleReprojection(coverage,request);
+ // reprojection
+ coverage=handleReprojection(coverage,outputCRS,axesInterpolations);
// reproject
} catch(IOException e) {
- throw new WcsException("Failed to read the coverage " + request.getCoverageId(), e);
+ throw new WCS20Exception("Failed to read the coverage " + request.getCoverageId(), e);
} finally {
// make sure the coverage will get cleaned at the end of the processing
if(coverage != null) {
@@ -313,29 +467,72 @@ public GridCoverage run(GetCoverageType request) {
/**
* @param coverage
- * @param request
+ * @param extensions
* @return
*/
- private GridCoverage2D handleReprojection(GridCoverage2D coverage, GetCoverageType request) {
- // look for scaling extension
- final ExtensionType extension = request.getExtension();
- if(extension==null){
- // NO SCALING
- return coverage;
+ private CoordinateReferenceSystem extractOutputCRS(GridCoverage2D coverage,
+ Map extensions) {
+ return extractCRS(coverage,extensions,false);
+ }
+
+ /**
+ * @param coverage
+ * @param extensions
+ * @return
+ */
+ private CoordinateReferenceSystem extractSubsettingCRS(GridCoverage2D coverage,Map extensions) {
+ return extractCRS(coverage,extensions,true);
+ }
+
+ /**
+ * @param coverage
+ * @param extensions
+ * @param b
+ * @return
+ */
+ private CoordinateReferenceSystem extractCRS(GridCoverage2D coverage, Map extensions,
+ boolean subsettingCRS) {
+
+ // look for subsettingCRS Extension extension
+ if(extensions==null||extensions.size()==0||!extensions.containsKey(subsettingCRS ? "subsettingCrs" : "outputCrs")){
+ // NO INTERPOLATION
+ return coverage.getCoordinateReferenceSystem2D();
}
- // look for a scaling extension
- final EList extensions = extension.getContents();
- for(ExtensionItemType extensionItem:extensions){
- try{
- final ScalingPolicy scaling= ScalingPolicy.valueOf(extensionItem.getName());// TODO extract scaling behavior
- return scaling.scale(coverage, extensionItem);
+ // look for an interpolation extension
+ final ExtensionItemType extensionItem=extensions.get(subsettingCRS ? "subsettingCrs" : "outputCrs");
+ if (extensionItem.getName().equals(subsettingCRS ? "subsettingCrs" : "outputCrs")) {
+ // get URI
+ String crsName = extensionItem.getSimpleContent();
+
+ // checks
+ if (crsName == null) {
+ throw new WCS20Exception(subsettingCRS ? "Subsetting" : "Output" + " CRS was null",
+ WCS20ExceptionCode.NotACrs, "null");
+ }
+
+ // instantiate
+ final int lastSlash = crsName.lastIndexOf("/");
+ // error no valid URI
+ // TODO improve checs
+ if (lastSlash < 0) {
+ throw new WCS20Exception("Invalid " + (subsettingCRS ? "subsetting" : "output")
+ + " CRS", WCS20Exception.WCS20ExceptionCode.NotACrs, crsName);
+ }
+ crsName = crsName.substring(lastSlash + 1, crsName.length());
+ // instantiate
+ try {
+ return CRS.decode("EPSG:" + crsName, false); // notice the usage of boolean param
} catch (Exception e) {
- // eat me
+ final WCS20Exception exception = new WCS20Exception("Invalid "
+ + (subsettingCRS ? "subsetting" : "output") + " CRS",
+ WCS20Exception.WCS20ExceptionCode.NotACrs, crsName);
+ exception.initCause(e);
+ throw exception;
}
+
}
- // no scaling
- return coverage;
+ return coverage.getCoordinateReferenceSystem2D();
}
/**
@@ -343,20 +540,190 @@ private GridCoverage2D handleReprojection(GridCoverage2D coverage, GetCoverageTy
* @param request
* @return
*/
- private GridCoverage2D handleRangeSubsettingExtension(GridCoverage2D coverage,
- GetCoverageType request) {
+ private Map extractExtensions(GridCoverage2D coverage, GetCoverageType request) {
+ // look for subsettingCRS Extension extension
+ final ExtensionType extension = request.getExtension();
+
+ // look for the various extensions
+ final Map parsedExtensions=new HashMap();
+ // no extensions?
+ if(extension!=null){
+ final EList extensions = extension.getContents();
+ for (final ExtensionItemType extensionItem : extensions) {
+ final String extensionName = extensionItem.getName();
+ if (extensionName == null || extensionName.length() <= 0) {
+ throw new WCS20Exception("Null extension");
+ }
+ if (extensionName.equals("subsettingCrs")) {
+ parsedExtensions.put("subsettingCrs", extensionItem);
+ } else if (extensionName.equals("outputCrs")) {
+ parsedExtensions.put("outputCrs", extensionItem);
+ } else if (extensionName.equals("Scaling")) {
+ parsedExtensions.put("Scaling", extensionItem);
+ } else if (extensionName.equals("Interpolation")) {
+ parsedExtensions.put("Interpolation", extensionItem);
+ } else if (extensionName.equals("rangeSubset")) {
+ parsedExtensions.put("rangeSubset", extensionItem);
+ } else if (extensionName.equals("rangeSubset")) {
+ parsedExtensions.put("rangeSubset", extensionItem);
+ }
+ }
+ }
+ return parsedExtensions;
+ }
+
+ /**
+ * @param coverage
+ * @param extensions2
+ * @return
+ */
+ private Map extractInterpolation(GridCoverage2D coverage, Map extensions) {
+ // preparation
+ final Map returnValue= new HashMap();
+ final Envelope envelope= coverage.getEnvelope();
+ final List axesNames = envelopeDimensionsMapper.getAxesNames(envelope, true);
+ for(String axisName:axesNames){
+ returnValue.put(axisName, InterpolationPolicy.getDefaultPolicy());// use defaults if no specified
+ }
+
+ // look for scaling extension
+ if(extensions==null||extensions.size()==0||!extensions.containsKey("Interpolation")){
+ // NO INTERPOLATION
+ return returnValue;
+ }
+
+ // look for an interpolation extension
+ final ExtensionItemType extensionItem=extensions.get("Interpolation");
+ // get interpolationType
+ InterpolationType interpolationType = (InterpolationType) extensionItem
+ .getObjectContent();
+ // which type
+ if (interpolationType.getInterpolationMethod() != null) {
+ InterpolationMethodType method = interpolationType.getInterpolationMethod();
+ InterpolationPolicy policy = InterpolationPolicy.getPolicy(method);
+ for (String axisName : axesNames) {
+ returnValue.put(axisName, policy);
+ }
+
+ } else if (interpolationType.getInterpolationAxes() != null) {
+ // make sure we don't set things twice
+ final List foundAxes=new ArrayList();
+
+ final InterpolationAxesType axes = interpolationType.getInterpolationAxes();
+ for (InterpolationAxisType axisInterpolation : axes.getInterpolationAxis()) {
+
+ // parse interpolation
+ final String method = axisInterpolation.getInterpolationMethod();
+ final InterpolationPolicy policy = InterpolationPolicy.getPolicy(method);
+
+ // parse axis
+ final String axis = axisInterpolation.getAxis();
+ // get label from axis
+ // TODO synonyms reduction
+ int index = axis.lastIndexOf("/");
+ final String axisLabel = (index >= 0 ? axis.substring(index+1, axis.length())
+ : axis);
+
+ // did we already set this interpolation?
+ if(foundAxes.contains(axisLabel)){
+ throw new WCS20Exception("Duplicated axis",WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel,axisLabel);
+ }
+ foundAxes.add(axisLabel);
+
+ // do we have this axis?
+ if(!returnValue.containsKey(axisLabel)){
+ throw new WCS20Exception("Invalid axes URI",WCS20Exception.WCS20ExceptionCode.NoSuchAxis,axisLabel);
+ }
+ returnValue.put(axisLabel, policy);
+ }
+ }
+
+ // final checks, we dont' supported different interpolations on Long and Lat
+ InterpolationPolicy lat=null,lon=null;
+ if(returnValue.containsKey("Long")){
+ lon=returnValue.get("Long");
+ }
+ if(returnValue.containsKey("Lat")){
+ lat=returnValue.get("Lat");
+ }
+ if(lat!=lon){
+ throw new WCS20Exception("We don't support different interpolations on Lat,Lon", WCS20Exception.WCS20ExceptionCode.InterpolationMethodNotSupported,"");
+ }
+ returnValue.get("Lat");
+ return returnValue;
+ }
+
+ /**
+ * @param coverage
+ * @param outputCRS
+ * @param axesInterpolations
+ * @return
+ */
+ private GridCoverage2D handleReprojection(GridCoverage2D coverage, CoordinateReferenceSystem outputCRS, Map axesInterpolations) {
+
+ // check the two crs tosee if we really need to do anything
+ if(CRS.equalsIgnoreMetadata(coverage.getCoordinateReferenceSystem2D(), outputCRS)){
+ return coverage;
+ }
+ // resample
+ return (GridCoverage2D) Operations.DEFAULT.resample(coverage, outputCRS);
+ }
+
+ /**
+ * @param coverage
+ * @param extensions
+ * @return
+ */
+ private GridCoverage2D handleRangeSubsettingExtension(
+ GridCoverage2D coverage,
+ Map extensions) {
+ // preparation
+ final List returnValue=new ArrayList();
+
+ // look for scaling extension
+ if(extensions==null||extensions.size()==0||!extensions.containsKey("rangeSubset")){
+ // NO INTERPOLATION
+ return coverage;
+ }
+
+ // look for an interpolation extension
+ final ExtensionItemType extensionItem=extensions.get("rangeSubset");
+ final RangeSubsetType range = (RangeSubsetType) extensionItem.getObjectContent();
+ for(RangeItemType rangeItem: range.getRangeItems()){
+ // there you go the range item
+
+ // single element
+ final String rangeComponent=rangeItem.getRangeComponent();
+
+ // range?
+ if(rangeComponent==null){
+ final RangeIntervalType rangeInterval = rangeItem.getRangeInterval();
+ final String startRangeComponent=rangeInterval.getStartComponent();
+ final String endRangeComponent=rangeInterval.getEndComponent();
+
+ returnValue.add(startRangeComponent);
+ returnValue.add(endRangeComponent );
+ } else {
+ returnValue.add(rangeComponent);
+ }
+ }
+
return coverage;
}
/**
* @param coverage
* @param request
+ * @param subsettingCRS
* @return
*/
- private GridCoverage2D handleSubsettingExtension(GridCoverage2D coverage, GetCoverageType request) {
+ private GridCoverage2D handleSubsettingExtension(
+ GridCoverage2D coverage,
+ GetCoverageType request,
+ CoordinateReferenceSystem subsettingCRS) {
// extract subsetting
- final GeneralEnvelope subset=extractSubsettingEnvelope(coverage,request);
+ final GeneralEnvelope subset=extractSubsettingEnvelope(coverage,request,subsettingCRS);
if(subset!=null){
return WCSUtils.crop(coverage, subset); // TODO I hate this classes that do it all
}
@@ -365,28 +732,31 @@ private GridCoverage2D handleSubsettingExtension(GridCoverage2D coverage, GetCov
/**
* @param coverage
- * @param request
+ * @param axesInterpolations
+ * @param extensions2
* @return
*/
- private GridCoverage2D handleScaling(GridCoverage2D coverage, GetCoverageType request) {
+ private GridCoverage2D handleScaling(GridCoverage2D coverage, Map extensions, Map axesInterpolations) {
// look for scaling extension
- final ExtensionType extension = request.getExtension();
- if(extension==null){
+ if(extensions==null||extensions.size()==0||!extensions.containsKey("Scaling")){
// NO SCALING
return coverage;
}
// look for a scaling extension
- final EList extensions = extension.getContents();
- for(ExtensionItemType extensionItem:extensions){
- try{
- final ScalingPolicy scaling= ScalingPolicy.valueOf(extensionItem.getName());// TODO extract scaling behavior
- return scaling.scale(coverage, extensionItem);
- } catch (Exception e) {
- // eat me
- }
+ final ExtensionItemType extensionItem=extensions.get("Scaling");
+ if(extensionItem!=null){
+
+ // get scaling
+ ScalingType scaling=(ScalingType) extensionItem.getObjectContent();
+
+ // instantiate enum
+
+ final ScalingPolicy scalingPolicy= ScalingPolicy.getPolicy(scaling);
+ return scalingPolicy.scale(coverage, scaling);
}
+
// no scaling
return coverage;
}
@@ -394,24 +764,67 @@ private GridCoverage2D handleScaling(GridCoverage2D coverage, GetCoverageType re
/**
* @param coverage
* @param request
+ * @param subsettingCRS
* @return
*/
- private GeneralEnvelope extractSubsettingEnvelope(GridCoverage coverage, GetCoverageType request) {
- //default
- GeneralEnvelope envelope=new GeneralEnvelope(coverage.getEnvelope());
+ private GeneralEnvelope extractSubsettingEnvelope(
+ GridCoverage coverage,
+ GetCoverageType request,
+ CoordinateReferenceSystem subsettingCRS) {
+ //default envelope
+ final CoordinateReferenceSystem sourceCRS=coverage.getCoordinateReferenceSystem();
+ GeneralEnvelope envelope=null;
+ if(subsettingCRS==null||CRS.equalsIgnoreMetadata(subsettingCRS,sourceCRS)){
+ envelope=new GeneralEnvelope(coverage.getEnvelope());
+ } else {
+ // reproject source coverage to subsetting crs for initialization
+ try {
+ envelope= CRS.transform(
+ CRS.findMathTransform(coverage.getCoordinateReferenceSystem(), subsettingCRS),
+ coverage.getEnvelope());
+ envelope.setCoordinateReferenceSystem(subsettingCRS);
+ } catch (Exception e) {
+ final WCS20Exception exception= new WCS20Exception(
+ "Unable to initialize subsetting envelope",
+ WCS20Exception.WCS20ExceptionCode.SubsettingCrsNotSupported,
+ subsettingCRS.toWKT()); // TODO extract code
+ exception.initCause(e);
+ throw exception;
+ }
+ }
// check what we need
final EList dimensions = request.getDimensionSubset();
if(dimensions==null||dimensions.size()<=0){
return null;
}
+
+ // TODO remove when we handle time and elevation
if(dimensions.size()>2){
-
+ throw new WCS20Exception(
+ "Invalid number of dimensions",
+ WCS20Exception.WCS20ExceptionCode.InvalidSubsetting,Integer.toString(dimensions.size()));
}
+
+ // put aside the dimensions that we have for double checking
+ final List axesNames = envelopeDimensionsMapper.getAxesNames(envelope, true);
+ final List foundDimensions= new ArrayList();
+
// parse dimensions
for(DimensionSubsetType dim:dimensions){
// get basic information
final String dimension=dim.getDimension(); // this is the dimension name which we compare to axes abbreviations from geotools
+ if(dimension==null||dimension.length()<=0||!axesNames.contains(dimension)){//TODO synonyms on axes labels
+ throw new WCS20Exception("Empty axis label provided",WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel,dimension==null?"Null":dimension);
+ }
+
+ // did we already do something with this dimension?
+ if(foundDimensions.contains(dimension)){
+ throw new WCS20Exception("Axis label already used during subsetting",WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel,dimension);
+ }
+ foundDimensions.add(dimension);
+
+ // now decide what to do
final String CRS= dim.getCRS();// TODO HOW DO WE USE THIS???
if(dim instanceof DimensionTrimType){
@@ -420,8 +833,13 @@ private GeneralEnvelope extractSubsettingEnvelope(GridCoverage coverage, GetCove
final double low = Double.parseDouble(trim.getTrimLow());
final double high = Double.parseDouble(trim.getTrimHigh());
+ final int axisIndex=envelopeDimensionsMapper.getAxisIndex(envelope, dimension);
+ if(axisIndex<0){
+ throw new WCS20Exception("Invalid axis provided",WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel,dimension);
+ }
+
// notice how we choose the order of the axes
- envelope.setRange(envelopeDimensionsMapper.getAxisIndex(envelope, dimension), low, high);
+ envelope.setRange(axisIndex, low, high);
} else if(dim instanceof DimensionSliceType){
// SLICING
@@ -429,18 +847,84 @@ private GeneralEnvelope extractSubsettingEnvelope(GridCoverage coverage, GetCove
final String slicePointS = slicing.getSlicePoint();
final double slicePoint=Double.parseDouble(slicePointS);
+ final int axisIndex=envelopeDimensionsMapper.getAxisIndex(envelope, dimension);
+ if(axisIndex<0){
+ throw new WCS20Exception("Invalid axis provided",WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel,dimension);
+ }
// notice how we choose the order of the axes
- envelope.setRange(envelopeDimensionsMapper.getAxisIndex(envelope, dimension), slicePoint, slicePoint);
+ AffineTransform affineTransform = getAffineTransform(coverage);
+ final double scale=axisIndex==0?affineTransform.getScaleX():-affineTransform.getScaleY();
+ envelope.setRange(axisIndex, slicePoint, slicePoint+scale);
} else {
- throw new WcsException(
+ throw new WCS20Exception(
"Invalid element found while attempting to parse dimension subsetting request",
- WcsExceptionCode.InvalidSubsetting,
+ WCS20Exception.WCS20ExceptionCode.InvalidSubsetting,
dim.getClass().toString());
}
}
+ //
+ // intersect with original envelope to make sure the subsetting is valid
+ //
+ final GeneralEnvelope sourceEnvelope = new GeneralEnvelope(coverage.getEnvelope());
+ if(CRS.equalsIgnoreMetadata(envelope, sourceEnvelope.getCoordinateReferenceSystem())){
+ envelope.intersect(sourceEnvelope);
+ envelope.setCoordinateReferenceSystem(coverage.getCoordinateReferenceSystem());
+ } else {
+ // reproject envelope to native crs for cropping
+ try {
+ envelope= CRS.transform(
+ CRS.findMathTransform(subsettingCRS,sourceCRS),
+ envelope);
+ envelope.setCoordinateReferenceSystem(sourceCRS);
+
+ // intersect
+ envelope.intersect(sourceEnvelope);
+ envelope.setCoordinateReferenceSystem(sourceCRS);
+ } catch (Exception e) {
+ final WCS20Exception exception= new WCS20Exception(
+ "Unable to initialize subsetting envelope",
+ WCS20Exception.WCS20ExceptionCode.SubsettingCrsNotSupported,
+ subsettingCRS.toWKT()); // TODO extract code
+ exception.initCause(e);
+ throw exception;
+ }
+ }
+
+ if(envelope.isEmpty()){
+ throw new WCS20Exception(
+ "Empty intersection after subsetting",
+ WCS20Exception.WCS20ExceptionCode.InvalidSubsetting,"");// TODO spit our envelope trimmed
+ }
return envelope;
}
+ /**
+ * Returns the "Sample to geophysics" transform as an affine transform, or {@code null}
+ * if none. Note that the returned instance may be an immutable one, not necessarly the
+ * default Java2D implementation.
+ *
+ * @param coverage The coverage for which to get the "grid to CRS" affine transform.
+ * @return The "grid to CRS" affine transform of the given coverage, or {@code null}
+ * if none or if the transform is not affine.
+ */
+ static AffineTransform getAffineTransform(final Coverage coverage) {
+ if (coverage instanceof GridCoverage) {
+ final GridGeometry geometry = ((GridCoverage) coverage).getGridGeometry();
+ if (geometry != null) {
+ final MathTransform gridToCRS;
+ if (geometry instanceof GridGeometry2D) {
+ gridToCRS = ((GridGeometry2D) geometry).getGridToCRS();
+ } else {
+ gridToCRS = geometry.getGridToCRS();
+ }
+ if (gridToCRS instanceof AffineTransform) {
+ return (AffineTransform) gridToCRS;
+ }
+ }
+ }
+ return null;
+ }
+
}
diff --git a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/exception/WCS20Exception.java b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/exception/WCS20Exception.java
index 383c39ce6fa..a9e1dbbe400 100644
--- a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/exception/WCS20Exception.java
+++ b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/exception/WCS20Exception.java
@@ -21,16 +21,34 @@ public class WCS20Exception extends OWS20Exception {
*/
private static final long serialVersionUID = -6110652531274829497L;
- public static class WCSExceptionCode extends OWS20Exception.OWSExceptionCode {
+ public static class WCS20ExceptionCode extends OWS20Exception.OWSExceptionCode {
- public final static OWSExceptionCode NoSuchCoverage = new WCSExceptionCode("NoSuchCoverage", 404);
- public final static OWSExceptionCode EmptyCoverageIdList = new WCSExceptionCode("emptyCoverageIdList", 404);
- public final static OWSExceptionCode InvalidEncodingSyntax = new WCSExceptionCode("InvalidEncodingSyntax", 400);
- public final static OWSExceptionCode InvalidScaleFactor = new WCSExceptionCode("InvalidScaleFactor", 404);
- public final static OWSExceptionCode InvalidExtent = new WCSExceptionCode("InvalidExtent", 404);
- public final static OWSExceptionCode ScalingAxisUndefined = new WCSExceptionCode("ScalingAxisUndefined", 404);
+ public final static WCS20ExceptionCode EmptyCoverageIdList = new WCS20ExceptionCode("emptyCoverageIdList", 404);
+ public final static WCS20ExceptionCode InvalidEncodingSyntax = new WCS20ExceptionCode("InvalidEncodingSyntax", 400);
+
+ // Scaling Extension
+ public final static WCS20ExceptionCode InvalidScaleFactor = new WCS20ExceptionCode("InvalidScaleFactor", 404);
+ public final static WCS20ExceptionCode InvalidExtent = new WCS20ExceptionCode("InvalidExtent", 404);
+ public final static WCS20ExceptionCode ScaleAxisUndefined = new WCS20ExceptionCode("ScaleAxisUndefined", 404);
+
+
+ // Interpolation Extension
+ public final static WCS20ExceptionCode NoSuchAxis = new WCS20ExceptionCode("ScalingAxisUndefined", 404);
+ public final static WCS20ExceptionCode InterpolationMethodNotSupported = new WCS20ExceptionCode("InterpolationMethodNotSupported", 404);
+
+ // CRS Extension
+ public final static WCS20ExceptionCode NotACrs = new WCS20ExceptionCode("NotACrs", 404);
+ public final static WCS20ExceptionCode SubsettingCrsNotSupported = new WCS20ExceptionCode("SubsettingCrs-NotSupported", 404);
+ public final static WCS20ExceptionCode OutputCrsNotSupported = new WCS20ExceptionCode("OutputCrs-NotSupported", 404);
+
- protected WCSExceptionCode(String exceptionCode, Integer httpCode) {
+ // CORE
+ public final static WCS20ExceptionCode NoSuchCoverage = new WCS20ExceptionCode("NoSuchCoverage", 404);
+ public final static WCS20ExceptionCode InvalidSubsetting = new WCS20ExceptionCode("InvalidSubsetting", 404);
+ public final static WCS20ExceptionCode InvalidAxisLabel = new WCS20ExceptionCode("InvalidAxisLabel", 404);
+
+
+ protected WCS20ExceptionCode(String exceptionCode, Integer httpCode) {
super(exceptionCode, httpCode);
}
}
diff --git a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/kvp/SubsetKvpParser.java b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/kvp/SubsetKvpParser.java
index ddf21699510..2dbce22155b 100644
--- a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/kvp/SubsetKvpParser.java
+++ b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/kvp/SubsetKvpParser.java
@@ -11,7 +11,7 @@
import org.geoserver.ows.KvpParser;
import org.geoserver.platform.OWS20Exception;
-import org.geoserver.wcs2_0.exception.WCS20Exception.WCSExceptionCode;
+import org.geoserver.wcs2_0.exception.WCS20Exception.WCS20ExceptionCode;
/**
* Parses the WCS 2.0 subset key
@@ -44,7 +44,7 @@ public Object parse(String value) throws Exception {
if (openIdx == -1 || closeIdx == -1 || closeIdx < value.length() - 1) {
throw new OWS20Exception("Invalid syntax, dimension [ , crs ] ( intervalOrPoint ) is expected",
- WCSExceptionCode.InvalidEncodingSyntax, "subset");
+ WCS20ExceptionCode.InvalidEncodingSyntax, "subset");
}
@@ -61,7 +61,7 @@ public Object parse(String value) throws Exception {
crs = dcElements[1];
} else {
throw new OWS20Exception("Invalid syntax, dimension [ , crs ] ( intervalOrPoint ) is expected",
- WCSExceptionCode.InvalidEncodingSyntax, "subset");
+ WCS20ExceptionCode.InvalidEncodingSyntax, "subset");
}
// parse the second part, intervalOrPoint
@@ -89,7 +89,7 @@ public Object parse(String value) throws Exception {
} else {
throw new OWS20Exception("Invalid syntax, dimension [ , crs ] ( intervalOrPoint ) "
+ "where interval or point has either 1 or two elements",
- WCSExceptionCode.InvalidEncodingSyntax, "subset");
+ WCS20ExceptionCode.InvalidEncodingSyntax, "subset");
}
}
@@ -102,7 +102,7 @@ private String parsePoint(String point, boolean allowStar) {
} else {
throw new OWS20Exception(
"Invalid usage of *, it can be used only when specifying an interval",
- WCSExceptionCode.InvalidEncodingSyntax, "subset");
+ WCS20ExceptionCode.InvalidEncodingSyntax, "subset");
}
} else if (point.startsWith("\"") && point.endsWith("\"")) {
point = point.substring(1, point.length() - 1);
@@ -113,7 +113,7 @@ private String parsePoint(String point, boolean allowStar) {
} catch (NumberFormatException e) {
throw new OWS20Exception("Invalid point value " + point
+ ", it is not a number and it's not between double quotes",
- WCSExceptionCode.InvalidEncodingSyntax, "subset");
+ WCS20ExceptionCode.InvalidEncodingSyntax, "subset");
}
}
diff --git a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/response/GMLCoverageResponseDelegate.java b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/response/GMLCoverageResponseDelegate.java
index 77b38a083e2..572494b8cfb 100644
--- a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/response/GMLCoverageResponseDelegate.java
+++ b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/response/GMLCoverageResponseDelegate.java
@@ -16,6 +16,8 @@
*/
package org.geoserver.wcs2_0.response;
+import java.awt.image.DataBuffer;
+import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
@@ -25,11 +27,14 @@
import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
+import javax.media.jai.PlanarImage;
+import javax.media.jai.iterator.RectIter;
+import javax.media.jai.iterator.RectIterFactory;
import javax.xml.transform.TransformerException;
import org.geoserver.platform.ServiceException;
import org.geoserver.wcs.responses.CoverageResponseDelegate;
-import org.geoserver.wcs2_0.util.EnvelopeDimensionsMapper;
+import org.geoserver.wcs2_0.util.EnvelopeAxesLabelsMapper;
import org.geotools.coverage.GridSampleDimension;
import org.geotools.coverage.TypeMap;
import org.geotools.coverage.grid.GridCoverage2D;
@@ -82,9 +87,9 @@ public class GMLCoverageResponseDelegate implements CoverageResponseDelegate {
*/
private static class GMLTransformer extends TransformerBase{
- private EnvelopeDimensionsMapper envelopeDimensionsMapper;
+ private EnvelopeAxesLabelsMapper envelopeDimensionsMapper;
- public GMLTransformer(EnvelopeDimensionsMapper envelopeDimensionsMapper ) {
+ public GMLTransformer(EnvelopeAxesLabelsMapper envelopeDimensionsMapper ) {
this.envelopeDimensionsMapper=envelopeDimensionsMapper;
}
@@ -321,7 +326,7 @@ private void handleRange(GridCoverage2D gc2d) {
end("gml:rangeParameters");
start("tupleList");
-// // walk through the coverage and spit it out!
+ // walk through the coverage and spit it out!
// final RenderedImage raster= gc2d.getRenderedImage();
// final int numBands=raster.getSampleModel().getNumBands();
// final int dataType=raster.getSampleModel().getDataType();
@@ -411,10 +416,11 @@ private void handleRangeType(GridCoverage2D gc2d) {
// get bands
final SampleDimension[] bands= gc2d.getSampleDimensions();
-
+ // handle bands
+ int i=1;
for(SampleDimension sd:bands){
final AttributesImpl fieldAttr = new AttributesImpl();
- fieldAttr.addAttribute("", "name", "name", "", sd.getDescription().toString()); // TODO NCNAME?
+ fieldAttr.addAttribute("", "name", "name", "", "band"+i++);//sd.getDescription().toString()); // TODO NCNAME?
start("swe:field",fieldAttr);
start("swe:Quantity");
@@ -619,11 +625,11 @@ public Translator createTranslator(ContentHandler handler) {
}
/** Can be used to map dimensions name to indexes*/
- private EnvelopeDimensionsMapper envelopeDimensionsMapper;
+ private EnvelopeAxesLabelsMapper envelopeDimensionsMapper;
- public GMLCoverageResponseDelegate(EnvelopeDimensionsMapper envelopeDimensionsMapper) {
+ public GMLCoverageResponseDelegate(EnvelopeAxesLabelsMapper envelopeDimensionsMapper) {
this.envelopeDimensionsMapper=envelopeDimensionsMapper;
}
diff --git a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/response/WCS20DescribeCoverageTransformer.java b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/response/WCS20DescribeCoverageTransformer.java
index 596c95c9548..c29aa052ed5 100644
--- a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/response/WCS20DescribeCoverageTransformer.java
+++ b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/response/WCS20DescribeCoverageTransformer.java
@@ -17,7 +17,7 @@
import org.geoserver.wcs.responses.CoverageResponseDelegateFinder;
import org.geoserver.wcs2_0.WCS20Const;
import org.geoserver.wcs2_0.exception.WCS20Exception;
-import org.geoserver.wcs2_0.util.EnvelopeDimensionsMapper;
+import org.geoserver.wcs2_0.util.EnvelopeAxesLabelsMapper;
import org.geoserver.wcs2_0.util.NCNameResourceCodec;
import org.geoserver.wcs2_0.util.StringUtils;
import org.geotools.geometry.jts.ReferencedEnvelope;
@@ -46,12 +46,12 @@ public class WCS20DescribeCoverageTransformer extends TransformerBase {
private CoverageResponseDelegateFinder responseFactory;
/** Utility class to map envelope dimension*/
- private EnvelopeDimensionsMapper envelopeDimensionsMapper;
+ private EnvelopeAxesLabelsMapper envelopeDimensionsMapper;
/**
* Creates a new WFSCapsTransformer object.
*/
- public WCS20DescribeCoverageTransformer(WCSInfo wcs, Catalog catalog, CoverageResponseDelegateFinder responseFactory,EnvelopeDimensionsMapper envelopeDimensionsMapper) {
+ public WCS20DescribeCoverageTransformer(WCSInfo wcs, Catalog catalog, CoverageResponseDelegateFinder responseFactory,EnvelopeAxesLabelsMapper envelopeDimensionsMapper) {
this.wcs = wcs;
this.catalog = catalog;
this.responseFactory = responseFactory;
@@ -105,7 +105,7 @@ public void encode(Object o) throws IllegalArgumentException {
if( ! badCoverageIds.isEmpty() ) {
String mergedIds = StringUtils.merge(badCoverageIds);
throw new WCS20Exception("Could not find the requested coverage(s): " + mergedIds
- , WCS20Exception.WCSExceptionCode.NoSuchCoverage, mergedIds);
+ , WCS20Exception.WCS20ExceptionCode.NoSuchCoverage, mergedIds);
}
// ok: build the response
diff --git a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/util/EnvelopeDimensionsMapper.java b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/util/EnvelopeAxesLabelsMapper.java
similarity index 95%
rename from src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/util/EnvelopeDimensionsMapper.java
rename to src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/util/EnvelopeAxesLabelsMapper.java
index e98d7314a13..f411d4ef3d3 100644
--- a/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/util/EnvelopeDimensionsMapper.java
+++ b/src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/util/EnvelopeAxesLabelsMapper.java
@@ -28,6 +28,7 @@
import org.geotools.util.logging.Logging;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
@@ -38,17 +39,17 @@
* TODO caching depending on CRS?
* TODO handle composite CRS
*/
-public class EnvelopeDimensionsMapper {
+public class EnvelopeAxesLabelsMapper {
/** Logger for this class*/
- private final static Logger LOGGER= Logging.getLogger(EnvelopeDimensionsMapper.class);
+ private final static Logger LOGGER= Logging.getLogger(EnvelopeAxesLabelsMapper.class);
public List getAxesNames(Envelope envelope, boolean swapAxes){
Utilities.ensureNonNull("envelope", envelope);
final CoordinateReferenceSystem crs= envelope.getCoordinateReferenceSystem();
// handle axes switch for geographic crs
- final boolean axesSwitch= CRS.getAxisOrder(crs)==AxisOrder.EAST_NORTH&&swapAxes;
+ final boolean axesSwitch= crs instanceof GeographicCRS &&swapAxes;
// additional fields for CRS
final CoordinateSystem cs=crs.getCoordinateSystem();
diff --git a/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/CRSExtentionTest.java b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/CRSExtentionTest.java
new file mode 100644
index 00000000000..ba2031d6bd2
--- /dev/null
+++ b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/CRSExtentionTest.java
@@ -0,0 +1,161 @@
+package org.geoserver.wcs2_0;
+
+import static junit.framework.Assert.assertEquals;
+
+import java.io.File;
+
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.geotools.coverage.grid.GridCoverage2D;
+import org.geotools.gce.geotiff.GeoTiffReader;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.referencing.CRS;
+import org.junit.Test;
+import org.opengis.coverage.grid.GridEnvelope;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import com.mockrunner.mock.web.MockHttpServletResponse;
+/**
+ *
+ * @author Simone Giannecchini, GeoSolutions SAS
+ *
+ */
+public class CRSExtentionTest extends WCSTestSupport {
+
+ @Test
+ public void testGetCoverageOutputCRSXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageOutputCRS.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null;
+ try {
+ targetCoverage = readerTarget.read(null);
+ final CoordinateReferenceSystem targetCRS=CRS.decode("EPSG:3857", true);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), targetCRS));
+
+ // checks
+ final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange();
+
+ final GeneralEnvelope expectedEnvelope= new GeneralEnvelope(
+ new double[]{1.6308305401213994E7,-5543147.203861462},
+ new double[]{1.6475284637403902E7,-5311971.846945147});
+ expectedEnvelope.setCoordinateReferenceSystem(targetCRS);
+
+ final double scale = getScale(targetCoverage);
+ assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale);
+ assertEquals(gridRange.getSpan(0), 360);
+ assertEquals(gridRange.getSpan(1), 360);
+
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ }
+
+ @Test
+ public void testGetCoverageSubsettingCRSFullXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageSubsettingCRS.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null;
+ try {
+ targetCoverage = readerTarget.read(null);
+ final CoordinateReferenceSystem targetCRS=CRS.decode("EPSG:3857", true);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), targetCRS));
+
+ // checks
+ final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange();
+
+ final GeneralEnvelope expectedEnvelope= new GeneralEnvelope(
+ new double[]{1.6308305401213994E7,-5543147.203861462},
+ new double[]{1.6475284637403902E7,-5311971.846945147});
+ expectedEnvelope.setCoordinateReferenceSystem(targetCRS);
+
+ final double scale = getScale(targetCoverage);
+ assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale);
+ assertEquals(gridRange.getSpan(0), 360);
+ assertEquals(gridRange.getSpan(1), 360);
+
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ }
+
+ @Test
+ public void testGetCoverageSubsettingTrimCRSXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageSubsettingTrimCRS.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null;
+ try {
+ targetCoverage = readerTarget.read(null);
+ final CoordinateReferenceSystem targetCRS=CRS.decode("EPSG:3857", true);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), targetCRS));
+
+ // checks
+ final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange();
+
+ final GeneralEnvelope expectedEnvelope= new GeneralEnvelope(
+ new double[]{1.6308305401213994E7,-5543147.203861462},
+ new double[]{1.6475284637403902E7,-5311971.846945147});
+ expectedEnvelope.setCoordinateReferenceSystem(targetCRS);
+
+ final double scale = getScale(targetCoverage);
+ assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale);
+ assertEquals(gridRange.getSpan(0), 360);
+ assertEquals(gridRange.getSpan(1), 360);
+
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ }
+
+}
diff --git a/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/GetCoverageTest.java b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/GetCoverageTest.java
index a5cd733d607..8bb5e86cb06 100644
--- a/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/GetCoverageTest.java
+++ b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/GetCoverageTest.java
@@ -2,20 +2,26 @@
import static junit.framework.Assert.assertEquals;
-import it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader;
-import it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReaderSpi;
-
import java.io.File;
-import javax.imageio.stream.FileImageInputStream;
+import junit.framework.Assert;
import org.apache.commons.io.FileUtils;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.gce.geotiff.GeoTiffReader;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.referencing.CRS;
import org.junit.Test;
+import org.opengis.coverage.grid.GridEnvelope;
import com.mockrunner.mock.web.MockHttpServletResponse;
-
+/**
+ * Testing WCS 2.0 Core {@link GetCoverage}
+ *
+ * @author Simone Giannecchini, GeoSolutions SAS
+ * @author Emanuele Tajariol, GeoSolutions SAS
+ *
+ */
public class GetCoverageTest extends WCSTestSupport {
@Test
@@ -24,326 +30,370 @@ public void testGetMissingCoverage() throws Exception {
checkOws20Exception(response, 404, "NoSuchCoverage", "coverageId");
}
+
+ /**
+ * Trimming only on Longitude
+ *
+ * @throws Exception
+ */
@Test
- public void testReprojectXML() throws Exception {
- String request = "\n" + "\n"
- + " wcs__BlueMarble\n"
- + " \n"
- + " Long\n"
- + " 146.5\n"
- + " 147.0\n"
- + " \n"
- + " \n"
- + " Lat\n"
- + " -43.5\n"
- + " -43.0\n"
- + " \n"
- + " \n"
- + " "
- + " http://www.opengis.net/def/crs/EPSG/0/4326"
- + " \n"
- + " \n"
- + " image/tiff\n"
- + "";
-
+ public void testCoverageTrimmingLatitudeNativeCRSXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageTrimmingLatitudeNativeCRSXML.xml");
+ final String request= FileUtils.readFileToString(xml);
MockHttpServletResponse response = postAsServletResponse("wcs", request);
-
+
assertEquals("image/tiff", response.getContentType());
byte[] tiffContents = getBinary(response);
File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
FileUtils.writeByteArrayToFile(file, tiffContents);
- // TODO: check the tiff structure is the one requested
- final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
- .createReaderInstance();
- reader.setInput(new FileImageInputStream(file));
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null;
+ try {
+ targetCoverage = readerTarget.read(null);
+
+ // checks
+ final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange();
+
+ final GeneralEnvelope expectedEnvelope= new GeneralEnvelope(
+ new double[]{targetCoverage.getEnvelope().getMinimum(0),-43.5},
+ new double[]{targetCoverage.getEnvelope().getMaximum(0),-43.0});
+ expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true));
+
+ final double scale = getScale(targetCoverage);
+ assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem()));
+ assertEquals(gridRange.getSpan(0), 360);
+ assertEquals(gridRange.getSpan(1), 120);
+
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
}
@Test
- public void testTrimmingCoverageXML() throws Exception {
- String request = "\n" + "\n"
- + " wcs__BlueMarble\n"
- + " \n"
- + " Long\n"
- + " 146.5\n"
- + " 147.0\n"
- + " \n"
- + " \n"
- + " Lat\n"
- + " -43.5\n"
- + " -43.0\n"
- + " \n"
- + " \n"
- + " "
- + " http://www.opengis.net/def/crs/EPSG/0/4326"
- + " \n"
- + " \n"
- + " image/tiff\n"
- + "";
-
+ public void testCoverageTrimmingNativeCRSXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageTrimmingNativeCRSXML.xml");
+ final String request= FileUtils.readFileToString(xml);
MockHttpServletResponse response = postAsServletResponse("wcs", request);
-
+
assertEquals("image/tiff", response.getContentType());
byte[] tiffContents = getBinary(response);
File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
FileUtils.writeByteArrayToFile(file, tiffContents);
- // TODO: check the tiff structure is the one requested
- final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
- .createReaderInstance();
- reader.setInput(new FileImageInputStream(file));
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null;
+ try {
+ targetCoverage = readerTarget.read(null);
+
+ // checks
+ final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange();
+
+ final GeneralEnvelope expectedEnvelope= new GeneralEnvelope(
+ new double[]{146.5,-43.5},
+ new double[]{147.0,-43.0});
+ expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true));
+
+ final double scale = getScale(targetCoverage);
+ assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem()));
+ assertEquals(gridRange.getSpan(0), 120);
+ assertEquals(gridRange.getSpan(1), 120);
+
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
}
@Test
- public void testScaleFactorIndividualXML() throws Exception {
- String request = "\n" + "\n"
- + " wcs__BlueMarble\n"
- + " \n"
- + " "
- + " "
- + " "
- + " http://www.opengis.net/def/axis/OGC/1/i"
- + " "
- + " 3.5"
- + " "
- + " "
- + " "
- + " http://www.opengis.net/def/axis/OGC/1/j"
- + " "
- + " 3.5"
- + " "
- + " "
- + " "
- + " http://www.opengis.net/def/axis/OGC/1/k"
- + " "
- + " 2.0"
- + " "
- + " "
- + " \n"
- + " image/tiff\n"
- + "";
-
+ public void testGetFullCoverageKVP() throws Exception {
+ MockHttpServletResponse response = getAsServletResponse("wcs?request=GetCoverage&service=WCS&version=2.0.1&coverageId=wcs__BlueMarble");
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = new File("./target/bm_full.tiff");
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null, sourceCoverage=null;
+ try {
+ targetCoverage = readerTarget.read(null);
+ sourceCoverage=(GridCoverage2D) this.getCatalog().getCoverageByName("BlueMarble").getGridCoverageReader(null, null).read(null);
+
+ // checks
+ assertEquals(sourceCoverage.getGridGeometry().getGridRange(), targetCoverage.getGridGeometry().getGridRange());
+ assertEquals(sourceCoverage.getCoordinateReferenceSystem(), targetCoverage.getCoordinateReferenceSystem());
+ assertEquals(sourceCoverage.getEnvelope(), targetCoverage.getEnvelope());
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(sourceCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ }
+
+ @Test
+ public void testGetFullCoverageXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetFullCoverage.xml");
+ final String request= FileUtils.readFileToString(xml);
MockHttpServletResponse response = postAsServletResponse("wcs", request);
-
+
assertEquals("image/tiff", response.getContentType());
byte[] tiffContents = getBinary(response);
File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ // check we can read it as a TIFF and it is similare to the origina one
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null, sourceCoverage=null;
+ try {
+ targetCoverage = readerTarget.read(null);
+ sourceCoverage=(GridCoverage2D) this.getCatalog().getCoverageByName("BlueMarble").getGridCoverageReader(null, null).read(null);
+
+ // checks
+ assertEquals(sourceCoverage.getGridGeometry().getGridRange(), targetCoverage.getGridGeometry().getGridRange());
+ assertEquals(sourceCoverage.getCoordinateReferenceSystem(), targetCoverage.getCoordinateReferenceSystem());
+ assertEquals(sourceCoverage.getEnvelope(), targetCoverage.getEnvelope());
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(sourceCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ }
- // TODO: check the tiff structure is the one requested
- final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
- .createReaderInstance();
- reader.setInput(new FileImageInputStream(file));
- }
+ /**
+ * Trimming only on Longitude
+ *
+ * @throws Exception
+ */
@Test
- public void testScaleSizeIndividualXML() throws Exception {
- String request = "\n" + "\n"
- + " wcs__BlueMarble\n"
- + " \n"
- + " \n"
- + " \n"
- + " \n"
- + " http://www.opengis.net/def/axis/OGC/1/i\n"
- + " \n"
- + " 10\n"
- + " 20\n"
- + " \n"
- + " \n"
- + " \n"
- + " http://www.opengis.net/def/axis/OGC/1/j\n"
- + " \n"
- + " 20\n"
- + " 30\n"
- + " \n"
- + " \n"
- + " image/tiff\n"
- + " \n"
- + "";
+ public void testCoverageTrimmingLongitudeNativeCRSXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageTrimmingLongNativeCRSXML.xml");
+ final String request= FileUtils.readFileToString(xml);
MockHttpServletResponse response = postAsServletResponse("wcs", request);
-
+
assertEquals("image/tiff", response.getContentType());
byte[] tiffContents = getBinary(response);
File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
FileUtils.writeByteArrayToFile(file, tiffContents);
-
- // TODO: check the tiff structure is the one requested
- final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
- .createReaderInstance();
- reader.setInput(new FileImageInputStream(file));
+
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null;
+ try {
+ targetCoverage = readerTarget.read(null);
+
+ // checks
+ final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange();
+
+ final GeneralEnvelope expectedEnvelope= new GeneralEnvelope(
+ new double[]{146.5,targetCoverage.getEnvelope().getMinimum(1)},
+ new double[]{147.0,targetCoverage.getEnvelope().getMaximum(1)});
+ expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true));
+
+ final double scale = getScale(targetCoverage);
+ assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem()));
+ assertEquals(gridRange.getSpan(0), 120);
+ assertEquals(gridRange.getSpan(1), 360);
+
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
}
-
@Test
- public void testScaleExtentIndividualXML() throws Exception {
- String request = "\n" + "\n"
- + " wcs__BlueMarble\n"
- + " \n"
- + " \n"
- + " \n"
- + " \n"
- + " http://www.opengis.net/def/axis/OGC/1/i\n"
- + " \n"
- + " 10\n"
- + " 20\n"
- + " \n"
- + " \n"
- + " \n"
- + " http://www.opengis.net/def/axis/OGC/1/j\n"
- + " \n"
- + " 20\n"
- + " 30\n"
- + " \n"
- + " \n"
- + " \n"
- + " image/tiff\n"
- + "";
-
+ public void testCoverageTrimmingSlicingNativeCRSXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageTrimmingSlicingNativeCRSXML.xml");
+ final String request= FileUtils.readFileToString(xml);
MockHttpServletResponse response = postAsServletResponse("wcs", request);
-
+
assertEquals("image/tiff", response.getContentType());
byte[] tiffContents = getBinary(response);
File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
FileUtils.writeByteArrayToFile(file, tiffContents);
-
- // TODO: check the tiff structure is the one requested
- final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
- .createReaderInstance();
- reader.setInput(new FileImageInputStream(file));
- }
+
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null;
+ try {
+ targetCoverage = readerTarget.read(null);
+
+ // checks
+ final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange();
+
+ // 1 dimensional slice along latitude
+ final GeneralEnvelope expectedEnvelope= new GeneralEnvelope(
+ new double[]{146.49999999999477,-43.5},
+ new double[]{146.99999999999477,-43.49583333333119});
+ expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true));
+
+ final double scale = getScale(targetCoverage);
+ assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem()));
+ assertEquals(gridRange.getSpan(1), 1);
+ assertEquals(gridRange.getSpan(0), 120);
+
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ }
@Test
- public void testScaleFactorXML() throws Exception {
- String request = "\n" + "\n"
- + " wcs__BlueMarble\n"
- + " \n"
- + " "
- + " 2.0"
- + " \n"
- + " \n"
- + " image/tiff\n"
- + "";
-
+ public void testCoverageTrimmingDuplicatedNativeCRSXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageTrimmingDuplicatedNativeCRSXML.xml");
+ final String request= FileUtils.readFileToString(xml);
MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("application/xml", response.getContentType());
+// checkOws20Exception(response, 404, "InvalidAxisLabel", "coverageId");
+
+ }
+ @Test
+ public void testCoverageSlicingLongitudeNativeCRSXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageSlicingLongitudeNativeCRSXML.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
assertEquals("image/tiff", response.getContentType());
byte[] tiffContents = getBinary(response);
File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
FileUtils.writeByteArrayToFile(file, tiffContents);
-
- // TODO: check the tiff structure is the one requested
- final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
- .createReaderInstance();
- reader.setInput(new FileImageInputStream(file));
- }
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null;
+ try {
+ targetCoverage = readerTarget.read(null);
+
+ // checks
+ final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange();
+
+ // 1 dimensional slice along longitude
+ final GeneralEnvelope expectedEnvelope= new GeneralEnvelope(
+ new double[]{146.5,-44.49999999999784},
+ new double[]{146.50416666666143,-42.99999999999787});
+ expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true));
+
+ final double scale = getScale(targetCoverage);
+ assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem()));
+ assertEquals(gridRange.getSpan(0), 1);
+ assertEquals(gridRange.getSpan(1), 360);
+
+ } finally {
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ }
+
@Test
- public void testGetFullCoverage() throws Exception {
- MockHttpServletResponse response = getAsServletResponse("wcs?request=GetCoverage&service=WCS&version=2.0.1&coverageId=wcs__BlueMarble");
+ public void testCoverageSlicingLatitudeNativeCRSXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageSlicingLatitudeNativeCRSXML.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
assertEquals("image/tiff", response.getContentType());
byte[] tiffContents = getBinary(response);
- File file = new File("./target/bm_full.tiff");
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
FileUtils.writeByteArrayToFile(file, tiffContents);
-
- // check we can read it as a TIFF
- GeoTiffReader reader = new GeoTiffReader(file);
- GridCoverage2D coverage = null;
+
+ GeoTiffReader readerTarget = new GeoTiffReader(file);
+ GridCoverage2D targetCoverage = null;
try {
- coverage = reader.read(null);
+ targetCoverage = readerTarget.read(null);
+
+ // checks
+ final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange();
+
+ // 1 dimensional slice along latitude
+ final GeneralEnvelope expectedEnvelope= new GeneralEnvelope(
+ new double[]{146.49999999999477,-43.499999999997854},
+ new double[]{147.99999999999474,-43.49583333333119});
+ expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true));
+
+ final double scale = getScale(targetCoverage);
+ assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem()));
+ assertEquals(gridRange.getSpan(1), 1);
+ assertEquals(gridRange.getSpan(0), 360);
+
} finally {
- reader.dispose();
- scheduleForCleaning(coverage);
+ try{
+ readerTarget.dispose();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ try{
+ scheduleForCleaning(targetCoverage);
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
}
-
- // TODO: add more checks, make sure we returned the whole thing
}
-
- // TODO: add tests for range subsetting
-//
-//
-// C0001
-//
-//
-//
-// band1
-//
-//
-//
-// band3
-// band5
-//
-//
-//
-//
-//
-
}
diff --git a/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/InterpolationExtentionsTest.java b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/InterpolationExtentionsTest.java
new file mode 100644
index 00000000000..03dc6368a9a
--- /dev/null
+++ b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/InterpolationExtentionsTest.java
@@ -0,0 +1,124 @@
+package org.geoserver.wcs2_0;
+
+import static junit.framework.Assert.assertEquals;
+import it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader;
+import it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReaderSpi;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+
+import javax.imageio.stream.FileImageInputStream;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Test;
+import org.w3c.dom.Document;
+
+import com.mockrunner.mock.web.MockHttpServletResponse;
+/**
+ *
+ * @author Simone Giannecchini, GeoSolutions
+ *
+ */
+public class InterpolationExtentionsTest extends WCSTestSupport {
+
+ @Test
+ public void testInterpolationSingleLinearXML() throws Exception {
+
+ final File xml= new File("./src/test/resources/requestGetCoverageInterpolationLinear.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ // TODO: check the tiff structure is the one requested
+ final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
+ .createReaderInstance();
+ reader.setInput(new FileImageInputStream(file));
+ assertEquals(360, reader.getWidth(0));
+ assertEquals(360, reader.getHeight(0));
+ reader.dispose();
+ }
+
+ @Test
+ public void testInterpolationSingleNearestXML() throws Exception {
+
+ final File xml= new File("./src/test/resources/requestGetCoverageInterpolationNearest.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ // TODO: check the tiff structure is the one requested
+ final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
+ .createReaderInstance();
+ reader.setInput(new FileImageInputStream(file));
+ assertEquals(360, reader.getWidth(0));
+ assertEquals(360, reader.getHeight(0));
+ reader.dispose();
+ }
+
+ @Test
+ public void testInterpolationMixedSupportedXML() throws Exception {
+
+ final File xml= new File("./src/test/resources/requestGetCoverageInterpolationMixedSupported.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ // TODO: check the tiff structure is the one requested
+ final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
+ .createReaderInstance();
+ reader.setInput(new FileImageInputStream(file));
+ assertEquals(360, reader.getWidth(0));
+ assertEquals(360, reader.getHeight(0));
+ reader.dispose();
+ }
+
+ @Test
+ public void testInterpolationMixedTimeXML() throws Exception {
+
+ final File xml= new File("./src/test/resources/requestGetCoverageInterpolationMixedTime.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("application/xml", response.getContentType());
+ Document dom = dom(new ByteArrayInputStream(response.getOutputStreamContent().getBytes()));
+ print(dom);
+ }
+
+ @Test
+ public void testInterpolationMixedUnsupportedXML() throws Exception {
+
+ final File xml= new File("./src/test/resources/requestGetCoverageInterpolationMixedUnsupported.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("application/xml", response.getContentType());
+ Document dom = dom(new ByteArrayInputStream(response.getOutputStreamContent().getBytes()));
+ print(dom);
+ }
+
+ @Test
+ public void testInterpolationMixedDuplicatedXML() throws Exception {
+
+ final File xml= new File("./src/test/resources/requestGetCoverageInterpolationMixedDuplicated.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("application/xml", response.getContentType());
+ Document dom = dom(new ByteArrayInputStream(response.getOutputStreamContent().getBytes()));
+ print(dom);
+ }
+
+
+}
diff --git a/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/RangeSubsetExtentionTest.java b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/RangeSubsetExtentionTest.java
new file mode 100644
index 00000000000..c0c4c6ebf9b
--- /dev/null
+++ b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/RangeSubsetExtentionTest.java
@@ -0,0 +1,45 @@
+package org.geoserver.wcs2_0;
+
+import static junit.framework.Assert.assertEquals;
+import it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader;
+import it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReaderSpi;
+
+import java.io.File;
+
+import javax.imageio.stream.FileImageInputStream;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Test;
+
+import com.mockrunner.mock.web.MockHttpServletResponse;
+/**
+ * Testing range subsetting capabilities
+ *
+ * @author Simone Giannecchini, GeoSolutions
+ *
+ */
+public class RangeSubsetExtentionTest extends WCSTestSupport {
+
+ @Test
+ public void testBasic() throws Exception {
+
+ final File xml= new File("./src/test/resources/requestGetCoverageRangeSubsetting.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ // TODO: check the tiff structure is the one requested
+ final TIFFImageReader reader = (TIFFImageReader) new TIFFImageReaderSpi()
+ .createReaderInstance();
+ reader.setInput(new FileImageInputStream(file));
+ assertEquals(360, reader.getWidth(0));
+ assertEquals(360, reader.getHeight(0));
+ reader.dispose();
+ }
+
+
+}
diff --git a/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/ScalingExtentionTest.java b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/ScalingExtentionTest.java
new file mode 100644
index 00000000000..0a0be76b0fe
--- /dev/null
+++ b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/ScalingExtentionTest.java
@@ -0,0 +1,123 @@
+package org.geoserver.wcs2_0;
+
+import static junit.framework.Assert.assertEquals;
+
+import java.io.File;
+
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.geotools.gce.geotiff.GeoTiffReader;
+import org.geotools.referencing.CRS;
+import org.junit.Test;
+
+import com.mockrunner.mock.web.MockHttpServletResponse;
+/**
+ * Testing Scaling Extension
+ *
+ * @author Simone Giannecchini, GeoSolution SAS
+ *
+ */
+public class ScalingExtentionTest extends WCSTestSupport {
+
+ @Test
+ public void testScaleAxesByFactorXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageScaleAxesByFactor.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ // check the tiff structure is the one requested
+ final GeoTiffReader reader = new GeoTiffReader(file);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(reader.getCrs(), CRS.decode("EPSG:4326",true)));
+ assertEquals(1260, reader.getOriginalGridRange().getSpan(0));
+ assertEquals(1260, reader.getOriginalGridRange().getSpan(1));
+ reader.dispose();
+ }
+ @Test
+ public void testScaleToSizeXML() throws Exception {
+
+ final File xml= new File("./src/test/resources/requestGetCoverageScaleToSize.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ // check the tiff structure is the one requested
+ final GeoTiffReader reader = new GeoTiffReader(file);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(reader.getCrs(), CRS.decode("EPSG:4326",true)));
+ assertEquals(1000, reader.getOriginalGridRange().getSpan(0));
+ assertEquals(1000, reader.getOriginalGridRange().getSpan(1));
+ reader.dispose();
+ }
+
+ @Test
+ public void testScaleToExtentXML() throws Exception {
+ final File xml= new File("./src/test/resources/requestGetCoverageScaleToExtent.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ // check the tiff structure is the one requested
+ final GeoTiffReader reader = new GeoTiffReader(file);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(reader.getCrs(), CRS.decode("EPSG:4326",true)));
+ assertEquals(200, reader.getOriginalGridRange().getSpan(0));
+ assertEquals(300, reader.getOriginalGridRange().getSpan(1));
+ reader.dispose();
+ }
+
+ @Test
+ public void testScaleByFactorXML() throws Exception {
+
+ final File xml= new File("./src/test/resources/requestGetCoverageScaleByFactor.xml");
+ final String request= FileUtils.readFileToString(xml);
+ MockHttpServletResponse response = postAsServletResponse("wcs", request);
+
+ assertEquals("image/tiff", response.getContentType());
+ byte[] tiffContents = getBinary(response);
+ File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target"));
+ FileUtils.writeByteArrayToFile(file, tiffContents);
+
+ // check the tiff structure is the one requested
+ final GeoTiffReader reader = new GeoTiffReader(file);
+ Assert.assertTrue(CRS.equalsIgnoreMetadata(reader.getCrs(), CRS.decode("EPSG:4326",true)));
+ assertEquals(900, reader.getOriginalGridRange().getSpan(0));
+ assertEquals(900, reader.getOriginalGridRange().getSpan(1));
+ reader.dispose();
+ }
+
+ // TODO: add tests for range subsetting
+//
+//
+// C0001
+//
+//
+//
+// band1
+//
+//
+//
+// band3
+// band5
+//
+//
+//
+//
+//
+
+}
diff --git a/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/WCSTestSupport.java b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/WCSTestSupport.java
index c499b0ed122..a23793f7d0c 100644
--- a/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/WCSTestSupport.java
+++ b/src/community/wcs2_0/src/test/java/org/geoserver/wcs2_0/WCSTestSupport.java
@@ -4,6 +4,7 @@
*/
package org.geoserver.wcs2_0;
+import java.awt.geom.AffineTransform;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
@@ -28,11 +29,17 @@
import org.geoserver.test.GeoServerSystemTestSupport;
import org.geoserver.wcs.CoverageCleanerCallback;
import org.geoserver.wcs.WCSInfo;
+import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.data.DataUtilities;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.referencing.operation.matrix.XAffineTransform;
import org.geotools.wcs.v2_0.WCSConfiguration;
import org.geotools.xml.Parser;
import org.junit.After;
+import org.opengis.coverage.Coverage;
import org.opengis.coverage.grid.GridCoverage;
+import org.opengis.coverage.grid.GridGeometry;
+import org.opengis.referencing.operation.MathTransform;
import org.w3c.dom.Document;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
@@ -54,6 +61,13 @@ public abstract class WCSTestSupport extends GeoServerSystemTestSupport {
List coverages = new ArrayList();
+ /**
+ * Small value for comparaison of sample values. Since most grid coverage implementations in
+ * Geotools 2 store geophysics values as {@code float} numbers, this {@code EPS} value must
+ * be of the order of {@code float} relative precision, not {@code double}.
+ */
+ static final float EPS = 1E-5f;
+
static {
final Map namespaceMap = new HashMap() {
{
@@ -193,5 +207,69 @@ public void cleanCoverages() {
}
}
+ /**
+ * Compares the envelopes of two coverages for equality using the smallest
+ * scale factor of their "grid to world" transform as the tolerance.
+ *
+ * @param expected The coverage having the expected envelope.
+ * @param actual The coverage having the actual envelope.
+ */
+ static void assertEnvelopeEquals(Coverage expected, Coverage actual) {
+ final double scaleA = getScale(expected);
+ final double scaleB = getScale(actual);
+
+ assertEnvelopeEquals((GeneralEnvelope)expected.getEnvelope(),scaleA,(GeneralEnvelope)actual.getEnvelope(),scaleB);
+ }
+
+ static void assertEnvelopeEquals(GeneralEnvelope expected,double scaleExpected, GeneralEnvelope actual,double scaleActual) {
+ final double tolerance;
+ if (scaleExpected <= scaleActual) {
+ tolerance = scaleExpected*1E-1;
+ } else if (!Double.isNaN(scaleActual)) {
+ tolerance = scaleActual*1E-1;
+ } else {
+ tolerance = EPS;
+ }
+ Assert.assertTrue(expected.equals(actual, tolerance, false));
+ }
+
+ /**
+ * Returns the "Sample to geophysics" transform as an affine transform, or {@code null}
+ * if none. Note that the returned instance may be an immutable one, not necessarly the
+ * default Java2D implementation.
+ *
+ * @param coverage The coverage for which to get the "grid to CRS" affine transform.
+ * @return The "grid to CRS" affine transform of the given coverage, or {@code null}
+ * if none or if the transform is not affine.
+ */
+ static AffineTransform getAffineTransform(final Coverage coverage) {
+ if (coverage instanceof GridCoverage) {
+ final GridGeometry geometry = ((GridCoverage) coverage).getGridGeometry();
+ if (geometry != null) {
+ final MathTransform gridToCRS;
+ if (geometry instanceof GridGeometry2D) {
+ gridToCRS = ((GridGeometry2D) geometry).getGridToCRS();
+ } else {
+ gridToCRS = geometry.getGridToCRS();
+ }
+ if (gridToCRS instanceof AffineTransform) {
+ return (AffineTransform) gridToCRS;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the scale of the "grid to CRS" transform, or {@link Double#NaN} if unknown.
+ *
+ * @param coverage The coverage for which to get the "grid to CRS" scale, or {@code null}.
+ * @return The "grid to CRS" scale, or {@code NaN} if none or if the transform is not affine.
+ */
+ static double getScale(final Coverage coverage) {
+ final AffineTransform gridToCRS = getAffineTransform(coverage);
+ return (gridToCRS != null) ? XAffineTransform.getScale(gridToCRS) : Double.NaN;
+ }
+
}
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationLinear.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationLinear.xml
new file mode 100644
index 00000000000..22c671e96a0
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationLinear.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedDuplicated.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedDuplicated.xml
new file mode 100644
index 00000000000..14e8ecd5fc9
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedDuplicated.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedSupported.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedSupported.xml
new file mode 100644
index 00000000000..81ce06e6291
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedSupported.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedTime.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedTime.xml
new file mode 100644
index 00000000000..e119e2ca390
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedTime.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedUnsupported.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedUnsupported.xml
new file mode 100644
index 00000000000..caef31f3bbd
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationMixedUnsupported.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationNearest.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationNearest.xml
new file mode 100644
index 00000000000..0351307eeac
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageInterpolationNearest.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageOutputCRS.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageOutputCRS.xml
new file mode 100644
index 00000000000..c3cdca9759d
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageOutputCRS.xml
@@ -0,0 +1,15 @@
+
+
+
+ http://www.opengis.net/def/crs/EPSG/0/3857
+
+ wcs__BlueMarble
+ image/tiff
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageRangeSubsetting.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageRangeSubsetting.xml
new file mode 100644
index 00000000000..03bb0e92158
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageRangeSubsetting.xml
@@ -0,0 +1,21 @@
+
+
+ wcs__BlueMarble
+
+
+
+ band1
+
+
+
+ band3
+ band5
+
+
+
+
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleAxesByFactor.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleAxesByFactor.xml
new file mode 100644
index 00000000000..50bb51af5e3
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleAxesByFactor.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+ http://www.opengis.net/def/axis/OGC/1/i
+
+ 3.5
+
+
+
+ http://www.opengis.net/def/axis/OGC/1/j
+
+ 3.5
+
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleByFactor.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleByFactor.xml
new file mode 100644
index 00000000000..506701cbae6
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleByFactor.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ 2.5
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleToExtent.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleToExtent.xml
new file mode 100644
index 00000000000..3aa9b0e5382
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleToExtent.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+ http://www.opengis.net/def/axis/OGC/1/i
+
+ 10
+ 209
+
+
+
+ http://www.opengis.net/def/axis/OGC/1/j
+
+ 20
+ 319
+
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleToSize.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleToSize.xml
new file mode 100644
index 00000000000..862ca3da127
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageScaleToSize.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+ http://www.opengis.net/def/axis/OGC/1/i
+
+ 1000
+
+
+
+ http://www.opengis.net/def/axis/OGC/1/j
+
+ 1000
+
+
+
+
+ wcs__BlueMarble
+ image/tiff
+
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageSlicingLatitudeNativeCRSXML.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageSlicingLatitudeNativeCRSXML.xml
new file mode 100644
index 00000000000..9d73fd89a88
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageSlicingLatitudeNativeCRSXML.xml
@@ -0,0 +1,16 @@
+
+
+ wcs__BlueMarble
+
+ Lat
+ -43.5
+
+ image/tiff
+
\ No newline at end of file
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageSlicingLongitudeNativeCRSXML.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageSlicingLongitudeNativeCRSXML.xml
new file mode 100644
index 00000000000..4dfad7cbb90
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageSlicingLongitudeNativeCRSXML.xml
@@ -0,0 +1,16 @@
+
+
+ wcs__BlueMarble
+
+ Long
+ 146.5
+
+ image/tiff
+
\ No newline at end of file
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageSubsettingCRS.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageSubsettingCRS.xml
new file mode 100644
index 00000000000..9eabb299330
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageSubsettingCRS.xml
@@ -0,0 +1,26 @@
+
+
+
+ Long
+ 146.5
+ 147.0
+
+
+ Lat
+ -43.5
+ -43.0
+
+
+ http://www.opengis.net/def/crs/EPSG/0/4326
+ http://www.opengis.net/def/crs/EPSG/0/3857
+
+ wcs__BlueMarble
+ image/tiff
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageSubsettingTrimCRS.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageSubsettingTrimCRS.xml
new file mode 100644
index 00000000000..523ff3b2141
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageSubsettingTrimCRS.xml
@@ -0,0 +1,25 @@
+
+
+
+ http://www.opengis.net/def/crs/EPSG/0/3857
+
+ http://www.opengis.net/def/crs/EPSG/0/3857
+
+
+ wcs__BlueMarble
+
+ X
+ 1.6308305401213994E7
+ 1.6475284637403902E7
+
+
+ Y
+ -5543147.203861462
+ -5311971.846945147
+
+ image/tiff
+
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingDuplicatedNativeCRSXML.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingDuplicatedNativeCRSXML.xml
new file mode 100644
index 00000000000..583289d4623
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingDuplicatedNativeCRSXML.xml
@@ -0,0 +1,21 @@
+
+
+ wcs__BlueMarble
+
+ Long
+ -43.5
+
+
+ Long
+ 146.5
+ 147.0
+
+ image/tiff
+
\ No newline at end of file
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingLatitudeNativeCRSXML.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingLatitudeNativeCRSXML.xml
new file mode 100644
index 00000000000..b27f588d272
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingLatitudeNativeCRSXML.xml
@@ -0,0 +1,17 @@
+
+
+ wcs__BlueMarble
+
+ Lat
+ -43.5
+ -43.0
+
+ image/tiff
+
\ No newline at end of file
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingLongNativeCRSXML.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingLongNativeCRSXML.xml
new file mode 100644
index 00000000000..1f163a87749
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingLongNativeCRSXML.xml
@@ -0,0 +1,17 @@
+
+
+ wcs__BlueMarble
+
+ Long
+ 146.5
+ 147.0
+
+ image/tiff
+
\ No newline at end of file
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingNativeCRSXML.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingNativeCRSXML.xml
new file mode 100644
index 00000000000..f770f633338
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingNativeCRSXML.xml
@@ -0,0 +1,24 @@
+
+
+ wcs__BlueMarble
+
+ Long
+ 146.5
+ 147.0
+
+
+ Lat
+ -43.5
+ -43.0
+
+ image/tiff
+
\ No newline at end of file
diff --git a/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingSlicingNativeCRSXML.xml b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingSlicingNativeCRSXML.xml
new file mode 100644
index 00000000000..4198a419230
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetCoverageTrimmingSlicingNativeCRSXML.xml
@@ -0,0 +1,21 @@
+
+
+ wcs__BlueMarble
+
+ Lat
+ -43.5
+
+
+ Long
+ 146.5
+ 147.0
+
+ image/tiff
+
\ No newline at end of file
diff --git a/src/community/wcs2_0/src/test/resources/requestGetFullCoverage.xml b/src/community/wcs2_0/src/test/resources/requestGetFullCoverage.xml
new file mode 100644
index 00000000000..3bb31fb4d8f
--- /dev/null
+++ b/src/community/wcs2_0/src/test/resources/requestGetFullCoverage.xml
@@ -0,0 +1,10 @@
+
+
+ wcs__BlueMarble
+ image/tiff
+
diff --git a/src/platform/src/main/java/org/geoserver/platform/OWS20Exception.java b/src/platform/src/main/java/org/geoserver/platform/OWS20Exception.java
index cc119be075d..67e0e6b66f2 100644
--- a/src/platform/src/main/java/org/geoserver/platform/OWS20Exception.java
+++ b/src/platform/src/main/java/org/geoserver/platform/OWS20Exception.java
@@ -7,7 +7,6 @@
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
-import org.geotools.util.logging.Logging;
/**
* Class for exceptions generated by an OWS2.0 service.
@@ -35,7 +34,8 @@ public static class OWSExceptionCode {
public final static OWSExceptionCode VersionNegotiationFailed = new OWSExceptionCode("VersionNegotiationFailed", 400, "Bad request");
public final static OWSExceptionCode InvalidUpdateSequence = new OWSExceptionCode("InvalidUpdateSequence", 400, "Bad request");
public final static OWSExceptionCode OptionNotSupported = new OWSExceptionCode("OptionNotSupported", 501, "Not Implemented");
- public final static OWSExceptionCode NoApplicableCode = new OWSExceptionCode("NoApplicableCode", 500, "Not Implemented");
+ public final static OWSExceptionCode NoApplicableCode = new OWSExceptionCode("NoApplicableCode", 500, "Not Implemented");
+ public final static OWSExceptionCode InvalidCoverageType = new OWSExceptionCode("InvalidCoverageType", 404, "Coverage addressed is not a grid coverage");
private final String exceptionCode;
private final Integer httpCode;