Skip to content

Commit

Permalink
added changes to address latest working draft of WoT TD/TM 1.1
Browse files Browse the repository at this point in the history
* addition of "synchronous" for Actions
* addition of "hreflang" for Links
* addition of "AdditionalSecurityScheme"
* making all SecurityScheme capable of receiving "additionalProperties"

Signed-off-by: Thomas Jaeckle <thomas.jaeckle@bosch.io>
  • Loading branch information
thjaeckle committed Jul 18, 2022
1 parent 86c5b1a commit 7fe9470
Show file tree
Hide file tree
Showing 44 changed files with 1,111 additions and 173 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ private void generateRootForms(final ThingModel thingModel,
.setAdditionalResponses(provideAdditionalResponses())
.build()
))
.collect(Collectors.toList())
.toList()
);
} else {
tdBuilder.setForms(List.of(
Expand Down Expand Up @@ -546,7 +546,7 @@ private void generatePropertiesForms(final ThingModel thingModel,
.setAdditionalResponses(provideAdditionalResponses())
.build()
)
.collect(Collectors.toList())
.toList()
))
.build()
)
Expand Down Expand Up @@ -596,7 +596,7 @@ private void generatePropertiesForms(final ThingModel thingModel,
}
);
}))
.map(propertyStream -> propertyStream.collect(Collectors.toList()))
.map(Stream::toList)
.map(Properties::from)
.ifPresent(tdBuilder::setProperties);
}
Expand Down Expand Up @@ -712,25 +712,27 @@ private void generateActionsForms(final ThingModel thingModel,
DittoHeaderDefinition.RESPONSE_REQUIRED.getKey());
return action.getForms()
.map(actionFormElements -> action.toBuilder()
.setSynchronous(true)
.setForms(ActionForms.of(actionFormElements.stream()
.map(afe -> afe.toBuilder()
.setHref(IRI.of(actionHref))
.setAdditionalResponses(provideAdditionalResponses())
.build()
)
.collect(Collectors.toList())
.toList()
))
.build()
)
.orElseGet(() -> action.toBuilder()
.setSynchronous(true)
.setForms(ActionForms.of(List.of(
buildActionFormElement(SingleActionFormElementOp.INVOKEACTION,
actionHref + uriVariablesParams)
)))
.build()
);
}))
.map(actionStream -> actionStream.collect(Collectors.toList()))
.map(Stream::toList)
.map(actionList -> Actions.fromJson(actionList.stream()
.map(a -> JsonField.newInstance(a.getActionName(), a.toJson()))
.collect(JsonCollectors.fieldsToObject()))
Expand Down Expand Up @@ -776,7 +778,7 @@ private void generateEventsForms(final ThingModel thingModel, final ThingDescrip
.setAdditionalResponses(provideAdditionalResponses())
.build()
)
.collect(Collectors.toList())
.toList()
))
.build()
)
Expand All @@ -787,7 +789,7 @@ private void generateEventsForms(final ThingModel thingModel, final ThingDescrip
.build()
);
}))
.map(eventStream -> eventStream.collect(Collectors.toList()))
.map(Stream::toList)
.map(Events::from)
.ifPresent(tdBuilder::setEvents);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

import org.eclipse.ditto.base.model.headers.DittoHeaders;
import org.eclipse.ditto.json.JsonCollectors;
Expand Down Expand Up @@ -58,12 +57,12 @@ public ThingModel resolveThingModelExtensions(final ThingModel thingModel, final
.filter(baseLink -> baseLink.getRel().filter(TM_EXTENDS::equals).isPresent())
.map(extendsLink -> thingModelFetcher.fetchThingModel(extendsLink.getHref(), dittoHeaders))
.map(CompletionStage::toCompletableFuture)
.collect(Collectors.toList());
.toList();
final CompletableFuture<Void> allModelFuture =
CompletableFuture.allOf(fetchedModelFutures.toArray(new CompletableFuture[0]));
return allModelFuture.thenApplyAsync(aVoid -> fetchedModelFutures.stream()
.map(CompletableFuture::join) // joining does not block anything here as "allOf" already guaranteed that all futures are ready
.collect(Collectors.toList()), executor)
.toList(), executor)
.join();
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

Expand Down Expand Up @@ -155,14 +154,14 @@ private Optional<Features> createFeaturesFromSubmodels(final ThingModel thingMod
dittoHeaders), executor)
.toCompletableFuture()
)
.collect(Collectors.toList());
.toList();

