Skip to content

Commit

Permalink
eclipse-ditto#1650 added unit tests covering the added validation fun…
Browse files Browse the repository at this point in the history
…ctionality
  • Loading branch information
thjaeckle committed Jul 29, 2024
1 parent 2ed2641 commit 9c2ed96
Show file tree
Hide file tree
Showing 10 changed files with 1,447 additions and 10 deletions.
4 changes: 2 additions & 2 deletions things/service/src/main/resources/things.conf
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ ditto {
# whether to enforce a thing whenever the "definition" of the thing is updated to a new/other WoT TM
# needed follow-up would likely be https://github.com/eclipse-ditto/ditto/issues/1843
# - only with that we would e.g. update all feature definitions to the ones of the new thing definitions
enforce-thing-description-modification = false # needs to be false until #1843 is done
enforce-thing-description-modification = true
enforce-thing-description-modification = ${?THINGS_WOT_TM_MODEL_VALIDATION_THING_ENFORCE_TD_MODIFICATION}

forbid-thing-description-deletion = true
Expand Down Expand Up @@ -315,7 +315,7 @@ ditto {

feature {
# whether to enforce a feature whenever the "definition"(s) of the feature is updated to a new/other WoT TM(s)
enforce-feature-description-modification = false # needs to be false until #1843 is done
enforce-feature-description-modification = true
enforce-feature-description-modification = ${?THINGS_WOT_TM_MODEL_VALIDATION_FEATURE_ENFORCE_FD_MODIFICATION}

forbid-feature-description-deletion = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import java.util.Collection;
import java.util.Optional;
import java.util.function.Consumer;

import javax.annotation.Nullable;

Expand Down Expand Up @@ -184,6 +185,12 @@ public B setType(@Nullable final DataSchemaType type) {
return myself;
}

@Override
public B enhanceObjectBuilder(final Consumer<JsonObjectBuilder> builderConsumer) {
builderConsumer.accept(wrappedObjectBuilder);
return myself;
}

protected <J> void putValue(final JsonFieldDefinition<J> definition, @Nullable final J value) {
final Optional<JsonKey> keyOpt = definition.getPointer().getRoot();
if (keyOpt.isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.eclipse.ditto.wot.model;

import java.util.Collection;
import java.util.function.Consumer;

import javax.annotation.Nullable;

Expand Down Expand Up @@ -127,6 +128,12 @@ public Property.Builder setDefault(@Nullable final JsonValue defaultValue) {
return myself;
}

@Override
public Property.Builder enhanceObjectBuilder(final Consumer<JsonObjectBuilder> builderConsumer) {
builderConsumer.accept(wrappedObjectBuilder);
return myself;
}

@Override
public Property.Builder setType(@Nullable final DataSchemaType type) {
if (type != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
Expand All @@ -25,6 +26,7 @@
import org.eclipse.ditto.json.JsonFactory;
import org.eclipse.ditto.json.JsonFieldDefinition;
import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.json.JsonObjectBuilder;
import org.eclipse.ditto.json.JsonValue;

/**
Expand Down Expand Up @@ -157,6 +159,8 @@ interface Builder<B extends Builder<B, S>, S extends SingleDataSchema> {

B setDefault(@Nullable JsonValue defaultValue);

B enhanceObjectBuilder(Consumer<JsonObjectBuilder> builderConsumer);

S build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ private static CompletableFuture<Void> enforceFeaturePropertyOnlyDefinedProperti
)
.toList());
final FeatureProperties featureProperties = FeatureProperties.newBuilder()
.setAll(propertyValue.asObject())
.setAll(propertyValue.isObject() ? propertyValue.asObject() : JsonObject.empty())
.build();
return ensureOnlyDefinedProperties(featureThingModel,
propertiesInCategory,
Expand Down Expand Up @@ -305,6 +305,16 @@ private static CompletableFuture<Void> enforceFeaturePropertyValidateProperties(
) {
if (isCategoryUpdate) {
final String dittoCategory = propertyPath.getRoot().orElseThrow().toString();
if (!propertyValue.isObject()) {
final WotThingModelPayloadValidationException.Builder exceptionBuilder =
WotThingModelPayloadValidationException
.newBuilder("Could not update Feature property category " +
"<" + dittoCategory + "> as its value was not a JSON object");
return CompletableFuture.failedFuture(exceptionBuilder
.dittoHeaders(context.dittoHeaders())
.build());
}

final List<Property> sameCategoryProperties = tdProperties.values().stream()
.filter(property ->
// gather all properties from the same category
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
final class InternalValidation {

private static final JsonSchemaTools JSON_SCHEMA_TOOLS = new JsonSchemaTools();
private static final String PROPERTIES_PATH_PREFIX = "/properties/";

private InternalValidation() {
throw new AssertionError();
Expand Down Expand Up @@ -286,11 +287,11 @@ static Map<String, Property> extractRequiredTmProperties(final Properties tdProp
final Map<String, Property> allRequiredProperties = new LinkedHashMap<>(tdProperties);
tmOptionalElements.stream()
.map(TmOptionalElement::toString)
.filter(el -> el.startsWith("/properties/"))
.map(el -> el.replace("/properties/", ""))
.filter(el -> el.startsWith(PROPERTIES_PATH_PREFIX))
.map(el -> el.replace(PROPERTIES_PATH_PREFIX, ""))
.forEach(allRequiredProperties::remove);
return allRequiredProperties;
}).orElseGet(LinkedHashMap::new);
}).orElse(tdProperties);
}

static boolean isTmPropertyRequired(final Property property,
Expand All @@ -299,8 +300,8 @@ static boolean isTmPropertyRequired(final Property property,
return thingModel.getTmOptional()
.map(tmOptionalElements -> tmOptionalElements.stream()
.map(TmOptionalElement::toString)
.filter(el -> el.startsWith("/properties/"))
.map(el -> el.replace("/properties/", ""))
.filter(el -> el.startsWith(PROPERTIES_PATH_PREFIX))
.map(el -> el.replace(PROPERTIES_PATH_PREFIX, ""))
.noneMatch(el -> property.getPropertyName().equals(el))
).orElse(false);
}
Expand Down Expand Up @@ -495,6 +496,7 @@ private static Optional<PropertyWithCategory> findPropertyBasedOnPath(final Thin
if (handleDittoCategory) {
return dittoCategories.stream()
.filter(category -> propertyPath.getRoot().orElseThrow().toString().equals(category))
.filter(category -> propertyPath.getLevelCount() > 1)
.map(category ->
tdProperties.getProperty(propertyPath.get(1).orElseThrow().toString())
.filter(p -> determineDittoCategory(thingModel, p)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public interface FeatureValidationConfig {
*/
enum ConfigValue implements KnownConfigValue {

ENFORCE_FEATURE_DESCRIPTION_MODIFICATION("enforce-feature-description-modification", false),
ENFORCE_FEATURE_DESCRIPTION_MODIFICATION("enforce-feature-description-modification", true),

FORBID_FEATURE_DESCRIPTION_DELETION("forbid-feature-description-deletion", true),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public interface ThingValidationConfig {
*/
enum ConfigValue implements KnownConfigValue {

ENFORCE_THING_DESCRIPTION_MODIFICATION("enforce-thing-description-modification", false),
ENFORCE_THING_DESCRIPTION_MODIFICATION("enforce-thing-description-modification", true),

FORBID_THING_DESCRIPTION_DELETION("forbid-thing-description-deletion", true),

Expand Down
Loading

0 comments on commit 9c2ed96

Please sign in to comment.