Skip to content

Commit

Permalink
Issue #611: Extended DittoHeaders regarding response-required:
Browse files Browse the repository at this point in the history
* Response-required is by default `true`.
* If response-required is set to `false` it is checked whether required ack labels are set. If so response-required evaluates to `true`.
* Deprecated `getBooleanForDefinition` method in `AbstractDittoHeaders` in favor of `isExpectedBoolean` as it is not necessary to parse header values to JSON for getting a boolean value as they look the same in plain Java.
* Adjusted Javadoc comments of `DittoHeaders` and `DittoHeadersBuilder`.

Signed-off-by: Juergen Fickel <juergen.fickel@bosch-si.com>
  • Loading branch information
Juergen Fickel authored and Juergen Fickel committed Feb 17, 2020
1 parent 25050a6 commit d4b7c48
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,18 +139,45 @@ public Optional<String> getChannel() {

@Override
public boolean isResponseRequired() {
return getBooleanForDefinition(DittoHeaderDefinition.RESPONSE_REQUIRED).orElse(true);
boolean result = true;
if (isExpectedBoolean(DittoHeaderDefinition.RESPONSE_REQUIRED, Boolean.FALSE)) {
final String reqAckLabels = headers.getOrDefault(DittoHeaderDefinition.REQUESTED_ACK_LABELS.getKey(), "");
result = !reqAckLabels.isEmpty();
}
return result;
}

/**
* Resolve type of a header not defined in {@link DittoHeaderDefinition}. Implementations should be fast because
* this method is called multiple times during serialization of each object.
* Indicates whether the value for the given HeaderDefinition evaluates to the given expected boolean.
* If no value exists for the given HeaderDefinition or if the value is not a valid String representation of the
* expected boolean, {@code false} will be returned.
*
* @param headerDefinition the definition of a supposed boolean value.
* @param expected the boolean value which is expected to be set for {@code headerDefinition}.
* @return {@code true} if and only if the header value for {@code headerDefinition} evaluates to {@code expected}.
* @since 1.1.0
*/
protected boolean isExpectedBoolean(final HeaderDefinition headerDefinition, final Boolean expected) {
final String expectedString = expected.toString();

// There is no need to do JSON parsing of the header value as String representations of boolean values look the
// same for plain Java and JSON.
return expectedString.equalsIgnoreCase(headers.get(headerDefinition.getKey()));
}

/**
* Resolve type of a header not defined in {@link DittoHeaderDefinition}.
* Implementations should be fast because this method is called multiple times during serialization of each object.
*
* @param key Name of the specific header.
* @return Header definition of the specific header.
*/
protected abstract Optional<HeaderDefinition> getSpecificDefinitionByKey(final CharSequence key);
protected abstract Optional<HeaderDefinition> getSpecificDefinitionByKey(CharSequence key);

/**
* @deprecated as of 1.1.0 please use {@link #isExpectedBoolean(HeaderDefinition, Boolean)} instead.
*/
@Deprecated
protected Optional<Boolean> getBooleanForDefinition(final HeaderDefinition definition) {
return getStringForDefinition(definition)
.map(JsonFactory::readFrom)
Expand All @@ -160,7 +187,7 @@ protected Optional<Boolean> getBooleanForDefinition(final HeaderDefinition defin

@Override
public boolean isDryRun() {
return getBooleanForDefinition(DittoHeaderDefinition.DRY_RUN).orElse(false);
return isExpectedBoolean(DittoHeaderDefinition.DRY_RUN, Boolean.TRUE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,11 @@ default DittoHeadersBuilder toBuilder() {
Optional<String> getChannel();

/**
* Returns whether a response to a command is required or if it may be omitted (fire and forget semantics)
* Returns whether a response to a command is required or if it may be omitted (fire and forget semantics).
* If acknowledgment labels are set the return value of this method is implicitly {@code true}.
*
* @return the "response required" value.
* @see #getRequestedAckLabels()
*/
boolean isResponseRequired();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ default B randomCorrelationId() {

/**
* Sets the responseRequired value.
* Call this method for explicitly waiving a response.
* <em>
* Please note: If requested ACK labels are set (see {@link #requestedAckLabels(Collection)} calling this method has
* no effect. Requested ACK labels always imply that a response is required.
* </em>
*
* @param responseRequired the responseRequired value to be set.
* @return this builder for Method Chaining.
Expand Down Expand Up @@ -211,6 +216,10 @@ default B randomCorrelationId() {
* {@link org.eclipse.ditto.model.base.acks.DittoAcknowledgementLabel#PERSISTED} also custom labels may be specified
* which can be sent back even by external systems.
* </p>
* <p>
* As long as ACK labels are requested, calls of {@link #responseRequired(boolean)} are neglected as requested ACK
* labels always imply that a response is required.
* </p>
*
* @param ackLabels the requested acknowledgement labels.
* @return this builder.
Expand All @@ -228,6 +237,10 @@ default B randomCorrelationId() {
* {@link org.eclipse.ditto.model.base.acks.DittoAcknowledgementLabel#PERSISTED} also custom labels may be specified
* which can be sent back even by external systems.
* </p>
* <p>
* As long as ACK labels are requested, calls of {@link #responseRequired(boolean)} are neglected as requested ACK
* labels always imply that a response is required.
* </p>
*
* @param ackLabel the requested acknowledgement labels.
* @param furtherAckLabels further requested acknowledgement labels.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.eclipse.ditto.json.JsonObjectBuilder;
import org.eclipse.ditto.json.JsonValue;
import org.eclipse.ditto.model.base.acks.AcknowledgementLabel;
import org.eclipse.ditto.model.base.acks.DittoAcknowledgementLabel;
import org.eclipse.ditto.model.base.auth.AuthorizationContext;
import org.eclipse.ditto.model.base.auth.AuthorizationModelFactory;
import org.eclipse.ditto.model.base.auth.AuthorizationSubject;
Expand Down Expand Up @@ -212,12 +213,29 @@ public void isResponseRequiredIsTrueByDefault() {
}

@Test
public void isResponseRequiredReturnsExpected() {
public void isResponseRequiredReturnsFalseLikeSet() {
final DittoHeaders underTest = DittoHeaders.newBuilder().responseRequired(false).build();

assertThat(underTest.isResponseRequired()).isFalse();
}

@Test
public void isResponseRequiredReturnsTrueLikeSet() {
final DittoHeaders underTest = DittoHeaders.newBuilder().responseRequired(true).build();

assertThat(underTest.isResponseRequired()).isTrue();
}

@Test
public void isResponseRequiredReturnsTrueIfRequiredAckLabelsAreSet() {
final DittoHeaders underTest = DittoHeaders.newBuilder()
.requestedAckLabels(DittoAcknowledgementLabel.PERSISTED)
.responseRequired(false)
.build();

assertThat(underTest.isResponseRequired()).isTrue();
}

@Test
public void isDryRunIsFalseByDefault() {
final DittoHeaders underTest = DittoHeaders.empty();
Expand Down

0 comments on commit d4b7c48

Please sign in to comment.