Skip to content

Commit

Permalink
Adding KVP parsing for the range subset extension
Browse files Browse the repository at this point in the history
  • Loading branch information
aaime committed Dec 16, 2012
1 parent 58d2cc9 commit f591d4a
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 2 deletions.
9 changes: 9 additions & 0 deletions src/community/wcs2_0/src/main/java/applicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@
<bean id="wcs20scaleAxesKvpParser" class="org.geoserver.wcs2_0.kvp.ScaleAxesKvpParser"/>
<bean id="wcs20scaleSizeKvpParser" class="org.geoserver.wcs2_0.kvp.ScaleSizeKvpParser"/>
<bean id="wcs20scaleExtentKvpParser" class="org.geoserver.wcs2_0.kvp.ScaleExtentKvpParser"/>
<bean id="wcs20rangeSubsetKvpParser" class="org.geoserver.wcs2_0.kvp.RangeSubsetKvpParser">
<property name="service" value="WCS"/>
<property name="version" value="2.0.0"/>
</bean>
<bean id="wcs201rangeSubsetKvpParser" class="org.geoserver.wcs2_0.kvp.RangeSubsetKvpParser">
<property name="service" value="WCS"/>
<property name="version" value="2.0.1"/>
</bean>


<bean id="wcs20getCoverageKvpParser" class="org.geoserver.wcs2_0.kvp.WCS20GetCoverageRequestReader"/>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* Copyright (c) 2012 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.wcs2_0.kvp;

import net.opengis.wcs20.RangeIntervalType;
import net.opengis.wcs20.RangeItemType;
import net.opengis.wcs20.RangeSubsetType;
import net.opengis.wcs20.Wcs20Factory;

import org.geoserver.ows.KvpParser;
import org.geoserver.wcs2_0.exception.WCS20Exception;

