Skip to content

Commit

Permalink
Issue #106: Added getter for feature property pointer and value and r…
Browse files Browse the repository at this point in the history
…emoved some redundancy.

Signed-off-by: Juergen Fickel <juergen.fickel@bosch.io>
  • Loading branch information
Juergen Fickel committed Dec 9, 2021
1 parent 5ff1414 commit 1299b14
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ final class MappingContext {

private static final JsonKey ATTRIBUTE_PATH_PREFIX = JsonKey.of("attributes");
private static final JsonKey FEATURE_PATH_PREFIX = JsonKey.of("features");
private static final int FEATURE_PROPERTY_PATH_LEVEL = 3;

private final Adaptable adaptable;

Expand Down Expand Up @@ -89,8 +90,7 @@ ThingId getThingId() {

Optional<Thing> getThing() {
final Optional<Thing> result;
final Payload payload = adaptable.getPayload();
final Optional<JsonValue> payloadValueOptional = payload.getValue();
final Optional<JsonValue> payloadValueOptional = getPayloadValue();
if (payloadValueOptional.isPresent()) {
final JsonValue jsonValue = payloadValueOptional.get();
if (jsonValue.isObject()) {
Expand All @@ -108,6 +108,11 @@ Optional<Thing> getThing() {
return result;
}

private Optional<JsonValue> getPayloadValue() {
final Payload payload = adaptable.getPayload();
return payload.getValue();
}

Thing getThingOrThrow() {
return getThing().orElseThrow(() ->
new IllegalAdaptableException(
Expand All @@ -123,19 +128,21 @@ JsonPointer getAttributePointerOrThrow() {
final MessagePath messagePath = payload.getPath();
if (!messagePath.getRoot().filter(ATTRIBUTE_PATH_PREFIX::equals).isPresent()) {
throw new IllegalAdaptableException(
MessageFormat.format("Message path of payload does not start with <{0}>.",
ATTRIBUTE_PATH_PREFIX.asPointer()),
MessageFormat.format("Please ensure that the payload of the Adaptable starts with <{0}>.",
getMessagePathInvalidPrefixMessage(ATTRIBUTE_PATH_PREFIX.asPointer()),
MessageFormat.format("Please ensure that the message path of the Adaptable starts with <{0}>.",
ATTRIBUTE_PATH_PREFIX.asPointer()),
adaptable.getDittoHeaders()
);
}
return messagePath.nextLevel();
}

private static String getMessagePathInvalidPrefixMessage(final Object expectedPrefix) {
return MessageFormat.format("Message path of payload does not start with <{0}>.", expectedPrefix);
}

Optional<JsonValue> getAttributeValue() {
final Payload payload = adaptable.getPayload();
return payload.getValue();
return getPayloadValue();
}

JsonValue getAttributeValueOrThrow() {
Expand All @@ -147,8 +154,7 @@ JsonValue getAttributeValueOrThrow() {

Optional<Attributes> getAttributes() {
final Optional<Attributes> result;
final Payload payload = adaptable.getPayload();
final Optional<JsonValue> payloadValueOptional = payload.getValue();
final Optional<JsonValue> payloadValueOptional = getPayloadValue();
if (payloadValueOptional.isPresent()) {
final JsonValue jsonValue = payloadValueOptional.get();
if (jsonValue.isObject()) {
Expand All @@ -169,33 +175,39 @@ Optional<Attributes> getAttributes() {

Optional<Features> getFeatures() {
final Optional<Features> result;
final Payload payload = adaptable.getPayload();
final Optional<JsonValue> payloadValueOptional = payload.getValue();
final Optional<JsonValue> payloadValueOptional = getPayloadValue();
if (payloadValueOptional.isPresent()) {
final JsonValue jsonValue = payloadValueOptional.get();
if (jsonValue.isObject()) {
result = Optional.of(ThingsModelFactory.newFeatures(jsonValue.asObject()));
} else {
throw new IllegalAdaptableException(
MessageFormat.format("Payload value is not a {0} as JSON object but <{1}>.",
Features.class.getSimpleName(),
jsonValue),
adaptable.getDittoHeaders()
);
throw newPayloadValueNotJsonObjectException(Features.class, jsonValue);
}
} else {
result = Optional.empty();
}
return result;
}

private IllegalAdaptableException newPayloadValueNotJsonObjectException(final Class<?> targetType,
final JsonValue jsonValue) {

return new IllegalAdaptableException(
MessageFormat.format("Payload value is not a {0} as JSON object but <{1}>.",
targetType.getSimpleName(),
jsonValue),
MessageFormat.format("Please ensure that the payload value is a JSON object representation of <{0}>.",
targetType),
adaptable.getDittoHeaders()
);
}

String getFeatureIdOrThrow() {
final Payload payload = adaptable.getPayload();
final MessagePath messagePath = payload.getPath();
if (!messagePath.getRoot().filter(FEATURE_PATH_PREFIX::equals).isPresent()) {
throw new IllegalAdaptableException(
MessageFormat.format("Message path of payload does not start with <{0}>.",
FEATURE_PATH_PREFIX.asPointer()),
getMessagePathInvalidPrefixMessage(FEATURE_PATH_PREFIX.asPointer()),
MessageFormat.format("Please ensure that the message path of the payload starts with <{0}>.",
FEATURE_PATH_PREFIX.asPointer()),
adaptable.getDittoHeaders()
Expand All @@ -215,21 +227,15 @@ String getFeatureIdOrThrow() {

Feature getFeatureOrThrow() {
final Feature result;
final Payload payload = adaptable.getPayload();
final Optional<JsonValue> payloadValueOptional = payload.getValue();
final Optional<JsonValue> payloadValueOptional = getPayloadValue();
if (payloadValueOptional.isPresent()) {
final JsonValue jsonValue = payloadValueOptional.get();
if (jsonValue.isObject()) {
result = ThingsModelFactory.newFeatureBuilder(jsonValue.asObject())
.useId(getFeatureIdOrThrow())
.build();
} else {
throw new IllegalAdaptableException(
MessageFormat.format("Payload value is not a {0} as JSON object but <{1}>.",
Feature.class.getSimpleName(),
jsonValue),
adaptable.getDittoHeaders()
);
throw newPayloadValueNotJsonObjectException(Feature.class, jsonValue);
}
} else {
throw new IllegalAdaptableException(
Expand All @@ -244,8 +250,7 @@ Feature getFeatureOrThrow() {

Optional<ThingDefinition> getThingDefinition() {
final Optional<ThingDefinition> result;
final Payload payload = adaptable.getPayload();
final Optional<JsonValue> payloadValueOptional = payload.getValue();
final Optional<JsonValue> payloadValueOptional = getPayloadValue();
if (payloadValueOptional.isPresent()) {
final JsonValue jsonValue = payloadValueOptional.get();
if (jsonValue.isString()) {
Expand All @@ -266,8 +271,7 @@ Optional<ThingDefinition> getThingDefinition() {

Optional<FeatureDefinition> getFeatureDefinition() {
final Optional<FeatureDefinition> result;
final Payload payload = adaptable.getPayload();
final Optional<JsonValue> payloadValueOptional = payload.getValue();
final Optional<JsonValue> payloadValueOptional = getPayloadValue();
if (payloadValueOptional.isPresent()) {
final JsonValue jsonValue = payloadValueOptional.get();
if (jsonValue.isArray()) {
Expand All @@ -288,30 +292,68 @@ Optional<FeatureDefinition> getFeatureDefinition() {

Optional<FeatureProperties> getFeatureProperties() {
final Optional<FeatureProperties> result;
final Payload payload = adaptable.getPayload();
final Optional<JsonValue> payloadValueOptional = payload.getValue();
final Optional<JsonValue> payloadValueOptional = getPayloadValue();
if (payloadValueOptional.isPresent()) {
final JsonValue jsonValue = payloadValueOptional.get();
if (jsonValue.isObject()) {
result = Optional.of(ThingsModelFactory.newFeatureProperties(jsonValue.asObject()));
} else {
throw new IllegalAdaptableException(
MessageFormat.format("Payload value is not a {0} as JSON object but <{1}>.",
FeatureProperties.class.getSimpleName(),
jsonValue),
adaptable.getDittoHeaders()
);
throw newPayloadValueNotJsonObjectException(FeatureProperties.class, jsonValue);
}
} else {
result = Optional.empty();
}
return result;
}

@SuppressWarnings("java:S3655")
JsonPointer getFeaturePropertyPointerOrThrow() {
final Payload payload = adaptable.getPayload();
final MessagePath messagePath = payload.getPath();
if (!messagePath.getRoot().filter(FEATURE_PATH_PREFIX::equals).isPresent()) {
throw new IllegalAdaptableException(
getMessagePathInvalidPrefixMessage(FEATURE_PATH_PREFIX.asPointer()),
MessageFormat.format("Please ensure that the message path of the Adaptable starts with <{0}>.",
FEATURE_PATH_PREFIX.asPointer()),
adaptable.getDittoHeaders()
);
} else {
if (messagePath.getLevelCount() <= FEATURE_PROPERTY_PATH_LEVEL) {
throw new IllegalAdaptableException(
MessageFormat.format("Message path of payload has <{0,number}> levels which is less than" +
" the required <{1,number}> levels.",
messagePath.getLevelCount(),
FEATURE_PROPERTY_PATH_LEVEL + 1),
"Please ensure that the message path complies to the schema" +
" \"features/${FEATURE_ID}/properties/${PROPERTY_SUB_PATH_OR_PROPERTY_NAME}\".",
adaptable.getDittoHeaders()
);
}
final JsonKey propertiesKey = JsonKey.of("properties");
final boolean hasExpectedPropertiesSegment = messagePath.get(FEATURE_PROPERTY_PATH_LEVEL - 1)
.filter(propertiesKey::equals)
.isPresent();
if (!hasExpectedPropertiesSegment) {
throw new IllegalAdaptableException(
MessageFormat.format("Message path of payload is not <{0}> at level <{1,number}>.",
propertiesKey,
FEATURE_PROPERTY_PATH_LEVEL - 1),
"Please ensure that the message path complies to the schema" +
" \"features/${FEATURE_ID}/properties/${PROPERTY_SUB_PATH_OR_PROPERTY_NAME}\".",
adaptable.getDittoHeaders()
);
}
return messagePath.getSubPointer(FEATURE_PROPERTY_PATH_LEVEL).get();
}
}

Optional<JsonValue> getFeaturePropertyValue() {
return getPayloadValue();
}

Optional<PolicyId> getPolicyId() {
final Optional<PolicyId> result;
final Payload payload = adaptable.getPayload();
final Optional<JsonValue> payloadValueOptional = payload.getValue();
final Optional<JsonValue> payloadValueOptional = getPayloadValue();
if (payloadValueOptional.isPresent()) {
final JsonValue jsonValue = payloadValueOptional.get();
if (jsonValue.isString()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public void getHttpStatusOrThrowThrowsExceptionIfContainsNoHttpStatus() {
}

@Test
public void getAttributePointerOrThrowReturnsPointerIfItHasAppropriatePrefix() {
public void getAttributePointerOrThrowReturnsPointerIfMessagePathHasAppropriatePrefix() {
final JsonPointer path = JsonPointer.of("attributes/manufacturer");
final Payload payload = ProtocolFactory.newPayloadBuilder()
.withPath(path)
Expand All @@ -195,7 +195,7 @@ public void getAttributePointerOrThrowReturnsPointerIfItHasAppropriatePrefix() {
}

@Test
public void getAttributePointerOrThrowThrowsExceptionIfItHasAnInappropriatePrefix() {
public void getAttributePointerOrThrowThrowsExceptionIfMessagePathHasAnInappropriatePrefix() {
final JsonPointer path = JsonPointer.of("ratattributes/manufacturer");
final Payload payload = ProtocolFactory.newPayloadBuilder()
.withPath(path)
Expand Down Expand Up @@ -559,6 +559,87 @@ public void getFeaturePropertiesReturnsEmptyOptionalIfPayloadContainsNoValue() {
assertThat(underTest.getFeatureProperties()).isEmpty();
}

@Test
public void getFeaturePropertyPointerOrThrowReturnsPointerIfMessagePathHasAppropriatePrefix() {
final JsonPointer path = JsonPointer.of("features/HX711/properties/uint8_t HX711_DT[3]");
final Payload payload = ProtocolFactory.newPayloadBuilder()
.withPath(path)
.build();
Mockito.when(adaptable.getPayload()).thenReturn(payload);
final MappingContext underTest = MappingContext.of(adaptable);

final JsonPointer featurePropertyPointer = underTest.getFeaturePropertyPointerOrThrow();

assertThat((CharSequence) featurePropertyPointer).isEqualTo(path.getSubPointer(3).get());
}

@Test
public void getFeaturePropertyPointerOrThrowThrowsExceptionIfMessagePathHasAnInappropriatePrefix() {
final JsonPointer path = JsonPointer.of("rfeatures/HX711/properties/uint8_t HX711_DT[3]");
final Payload payload = ProtocolFactory.newPayloadBuilder()
.withPath(path)
.build();
Mockito.when(adaptable.getPayload()).thenReturn(payload);
final MappingContext underTest = MappingContext.of(adaptable);

assertThatExceptionOfType(IllegalAdaptableException.class)
.isThrownBy(underTest::getFeaturePropertyPointerOrThrow)
.withMessage("Message path of payload does not start with <%s>.", "/features")
.withNoCause();
}

@Test
public void getFeaturePropertyPointerOrThrowThrowsExceptionIfMessagePathHasUnexpectedLevelCount() {
final JsonPointer path = JsonPointer.of("features/HX711/uint8_t HX711_DT[3]");
final Payload payload = ProtocolFactory.newPayloadBuilder()
.withPath(path)
.build();
Mockito.when(adaptable.getPayload()).thenReturn(payload);
final MappingContext underTest = MappingContext.of(adaptable);

assertThatExceptionOfType(IllegalAdaptableException.class)
.isThrownBy(underTest::getFeaturePropertyPointerOrThrow)
.withMessage("Message path of payload has <%d> levels which is less than the required <4> levels.",
path.getLevelCount())
.withNoCause();
}

@Test
public void getFeaturePropertyPointerOrThrowThrowsExceptionIfMessagePathHasNoPropertiesSegment() {
final JsonPointer path = JsonPointer.of("features/HX711/foo/uint8_t HX711_DT[3]");
final Payload payload = ProtocolFactory.newPayloadBuilder()
.withPath(path)
.build();
Mockito.when(adaptable.getPayload()).thenReturn(payload);
final MappingContext underTest = MappingContext.of(adaptable);

assertThatExceptionOfType(IllegalAdaptableException.class)
.isThrownBy(underTest::getFeaturePropertyPointerOrThrow)
.withMessage("Message path of payload is not <properties> at level <2>.")
.withNoCause();
}

@Test
public void getFeaturePropertyValueReturnsExpectedIfContainedInPayload() {
final JsonValue propertyValue = JsonValue.of("{A1, 11, 7}");
final Payload payload = ProtocolFactory.newPayloadBuilder()
.withValue(propertyValue)
.build();
Mockito.when(adaptable.getPayload()).thenReturn(payload);
final MappingContext underTest = MappingContext.of(adaptable);

assertThat(underTest.getFeaturePropertyValue()).contains(propertyValue);
}

@Test
public void getFeaturePropertyValueReturnsEmptyOptionalIfPayloadHasNoValue() {
final Payload payload = ProtocolFactory.newPayloadBuilder().build();
Mockito.when(adaptable.getPayload()).thenReturn(payload);
final MappingContext underTest = MappingContext.of(adaptable);

assertThat(underTest.getFeaturePropertyValue()).isEmpty();
}

@Test
public void getPolicyIdReturnsPolicyIfContainedInPayload() {
final PolicyId policyId = PolicyId.inNamespaceWithRandomName("org.ditto");
Expand Down

0 comments on commit 1299b14

Please sign in to comment.