From aa360c9f025772c516fb878f3e032408be419fb0 Mon Sep 17 00:00:00 2001 From: trifonovt <87468028+TihomirTrifonov@users.noreply.github.com> Date: Fri, 5 Jun 2026 14:39:00 +0200 Subject: [PATCH] Decouple runtime event window bundle selection --- .../model/RuntimeTimelineEventBundle.java | 39 +++++++++++++++++++ .../RuntimeIntervalEventWindowSelector.java | 39 +++++-------------- ...phFileSessionUnifiedDriverEventSource.java | 13 ++++--- ...hFileSessionUnifiedVehicleEventSource.java | 24 +++++++++--- .../model/TachographTimelineEventBundle.java | 11 ++++++ 5 files changed, 86 insertions(+), 40 deletions(-) create mode 100644 src/main/java/at/procon/eventhub/processing/model/RuntimeTimelineEventBundle.java diff --git a/src/main/java/at/procon/eventhub/processing/model/RuntimeTimelineEventBundle.java b/src/main/java/at/procon/eventhub/processing/model/RuntimeTimelineEventBundle.java new file mode 100644 index 0000000..55c08a1 --- /dev/null +++ b/src/main/java/at/procon/eventhub/processing/model/RuntimeTimelineEventBundle.java @@ -0,0 +1,39 @@ +package at.procon.eventhub.processing.model; + +import at.procon.eventhub.dto.EventHubEventDto; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public record RuntimeTimelineEventBundle( + List activityEvents, + List vehicleUsageEvents, + List supportEvents +) { + public RuntimeTimelineEventBundle { + activityEvents = copy(activityEvents); + vehicleUsageEvents = copy(vehicleUsageEvents); + supportEvents = copy(supportEvents); + } + + public static RuntimeTimelineEventBundle empty() { + return new RuntimeTimelineEventBundle(List.of(), List.of(), List.of()); + } + + public List allEvents() { + List result = new ArrayList<>(activityEvents.size() + vehicleUsageEvents.size() + supportEvents.size()); + result.addAll(activityEvents); + result.addAll(vehicleUsageEvents); + result.addAll(supportEvents); + result.sort(Comparator.comparing(EventHubEventDto::occurredAt) + .thenComparing(event -> event.eventDomain().name()) + .thenComparing(event -> event.eventType().name()) + .thenComparing(event -> event.lifecycle().name()) + .thenComparing(EventHubEventDto::externalSourceEventId)); + return List.copyOf(result); + } + + private static List copy(List events) { + return events == null ? List.of() : List.copyOf(events); + } +} diff --git a/src/main/java/at/procon/eventhub/processing/service/RuntimeIntervalEventWindowSelector.java b/src/main/java/at/procon/eventhub/processing/service/RuntimeIntervalEventWindowSelector.java index 5630422..0f1fb08 100644 --- a/src/main/java/at/procon/eventhub/processing/service/RuntimeIntervalEventWindowSelector.java +++ b/src/main/java/at/procon/eventhub/processing/service/RuntimeIntervalEventWindowSelector.java @@ -3,9 +3,8 @@ package at.procon.eventhub.processing.service; import at.procon.eventhub.dto.EventHubEventDto; import at.procon.eventhub.dto.EventLifecycle; import at.procon.eventhub.dto.EventType; +import at.procon.eventhub.processing.model.RuntimeTimelineEventBundle; import at.procon.eventhub.processing.support.RuntimeEventIdentityResolver; -import com.fasterxml.jackson.databind.JsonNode; -import at.procon.eventhub.tachographfilesession.model.TachographTimelineEventBundle; import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -16,23 +15,23 @@ final class RuntimeIntervalEventWindowSelector { private RuntimeIntervalEventWindowSelector() { } - static TachographTimelineEventBundle filterBundle( - TachographTimelineEventBundle bundle, + static RuntimeTimelineEventBundle filterBundle( + RuntimeTimelineEventBundle bundle, OffsetDateTime occurredFrom, OffsetDateTime occurredTo, boolean includeIntersectingIntervals ) { if (bundle == null) { - return new TachographTimelineEventBundle(List.of(), List.of(), List.of()); + return RuntimeTimelineEventBundle.empty(); } - return new TachographTimelineEventBundle( + return new RuntimeTimelineEventBundle( filterIntervalEvents(bundle.activityEvents(), occurredFrom, occurredTo, includeIntersectingIntervals), filterIntervalEvents(bundle.vehicleUsageEvents(), occurredFrom, occurredTo, includeIntersectingIntervals), filterPointEvents(bundle.supportEvents(), occurredFrom, occurredTo) ); } - private static List filterIntervalEvents( + static List filterIntervalEvents( List events, OffsetDateTime occurredFrom, OffsetDateTime occurredTo, @@ -59,11 +58,14 @@ final class RuntimeIntervalEventWindowSelector { return List.copyOf(result); } - private static List filterPointEvents( + static List filterPointEvents( List events, OffsetDateTime occurredFrom, OffsetDateTime occurredTo ) { + if (events == null || events.isEmpty()) { + return List.of(); + } return events.stream() .filter(event -> withinWindow(event.occurredAt(), occurredFrom, occurredTo)) .toList(); @@ -87,27 +89,6 @@ final class RuntimeIntervalEventWindowSelector { return RuntimeEventIdentityResolver.runtimeIntervalKey(event); } - private static JsonNode raw(EventHubEventDto event) { - JsonNode payload = event == null ? null : event.payload(); - if (payload == null || payload.isNull() || payload.isMissingNode()) { - return null; - } - JsonNode raw = payload.get("raw"); - return raw == null || raw.isNull() ? payload : raw; - } - - private static String text(JsonNode node, String field) { - if (node == null || field == null) { - return null; - } - JsonNode value = node.get(field); - if (value == null || value.isNull()) { - return null; - } - String text = value.asText(null); - return text == null || text.isBlank() ? null : text.trim(); - } - private static final class IntervalGroup { private final List events = new ArrayList<>(); private OffsetDateTime startedAt; diff --git a/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedDriverEventSource.java b/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedDriverEventSource.java index fc1721f..9bcc91b 100644 --- a/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedDriverEventSource.java +++ b/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedDriverEventSource.java @@ -54,11 +54,14 @@ public class TachographFileSessionUnifiedDriverEventSource implements UnifiedDri DriverExtractionSession driver, UnifiedDriverEventsRequest request ) { - return RuntimeIntervalEventWindowSelector.filterBundle( - eventBuilder.buildEventBundle(session, driver), - request.occurredFrom(), - request.occurredTo(), - request.includeIntersectingIntervals() + TachographTimelineEventBundle bundle = eventBuilder.buildEventBundle(session, driver); + return TachographTimelineEventBundle.fromRuntimeBundle( + RuntimeIntervalEventWindowSelector.filterBundle( + bundle == null ? null : bundle.toRuntimeBundle(), + request.occurredFrom(), + request.occurredTo(), + request.includeIntersectingIntervals() + ) ); } } diff --git a/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedVehicleEventSource.java b/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedVehicleEventSource.java index 139d222..ca7be33 100644 --- a/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedVehicleEventSource.java +++ b/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedVehicleEventSource.java @@ -5,6 +5,7 @@ import at.procon.eventhub.dto.VehicleRefDto; import at.procon.eventhub.processing.model.UnifiedEventSourceFamily; import at.procon.eventhub.processing.model.UnifiedVehicleEventsRequest; import at.procon.eventhub.reference.TachographNationRegistry; +import at.procon.eventhub.tachographfilesession.model.DriverExtractionSession; import at.procon.eventhub.tachographfilesession.model.TachographFileSession; import at.procon.eventhub.tachographfilesession.model.TachographTimelineEventBundle; import at.procon.eventhub.tachographfilesession.service.DriverTimelineEventBuilder; @@ -37,18 +38,29 @@ public class TachographFileSessionUnifiedVehicleEventSource implements UnifiedVe TachographFileSession session = repository.find(request.sessionId()) .orElseThrow(() -> new TachographFileSessionNotFoundException(request.sessionId())); return session.driversByKey().values().stream() - .map(driver -> RuntimeIntervalEventWindowSelector.filterBundle( - eventBuilder.buildEventBundle(session, driver), - request.occurredFrom(), - request.occurredTo(), - request.includeIntersectingIntervals() - ).allEvents()) + .map(driver -> filterBundle(session, driver, request).allEvents()) .flatMap(List::stream) .filter(event -> matchesVehicle(event.vehicleRef(), request)) .distinct() .toList(); } + private TachographTimelineEventBundle filterBundle( + TachographFileSession session, + DriverExtractionSession driver, + UnifiedVehicleEventsRequest request + ) { + TachographTimelineEventBundle bundle = eventBuilder.buildEventBundle(session, driver); + return TachographTimelineEventBundle.fromRuntimeBundle( + RuntimeIntervalEventWindowSelector.filterBundle( + bundle == null ? null : bundle.toRuntimeBundle(), + request.occurredFrom(), + request.occurredTo(), + request.includeIntersectingIntervals() + ) + ); + } + private boolean matchesVehicle(VehicleRefDto vehicleRef, UnifiedVehicleEventsRequest request) { if (vehicleRef == null || !vehicleRef.hasAnyReference()) { return false; diff --git a/src/main/java/at/procon/eventhub/tachographfilesession/model/TachographTimelineEventBundle.java b/src/main/java/at/procon/eventhub/tachographfilesession/model/TachographTimelineEventBundle.java index 503f0dc..35cc739 100644 --- a/src/main/java/at/procon/eventhub/tachographfilesession/model/TachographTimelineEventBundle.java +++ b/src/main/java/at/procon/eventhub/tachographfilesession/model/TachographTimelineEventBundle.java @@ -1,6 +1,7 @@ package at.procon.eventhub.tachographfilesession.model; import at.procon.eventhub.dto.EventHubEventDto; +import at.procon.eventhub.processing.model.RuntimeTimelineEventBundle; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -29,6 +30,16 @@ public record TachographTimelineEventBundle( return List.copyOf(result); } + public RuntimeTimelineEventBundle toRuntimeBundle() { + return new RuntimeTimelineEventBundle(activityEvents, vehicleUsageEvents, supportEvents); + } + + public static TachographTimelineEventBundle fromRuntimeBundle(RuntimeTimelineEventBundle bundle) { + return bundle == null + ? new TachographTimelineEventBundle(List.of(), List.of(), List.of()) + : new TachographTimelineEventBundle(bundle.activityEvents(), bundle.vehicleUsageEvents(), bundle.supportEvents()); + } + private static List copy(List events) { return events == null ? List.of() : List.copyOf(events); }