Skip to content

Commit

Permalink
added feature id placeholder
Browse files Browse the repository at this point in the history
Signed-off-by: Johannes Schneider <johannes.schneider@bosch.io>
  • Loading branch information
jokraehe committed Oct 27, 2020
1 parent f9060b6 commit ff733f4
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2020 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.model.placeholders;

/**
* A {@link Placeholder} that requires a {@code String} (a valid Feature ID) to resolve it's placeholders.
*
* @since 1.5.0
*/
public interface FeaturePlaceholder extends Placeholder<String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2020 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.model.placeholders;

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

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import javax.annotation.concurrent.Immutable;

/**
* Placeholder implementation that replaces {@code feature:id}. The input value is a String and must be a valid Feature
* ID.
*
* @since 1.5.0
*/
@Immutable
final class ImmutableFeaturePlaceholder implements FeaturePlaceholder {

private static final String ID_PLACEHOLDER = "id";

private static final List<String> SUPPORTED = Collections.singletonList(ID_PLACEHOLDER);

/**
* Singleton instance of the {@code ImmutableFeaturePlaceholder}.
*/
static final ImmutableFeaturePlaceholder INSTANCE = new ImmutableFeaturePlaceholder();

@Override
public Optional<String> resolve(final String featureId, final String placeholder) {
checkNotNull(featureId, "featureId");
argumentNotEmpty(placeholder, "placeholder");
if (ID_PLACEHOLDER.equals(placeholder)) {
return Optional.of(featureId);
}
return Optional.empty();
}

@Override
public String getPrefix() {
return "feature";
}

@Override
public List<String> getSupportedNames() {
return SUPPORTED;
}

@Override
public boolean supports(final String name) {
return SUPPORTED.contains(name);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ public static PolicyPlaceholder newPolicyPlaceholder() {
return ImmutablePolicyPlaceholder.INSTANCE;
}

/**
* @return new instance of the {@link FeaturePlaceholder}
* @since 1.5.0
*/
public static FeaturePlaceholder newFeaturePlaceholder() {
return ImmutableFeaturePlaceholder.INSTANCE;
}

/**
* @return new instance of the {@link EntityPlaceholder}
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2020 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.model.placeholders;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;
import org.mutabilitydetector.unittesting.MutabilityAssert;
import org.mutabilitydetector.unittesting.MutabilityMatchers;

import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;

/**
* Tests {@link ImmutableFeaturePlaceholder}.
*/
public final class ImmutableFeaturePlaceholderTest {

private static final String FEATURE_ID = "FluxCapacitor";
private static final FeaturePlaceholder UNDER_TEST = ImmutableFeaturePlaceholder.INSTANCE;

@Test
public void assertImmutability() {
MutabilityAssert.assertInstancesOf(ImmutableFeaturePlaceholder.class, MutabilityMatchers.areImmutable());
}

@Test
public void testHashCodeAndEquals() {
EqualsVerifier.forClass(ImmutableFeaturePlaceholder.class)
.suppress(Warning.INHERITED_DIRECTLY_FROM_OBJECT)
.usingGetClass()
.verify();
}

@Test
public void testReplaceFeatureId() {
assertThat(UNDER_TEST.resolve(FEATURE_ID, "id")).contains(FEATURE_ID);
}

@Test
public void testUnknownPlaceholderReturnsEmpty() {
assertThat(UNDER_TEST.resolve(FEATURE_ID, "feature_id")).isEmpty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.eclipse.ditto.services.models.connectivity.ExternalMessage;
import org.eclipse.ditto.services.models.connectivity.OutboundSignal;
import org.eclipse.ditto.signals.base.Signal;
import org.eclipse.ditto.signals.base.WithFeatureId;

/**
* Creator of expression resolvers for incoming and outgoing messages.
Expand All @@ -54,6 +55,13 @@ private Resolvers() {
return null;
}
}),
ResolverCreator.of(PlaceholderFactory.newFeaturePlaceholder(), (e, s, t, a, c) -> {
if (s instanceof WithFeatureId) {
return ((WithFeatureId) s).getFeatureId();
} else {
return null;
}
}),
ResolverCreator.of(PlaceholderFactory.newTopicPathPlaceholder(), (e, s, t, a, c) -> t),
ResolverCreator.of(PlaceholderFactory.newRequestPlaceholder(), (e, s, t, a, c) -> a),
ResolverCreator.of(PlaceholderFactory.newConnectionIdPlaceholder(), (e, s, t, a, c) -> c)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ protected void validateSource(final Source source, final DittoHeaders dittoHeade
enforcement.getFilters().forEach(filterTemplate ->
validateTemplate(filterTemplate, dittoHeaders, PlaceholderFactory.newThingPlaceholder(),
PlaceholderFactory.newPolicyPlaceholder(),
PlaceholderFactory.newEntityPlaceholder()));
PlaceholderFactory.newEntityPlaceholder(),
PlaceholderFactory.newFeaturePlaceholder()));
});
source.getHeaderMapping().ifPresent(mapping -> validateHeaderMapping(mapping, dittoHeaders));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.eclipse.ditto.model.connectivity.ConnectionType;
import org.eclipse.ditto.model.connectivity.Source;
import org.eclipse.ditto.model.connectivity.Target;
import org.eclipse.ditto.model.placeholders.PlaceholderFactory;
import org.eclipse.ditto.services.connectivity.messaging.validation.AbstractProtocolValidator;

import akka.actor.ActorSystem;
Expand Down Expand Up @@ -91,7 +92,7 @@ protected void validateTarget(final Target target, final DittoHeaders dittoHeade
final Supplier<String> targetDescription) {
target.getHeaderMapping().ifPresent(mapping -> validateHeaderMapping(mapping, dittoHeaders));
validateTemplate(target.getAddress(), dittoHeaders, newThingPlaceholder(), newTopicPathPlaceholder(),
newHeadersPlaceholder());
newHeadersPlaceholder(), PlaceholderFactory.newFeaturePlaceholder());
validateTargetAddress(target.getAddress(), dittoHeaders, targetDescription);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ protected void validateTarget(final Target target, final DittoHeaders dittoHeade

validateTargetQoS(qos.get(), dittoHeaders, targetDescription);
validateTemplate(target.getAddress(), dittoHeaders, newThingPlaceholder(), newTopicPathPlaceholder(),
newHeadersPlaceholder());
newHeadersPlaceholder(), PlaceholderFactory.newFeaturePlaceholder());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ protected void validateSource(final Source source, final DittoHeaders dittoHeade
validateTemplate(enforcement.getInput(), dittoHeaders, PlaceholderFactory.newHeadersPlaceholder());
enforcement.getFilters().forEach(filterTemplate ->
validateTemplate(filterTemplate, dittoHeaders, PlaceholderFactory.newThingPlaceholder(),
PlaceholderFactory.newPolicyPlaceholder(), PlaceholderFactory.newEntityPlaceholder()));
PlaceholderFactory.newPolicyPlaceholder(), PlaceholderFactory.newEntityPlaceholder(),
PlaceholderFactory.newFeaturePlaceholder()));
});
source.getHeaderMapping().ifPresent(mapping -> validateHeaderMapping(mapping, dittoHeaders));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public void testValidMatchers() {
@Test
public void testValidPlaceholdersInTargetAddress() {
final Target target = newTargetBuilder()
.address("some.address.{{ topic:action-subject }}.{{ thing:id }}.{{ header:correlation-id }}")
.address("some.address.{{ topic:action-subject }}.{{ thing:id }}.{{ feature:id }}.{{ header:correlation-id }}")
.authorizationContext(AUTHORIZATION_CONTEXT)
.topics(Topic.LIVE_COMMANDS)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ public void testValidTargetAddress() {
underTest.validate(getConnectionWithTarget("PUT:ditto/{{thing:id}}"), emptyDittoHeaders, actorSystem);
underTest.validate(getConnectionWithTarget("PATCH:/{{thing:namespace}}/{{thing:name}}"), emptyDittoHeaders,
actorSystem);
underTest.validate(getConnectionWithTarget("PATCH:/{{thing:namespace}}/{{thing:name}}/{{ feature:id }}"), emptyDittoHeaders,
actorSystem);
underTest.validate(getConnectionWithTarget("PUT:events#{{topic:full}}"), emptyDittoHeaders, actorSystem);
underTest.validate(getConnectionWithTarget("POST:ditto?{{header:x}}"), emptyDittoHeaders, actorSystem);
underTest.validate(getConnectionWithTarget("POST:"), emptyDittoHeaders, actorSystem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ public void testValidTargetAddress() {
UNDER_TEST.validate(connectionWithTarget("ditto/rabbit"), DittoHeaders.empty(), actorSystem);
UNDER_TEST.validate(connectionWithTarget("ditto"), DittoHeaders.empty(), actorSystem);
UNDER_TEST.validate(connectionWithTarget("ditto/{{thing:id}}"), DittoHeaders.empty(), actorSystem);
UNDER_TEST.validate(connectionWithTarget("ditto/{{thing:id}}/{{feature:id}}"), DittoHeaders.empty(),
actorSystem);
UNDER_TEST.validate(connectionWithTarget("ditto/{{topic:full}}"), DittoHeaders.empty(), actorSystem);
UNDER_TEST.validate(connectionWithTarget("ditto/{{header:x}}"), DittoHeaders.empty(), actorSystem);
}
Expand Down

0 comments on commit ff733f4

Please sign in to comment.