Skip to content

Commit

Permalink
adjusted method name of exception builder
Browse files Browse the repository at this point in the history
* restructured IfEqualPreconditionHeader logic to be more readable
* fixed that an inline policy in a "MergeThing" command would always cause inequality

Signed-off-by: Thomas Jäckle <thomas.jaeckle@beyonnex.io>
(cherry picked from commit 73fb51c)
  • Loading branch information
thjaeckle committed Jul 21, 2023
1 parent e7f0533 commit 1099f53
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 44 deletions.
Expand Up @@ -60,7 +60,7 @@ public DittoRuntimeExceptionBuilder<?> createPreconditionNotModifiedExceptionBui
}

@Override
public DittoRuntimeExceptionBuilder<?> createPreconditionNotModifiedForEqualityExceptionBuilder() {
public DittoRuntimeExceptionBuilder<?> createPreconditionFailedForEqualityExceptionBuilder() {
return ConnectionPreconditionFailedException.newBuilder()
.message("The previous value was equal to the new value and the 'if-equal' header was set to 'skip'.")
.description("Your changes were not applied, which is probably the expected outcome.");
Expand Down
Expand Up @@ -63,14 +63,14 @@ DittoRuntimeExceptionBuilder<?> createPreconditionNotModifiedExceptionBuilder(St
String matched);

/**
* Returns a builder for a {@link DittoRuntimeException} in case status {@code 304 (Not Modified)} should be
* returned for when an updated value was equal to its previous value and the {@code if-equal} condition was
* Returns a builder for a {@link DittoRuntimeException} in case status {@code 412 (Precondition failed)} should
* be returned for when an updated value was equal to its previous value and the {@code if-equal} condition was
* set to "skip".
*
* @return the builder.
* @since 3.3.0
*/
DittoRuntimeExceptionBuilder<?> createPreconditionNotModifiedForEqualityExceptionBuilder();
DittoRuntimeExceptionBuilder<?> createPreconditionFailedForEqualityExceptionBuilder();
}

private final ValidationSettings validationSettings;
Expand Down
Expand Up @@ -111,43 +111,10 @@ public boolean meetsConditionFor(@Nullable final Entity<?> entity) {
if (ifEqual == IfEqual.SKIP) {
if (command.getCategory() == Command.Category.MODIFY &&
command instanceof WithOptionalEntity withOptionalEntity) {
return withOptionalEntity.getEntity()
.map(newValue -> {
final Predicate<JsonField> nonHiddenAndNamespace =
FieldType.notHidden()
.or(jsonField -> jsonField.getKey().equals(JsonKey.of("_namespace")));
final Optional<JsonValue> previousValue = entity.toJson(JsonSchemaVersion.LATEST, nonHiddenAndNamespace)
.getValue(command.getResourcePath());
return previousValue.filter(jsonValue -> jsonValue.equals(newValue))
.isPresent();
})
.orElse(false);
return meetsConditionForModifyCommand(entity, withOptionalEntity);
} else if (command.getCategory() == Command.Category.MERGE &&
command instanceof WithOptionalEntity withOptionalEntity) {
return withOptionalEntity.getEntity()
.map(newValue -> {
final Optional<JsonValue> previousValue = entity.toJson()
.getValue(command.getResourcePath());
if (newValue.isObject()) {
return previousValue.filter(JsonValue::isObject)
.map(JsonValue::asObject)
.filter(previousObject -> {
final JsonObject patchedAndSortedNewObject =
JsonFactory.mergeJsonValues(newValue.asObject(), previousObject)
.asObject().stream()
.sorted(Comparator.comparing(j -> j.getKey().toString()))
.collect(JsonCollectors.fieldsToObject());
final JsonObject sortedOldObject = previousObject.stream()
.sorted(Comparator.comparing(j -> j.getKey().toString()))
.collect(JsonCollectors.fieldsToObject());
return patchedAndSortedNewObject.equals(sortedOldObject);
}).isPresent();
} else {
return previousValue.filter(jsonValue -> jsonValue.equals(newValue))
.isPresent();
}
})
.orElse(false);
return meetsConditionForMergeCommand(entity, withOptionalEntity);
} else {
// other commands to "MODIFY" and "MERGE" do never match the "if-equal" precondition header
return false;
Expand All @@ -158,6 +125,60 @@ public boolean meetsConditionFor(@Nullable final Entity<?> entity) {
}
}

private Boolean meetsConditionForModifyCommand(final Entity<?> entity,
final WithOptionalEntity withOptionalEntity) {

return withOptionalEntity.getEntity()
.map(newValue -> {
final Predicate<JsonField> nonHiddenAndNamespace =
FieldType.notHidden()
.or(jsonField -> jsonField.getKey().equals(JsonKey.of("_namespace")));
final Optional<JsonValue> previousValue =
entity.toJson(JsonSchemaVersion.LATEST, nonHiddenAndNamespace)
.getValue(command.getResourcePath());
return previousValue.filter(jsonValue -> jsonValue.equals(newValue))
.isPresent();
})
.orElse(false);
}

private Boolean meetsConditionForMergeCommand(final Entity<?> entity, final WithOptionalEntity withOptionalEntity) {

return withOptionalEntity.getEntity()
.map(newValue -> {
final Optional<JsonValue> previousValue = entity.toJson().getValue(command.getResourcePath());
if (newValue.isObject()) {
final JsonObject newObject;
if (command.getResourcePath().isEmpty()) {
// filter "special fields" for e.g. on thing level the inline "_policy":
newObject = newValue.asObject()
.stream()
.filter(jsonField -> !jsonField.getKeyName().startsWith("_"))
.collect(JsonCollectors.fieldsToObject());
} else {
newObject = newValue.asObject();
}
return previousValue.filter(JsonValue::isObject)
.map(JsonValue::asObject)
.filter(previousObject -> {
final JsonObject patchedAndSortedNewObject =
JsonFactory.mergeJsonValues(newObject, previousObject)
.asObject().stream()
.sorted(Comparator.comparing(j -> j.getKey().toString()))
.collect(JsonCollectors.fieldsToObject());
final JsonObject sortedOldObject = previousObject.stream()
.sorted(Comparator.comparing(j -> j.getKey().toString()))
.collect(JsonCollectors.fieldsToObject());
return patchedAndSortedNewObject.equals(sortedOldObject);
}).isPresent();
} else {
return previousValue.filter(jsonValue -> jsonValue.equals(newValue))
.isPresent();
}
})
.orElse(false);
}

/**
* Handles the {@link #command} field of this class by invoking the passed {@code isCompletelyEqualSupplier} to
* check whether the affected entity would be completely equal after applying the {@link #command}.
Expand All @@ -176,7 +197,7 @@ C handleCommand(final BooleanSupplier isCompletelyEqualSupplier) {
final Command.Category category = command.getCategory();
if (completelyEqual &&
(category == Command.Category.MODIFY || category == Command.Category.MERGE)) {
potentiallyAdjustedCommand = respondWithNotModified();
potentiallyAdjustedCommand = respondWithPreconditionFailed();
} else {
potentiallyAdjustedCommand = command;
}
Expand All @@ -186,9 +207,9 @@ C handleCommand(final BooleanSupplier isCompletelyEqualSupplier) {
return potentiallyAdjustedCommand;
}

private C respondWithNotModified() {
private C respondWithPreconditionFailed() {
throw validationSettings
.createPreconditionNotModifiedForEqualityExceptionBuilder()
.createPreconditionFailedForEqualityExceptionBuilder()
.dittoHeaders(command.getDittoHeaders())
.build();
}
Expand Down
Expand Up @@ -58,7 +58,7 @@ public DittoRuntimeExceptionBuilder<?> createPreconditionNotModifiedExceptionBui
}

@Override
public DittoRuntimeExceptionBuilder<?> createPreconditionNotModifiedForEqualityExceptionBuilder() {
public DittoRuntimeExceptionBuilder<?> createPreconditionFailedForEqualityExceptionBuilder() {
return PolicyPreconditionFailedException.newBuilder()
.message("The previous value was equal to the new value and the 'if-equal' header was set to 'skip'.")
.description("Your changes were not applied, which is probably the expected outcome.");
Expand Down
Expand Up @@ -70,7 +70,7 @@ public DittoRuntimeExceptionBuilder<?> createPreconditionNotModifiedExceptionBui
}

@Override
public DittoRuntimeExceptionBuilder<?> createPreconditionNotModifiedForEqualityExceptionBuilder() {
public DittoRuntimeExceptionBuilder<?> createPreconditionFailedForEqualityExceptionBuilder() {
return ThingPreconditionFailedException.newBuilder()
.message("The previous value was equal to the new value and the 'if-equal' header was set to 'skip'.")
.description("Your changes were not applied, which is probably the expected outcome.");
Expand Down

0 comments on commit 1099f53

Please sign in to comment.