Skip to content

Commit

Permalink
Switching count to limit, some fixes on paths lookups
Browse files Browse the repository at this point in the history
  • Loading branch information
aaime committed May 10, 2018
1 parent 008d81b commit c909c27
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 52 deletions.
4 changes: 4 additions & 0 deletions src/community/wfs3/pom.xml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@
<artifactId>xmlunit</artifactId> <artifactId>xmlunit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
</dependencies> </dependencies>


</project> </project>
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ public void handleServiceException(ServiceException exception, Request request)
response.setStatus(500); response.setStatus(500);
} }
} else { } else {
response.setStatus(500); OWS20Exception.OWSExceptionCode code = OWS20Exception.OWSExceptionCode.getByCode
(exception.getCode());
if (code != null) {
response.setStatus(code.getHttpCode());
} else {
response.setStatus(500);
}
} }


Map<String, String> error = new LinkedHashMap<>(); Map<String, String> error = new LinkedHashMap<>();
Expand Down
117 changes: 73 additions & 44 deletions src/community/wfs3/src/main/java/org/geoserver/wfs3/WFS3Filter.java
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.RequestWrapper; import javax.xml.ws.RequestWrapper;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/** /**
* Simple hack to bridge part of the path based approach in WFS 3 to traditional OWS mappings. * Simple hack to bridge part of the path based approach in WFS 3 to traditional OWS mappings.
Expand Down Expand Up @@ -83,7 +88,7 @@ private class RequestWrapper extends HttpServletRequestWrapper {
private String typeName; private String typeName;
private String outputFormat; private String outputFormat;
private String featureId; private String featureId;
private boolean mapped; private String limit;


private RequestWrapper(HttpServletRequest wrapped) { private RequestWrapper(HttpServletRequest wrapped) {
super(wrapped); super(wrapped);
Expand All @@ -95,58 +100,63 @@ private RequestWrapper(HttpServletRequest wrapped) {
} else if (pathInfo.endsWith("/conformance") || pathInfo.endsWith("/conformance/")) { } else if (pathInfo.endsWith("/conformance") || pathInfo.endsWith("/conformance/")) {
request = "conformance"; request = "conformance";
} else if (pathInfo.startsWith("/collections")) { } else if (pathInfo.startsWith("/collections")) {
if (pathInfo.contains("items")) { List<Function<String, Boolean>> matchers = new ArrayList<>();
if (pathInfo.startsWith("/collections/")) { matchers.add(path -> {
pathInfo = pathInfo.substring("/collections/".length()); Matcher matcher = Pattern.compile("/collections/([^/]+)/items/(.+)").matcher(path);
} boolean matches = matcher.matches();
// selection by feature id? if (matches) {
if (pathInfo.contains("/")) { request = "getFeature";
String[] split = pathInfo.split("/"); String layerName = matcher.group(1);
if (split.length > 2) { setLayerName(layerName);
throw new HttpErrorCodeException( this.featureId = matcher.group(2);
HttpStatus.NOT_FOUND.value(), "Invalid path " + pathInfo);
}
pathInfo = split[0];
featureId = split[1];
} }
List<LayerInfo> layers = NCNameResourceCodec.getLayers(catalog, pathInfo); return matches;
if (!layers.isEmpty()) { });
matchers.add(path -> {
Matcher matcher = Pattern.compile("/collections/([^/]+)/items/?").matcher(path);
boolean matches = matcher.matches();
if (matches) {
request = "getFeature"; request = "getFeature";
typeName = layers.get(0).prefixedName(); String layerName = matcher.group(1);
} else { setLayerName(layerName);
throw new HttpErrorCodeException(
HttpStatus.NOT_FOUND.value(), "Could not find layer " + pathInfo);
}
} else {
pathInfo = pathInfo.substring("/collections".length());
if (pathInfo.startsWith("/")) {
pathInfo = pathInfo.substring(1);
}
if (pathInfo.endsWith("/")) {
pathInfo = pathInfo.substring(0, pathInfo.length() -1);
} }
request = "collections"; return matches;
if (!pathInfo.isEmpty()) { });
// is it a request to the list of collections, one to a specific collection, matchers.add(path -> {
// or something else? Matcher matcher = Pattern.compile("/collections/([^/]+)/?").matcher(path);
List<LayerInfo> layers = NCNameResourceCodec.getLayers(catalog, pathInfo); boolean matches = matcher.matches();
if (layers.isEmpty()) { if (matches) {
throw new HttpErrorCodeException( request = "collections";
HttpStatus.NOT_FOUND.value(), String layerName = matcher.group(1);
"Could not find layer " + pathInfo); setLayerName(layerName);
} else {
typeName = layers.get(0).prefixedName();
}

} }
} return matches;
});
matchers.add(path -> {
Matcher matcher = Pattern.compile("/collections/?").matcher(path);
boolean matches = matcher.matches();
if (matches) {
request = "collections";
}
return matches;
});


// loop over the matchers
boolean matched = false;
for (Function<String,Boolean> matcher : matchers) {
if (matcher.apply(pathInfo)) {
matched = true;
break;
}
}
// if none matches, complain
if (!matched) {
throw new HttpErrorCodeException(HttpStatus.NOT_FOUND.value(), "Unsupported path " + pathInfo);
}
} else { } else {
throw new HttpErrorCodeException(HttpStatus.NOT_FOUND.value(), "Unsupported path " + pathInfo); throw new HttpErrorCodeException(HttpStatus.NOT_FOUND.value(), "Unsupported path " + pathInfo);
} }


mapped = request != null;

// everything defaults to JSON in WFS3 // everything defaults to JSON in WFS3
String f = wrapped.getParameter("f"); String f = wrapped.getParameter("f");
if (f != null) { if (f != null) {
Expand All @@ -162,6 +172,22 @@ private RequestWrapper(HttpServletRequest wrapped) {
} else { } else {
this.outputFormat = BaseRequest.JSON_MIME; this.outputFormat = BaseRequest.JSON_MIME;
} }

// support for the limit parameter
String limit = wrapped.getParameter("limit");
if (limit != null) {
this.limit = limit;
}
}

private void setLayerName(String layerName) {
List<LayerInfo> layers = NCNameResourceCodec.getLayers(catalog, layerName);
if (!layers.isEmpty()) {
typeName = layers.get(0).prefixedName();
} else {
throw new HttpErrorCodeException(
HttpStatus.NOT_FOUND.value(), "Could not find layer " + layerName);
}
} }


@Override @Override
Expand Down Expand Up @@ -205,6 +231,9 @@ public Map<String, String[]> getParameterMap() {
if (featureId != null && !featureId.isEmpty()) { if (featureId != null && !featureId.isEmpty()) {
filtered.put("featureId", featureId); filtered.put("featureId", featureId);
} }
if (limit != null && !limit.isEmpty()) {
filtered.put("count", limit);
}
return filtered; return filtered;
} }


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class APIDocument {
public static final String IN_PATH = "path"; public static final String IN_PATH = "path";
private static final Reference REF_FORMAT = new Reference("#/components/parameters/f"); private static final Reference REF_FORMAT = new Reference("#/components/parameters/f");
private static final Reference REF_START_INDEX = new Reference("#/components/parameters/startIndex"); private static final Reference REF_START_INDEX = new Reference("#/components/parameters/startIndex");
private static final Reference REF_COUNT = new Reference("#/components/parameters/count"); private static final Reference REF_LIMIT = new Reference("#/components/parameters/limit");
private static final Reference REF_BBOX = new Reference("#/components/parameters/bbox"); private static final Reference REF_BBOX = new Reference("#/components/parameters/bbox");
private static final Reference REF_RESULT_TYPE = new Reference("#/components/parameters/resultType"); private static final Reference REF_RESULT_TYPE = new Reference("#/components/parameters/resultType");
private static final Reference REF_ID = new Reference("#/components/parameters/id"); private static final Reference REF_ID = new Reference("#/components/parameters/id");
Expand Down Expand Up @@ -568,7 +568,7 @@ public Map<String, Object> getPaths() {
layer.addTag("Features"); layer.addTag("Features");
layer.addParameter(REF_FORMAT); layer.addParameter(REF_FORMAT);
layer.addParameter(REF_START_INDEX); layer.addParameter(REF_START_INDEX);
layer.addParameter(REF_COUNT); layer.addParameter(REF_LIMIT);
layer.addParameter(REF_RESULT_TYPE); layer.addParameter(REF_RESULT_TYPE);
layer.addParameter(REF_BBOX); layer.addParameter(REF_BBOX);
Response layerResponse = new Response("Information about the feature collection plus the first features " + Response layerResponse = new Response("Information about the feature collection plus the first features " +
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4,17 +4,34 @@
*/ */
package org.geoserver.wfs3; package org.geoserver.wfs3;