final List<Feature> features = CompletableFuture.allOf(futureList.toArray(CompletableFuture<?>[]::new))
.thenApply(v -> futureList.stream()
.map(CompletableFuture::join)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList())
.toList()
).join();

if (features.isEmpty()) {
Expand Down Expand Up @@ -221,14 +220,13 @@ private static Optional<JsonValue> determineInitialPropertyValue(final SingleDat
.or(dataSchema::getDefault)
.or(() -> {
final SingleDataSchema actualSchema;
if (dataSchema instanceof Property) {
actualSchema = resolveActualPropertySchema((Property) dataSchema);
if (dataSchema instanceof Property property) {
actualSchema = resolveActualPropertySchema(property);
} else {
actualSchema = dataSchema;
}

if (actualSchema instanceof ObjectSchema) {
final ObjectSchema objectSchema = (ObjectSchema) actualSchema;
if (actualSchema instanceof ObjectSchema objectSchema) {
final List<String> required = objectSchema.getRequired();
if (!required.isEmpty()) {
final JsonObjectBuilder objectBuilder = JsonObject.newBuilder();
Expand All @@ -240,14 +238,13 @@ private static Optional<JsonValue> determineInitialPropertyValue(final SingleDat
return Optional.of(objectBuilder.build());
}
return Optional.of(JsonObject.empty());
} else if (actualSchema instanceof ArraySchema) {
final ArraySchema arraySchema = (ArraySchema) actualSchema;
} else if (actualSchema instanceof ArraySchema arraySchema) {
final JsonArrayBuilder arrayBuilder = JsonArray.newBuilder();
arraySchema.getItems()
.ifPresent(itemsSchema -> {
if (itemsSchema instanceof SingleDataSchema) {
if (itemsSchema instanceof SingleDataSchema singleDataSchema) {
final int neutralElementCount = arraySchema.getMinItems().orElse(1);
provideNeutralElementForDataSchema((SingleDataSchema) itemsSchema)
provideNeutralElementForDataSchema(singleDataSchema)
.ifPresent(ne -> IntStream.range(0, neutralElementCount)
.forEach(i -> arrayBuilder.add(ne))
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ public Optional<IRI> getAnchor() {
.map(IRI::of);
}

@Override
public Optional<Hreflang> getHreflang() {
return Optional.ofNullable(
TdHelpers.getValueIgnoringWrongType(wrappedObject, BaseLinkJsonFields.HREFLANG_MULTIPLE)
.map(MultipleHreflang::fromJson)
.map(Hreflang.class::cast)
.orElseGet(() -> wrappedObject.getValue(BaseLinkJsonFields.HREFLANG)
.map(SingleHreflang::of)
.orElse(null)
)
);
}

@Override
public JsonObject toJson() {
return wrappedObject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,19 @@ public B setAnchor(@Nullable final IRI anchor) {
return myself;
}

@Override
public B setHreflang(@Nullable final Hreflang hreflang) {
if (hreflang != null) {
if (hreflang instanceof MultipleHreflang) {
putValue(BaseLink.BaseLinkJsonFields.HREFLANG_MULTIPLE, ((MultipleHreflang) hreflang).toJson());
} else if (hreflang instanceof SingleHreflang) {
putValue(BaseLink.BaseLinkJsonFields.HREFLANG, hreflang.toString());
} else {
throw new IllegalArgumentException("Unsupported hreflang: " + hreflang.getClass().getSimpleName());
}
} else {
remove(BaseLink.BaseLinkJsonFields.HREFLANG);
}
return myself;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@
/**
* Abstract implementation of {@link SecurityScheme}.
*/
abstract class AbstractSecurityScheme implements SecurityScheme {
abstract class AbstractSecurityScheme extends AbstractTypedJsonObject<SecurityScheme> implements SecurityScheme {

private final String securitySchemeName;
protected final JsonObject wrappedObject;

AbstractSecurityScheme(final String securitySchemeName, final JsonObject wrappedObject) {
super(wrappedObject);
this.securitySchemeName = securitySchemeName;
this.wrappedObject = wrappedObject;
}

@Override
Expand Down Expand Up @@ -70,9 +69,7 @@ public Optional<IRI> getProxy() {
@Override
public SecuritySchemeScheme getScheme() {
final String schemeStr = wrappedObject.getValueOrThrow(SecuritySchemeJsonFields.SCHEME);
return SecuritySchemeScheme.forName(schemeStr)
.orElseThrow(() -> new IllegalArgumentException("Unknown scheme: " + schemeStr));

return SecuritySchemeScheme.of(schemeStr);
}

@Override
Expand All @@ -93,6 +90,7 @@ public boolean equals(@Nullable final Object o) {
Objects.equals(wrappedObject, that.wrappedObject);
}

@Override
protected boolean canEqual(@Nullable final Object other) {
return other instanceof AbstractSecurityScheme;
}
Expand All @@ -104,8 +102,8 @@ public int hashCode() {

@Override
public String toString() {
return "securitySchemeName=" + securitySchemeName +
", wrappedObject=" + wrappedObject;
return super.toString() +
", securitySchemeName=" + securitySchemeName;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,24 @@

import static org.eclipse.ditto.base.model.common.ConditionChecker.checkNotNull;

import java.util.Optional;

import javax.annotation.Nullable;

import org.eclipse.ditto.json.JsonFieldDefinition;
import org.eclipse.ditto.json.JsonKey;
import org.eclipse.ditto.json.JsonObjectBuilder;

/**
* Abstract implementation of {@link org.eclipse.ditto.wot.model.SecurityScheme.Builder}.
*/
abstract class AbstractSecuritySchemeBuilder<B extends SecurityScheme.Builder<B, S>, S extends SecurityScheme>
extends AbstractTypedJsonObjectBuilder<B, S>
implements SecurityScheme.Builder<B, S> {

protected final String securitySchemeName;
protected final B myself;
protected final JsonObjectBuilder wrappedObjectBuilder;

@SuppressWarnings("unchecked")
protected AbstractSecuritySchemeBuilder(final String securitySchemeName,
final JsonObjectBuilder wrappedObjectBuilder,
final Class<?> selfType) {
super(wrappedObjectBuilder, selfType);
this.securitySchemeName = checkNotNull(securitySchemeName, "securitySchemeName");
myself = (B) selfType.cast(this);
this.wrappedObjectBuilder = checkNotNull(wrappedObjectBuilder, "wrappedObjectBuilder");
setScheme(getSecuritySchemeScheme());
}

Expand All @@ -63,7 +56,7 @@ public B setAtType(@Nullable final AtType atType) {
@Override
public B setScheme(@Nullable final SecuritySchemeScheme scheme) {
if (scheme != null) {
putValue(SecurityScheme.SecuritySchemeJsonFields.SCHEME, scheme.getName());
putValue(SecurityScheme.SecuritySchemeJsonFields.SCHEME, scheme.toString());
} else {
remove(SecurityScheme.SecuritySchemeJsonFields.SCHEME);
}
Expand Down Expand Up @@ -100,21 +93,4 @@ public B setProxy(@Nullable final IRI proxy) {
return myself;
}

protected <J> void putValue(final JsonFieldDefinition<J> definition, @Nullable final J value) {
final Optional<JsonKey> keyOpt = definition.getPointer().getRoot();
if (keyOpt.isPresent()) {
final JsonKey key = keyOpt.get();
if (null != value) {
checkNotNull(value, definition.getPointer().toString());
wrappedObjectBuilder.remove(key);
wrappedObjectBuilder.set(definition, value);
} else {
wrappedObjectBuilder.remove(key);
}
}
}

protected void remove(final JsonFieldDefinition<?> fieldDefinition) {
wrappedObjectBuilder.remove(fieldDefinition);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ default Action.Builder toBuilder() {

boolean isIdempotent();

Optional<Boolean> isSynchronous();

interface Builder extends Interaction.Builder<Builder, Action, ActionFormElement, ActionForms> {

static Builder newBuilder(final CharSequence actionName) {
Expand All @@ -76,6 +78,8 @@ static Builder newBuilder(final CharSequence actionName, final JsonObject jsonOb
Builder setSafe(@Nullable Boolean safe);

Builder setIdempotent(@Nullable Boolean idempotent);

Builder setSynchronous(@Nullable Boolean synchronous);
}

/**
Expand All @@ -96,6 +100,9 @@ final class JsonFields {
public static final JsonFieldDefinition<Boolean> IDEMPOTENT = JsonFactory.newBooleanFieldDefinition(
"idempotent");

public static final JsonFieldDefinition<Boolean> SYNCHRONOUS = JsonFactory.newBooleanFieldDefinition(
"synchronous");

private JsonFields() {
throw new AssertionError();
}
Expand Down
Loading

0 comments on commit 7fe9470

Please sign in to comment.