Skip to content

Commit aa7faaf

Browse files
gunplarhirenkp2000
andauthored
Property selection for post spatial, search, iterate, get by IDs or single ID (#185)
* implementation * test not working yet * selection tests * clip tests, disable clipping for now due to technical limits * PR comments * implementation with tests * MCPODS-6785 Search API selection * MCPODS-6785 Search test fix * MCPODS-6573 Get features by single or multiple IDs output JSON property selection * MCPODS-6787 iterate features output JSON property selection * PR comments --------- Co-authored-by: Hiren Patel <[email protected]>
1 parent d31c449 commit aa7faaf

File tree

32 files changed

+615
-66
lines changed

32 files changed

+615
-66
lines changed

here-naksha-app-service/src/main/java/com/here/naksha/app/service/http/tasks/ReadFeatureApiTask.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ protected void init() {}
118118
final String spaceId = ApiParams.extractMandatoryPathParam(routingContext, SPACE_ID);
119119
final QueryParameterList queryParameters = queryParamsFromRequest(routingContext);
120120
final List<String> featureIds = extractParamAsStringList(queryParameters, FEATURE_IDS);
121+
final Set<String> propPaths = PropertySelectionUtil.buildPropPathSetFromQueryParams(queryParameters);
121122

122123
// Validate parameters
123124
if (featureIds == null || featureIds.isEmpty()) {
@@ -127,22 +128,28 @@ protected void init() {}
127128

128129
// Forward request to NH Space Storage reader instance
129130
try (Result result = executeReadRequestFromSpaceStorage(rdRequest)) {
131+
final F1<XyzFeature, XyzFeature> preResponseProcessing =
132+
standardReadFeaturesPreResponseProcessing(propPaths, false, null);
130133
// transform Result to Http FeatureCollection response
131-
return transformReadResultToXyzCollectionResponse(result, XyzFeature.class);
134+
return transformReadResultToXyzCollectionResponse(result, XyzFeature.class, preResponseProcessing);
132135
}
133136
}
134137

135138
private @NotNull XyzResponse executeFeatureById() {
136139
// Parse and validate Path parameters
137140
final String spaceId = extractMandatoryPathParam(routingContext, SPACE_ID);
138141
final String featureId = extractMandatoryPathParam(routingContext, FEATURE_ID);
142+
final QueryParameterList queryParameters = queryParamsFromRequest(routingContext);
143+
final Set<String> propPaths = PropertySelectionUtil.buildPropPathSetFromQueryParams(queryParameters);
139144

140145
final ReadFeatures rdRequest = RequestHelper.readFeaturesByIdRequest(spaceId, featureId);
141146

142147
// Forward request to NH Space Storage reader instance
143148
try (Result result = executeReadRequestFromSpaceStorage(rdRequest)) {
149+
final F1<XyzFeature, XyzFeature> preResponseProcessing =
150+
standardReadFeaturesPreResponseProcessing(propPaths, false, null);
144151
// transform Result to Http XyzFeature response
145-
return transformReadResultToXyzFeatureResponse(result, XyzFeature.class);
152+
return transformReadResultToXyzFeatureResponse(result, XyzFeature.class, preResponseProcessing);
146153
}
147154
}
148155

@@ -227,6 +234,7 @@ protected void init() {}
227234
routingContext, XyzError.ILLEGAL_ARGUMENT, "Missing mandatory query parameters");
228235
}
229236
long limit = ApiParams.extractQueryParamAsLong(queryParams, LIMIT, false, DEF_FEATURE_LIMIT);
237+
final Set<String> propPaths = PropertySelectionUtil.buildPropPathSetFromQueryParams(queryParams);
230238
// validate values
231239
limit = (limit < 0 || limit > DEF_FEATURE_LIMIT) ? DEF_FEATURE_LIMIT : limit;
232240

@@ -242,8 +250,11 @@ protected void init() {}
242250

243251
// Forward request to NH Space Storage reader instance
244252
final Result result = executeReadRequestFromSpaceStorage(rdRequest);
253+
final F1<XyzFeature, XyzFeature> preResponseProcessing =
254+
standardReadFeaturesPreResponseProcessing(propPaths, false, null);
245255
// transform Result to Http FeatureCollection response, restricted by given feature limit
246-
return transformReadResultToXyzCollectionResponse(result, XyzFeature.class, limit);
256+
return transformReadResultToXyzCollectionResponse(
257+
result, XyzFeature.class, 0, limit, null, preResponseProcessing);
247258
}
248259