/**
* KVP parser for the WCS 2.0 {@link RangeSubsetType}
*
* @author Andrea Aime - GeoSolutions
*/
public class RangeSubsetKvpParser extends KvpParser {

public RangeSubsetKvpParser() {
super("rangesubset", RangeSubsetType.class);
}

@Override
public Object parse(String value) throws Exception {
RangeSubsetType result = Wcs20Factory.eINSTANCE.createRangeSubsetType();

// remove space
value = value.trim();

// minimal validation
if(value.matches(".*,\\s*,.*")) {
// two consequent commas
throwInvalidSyntaxException();
} else if(value.startsWith(",") || value.endsWith(",")) {
throwInvalidSyntaxException();
}

String[] components = value.split("\\s*,\\s*");
for (String component : components) {
if (component.contains(":")) {
String[] lowHigh = component.split(":");
if (lowHigh.length != 2) {
throwInvalidSyntaxException();
}
RangeIntervalType ri = Wcs20Factory.eINSTANCE.createRangeIntervalType();
ri.setStartComponent(lowHigh[0]);
ri.setEndComponent(lowHigh[1]);
RangeItemType item = Wcs20Factory.eINSTANCE.createRangeItemType();
item.setRangeInterval(ri);

result.getRangeItems().add(item);
} else {
RangeItemType item = Wcs20Factory.eINSTANCE.createRangeItemType();
item.setRangeComponent(component);

result.getRangeItems().add(item);
}
}

return result;
}

protected void throwInvalidSyntaxException() {
throw new WCS20Exception(
"Invalid RangeSubset syntax, expecting a list of band names or band ranges (b1:b2)",
WCS20Exception.WCSExceptionCode.InvalidEncodingSyntax, "rangeSubset");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.geoserver.ows.kvp.EMFKvpRequestReader;
import org.geoserver.ows.util.KvpUtils;
import org.geotools.wcs.v2_0.RangeSubset;
import org.geotools.wcs.v2_0.Scaling;

/**
Expand Down Expand Up @@ -54,6 +55,7 @@ public Object read(Object request, Map kvp, Map rawKvp) throws Exception {
// with the XML, everything else is in GetCoverage
parseGeoTiffExtension(gc, kvp);
parseScalingExtension(gc, kvp);
parseRangeSubsetExtension(gc, kvp);

return gc;
}
Expand All @@ -73,7 +75,6 @@ private void parseGeoTiffExtension(GetCoverageType gc, Map kvp) {
gc.getExtension().getContents().add(item);
}
}

}

private void parseScalingExtension(GetCoverageType gc, Map kvp) {
Expand Down Expand Up @@ -107,7 +108,17 @@ private void parseScalingExtension(GetCoverageType gc, Map kvp) {
item.setObjectContent(scaling);
gc.getExtension().getContents().add(item);
}

}

private void parseRangeSubsetExtension(GetCoverageType gc, Map kvp) {
if(kvp.containsKey("rangesubset")) {
ExtensionItemType item = WCS20_FACTORY.createExtensionItemType();
item.setNamespace(RangeSubset.NAMESPACE);
item.setName("RangeSubset");
item.setObjectContent(kvp.get("rangesubset"));
gc.getExtension().getContents().add(item);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ private void handleServiceIdentification() {
element("ows:Profile", "http://www.opengis.net/spec/WCS_protocol-binding_post-xml/1.0");

element("ows:Profile","http://www.opengis.net/spec/WCS_service-extension_scaling/1.0/conf/scaling");
element("ows:Profile","http://www.opengis.net/spec/WCS_service-extension_range-subsetting/1.0/conf/record-subsetting");
// don't believe we support these
// element("ows:Profile","http://www.opengis.net/spec/WCS_service-extension_array-subsetting/1.0/conf/array-subsetting");
// element("ows:Profile","http://www.opengis.net/spec/WCS_service-extension_range-subsetting/1.0/conf/nested-subsetting");

// element("ows:Profile","http://www.opengis.net/spec/WCS_coverage-encoding/1.0/conf/coverage-encoding"); // TODO: check specs and URL
element("ows:Profile","http://www.opengis.net/spec/GMLCOV_geotiff-coverages/1.0/conf/geotiff-coverage");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import net.opengis.wcs20.ExtensionItemType;
import net.opengis.wcs20.GetCoverageType;
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;
Expand All @@ -20,6 +22,7 @@
import org.geoserver.data.test.SystemTestData;
import org.geoserver.ows.util.KvpUtils;
import org.geoserver.test.GeoServerSystemTestSupport;
import org.geotools.wcs.v2_0.RangeSubset;
import org.geotools.wcs.v2_0.Scaling;
import org.junit.Test;

Expand Down Expand Up @@ -137,6 +140,30 @@ public void testExtensionScaleExtent() throws Exception {
assertEquals(30.0, tax.getHigh(), 0d);
}

@Test
public void testExtensionRangeSubset() throws Exception {
GetCoverageType gc = parse("wcs?request=GetCoverage&service=WCS&version=2.0.1" +
"&coverageId=theCoverage&rangesubset=band01,band03:band05,band10,band19:band21");

Map<String, Object> extensions = getExtensionsMap(gc);

assertEquals(1, extensions.size());
RangeSubsetType rangeSubset = (RangeSubsetType) extensions.get(RangeSubset.NAMESPACE + ":RangeSubset");

EList<RangeItemType> items = rangeSubset.getRangeItems();
assertEquals(4, items.size());
RangeItemType i1 = items.get(0);
assertEquals("band01", i1.getRangeComponent());
RangeItemType i2 = items.get(1);
assertEquals("band03", i2.getRangeInterval().getStartComponent());
assertEquals("band05", i2.getRangeInterval().getEndComponent());
RangeItemType i3 = items.get(2);
assertEquals("band10", i3.getRangeComponent());
RangeItemType i4 = items.get(3);
assertEquals("band19", i4.getRangeInterval().getStartComponent());
assertEquals("band21", i4.getRangeInterval().getEndComponent());
}

private Map<String, Object> getExtensionsMap(GetCoverageType gc) {
// collect extensions
Map<String, Object> extensions = new HashMap<String, Object>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.geoserver.wcs2_0.kvp;

import static org.junit.Assert.*;

import net.opengis.wcs20.RangeItemType;
import net.opengis.wcs20.RangeSubsetType;

import org.eclipse.emf.common.util.EList;
import org.geoserver.platform.OWS20Exception;
import org.junit.Test;

public class RangeSubsetKvpParserTest {

RangeSubsetKvpParser parser = new RangeSubsetKvpParser();

@Test
public void testInvalidValues() throws Exception {
try {
parser.parse("axis::blah");
fail("should have thrown an exception");
} catch(OWS20Exception e) {
checkInvalidSyntaxException(e);
}

try {
parser.parse("band1,band2:band3:band4");
fail("should have thrown an exception");
} catch(OWS20Exception e) {
checkInvalidSyntaxException(e);
}

try {
parser.parse("band1,,band2");
fail("should have thrown an exception");
} catch(OWS20Exception e) {
checkInvalidSyntaxException(e);
}

try {
parser.parse("band1,band2,");
fail("should have thrown an exception");
} catch(OWS20Exception e) {
checkInvalidSyntaxException(e);
}

}

private void checkInvalidSyntaxException(OWS20Exception e) {
assertNotNull(e.getHttpCode());
assertEquals(400, e.getHttpCode().intValue());
assertEquals("InvalidEncodingSyntax", e.getCode());
assertEquals("rangeSubset", e.getLocator());
}

@Test
public void testMixed() throws Exception {
RangeSubsetType rs = (RangeSubsetType) parser.parse("band01,band03:band05,band10,band19:band21");
EList<RangeItemType> items = rs.getRangeItems();
assertEquals(4, items.size());
RangeItemType i1 = items.get(0);
assertEquals("band01", i1.getRangeComponent());
RangeItemType i2 = items.get(1);
assertEquals("band03", i2.getRangeInterval().getStartComponent());
assertEquals("band05", i2.getRangeInterval().getEndComponent());
RangeItemType i3 = items.get(2);
assertEquals("band10", i3.getRangeComponent());
RangeItemType i4 = items.get(3);
assertEquals("band19", i4.getRangeInterval().getStartComponent());
assertEquals("band21", i4.getRangeInterval().getEndComponent());
}

}

0 comments on commit f591d4a

Please sign in to comment.