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 Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@
<artifactId>xmlunit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ public void handleServiceException(ServiceException exception, Request request)
response.setStatus(500);
}
} 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<>();
Expand Down
117 changes: 73 additions & 44 deletions src/community/wfs3/src/main/java/org/geoserver/wfs3/WFS3Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.RequestWrapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
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.
Expand Down Expand Up @@ -83,7 +88,7 @@ private class RequestWrapper extends HttpServletRequestWrapper {
private String typeName;
private String outputFormat;
private String featureId;
private boolean mapped;
private String limit;

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

mapped = request != null;

// everything defaults to JSON in WFS3
String f = wrapped.getParameter("f");
if (f != null) {
Expand All @@ -162,6 +172,22 @@ private RequestWrapper(HttpServletRequest wrapped) {
} else {
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
Expand Down Expand Up @@ -205,6 +231,9 @@ public Map<String, String[]> getParameterMap() {
if (featureId != null && !featureId.isEmpty()) {
filtered.put("featureId", featureId);
}
if (limit != null && !limit.isEmpty()) {
filtered.put("count", limit);
}
return filtered;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class APIDocument {
public static final String IN_PATH = "path";
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_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_RESULT_TYPE = new Reference("#/components/parameters/resultType");
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.addParameter(REF_FORMAT);
layer.addParameter(REF_START_INDEX);
layer.addParameter(REF_COUNT);
layer.addParameter(REF_LIMIT);
layer.addParameter(REF_RESULT_TYPE);
layer.addParameter(REF_BBOX);
Response layerResponse = new Response("Information about the feature collection plus the first features " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,34 @@
*/
package org.geoserver.wfs3;

import com.jayway.jsonpath.DocumentContext;
import net.sf.json.JSON;
import org.geoserver.data.test.MockData;
import org.hamcrest.CoreMatchers;
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 {

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@
*/
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.opengis.feature.type.Name;
import org.springframework.mock.web.MockHttpServletResponse;

import javax.servlet.Filter;
import javax.xml.namespace.QName;
import java.util.Collections;
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 {

@Override
Expand All @@ -27,4 +34,17 @@ protected String getEncodedName(QName qName) {
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.