249260
private @NotNull XyzResponse executeIterate() {
@@ -253,6 +264,9 @@ protected void init() {}
253264
// Parse and validate Query parameters
254265
final QueryParameterList queryParams = queryParamsFromRequest(routingContext);
255266

267+
// Parse property selection
268+
final Set<String> propPaths = PropertySelectionUtil.buildPropPathSetFromQueryParams(queryParams);
269+
256270
// Note : subsequent steps need to support queryParams being null
257271

258272
// extract limit parameter
@@ -273,9 +287,12 @@ protected void init() {}
273287

274288
// Forward request to NH Space Storage reader instance
275289
final Result result = executeReadRequestFromSpaceStorage(rdRequest);
290+
final F1<XyzFeature, XyzFeature> preResponseProcessing =
291+
standardReadFeaturesPreResponseProcessing(propPaths, false, null);
276292
// transform Result to Http FeatureCollection response,
277293
// restricted by given feature limit and by adding "handle" attribute to support subsequent iteration
278-
return transformReadResultToXyzCollectionResponse(result, XyzFeature.class, offset, limit, handle);
294+
return transformReadResultToXyzCollectionResponse(
295+
result, XyzFeature.class, offset, limit, handle, preResponseProcessing);
279296
}
280297

281298
private @NotNull XyzResponse executeFeaturesByRadius() {
@@ -373,6 +390,8 @@ protected void init() {}
373390
// NOTE : queryParams can be null. Subsequent steps should respect the same.
374391
final long radius = ApiParams.extractQueryParamAsLong(queryParams, RADIUS, false, 0);
375392
long limit = ApiParams.extractQueryParamAsLong(queryParams, LIMIT, false, DEF_FEATURE_LIMIT);
393+
final Set<String> propPaths = PropertySelectionUtil.buildPropPathSetFromQueryParams(queryParams);
394+
final boolean clip = ApiParams.extractQueryParamAsBoolean(queryParams, CLIP_GEO, false);
376395
// validate values
377396
limit = (limit < 0 || limit > DEF_FEATURE_LIMIT) ? DEF_FEATURE_LIMIT : limit;
378397
ApiParams.validateParamRange(RADIUS, radius, 0, Long.MAX_VALUE);
@@ -390,7 +409,11 @@ protected void init() {}
390409

391410
// Forward request to NH Space Storage reader instance
392411
final Result result = executeReadRequestFromSpaceStorage(rdRequest);
412+
// TODO pass the correct transformed geometry into this method call, also use the boolean clip
413+
final F1<XyzFeature, XyzFeature> preResponseProcessing =
414+
standardReadFeaturesPreResponseProcessing(propPaths, false, radiusOp.getGeometry());
393415
// transform Result to Http FeatureCollection response, restricted by given feature limit
394-
return transformReadResultToXyzCollectionResponse(result, XyzFeature.class, limit);
416+
return transformReadResultToXyzCollectionResponse(
417+
result, XyzFeature.class, 0, limit, null, preResponseProcessing);
395418
}
396419
}

