use of org.eclipse.ditto.base.model.signals.Signal in project ditto by eclipse.
the class SignalFilter method matchesFilterBeforeEnrichment.
private static boolean matchesFilterBeforeEnrichment(final FilteredTopic filteredTopic, final Signal<?> signal) {
final Optional<String> filterOptional = filteredTopic.getFilter();
if (filterOptional.isPresent()) {
// match filter ignoring "extraFields"
final TopicPath topicPath = DITTO_PROTOCOL_ADAPTER.toTopicPath(signal);
final PlaceholderResolver<TopicPath> topicPathPlaceholderResolver = PlaceholderFactory.newPlaceholderResolver(TOPIC_PATH_PLACEHOLDER, topicPath);
final PlaceholderResolver<WithResource> resourcePlaceholderResolver = PlaceholderFactory.newPlaceholderResolver(RESOURCE_PLACEHOLDER, signal);
final PlaceholderResolver<Object> timePlaceholderResolver = PlaceholderFactory.newPlaceholderResolver(TIME_PLACEHOLDER, new Object());
final Criteria criteria = parseCriteria(filterOptional.get(), signal.getDittoHeaders(), topicPathPlaceholderResolver, resourcePlaceholderResolver, timePlaceholderResolver);
final Set<JsonPointer> extraFields = filteredTopic.getExtraFields().map(JsonFieldSelector::getPointers).orElse(Collections.emptySet());
if (signal instanceof ThingEvent) {
return ThingEventToThingConverter.thingEventToThing((ThingEvent<?>) signal).filter(thing -> Thing3ValuePredicateVisitor.couldBeTrue(criteria, extraFields, thing, topicPathPlaceholderResolver, resourcePlaceholderResolver, timePlaceholderResolver)).isPresent();
} else {
final Thing emptyThing = Thing.newBuilder().build();
return Thing3ValuePredicateVisitor.couldBeTrue(criteria, extraFields, emptyThing, topicPathPlaceholderResolver, resourcePlaceholderResolver, timePlaceholderResolver);
}
} else {
return true;
}
}
use of org.eclipse.ditto.base.model.signals.Signal in project ditto by eclipse.
the class StreamingSessionActor method createOutgoingSignalBehavior.
private Receive createOutgoingSignalBehavior() {
final PartialFunction<Object, Object> setCorrelationIdAndStartAckForwarder = new PFBuilder<>().match(Signal.class, this::startAckForwarder).match(DittoRuntimeException.class, x -> x).build();
final Receive publishSignal = ReceiveBuilder.create().match(SubscriptionEvent.class, signal -> {
logger.debug("Got SubscriptionEvent in <{}> session, publishing: {}", type, signal);
eventAndResponsePublisher.offer(SessionedJsonifiable.subscription(signal));
}).match(CommandResponse.class, this::publishResponseOrError).match(DittoRuntimeException.class, this::publishResponseOrError).match(Signal.class, this::isSameOrigin, signal -> logger.withCorrelationId(signal).debug("Got Signal of type <{}> in <{}> session, but this was issued by " + " this connection itself, not publishing", signal.getType(), type)).match(Signal.class, signal -> {
// check if this session is "allowed" to receive the Signal
final var streamingType = determineStreamingType(signal);
@Nullable final var session = streamingSessions.get(streamingType);
if (null != session && isSessionAllowedToReceiveSignal(signal, session, streamingType)) {
final ThreadSafeDittoLoggingAdapter l = logger.withCorrelationId(signal);
l.info("Publishing Signal of type <{}> in <{}> session", signal.getType(), type);
l.debug("Publishing Signal of type <{}> in <{}> session: {}", type, signal.getType(), signal);
final DittoHeaders sessionHeaders = DittoHeaders.newBuilder().authorizationContext(authorizationContext).schemaVersion(jsonSchemaVersion).build();
final var sessionedJsonifiable = SessionedJsonifiable.signal(signal, sessionHeaders, session);
eventAndResponsePublisher.offer(sessionedJsonifiable);
}
}).matchEquals(Done.getInstance(), done -> {
/* already done, nothing to publish */
}).build();
return addPreprocessors(List.of(setCorrelationIdAndStartAckForwarder), publishSignal);
}
use of org.eclipse.ditto.base.model.signals.Signal in project ditto by eclipse.
the class PublishSignal method fromJson.
/**
* Deserialize this command.
*
* @param jsonObject the JSON representation of this command.
* @param dittoHeaders the Ditto headers of the underlying signal.
* @param parseInnerJson function to parse the inner JSON.
* @return the deserialized command.
*/
// called by reflection in AnnotationBasedJsonParsable.parse
@SuppressWarnings("unused")
public static PublishSignal fromJson(final JsonObject jsonObject, final DittoHeaders dittoHeaders, final JsonParsable.ParseInnerJson parseInnerJson) {
try {
final Signal<?> signal = (Signal<?>) parseInnerJson.parseInnerJson(jsonObject.getValueOrThrow(JsonFields.SIGNAL));
final Map<String, Integer> groups = jsonObject.getValueOrThrow(JsonFields.GROUPS).stream().collect(Collectors.toMap(JsonField::getKeyName, field -> field.getValue().asInt()));
return new PublishSignal(signal, groups);
} catch (final NotSerializableException e) {
throw new JsonParseException(e.getMessage());
}
}
use of org.eclipse.ditto.base.model.signals.Signal in project ditto by eclipse.
the class MessageMappingProcessorActorTest method testThingIdEnforcementExternalMessageInDittoProtocolIsProcessed.
@Test
public void testThingIdEnforcementExternalMessageInDittoProtocolIsProcessed() {
final Enforcement mqttEnforcement = ConnectivityModelFactory.newEnforcement("{{ test:placeholder }}", "mqtt/topic/{{ thing:namespace }}/{{ thing:name }}");
final EnforcementFilterFactory<String, Signal<?>> factory = EnforcementFactoryFactory.newEnforcementFilterFactory(mqttEnforcement, new TestPlaceholder());
final EnforcementFilter<Signal<?>> enforcementFilter = factory.getFilter("mqtt/topic/my/thing");
testExternalMessageInDittoProtocolIsProcessed(enforcementFilter);
}
use of org.eclipse.ditto.base.model.signals.Signal in project ditto by eclipse.
the class AbstractMessageMappingProcessorActorTest method testExternalMessageInDittoProtocolIsProcessed.
void testExternalMessageInDittoProtocolIsProcessed(@Nullable final EnforcementFilter<Signal<?>> enforcement, final boolean expectSuccess, @Nullable final String mapping, final Consumer<ThingErrorResponse> verifyErrorResponse) {
new TestKit(actorSystem) {
{
final ActorRef outboundMappingProcessorActor = createOutboundMappingProcessorActor(this);
final ActorRef inboundMappingProcessorActor = createInboundMappingProcessorActor(this, outboundMappingProcessorActor);
final ModifyAttribute modifyCommand = createModifyAttributeCommand();
final PayloadMapping mappings = ConnectivityModelFactory.newPayloadMapping(mapping);
final ExternalMessage externalMessage = ExternalMessageFactory.newExternalMessageBuilder(modifyCommand.getDittoHeaders()).withText(ProtocolFactory.wrapAsJsonifiableAdaptable(DITTO_PROTOCOL_ADAPTER.toAdaptable(modifyCommand)).toJsonString()).withAuthorizationContext(TestConstants.Authorization.AUTHORIZATION_CONTEXT).withEnforcement(enforcement).withPayloadMapping(mappings).withInternalHeaders(HEADERS_WITH_REPLY_INFORMATION).build();
TestProbe collectorProbe = TestProbe.apply("collector", actorSystem);
inboundMappingProcessorActor.tell(new InboundMappingSink.ExternalMessageWithSender(externalMessage, collectorProbe.ref()), ActorRef.noSender());
if (expectSuccess) {
final ModifyAttribute modifyAttribute = expectMsgClass(ModifyAttribute.class);
assertThat(modifyAttribute.getType()).isEqualTo(ModifyAttribute.TYPE);
assertThat(modifyAttribute.getDittoHeaders().getCorrelationId()).contains(modifyCommand.getDittoHeaders().getCorrelationId().orElse(null));
assertThat(modifyAttribute.getDittoHeaders().getAuthorizationContext()).isEqualTo(TestConstants.Authorization.AUTHORIZATION_CONTEXT);
// thing ID is included in the header for error reporting
assertThat(modifyAttribute.getDittoHeaders()).extracting(headers -> {
final String prefixedEntityId = headers.get(DittoHeaderDefinition.ENTITY_ID.getKey());
return prefixedEntityId.substring(prefixedEntityId.indexOf(":") + 1);
}).isEqualTo(KNOWN_THING_ID.toString());
// internal headers added by consumer actors are appended
assertThat(modifyAttribute.getDittoHeaders()).containsEntry("ditto-reply-target", "0");
final String expectedMapperHeader = mapping == null ? "default" : mapping;
assertThat(modifyAttribute.getDittoHeaders().getInboundPayloadMapper()).contains(expectedMapperHeader);
if (ADD_HEADER_MAPPER.equals(mapping)) {
assertThat(modifyAttribute.getDittoHeaders()).contains(AddHeaderMessageMapper.INBOUND_HEADER);
}
final ModifyAttributeResponse commandResponse = ModifyAttributeResponse.modified(KNOWN_THING_ID, modifyAttribute.getAttributePointer(), modifyAttribute.getDittoHeaders());
outboundMappingProcessorActor.tell(commandResponse, getRef());
final OutboundSignal.Mapped responseMessage = expectMsgClass(BaseClientActor.PublishMappedMessage.class).getOutboundSignal().first();
if (ADD_HEADER_MAPPER.equals(mapping)) {
final Map<String, String> headers = responseMessage.getExternalMessage().getHeaders();
assertThat(headers).contains(AddHeaderMessageMapper.OUTBOUND_HEADER);
}
} else {
final OutboundSignal errorResponse = expectMsgClass(BaseClientActor.PublishMappedMessage.class).getOutboundSignal();
assertThat(errorResponse.getSource()).isInstanceOf(ThingErrorResponse.class);
final ThingErrorResponse response = (ThingErrorResponse) errorResponse.getSource();
verifyErrorResponse.accept(response);
}
}
};
}
Aggregations