import com.jayway.jsonpath.DocumentContext;
import net.sf.json.JSON; import net.sf.json.JSON;
import org.geoserver.data.test.MockData; import org.geoserver.data.test.MockData;
import org.hamcrest.CoreMatchers;
import org.junit.Test; import org.junit.Test;


import static org.hamcrest.CoreMatchers.both;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

public class FeatureTest extends WFS3TestSupport { public class FeatureTest extends WFS3TestSupport {


@Test @Test
public void testGetLayerAsGeoJson() throws Exception { public void testGetLayerAsGeoJson() throws Exception {
String roadSegments = getEncodedName(MockData.ROAD_SEGMENTS); String roadSegments = getEncodedName(MockData.ROAD_SEGMENTS);
JSON json = getAsJSON("wfs3/collections/" + roadSegments); DocumentContext json = getAsJSONPath("wfs3/collections/" + roadSegments + "/items",
print(json); 200);
assertEquals(5, (int) json.read("features.length()", Integer.class));
}


@Test
public void testLimit() throws Exception {
String roadSegments = getEncodedName(MockData.ROAD_SEGMENTS);
DocumentContext json = getAsJSONPath("wfs3/collections/" + roadSegments +
"/items?limit=3", 200);
assertEquals(3, (int) json.read("features.length()", Integer.class));
} }


// @Test // @Test
Expand All @@ -27,8 +44,10 @@ public void testGetLayerAsGeoJson() throws Exception {
@Test @Test
public void testErrorHandling() throws Exception { public void testErrorHandling() throws Exception {
String roadSegments = getEncodedName(MockData.ROAD_SEGMENTS); String roadSegments = getEncodedName(MockData.ROAD_SEGMENTS);
JSON json = getAsJSON("wfs3/collections/" + roadSegments + "?count=abc"); DocumentContext json = getAsJSONPath("wfs3/collections/" + roadSegments +
print(json); "/items?limit=abc", 400);
assertEquals("InvalidParameterValue", json.read("code"));
assertThat(json.read("description"), both(containsString("COUNT")).and(containsString("abc")));
} }


} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@
*/ */
package org.geoserver.wfs3; package org.geoserver.wfs3;


import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.internal.JsonContext;
import org.geoserver.test.GeoServerSystemTestSupport; import org.geoserver.test.GeoServerSystemTestSupport;
import org.opengis.feature.type.Name; import org.springframework.mock.web.MockHttpServletResponse;


import javax.servlet.Filter; import javax.servlet.Filter;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;


import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

public class WFS3TestSupport extends GeoServerSystemTestSupport { public class WFS3TestSupport extends GeoServerSystemTestSupport {


@Override @Override
Expand All @@ -27,4 +34,17 @@ protected String getEncodedName(QName qName) {
return qName.getLocalPart(); return qName.getLocalPart();
} }
} }

protected DocumentContext getAsJSONPath(String path, int expectedHttpCode) throws Exception {
MockHttpServletResponse response = getAsServletResponse(path);


assertEquals(expectedHttpCode, response.getStatus());
assertThat(response.getContentType(), startsWith("application/json"));
JsonContext json = (JsonContext) JsonPath.parse(response.getContentAsString());
if (!isQuietTests()) {
print(json(response));
}
return json;
}
} }

0 comments on commit c909c27

Please sign in to comment.