here-naksha-app-service/src/main/resources/swagger/openapi.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ paths:
476476
parameters:
477477
- $ref: '#/components/parameters/SpaceId'
478478
- $ref: '#/components/parameters/RequiredIds'
479+
- $ref: '#/components/parameters/PropertiesSelection'
479480
responses:
480481
'200':
481482
$ref: '#/components/responses/FeatureCollectionResponse'
@@ -627,6 +628,8 @@ paths:
627628
summary: Get a feature by ID
628629
description: Retrieves the feature with the provided identifier.
629630
operationId: getFeature
631+
parameters:
632+
- $ref: '#/components/parameters/PropertiesSelection'
630633
responses:
631634
'200':
632635
$ref: '#/components/responses/FeatureResponse'
@@ -880,6 +883,8 @@ paths:
880883
- $ref: '#/components/parameters/TagList'
881884
- $ref: '#/components/parameters/Limit'
882885
- $ref: '#/components/parameters/PropertiesQuery'
886+
- $ref: '#/components/parameters/PropertiesSelection'
887+
# - $ref: '#/components/parameters/Clip'
883888
requestBody:
884889
$ref: '#/components/requestBodies/GeometryRequest'
885890
responses:
@@ -917,6 +922,7 @@ paths:
917922
- $ref: '#/components/parameters/TagList'
918923
- $ref: '#/components/parameters/Limit'
919924
- $ref: '#/components/parameters/PropertiesQuery'
925+
- $ref: '#/components/parameters/PropertiesSelection'
920926
responses:
921927
'200':
922928
$ref: '#/components/responses/FeatureCollectionResponse'
@@ -951,6 +957,7 @@ paths:
951957
- $ref: '#/components/parameters/SpaceId'
952958
- $ref: '#/components/parameters/Limit'
953959
- $ref: '#/components/parameters/Handle'
960+
- $ref: '#/components/parameters/PropertiesSelection'
954961
responses:
955962
'200':
956963
$ref: '#/components/responses/IterateResponse'

here-naksha-app-service/src/test/java/com/here/naksha/app/service/IterateFeaturesTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,41 @@ void tc1103_testIterateWithInvalidHandle() throws URISyntaxException, Interrupte
170170
.hasJsonBody(expectedBodyPart, "Iterate Feature Error response body doesn't match");
171171
}
172172

173+
@Test
174+
void tc1104_testIterateInTwoPagesWithPropSelection() throws URISyntaxException, InterruptedException, IOException {
175+
// Test API : GET /hub/spaces/{spaceId}/iterate
176+
// Validate all features getting returned in two iterations, with:
177+
// - first iteration returning features and nextPageToken, selecting: 1 normal prop, 1 URI encoded prop, 1 prop not existing
178+
// - second iteration accepting handle but use the wrong selection delimiter (should return 400)
179+
180+
// Given: iterate parameters for first request
181+
final String limitQueryParam = "limit=3";
182+
final String firstStreamId = UUID.randomUUID().toString();
183+
final String firstExpectedBodyPart = loadFileOrFail("ReadFeatures/Iterate/TC1104_testIterateInTwoPagesWithPropSelection/iterate_response_1.json")
184+
.replaceAll("\\{\\{streamId}}",firstStreamId);
185+
final String selectionParams = "selection=p.speedLimit,p.unknown_prop,%s".formatted(urlEncoded("p.@ns:com:here:xyz.tags"));
186+
187+
// When: First iterate Features request is submitted to NakshaHub
188+
HttpResponse<String> response = nakshaClient.get("hub/spaces/" + SPACE_ID + "/iterate" + "?" + limitQueryParam + "&" + selectionParams, firstStreamId);
189+
// Then: Perform assertions
190+
ResponseAssertions.assertThat(response)
191+
.hasStatus(200)
192+
.hasStreamIdHeader(firstStreamId)
193+
.hasJsonBody(firstExpectedBodyPart, "First Iterate response body doesn't match", true);
194+
195+
// Given: iterate parameters for second request
196+
final String handleQueryParam = "handle=" + urlEncoded(parseJson(response.body(), XyzFeatureCollection.class).getNextPageToken());
197+
final String secondExpectedBodyPart = loadFileOrFail("ReadFeatures/Iterate/TC1104_testIterateInTwoPagesWithPropSelection/iterate_response_2.json");
198+
final String secondStreamId = UUID.randomUUID().toString();
199+
final String selectionWrongDelimiterParams = "selection=p.speedLimit+p.unknown_prop";
200+
201+
// When: Second iterate Features request is submitted to NakshaHub
202+
response = nakshaClient.get("hub/spaces/" + SPACE_ID + "/iterate" + "?" + handleQueryParam + "&" + selectionWrongDelimiterParams, secondStreamId);
203+
// Then: Perform assertions
204+
ResponseAssertions.assertThat(response)
205+
.hasStatus(400)
206+
.hasStreamIdHeader(secondStreamId)
207+
.hasJsonBody(secondExpectedBodyPart, "Final Iterate response body doesn't match");
208+
}
209+
173210
}

0 commit comments

Comments
 (0)