From 2f5217050dce124df9f0408c3eeab5d4f32e3a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20J=C3=A4ckle?= Date: Thu, 26 Oct 2023 16:23:47 +0200 Subject: [PATCH] fix that ThingFieldSelector did not allow specific paths of "_metadata" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * it only allowed to select top-level "_metadata" - which does not make sense to limit, as even selecting only specific _metadata is already supported * also add missing support for featureId wildcard when selecting e.g. "_metadata/features/*/properties" Signed-off-by: Thomas Jäckle --- .../things/model/ThingFieldSelector.java | 4 +-- .../things/model/ThingsModelFactory.java | 35 ++++++++++++++++--- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/things/model/src/main/java/org/eclipse/ditto/things/model/ThingFieldSelector.java b/things/model/src/main/java/org/eclipse/ditto/things/model/ThingFieldSelector.java index 81c3e55e8a..6dc28c152f 100644 --- a/things/model/src/main/java/org/eclipse/ditto/things/model/ThingFieldSelector.java +++ b/things/model/src/main/java/org/eclipse/ditto/things/model/ThingFieldSelector.java @@ -38,8 +38,8 @@ public final class ThingFieldSelector implements JsonFieldSelector { .withoutUrlDecoding() .build(); static final List SELECTABLE_FIELDS = Arrays.asList("thingId", "policyId", "definition", - "_namespace", "_revision", "_created", "_modified", "_metadata", "_policy", "_context", "_context(/[^,]+)?", - "features(/[^,]+)?", "attributes(/[^,]+)?"); + "_namespace", "_revision", "_created", "_modified", "_metadata(/[^,]+)?", "_policy", "_context", + "_context(/[^,]+)?", "features(/[^,]+)?", "attributes(/[^,]+)?"); private static final String KNOWN_FIELDS_REGEX = "/?(" + String.join("|", SELECTABLE_FIELDS) + ")"; private static final String FIELD_SELECTION_REGEX = "^" + KNOWN_FIELDS_REGEX + "(," + KNOWN_FIELDS_REGEX + ")*$"; private static final Pattern FIELD_SELECTION_PATTERN = Pattern.compile(FIELD_SELECTION_REGEX); diff --git a/things/model/src/main/java/org/eclipse/ditto/things/model/ThingsModelFactory.java b/things/model/src/main/java/org/eclipse/ditto/things/model/ThingsModelFactory.java index 4ba8534440..4938180f86 100755 --- a/things/model/src/main/java/org/eclipse/ditto/things/model/ThingsModelFactory.java +++ b/things/model/src/main/java/org/eclipse/ditto/things/model/ThingsModelFactory.java @@ -796,7 +796,12 @@ public static JsonFieldSelector expandFeatureIdWildcards(final Collection expandFeatureIdWildcard(final Collection featureIds, final JsonPointer jsonPointer) { - if (hasFeatureIdWildcard(jsonPointer)) { + if (hasMetadataFeatureIdWildcard(jsonPointer)) { + return featureIds.stream().map(fid -> Thing.JsonFields.METADATA.getPointer() + .append(Thing.JsonFields.FEATURES.getPointer()) + .append(JsonPointer.of(fid)) + .append(jsonPointer.getSubPointer(3).orElse(JsonPointer.empty()))); + } else if (hasFeatureIdWildcard(jsonPointer)) { return featureIds.stream().map(fid -> Thing.JsonFields.FEATURES.getPointer() .append(JsonPointer.of(fid)) .append(jsonPointer.getSubPointer(2).orElse(JsonPointer.empty()))); @@ -806,11 +811,33 @@ public static Stream expandFeatureIdWildcard(final Collection 1 - && pointer.getRoot() + return pointer.getLevelCount() > 1 && + isFeaturePath(pointer) && pointer.get(1).filter(FEATURE_ID_WILDCARD::equals).isPresent(); + } + + private static boolean isFeaturePath(final JsonPointer pointer) { + return pointer.getRoot() .filter(root -> Thing.JsonFields.FEATURES.getPointer().equals(JsonPointer.of(root))) + .isPresent(); + } + + private static boolean hasMetadataFeatureIdWildcard(final JsonPointer pointer) { + return pointer.getLevelCount() > 2 && + isMetadataFeaturePath(pointer) && + pointer.get(2).filter(FEATURE_ID_WILDCARD::equals).isPresent(); + } + + private static boolean isMetadataFeaturePath(final JsonPointer pointer) { + return pointer.getRoot() + .filter(root -> Thing.JsonFields.METADATA.getPointer().equals(JsonPointer.of(root))) .isPresent() - && pointer.get(1).filter(FEATURE_ID_WILDCARD::equals).isPresent(); + && + pointer.getSubPointer(1) + .map(metadataRoot -> metadataRoot.getRoot() + .filter(subRoot -> Thing.JsonFields.FEATURES.getPointer() + .equals(JsonPointer.of(subRoot))) + .isPresent() + ).orElse(false); } }