diff --git a/bom/pom.xml b/bom/pom.xml index c067ea1824..7cc070afdd 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -34,7 +34,7 @@ 0.9.5 2.17.2 - 1.5.1 + 1.5.4 1.4.3 0.6.1 3.7.1 diff --git a/wot/api/src/main/java/org/eclipse/ditto/wot/api/generator/DefaultWotThingModelExtensionResolver.java b/wot/api/src/main/java/org/eclipse/ditto/wot/api/generator/DefaultWotThingModelExtensionResolver.java index 231c453e3c..58531a6c54 100644 --- a/wot/api/src/main/java/org/eclipse/ditto/wot/api/generator/DefaultWotThingModelExtensionResolver.java +++ b/wot/api/src/main/java/org/eclipse/ditto/wot/api/generator/DefaultWotThingModelExtensionResolver.java @@ -15,10 +15,12 @@ import static org.eclipse.ditto.base.model.common.ConditionChecker.checkNotNull; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.Executor; import java.util.function.BiFunction; +import java.util.stream.Stream; import org.eclipse.ditto.base.model.headers.DittoHeaders; import org.eclipse.ditto.json.JsonCollectors; @@ -28,7 +30,9 @@ import org.eclipse.ditto.json.JsonPointer; import org.eclipse.ditto.json.JsonValue; import org.eclipse.ditto.wot.api.provider.WotThingModelFetcher; +import org.eclipse.ditto.wot.model.BaseLink; import org.eclipse.ditto.wot.model.IRI; +import org.eclipse.ditto.wot.model.Links; import org.eclipse.ditto.wot.model.ThingModel; import org.eclipse.ditto.wot.model.WotThingModelRefInvalidException; @@ -73,7 +77,7 @@ public CompletionStage resolveThingModelExtensions(final ThingModel return CompletableFuture.completedFuture(thingModel); } else { CompletionStage currentStage = - resolveThingModelExtensions(extendedModels.get(0), dittoHeaders) // recurse! + resolveThingModelExtensions(extendedModels.getFirst(), dittoHeaders) // recurse! .thenApply(extendedModel -> mergeThingModelIntoBuilder().apply(tmBuilder, extendedModel) ); @@ -91,13 +95,52 @@ public CompletionStage resolveThingModelExtensions(final ThingModel private BiFunction mergeThingModelIntoBuilder() { return (builder, model) -> { - final JsonObject mergedTmObject = JsonFactory.mergeJsonValues(builder.build(), model).asObject(); + final ThingModel newModel = builder.build(); + final JsonObject mergedTmObject = JsonFactory.mergeJsonValues(newModel, model).asObject(); builder.removeAll(); builder.setAll(mergedTmObject); + mergeLinks(model.getLinks(), newModel.getLinks()).ifPresent(builder::setLinks); return builder; }; } + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static Optional mergeLinks(final Optional oldOptionalLinks, + final Optional newOptionalLinks) + { + return oldOptionalLinks + .map(oldLinks -> filterOutTmExtendsLinkFromOldLinks(newOptionalLinks, oldLinks)) + .map(adjustedOldLinks -> + newOptionalLinks.stream() + .flatMap(newLinks -> Stream.concat(adjustedOldLinks, newLinks.stream())) + ) + .map(Stream::toList) + .map(Links::of); + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static Stream> filterOutTmExtendsLinkFromOldLinks(final Optional newOptionalLinks, + final Links oldLinks) + { + return oldLinks.stream() + .filter(oldLink -> { + if (isTmExtendsLink(oldLink)) { + return newOptionalLinks.filter(DefaultWotThingModelExtensionResolver::containsTmExtendsLink) + .isEmpty(); + } else { + return true; + } + }); + } + + private static boolean containsTmExtendsLink(final Links links) { + return links.stream().anyMatch(DefaultWotThingModelExtensionResolver::isTmExtendsLink); + } + + private static boolean isTmExtendsLink(final BaseLink link) { + return link.getRel().isPresent() && link.getRel().filter(TM_EXTENDS::equals).isPresent(); + } + @Override public CompletionStage resolveThingModelRefs(final ThingModel thingModel, final DittoHeaders dittoHeaders) { return potentiallyResolveRefs(thingModel, dittoHeaders).thenApply(ThingModel::fromJson);