Skip to content

Commit

Permalink
Ffw storage prop search (#212)
Browse files Browse the repository at this point in the history
MCPODS-7069
  • Loading branch information
adamczyk-HERE authored Mar 12, 2024
1 parent c665037 commit 91fd92b
Show file tree
Hide file tree
Showing 7 changed files with 592 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.here.naksha.app.service;

import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.params.provider.Arguments;

import java.util.stream.Stream;

import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.here.naksha.app.common.TestUtil.urlEncoded;

public class PropertySearchSamples {

static Stream<Arguments> queryParams() {
return Stream.of(
Pair.of("properties.alone_prop=1", "properties.alone_prop=1"),
Pair.of("properties.alone_prop=1,2,3,4", "properties.alone_prop=1,2,3,4"),
Pair.of(
"properties.json_prop=" + urlEncoded("{\"arr1\":[1,2],\"arr2\":[]}"),
"properties.json_prop={\"arr1\":[1,2],\"arr2\":[]}"
),
Pair.of("properties.long_or=1,2,3,4,4,4,3,2,1,true,false", "properties.long_or=1,2,3,4,4,4,3,2,1,true,false"),
Pair.of("properties.very.very.very.nested.even.more=1", "properties.very.very.very.nested.even.more=1"),
Pair.of(
// Naksha does not interpret encoded %3E (">" sign) as a gt operation and passes it as properties.prop_> path with "=" operation
"properties.prop%3E=value_2,value_22",
// Http storege actually sends request with ">" reencoded to %3E, but Wiremock expects decoded string in verify matcher
"properties.prop>=value_2,value_22"
),
Pair.of("properties.prop=lte=1", "properties.prop=lte=1"),
Pair.of("properties.prop=.null", "properties.prop=.null"),
Pair.of("properties.prop=null", "properties.prop=null"),
Pair.of("properties.prop!=.null", "properties.prop!=.null"),
Pair.of("f.id=1", "f.id=1"),
Pair.of("f.specProp=1", "properties.@ns:com:here:xyz.specProp=1"),
Pair.of("properties.%40ns%3Acom%3Ahere%3Axyz.specProp=1", "properties.@ns:com:here:xyz.specProp=1"),
Pair.of("p.propWithShortPrefix=1", "properties.propWithShortPrefix=1"),
Pair.of("""
f.id!=1
&properties.prop_2!=value_2,value_22
&properties.prop_3=.null,value_33
&properties.prop_4!=.null,value_44
&properties.prop_5=gte=5.5,55
&properties.prop_5_1=cs=%7B%22id%22%3A%22123%22%7D,%5B%7B%22id%22%3A%22123%22%7D%5D
&properties.prop_5_2!=%7B%22id%22%3A%22123%22%7D,%7B%22id%22%3A%22456%22%7D,.null
&properties.prop_6=lte=6,66
&properties.prop_7=gt=7,77
&properties.prop_8=lt=8,88
&properties.array_1=cs=%40element_1,element_2
&properties.prop_10=gte=555,5555
&properties.prop_11=lte=666,6666
&properties.prop_12=gt=777,7777
&properties.prop_13=lt=888,8888
&p.prop_14=lt=999,9999
&f.prop_15=lt=111,1111
&properties.%40ns%3Acom%3Ahere%3Axyz.prop_16=lt=222,2222
&properties.@ns:com:here:xyz.tags=cs=%7B%22id%22%3A%22123%22%7D,%5B%7B%22id%22%3A%22123%22%7D%5D,element_4
&properties.@ns:com:here:xyz.tags=cs=element_5"""
.replace(System.lineSeparator(), "")
,
"""
f.id!=1
&properties.prop_2!=value_2,value_22
&properties.prop_3=.null,value_33
&properties.prop_4!=.null,value_44
&properties.prop_5=gte=5.5,55
&properties.prop_5_1=cs={\"id\":\"123\"},[{\"id\":\"123\"}],[{\"id\":\"123\"}]
&properties.prop_5_2!={\"id\":\"123\"},{\"id\":\"456\"},.null
&properties.prop_6=lte=6,66
&properties.prop_7=gt=7,77
&properties.prop_8=lt=8,88
&properties.array_1=cs=@element_1,element_2
&properties.prop_10=gte=555,5555
&properties.prop_11=lte=666,6666
&properties.prop_12=gt=777,7777
&properties.prop_13=lt=888,8888
&properties.prop_14=lt=999,9999
&properties.@ns:com:here:xyz.prop_15=lt=111,1111
&properties.@ns:com:here:xyz.prop_16=lt=222,2222
""".replace(System.lineSeparator(), "")
)
).map(pair -> {
RequestPatternBuilder builder = queryToPatternBuilder(pair.getRight());
return Arguments.of(
pair.getLeft(),
builder
);
});
}

private static @NotNull RequestPatternBuilder queryToPatternBuilder(String query) {
RequestPatternBuilder builder = new RequestPatternBuilder();
for (String param : query.split("&")) {
String[] paramValuePair = param.trim().split("=", 2);
builder.withQueryParam(paramValuePair[0], equalTo(paramValuePair[1]));
}
return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,21 @@
package com.here.naksha.app.service;

import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder;
import com.github.tomakehurst.wiremock.matching.UrlPattern;
import com.here.naksha.app.common.ApiTest;
import com.here.naksha.app.common.NakshaTestWebClient;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.http.HttpResponse;
import java.util.UUID;
import java.util.stream.Stream;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.here.naksha.app.common.CommonApiTestSetup.createHandler;
Expand Down Expand Up @@ -228,4 +233,22 @@ void tc0711_testGetByBBoxOnViewSpace() throws Exception {
verify(1, getRequestedFor(endpointPath));
}

@ParameterizedTest
@MethodSource("propSearchTestParams")
void tc800_testPropertySearch(String inputQueryString, RequestPatternBuilder outputQueryPattern) throws Exception {
final String bboxQueryParam = "west=-180.0&north=90.0&east=180.0&south=-90.0&limit=30000";

String streamId = UUID.randomUUID().toString();

// When: Get Features By BBox request is submitted to NakshaHub
nakshaClient.get("hub/spaces/" + HTTP_SPACE_ID + "/bbox?" + bboxQueryParam + "&" + inputQueryString, streamId);

stubFor(any(anyUrl()).willReturn(ok()));

verify(1, outputQueryPattern);
}

private static Stream<Arguments> propSearchTestParams(){
return PropertySearchSamples.queryParams();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.github.tomakehurst.wiremock.client.MappingBuilder;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder;
import com.github.tomakehurst.wiremock.matching.UrlPathPattern;
import com.here.naksha.app.common.ApiTest;
import com.here.naksha.app.common.NakshaTestWebClient;
Expand Down Expand Up @@ -48,7 +49,7 @@ class ReadFeaturesByTileHttpStorageTest extends ApiTest {

private static final NakshaTestWebClient nakshaClient = new NakshaTestWebClient();

private static final String SPACE_ID = "read_features_by_tile_http_test_space";
private static final String HTTP_SPACE_ID = "read_features_by_tile_http_test_space";
private static final String TYPE_QUADKEY = "quadkey";

@BeforeAll
Expand Down Expand Up @@ -175,7 +176,7 @@ void standardTestExecution(

// When: Get Features By Tile request is submitted to NakshaHub
final HttpResponse<String> response = nakshaClient
.get("hub/spaces/" + SPACE_ID + "/tile/" + tileType + "/" + tileId + "?" + urlQueryParams, streamId);
.get("hub/spaces/" + HTTP_SPACE_ID + "/tile/" + tileType + "/" + tileId + "?" + urlQueryParams, streamId);

// Then: Perform standard assertions
assertThat(response)
Expand All @@ -198,4 +199,21 @@ private void withQueryParams(MappingBuilder mappingBuilder, List<String> queryPa
});
}

@ParameterizedTest
@MethodSource("propSearchTestParams")
void tc900_testPropertySearch(String inputQueryString, RequestPatternBuilder outputQueryPattern) throws Exception {

String streamId = UUID.randomUUID().toString();

// When: Get Features By tile request is submitted to NakshaHub
nakshaClient.get("hub/spaces/" + HTTP_SPACE_ID + "/tile/" + TYPE_QUADKEY + "/11111?" + inputQueryString, streamId);

stubFor(any(anyUrl()));

verify(1, outputQueryPattern);
}

private static Stream<Arguments> propSearchTestParams(){
return PropertySearchSamples.queryParams();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ protected EventProcessingStrategy processingStrategyFor(IEvent event) {
} else {

view.setViewLayerCollection(
prepareViewLayerCollection(nakshaHub().getSpaceStorage(), properties.getSpaceIds()));
prepareViewLayerCollection(nakshaHub().getSpaceStorage(), properties.getSpaceIds()));
// TODO MCPODS-7046 Replace the way how view is created. Should be immutable without need to use set
// method.
return processRequest(ctx, view, request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,9 @@ private static Result executeFeatureByBBox(
@NotNull NakshaContext context, ReadFeaturesProxyWrapper readRequest, RequestSender requestSender) {
String queryParamsString = keysToKeyValuesStrings(readRequest, WEST, NORTH, EAST, SOUTH, LIMIT);

warnOnUnsupportedQueryParam(readRequest, PROPERTY_SEARCH_OP);

HttpResponse<String> response = requestSender.sendRequest(
String.format("/%s/bbox?%s", baseEndpoint(readRequest), queryParamsString),
String.format(
"/%s/bbox?%s%s", baseEndpoint(readRequest), queryParamsString, getPOpQueryOrEmpty(readRequest)),
Map.of(HDR_STREAM_ID, context.getStreamId()));

return prepareResult(response, XyzFeatureCollection.class, XyzFeatureCollection::getFeatures);
Expand All @@ -101,10 +100,11 @@ private static Result executeFeaturesByTile(

if (tileType != null && !tileType.equals(TILE_TYPE_QUADKEY))
return new ErrorResult(XyzError.NOT_IMPLEMENTED, "Tile type other than " + TILE_TYPE_QUADKEY);
warnOnUnsupportedQueryParam(readRequest, PROPERTY_SEARCH_OP);

HttpResponse<String> response = requestSender.sendRequest(
String.format("/%s/quadkey/%s?%s", baseEndpoint(readRequest), tileId, queryParamsString),
String.format(
"/%s/quadkey/%s?%s%s",
baseEndpoint(readRequest), tileId, queryParamsString, getPOpQueryOrEmpty(readRequest)),
Map.of(HDR_STREAM_ID, context.getStreamId()));

return prepareResult(response, XyzFeatureCollection.class, XyzFeatureCollection::getFeatures);
Expand All @@ -122,10 +122,12 @@ private static <T extends Typed> Result prepareResult(
return createHttpResultFromFeatureList(typedResponseToFeatureList.apply(resultFeatures));
}

private static void warnOnUnsupportedQueryParam(ReadFeaturesProxyWrapper readRequest, String key) {
if (readRequest.getQueryParameter(key) != null)
log.warn("The " + key + " query param for " + readRequest.getReadRequestType()
+ " is not supported yet and will be ignored.");
/**
* @return either POp query string starting with "&" or an empty string if the POp is null
*/
private static String getPOpQueryOrEmpty(ReadFeaturesProxyWrapper readRequest) {
POp pOp = readRequest.getQueryParameter(PROPERTY_SEARCH_OP);
return pOp == null ? "" : "&" + POpToQueryConverter.p0pToQuery(pOp);
}

/**
Expand Down
Loading

0 comments on commit 91fd92b

Please sign in to comment.