-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Issue #106: Extract 'channel=live' header also for Error responses
* the channel header is already extracted for normal messages * now it will also be extracted for Error responses, when available * Refactor header-extraction to reuse for normal and error responses Signed-off-by: Joel Bartelheimer <joel.bartelheimer@bosch.io>
- Loading branch information
Showing
5 changed files
with
263 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
protocol/src/main/java/org/eclipse/ditto/protocol/adapter/HeadersFromTopicPath.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* | ||
* Copyright (c) 2021 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.eclipse.ditto.protocol.adapter; | ||
|
||
import java.util.AbstractMap.SimpleImmutableEntry; | ||
import java.util.Arrays; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.function.Function; | ||
import java.util.stream.Collectors; | ||
|
||
import org.eclipse.ditto.base.model.headers.DittoHeaderDefinition; | ||
import org.eclipse.ditto.base.model.headers.DittoHeaders; | ||
import org.eclipse.ditto.protocol.TopicPath; | ||
|
||
/** | ||
* A function to extract information from the topic path and enrich the ditto headers with them. | ||
* | ||
* A set of available extractors, e.g. for live-channel and entityId, which can be used for | ||
* {@link #injectHeaders(DittoHeaders, TopicPath, Extractor[])} is provided by inner class {@link Extractor}. | ||
*/ | ||
public final class HeadersFromTopicPath { | ||
|
||
private HeadersFromTopicPath() { | ||
} | ||
|
||
/** | ||
* Injects new headers | ||
* | ||
* @param dittoHeaders the headers where the additional headers shall be injected into. | ||
* @param topicPath where the headers will be extracted from. | ||
* @param topicPathExtractors the extractor functions. Use {@link Extractor} | ||
* @return new enriched ditto headers. | ||
*/ | ||
public static DittoHeaders injectHeaders(final DittoHeaders dittoHeaders, | ||
final TopicPath topicPath, | ||
final Extractor... topicPathExtractors) { | ||
|
||
final Map<String, String> headersFromTopicPath = Arrays.stream(topicPathExtractors) | ||
.map(fn -> fn.apply(topicPath)) | ||
.filter(Optional::isPresent) | ||
.map(Optional::get) | ||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); | ||
|
||
return dittoHeaders | ||
.toBuilder() | ||
.putHeaders(headersFromTopicPath) | ||
.build(); | ||
} | ||
|
||
/** | ||
* only a type declaration and a set of implemented extractor functions, which can be used for | ||
* {@link #injectHeaders(DittoHeaders, TopicPath, Extractor[])} | ||
*/ | ||
public interface Extractor extends Function<TopicPath, Optional<Map.Entry<String, String>>> { | ||
|
||
/** | ||
* Extracts the channel, if it is 'live' | ||
* | ||
* @param topicPath the topic path to extract information from. | ||
* @return header KV containing the extra information from topic path. | ||
*/ | ||
public static Optional<Map.Entry<String, String>> liveChannelExtractor(final TopicPath topicPath) { | ||
if (topicPath.isChannel(TopicPath.Channel.LIVE)) { | ||
final String key = DittoHeaderDefinition.CHANNEL.getKey(); | ||
final String value = TopicPath.Channel.LIVE.getName(); | ||
|
||
return Optional.of(new SimpleImmutableEntry<>(key, value)); | ||
} else { | ||
return Optional.empty(); | ||
} | ||
} | ||
|
||
/** | ||
* Extracts the entityId from the Topic-Path if none of the pieces is a placeholder ('_'). | ||
* | ||
* @param topicPath the topic path to extract information from. | ||
* @return header KV containing the extra information from topic path. | ||
*/ | ||
static Optional<Map.Entry<String, String>> entityIdExtractor(final TopicPath topicPath) { | ||
return getEntityId(topicPath) | ||
.map(entityId -> new SimpleImmutableEntry<>(DittoHeaderDefinition.ENTITY_ID.getKey(), entityId)); | ||
} | ||
|
||
} | ||
|
||
private static Optional<String> getEntityId(final TopicPath topicPath) { | ||
final TopicPath.Group group = topicPath.getGroup(); | ||
final String namespace = topicPath.getNamespace(); | ||
final String entityName = topicPath.getEntityName(); | ||
if (!TopicPath.ID_PLACEHOLDER.equals(namespace) && !TopicPath.ID_PLACEHOLDER.equals(entityName)) { | ||
return Optional.of(String.join(":", group.getEntityType(), namespace, entityName)); | ||
} else { | ||
return Optional.empty(); | ||
} | ||
} | ||
|
||
} |
118 changes: 118 additions & 0 deletions
118
protocol/src/test/java/org/eclipse/ditto/protocol/adapter/HeadersFromTopicPathTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* Copyright (c) 2021 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.eclipse.ditto.protocol.adapter; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import org.eclipse.ditto.base.model.headers.DittoHeaderDefinition; | ||
import org.eclipse.ditto.base.model.headers.DittoHeaders; | ||
import org.eclipse.ditto.protocol.ProtocolFactory; | ||
import org.eclipse.ditto.protocol.TopicPath; | ||
import org.eclipse.ditto.things.model.ThingConstants; | ||
import org.eclipse.ditto.things.model.ThingId; | ||
import org.junit.Test; | ||
|
||
/** | ||
* Test for {@link HeadersFromTopicPath} | ||
*/ | ||
public final class HeadersFromTopicPathTest { | ||
|
||
@Test | ||
public void shallExtractLiveChannel() { | ||
// Arrange | ||
final TopicPath topicPath = TopicPath.newBuilder(ThingId.of("org.eclipse.ditto:fancy-thing")) | ||
.live() | ||
.commands() | ||
.modify() | ||
.build(); | ||
|
||
// Act | ||
final DittoHeaders dittoHeaders = HeadersFromTopicPath.injectHeaders(DittoHeaders.empty(), | ||
topicPath, | ||
HeadersFromTopicPath.Extractor::liveChannelExtractor); | ||
|
||
// Assert | ||
assertThat(dittoHeaders.getChannel()).hasValue("live"); | ||
} | ||
|
||
@Test | ||
public void shallNotExtractOtherChannels() { | ||
// Arrange | ||
final TopicPath topicPath = TopicPath.newBuilder(ThingId.of("org.eclipse.ditto:fancy-thing")) | ||
.twin() | ||
.commands() | ||
.modify() | ||
.build(); | ||
|
||
// Act | ||
final DittoHeaders dittoHeaders = HeadersFromTopicPath.injectHeaders(DittoHeaders.empty(), | ||
topicPath, | ||
HeadersFromTopicPath.Extractor::liveChannelExtractor); | ||
|
||
// Assert | ||
assertThat(dittoHeaders).isEmpty(); | ||
} | ||
|
||
@Test | ||
public void shallNotFailWhenNoneChannel() { | ||
// Arrange | ||
final TopicPath topicPath = TopicPath.newBuilder(ThingId.of("org.eclipse.ditto:fancy-thing")) | ||
.none() | ||
.commands() | ||
.modify() | ||
.build(); | ||
|
||
// Act | ||
final DittoHeaders dittoHeaders = HeadersFromTopicPath.injectHeaders(DittoHeaders.empty(), | ||
topicPath, | ||
HeadersFromTopicPath.Extractor::liveChannelExtractor); | ||
|
||
// Assert | ||
assertThat(dittoHeaders).isEmpty(); | ||
} | ||
|
||
@Test | ||
public void shallExtractEntityId() { | ||
// Arrange | ||
final ThingId thingId = ThingId.of("org.eclipse.ditto:fancy-thing"); | ||
final String expectedDittoEntityId = ThingConstants.ENTITY_TYPE + ":" + thingId; | ||
|
||
final TopicPath topicPath = TopicPath.newBuilder(thingId) | ||
.live() | ||
.commands() | ||
.modify() | ||
.build(); | ||
|
||
// Act | ||
final DittoHeaders dittoHeaders = HeadersFromTopicPath.injectHeaders(DittoHeaders.empty(), | ||
topicPath, | ||
HeadersFromTopicPath.Extractor::entityIdExtractor); | ||
|
||
// Assert | ||
assertThat(dittoHeaders.get(DittoHeaderDefinition.ENTITY_ID.getKey())).isEqualTo(expectedDittoEntityId); | ||
} | ||
|
||
@Test | ||
public void shallNotFailWithPlaceholder() { | ||
// Arrange | ||
final TopicPath topicPath = ProtocolFactory.newTopicPath("_/_/things/twin/commands/modify"); | ||
|
||
// Act | ||
final DittoHeaders dittoHeaders = HeadersFromTopicPath.injectHeaders(DittoHeaders.empty(), | ||
topicPath, | ||
HeadersFromTopicPath.Extractor::entityIdExtractor); | ||
|
||
// Assert | ||
assertThat(dittoHeaders).isEmpty(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters