From 5cf0cedc419098e5943e15f2bd4236413d8a96f6 Mon Sep 17 00:00:00 2001 From: trifonovt <87468028+TihomirTrifonov@users.noreply.github.com> Date: Fri, 5 Jun 2026 14:39:36 +0200 Subject: [PATCH] Decouple runtime timelines from tachograph models --- .../UnifiedRuntimeProcessingController.java | 4 +- .../RuntimeVehicleUsageIntervalDebugDto.java | 4 +- .../VehicleEvidenceAttachmentModule.java | 4 +- .../epl/DriverWorkingTimeEplEventMapper.java | 14 +- .../RuntimeSupportEvidenceNormalizer.java | 10 +- .../model/RuntimeActivityInterval.java | 99 ++++++++ .../model/RuntimeDriverTimeline.java | 15 ++ .../model/RuntimeExtractionWarning.java | 8 + .../processing/model/RuntimeSupportEvent.java | 30 +++ .../model/RuntimeVehicleUsageInterval.java | 50 ++++ ...riverVehicleEvidenceAttachmentService.java | 38 +-- ...iverWorkingTimeScopeProcessingService.java | 4 +- ...ileSessionUnifiedDriverTimelineSource.java | 9 +- .../service/UnifiedDriverTimelineService.java | 4 +- .../service/UnifiedDriverTimelineSource.java | 4 +- .../UnifiedEventTimelineReconstructor.java | 100 ++++---- ...nifiedRuntimeDerivedProjectionService.java | 53 +--- .../UnifiedRuntimeDriverTimelineService.java | 8 +- .../RuntimeDriverWorkingTimeAdapter.java | 123 +++++++++ ...va => RuntimeEntityReferenceResolver.java} | 4 +- .../support/RuntimeEventIdentityResolver.java | 14 +- .../EventBackedDriverTimelineBuilder.java | 17 +- .../TachographCompositeSessionService.java | 17 +- ...raphEventTimelineReconstructionHelper.java | 11 +- .../RuntimeTimelineCompatibilityAdapter.java | 237 ++++++++++++++++++ ...nifiedRuntimeProcessingControllerTest.java | 13 +- .../UnifiedDriverTimelineServiceTest.java | 4 +- ...UnifiedEventTimelineReconstructorTest.java | 8 +- ...ifiedRuntimeDriverTimelineServiceTest.java | 4 +- ...TachographCompositeSessionServiceTest.java | 26 +- 30 files changed, 746 insertions(+), 190 deletions(-) create mode 100644 src/main/java/at/procon/eventhub/processing/model/RuntimeActivityInterval.java create mode 100644 src/main/java/at/procon/eventhub/processing/model/RuntimeDriverTimeline.java create mode 100644 src/main/java/at/procon/eventhub/processing/model/RuntimeExtractionWarning.java create mode 100644 src/main/java/at/procon/eventhub/processing/model/RuntimeSupportEvent.java create mode 100644 src/main/java/at/procon/eventhub/processing/model/RuntimeVehicleUsageInterval.java create mode 100644 src/main/java/at/procon/eventhub/processing/support/RuntimeDriverWorkingTimeAdapter.java rename src/main/java/at/procon/eventhub/processing/support/{TachographRuntimeIdentityResolver.java => RuntimeEntityReferenceResolver.java} (98%) create mode 100644 src/main/java/at/procon/eventhub/tachographfilesession/support/RuntimeTimelineCompatibilityAdapter.java diff --git a/src/main/java/at/procon/eventhub/processing/api/UnifiedRuntimeProcessingController.java b/src/main/java/at/procon/eventhub/processing/api/UnifiedRuntimeProcessingController.java index 718f98a..e8ac603 100644 --- a/src/main/java/at/procon/eventhub/processing/api/UnifiedRuntimeProcessingController.java +++ b/src/main/java/at/procon/eventhub/processing/api/UnifiedRuntimeProcessingController.java @@ -17,12 +17,12 @@ import at.procon.eventhub.processing.eventprocessing.validation.RuntimeMixedSour import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationApiRequest; import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationResultDto; import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationService; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; import at.procon.eventhub.processing.model.UnifiedRuntimeEventBundle; import at.procon.eventhub.processing.service.UnifiedRuntimeDerivedProjectionService; import at.procon.eventhub.processing.service.UnifiedRuntimeDriverTimelineService; import at.procon.eventhub.processing.service.UnifiedRuntimeEventAssemblyService; import at.procon.eventhub.processing.service.RuntimeDriverWorkingTimeScopeProcessingService; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -106,7 +106,7 @@ public class UnifiedRuntimeProcessingController { } @PostMapping("/driver-timeline") - public ResponseEntity loadDriverTimeline( + public ResponseEntity loadDriverTimeline( @RequestBody UnifiedRuntimeProcessingApiRequest request ) { return ResponseEntity.ok(runtimeDriverTimelineService.loadDriverTimeline(request.toRuntimeRequest())); diff --git a/src/main/java/at/procon/eventhub/processing/dto/RuntimeVehicleUsageIntervalDebugDto.java b/src/main/java/at/procon/eventhub/processing/dto/RuntimeVehicleUsageIntervalDebugDto.java index e29dfad..e6096e9 100644 --- a/src/main/java/at/procon/eventhub/processing/dto/RuntimeVehicleUsageIntervalDebugDto.java +++ b/src/main/java/at/procon/eventhub/processing/dto/RuntimeVehicleUsageIntervalDebugDto.java @@ -1,7 +1,7 @@ package at.procon.eventhub.processing.dto; import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVehicleUsageInterval; -import at.procon.eventhub.tachographfilesession.model.ResolvedVehicleUsageInterval; +import at.procon.eventhub.processing.model.RuntimeVehicleUsageInterval; import java.time.OffsetDateTime; public record RuntimeVehicleUsageIntervalDebugDto( @@ -12,7 +12,7 @@ public record RuntimeVehicleUsageIntervalDebugDto( String vehicleKey, String sourceKind ) { - public static RuntimeVehicleUsageIntervalDebugDto from(ResolvedVehicleUsageInterval interval) { + public static RuntimeVehicleUsageIntervalDebugDto from(RuntimeVehicleUsageInterval interval) { if (interval == null) { return null; } diff --git a/src/main/java/at/procon/eventhub/processing/eventprocessing/module/VehicleEvidenceAttachmentModule.java b/src/main/java/at/procon/eventhub/processing/eventprocessing/module/VehicleEvidenceAttachmentModule.java index 2a5f8d2..871be89 100644 --- a/src/main/java/at/procon/eventhub/processing/eventprocessing/module/VehicleEvidenceAttachmentModule.java +++ b/src/main/java/at/procon/eventhub/processing/eventprocessing/module/VehicleEvidenceAttachmentModule.java @@ -14,7 +14,7 @@ import at.procon.eventhub.processing.model.UnifiedRuntimeEventBundle; import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest; import at.procon.eventhub.processing.service.RuntimeDriverVehicleEvidenceAttachmentService; import at.procon.eventhub.processing.support.RuntimeEventIdentityResolver; -import at.procon.eventhub.processing.support.TachographRuntimeIdentityResolver; +import at.procon.eventhub.processing.support.RuntimeEntityReferenceResolver; import com.fasterxml.jackson.databind.JsonNode; import java.util.ArrayList; import java.util.Comparator; @@ -260,7 +260,7 @@ public class VehicleEvidenceAttachmentModule implements RuntimeProcessingModule } private String driverKey(EventHubEventDto event) { - return TachographRuntimeIdentityResolver.driverKey(event); + return RuntimeEntityReferenceResolver.driverKey(event); } private JsonNode rawPayload(EventHubEventDto event) { diff --git a/src/main/java/at/procon/eventhub/processing/eventprocessing/module/epl/DriverWorkingTimeEplEventMapper.java b/src/main/java/at/procon/eventhub/processing/eventprocessing/module/epl/DriverWorkingTimeEplEventMapper.java index f55b1cb..38ec905 100644 --- a/src/main/java/at/procon/eventhub/processing/eventprocessing/module/epl/DriverWorkingTimeEplEventMapper.java +++ b/src/main/java/at/procon/eventhub/processing/eventprocessing/module/epl/DriverWorkingTimeEplEventMapper.java @@ -9,7 +9,7 @@ import at.procon.eventhub.processing.eventprocessing.module.RuntimeProcessingMod import at.procon.eventhub.processing.eventprocessing.module.RuntimeProcessingModuleResult; import at.procon.eventhub.processing.model.UnifiedRuntimeEventBundle; import at.procon.eventhub.processing.support.RuntimeEventIdentityResolver; -import at.procon.eventhub.processing.support.TachographRuntimeIdentityResolver; +import at.procon.eventhub.processing.support.RuntimeEntityReferenceResolver; import com.fasterxml.jackson.databind.JsonNode; import java.time.OffsetDateTime; import java.util.ArrayList; @@ -156,7 +156,7 @@ public final class DriverWorkingTimeEplEventMapper { JsonNode attributes = attributes(sourceEvent); String intervalId = RuntimeEventIdentityResolver.presentationIntervalId(sourceEvent); String runtimeIntervalKey = RuntimeEventIdentityResolver.runtimeIntervalKey(sourceEvent); - String driverKey = TachographRuntimeIdentityResolver.driverKey(sourceEvent); + String driverKey = RuntimeEntityReferenceResolver.driverKey(sourceEvent); if (driverKey == null || intervalId == null || runtimeIntervalKey == null) { return null; } @@ -175,8 +175,8 @@ public final class DriverWorkingTimeEplEventMapper { event.put("cardSlot", firstNonBlank(text(raw, "cardSlot"), text(attributes, "cardSlot"))); event.put("cardStatus", firstNonBlank(text(raw, "cardStatus"), text(attributes, "cardStatus"))); event.put("drivingStatus", firstNonBlank(text(raw, "drivingStatus"), text(attributes, "drivingStatus"))); - event.put("registrationKey", TachographRuntimeIdentityResolver.registrationKey(sourceEvent)); - event.put("vehicleKey", TachographRuntimeIdentityResolver.vehicleKey(sourceEvent)); + event.put("registrationKey", RuntimeEntityReferenceResolver.registrationKey(sourceEvent)); + event.put("vehicleKey", RuntimeEntityReferenceResolver.vehicleKey(sourceEvent)); event.put("sourceKind", firstNonBlank(text(raw, "sourceKind"), sourceKind(sourceEvent))); event.put("synthetic", booleanValue(raw, "synthetic", false)); event.put("clippedToRequestedPeriod", booleanValue(raw, "clippedToRequestedPeriod", false)); @@ -199,7 +199,7 @@ public final class DriverWorkingTimeEplEventMapper { JsonNode raw = rawPayload(sourceEvent); String intervalId = RuntimeEventIdentityResolver.presentationIntervalId(sourceEvent); String runtimeIntervalKey = RuntimeEventIdentityResolver.runtimeIntervalKey(sourceEvent); - String driverKey = TachographRuntimeIdentityResolver.driverKey(sourceEvent); + String driverKey = RuntimeEntityReferenceResolver.driverKey(sourceEvent); if (driverKey == null || intervalId == null || runtimeIntervalKey == null) { return null; } @@ -214,8 +214,8 @@ public final class DriverWorkingTimeEplEventMapper { event.put("lifecycle", sourceEvent.lifecycle().name()); event.put("occurredAt", sourceEvent.occurredAt()); event.put("occurredAtEpochSecond", sourceEvent.occurredAt().toEpochSecond()); - event.put("registrationKey", TachographRuntimeIdentityResolver.registrationKey(sourceEvent)); - event.put("vehicleKey", TachographRuntimeIdentityResolver.vehicleKey(sourceEvent)); + event.put("registrationKey", RuntimeEntityReferenceResolver.registrationKey(sourceEvent)); + event.put("vehicleKey", RuntimeEntityReferenceResolver.vehicleKey(sourceEvent)); event.put("sourceKind", firstNonBlank(text(raw, "sourceKind"), sourceKind(sourceEvent))); event.put("odometerKm", odometerKm(sourceEvent, raw)); return event; diff --git a/src/main/java/at/procon/eventhub/processing/eventprocessing/support/RuntimeSupportEvidenceNormalizer.java b/src/main/java/at/procon/eventhub/processing/eventprocessing/support/RuntimeSupportEvidenceNormalizer.java index 10f6b95..3f04b4a 100644 --- a/src/main/java/at/procon/eventhub/processing/eventprocessing/support/RuntimeSupportEvidenceNormalizer.java +++ b/src/main/java/at/procon/eventhub/processing/eventprocessing/support/RuntimeSupportEvidenceNormalizer.java @@ -8,7 +8,7 @@ import at.procon.eventhub.dto.EventLifecycle; import at.procon.eventhub.dto.EventType; import at.procon.eventhub.dto.GeoPointDto; import at.procon.eventhub.dto.VehicleRefDto; -import at.procon.eventhub.processing.support.TachographRuntimeIdentityResolver; +import at.procon.eventhub.processing.support.RuntimeEntityReferenceResolver; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -82,9 +82,9 @@ public class RuntimeSupportEvidenceNormalizer { event.eventDomain() == null ? null : event.eventDomain().name(), event.eventType() == null ? null : event.eventType().name(), event.lifecycle() == null ? null : event.lifecycle().name(), - firstNonBlank(TachographRuntimeIdentityResolver.driverKey(event), fallbackDriverKey), - TachographRuntimeIdentityResolver.vehicleKey(event), - TachographRuntimeIdentityResolver.registrationKey(event), + firstNonBlank(RuntimeEntityReferenceResolver.driverKey(event), fallbackDriverKey), + RuntimeEntityReferenceResolver.vehicleKey(event), + RuntimeEntityReferenceResolver.registrationKey(event), event.occurredAt(), event.occurredAt() == null ? null : event.occurredAt().toEpochSecond(), latitude, @@ -288,7 +288,7 @@ public class RuntimeSupportEvidenceNormalizer { } private JsonNode rawPayload(EventHubEventDto event) { - return TachographRuntimeIdentityResolver.rawPayload(event); + return RuntimeEntityReferenceResolver.rawPayload(event); } private String detailText(EventHubEventDto event, String field) { diff --git a/src/main/java/at/procon/eventhub/processing/model/RuntimeActivityInterval.java b/src/main/java/at/procon/eventhub/processing/model/RuntimeActivityInterval.java new file mode 100644 index 0000000..8b2133d --- /dev/null +++ b/src/main/java/at/procon/eventhub/processing/model/RuntimeActivityInterval.java @@ -0,0 +1,99 @@ +package at.procon.eventhub.processing.model; + +import java.time.Duration; +import java.time.OffsetDateTime; +import java.util.List; + +public record RuntimeActivityInterval( + String intervalId, + OffsetDateTime from, + OffsetDateTime to, + long durationSeconds, + String activityType, + String slot, + String cardStatus, + String drivingStatus, + String registrationKey, + String vehicleKey, + String sourceKind, + List sourceIntervalIds, + boolean synthetic, + boolean clippedToRequestedPeriod, + String level +) { + public static RuntimeActivityInterval raw( + String intervalId, + OffsetDateTime from, + OffsetDateTime to, + String activityType, + String slot, + String cardStatus, + String drivingStatus, + String registrationKey, + String vehicleKey, + String sourceKind, + List sourceIntervalIds + ) { + return new RuntimeActivityInterval( + intervalId, + from, + to, + Duration.between(from, to).getSeconds(), + activityType, + slot, + cardStatus, + drivingStatus, + registrationKey, + vehicleKey, + sourceKind, + sourceIntervalIds == null ? List.of() : List.copyOf(sourceIntervalIds), + false, + false, + "RAW_INTERVAL" + ); + } + + public RuntimeActivityInterval withTime(OffsetDateTime newFrom, OffsetDateTime newTo, boolean clipped) { + return new RuntimeActivityInterval( + intervalId, + newFrom, + newTo, + Duration.between(newFrom, newTo).getSeconds(), + activityType, + slot, + cardStatus, + drivingStatus, + registrationKey, + vehicleKey, + sourceKind, + sourceIntervalIds, + synthetic, + clipped, + level + ); + } + + public RuntimeActivityInterval asMerged( + String mergedIntervalId, + OffsetDateTime newTo, + List mergedSourceIntervalIds + ) { + return new RuntimeActivityInterval( + mergedIntervalId, + from, + newTo, + Duration.between(from, newTo).getSeconds(), + activityType, + slot, + cardStatus, + drivingStatus, + registrationKey, + vehicleKey, + sourceKind, + mergedSourceIntervalIds == null ? List.of() : List.copyOf(mergedSourceIntervalIds), + synthetic, + clippedToRequestedPeriod, + "MERGED_ACTIVITY" + ); + } +} \ No newline at end of file diff --git a/src/main/java/at/procon/eventhub/processing/model/RuntimeDriverTimeline.java b/src/main/java/at/procon/eventhub/processing/model/RuntimeDriverTimeline.java new file mode 100644 index 0000000..08d6805 --- /dev/null +++ b/src/main/java/at/procon/eventhub/processing/model/RuntimeDriverTimeline.java @@ -0,0 +1,15 @@ +package at.procon.eventhub.processing.model; + +import java.time.OffsetDateTime; +import java.util.List; + +public record RuntimeDriverTimeline( + String sourceKind, + OffsetDateTime loadedFrom, + OffsetDateTime loadedTo, + List vehicleUsageIntervals, + List activityIntervals, + List supportEvents, + List warnings +) { +} \ No newline at end of file diff --git a/src/main/java/at/procon/eventhub/processing/model/RuntimeExtractionWarning.java b/src/main/java/at/procon/eventhub/processing/model/RuntimeExtractionWarning.java new file mode 100644 index 0000000..2643cc0 --- /dev/null +++ b/src/main/java/at/procon/eventhub/processing/model/RuntimeExtractionWarning.java @@ -0,0 +1,8 @@ +package at.procon.eventhub.processing.model; + +public record RuntimeExtractionWarning( + String code, + String message, + String rawRecordPath +) { +} \ No newline at end of file diff --git a/src/main/java/at/procon/eventhub/processing/model/RuntimeSupportEvent.java b/src/main/java/at/procon/eventhub/processing/model/RuntimeSupportEvent.java new file mode 100644 index 0000000..b1bc395 --- /dev/null +++ b/src/main/java/at/procon/eventhub/processing/model/RuntimeSupportEvent.java @@ -0,0 +1,30 @@ +package at.procon.eventhub.processing.model; + +import java.math.BigDecimal; +import java.time.OffsetDateTime; + +public record RuntimeSupportEvent( + String eventId, + String driverKey, + OffsetDateTime occurredAt, + String eventDomain, + String eventType, + String eventLifecycle, + String slot, + String registrationKey, + String vehicleKey, + String country, + String region, + String countryFrom, + String countryTo, + String operation, + BigDecimal latitude, + BigDecimal longitude, + String authenticationStatus, + Long odometerKm, + String code, + BigDecimal avgSpeedKmh, + BigDecimal maxSpeedKmh, + String rawRecordPath +) { +} \ No newline at end of file diff --git a/src/main/java/at/procon/eventhub/processing/model/RuntimeVehicleUsageInterval.java b/src/main/java/at/procon/eventhub/processing/model/RuntimeVehicleUsageInterval.java new file mode 100644 index 0000000..2979af4 --- /dev/null +++ b/src/main/java/at/procon/eventhub/processing/model/RuntimeVehicleUsageInterval.java @@ -0,0 +1,50 @@ +package at.procon.eventhub.processing.model; + +import java.time.Duration; +import java.time.OffsetDateTime; +import java.util.List; +import java.util.UUID; + +public record RuntimeVehicleUsageInterval( + UUID sessionId, + String driverKey, + String intervalId, + OffsetDateTime from, + OffsetDateTime to, + long durationSeconds, + Long odometerBeginKm, + Long odometerEndKm, + String registrationKey, + String vehicleKey, + String sourceKind, + List sourceIntervalIds +) { + public static RuntimeVehicleUsageInterval resolved( + UUID sessionId, + String driverKey, + String intervalId, + OffsetDateTime from, + OffsetDateTime to, + Long odometerBeginKm, + Long odometerEndKm, + String registrationKey, + String vehicleKey, + String sourceKind, + List sourceIntervalIds + ) { + return new RuntimeVehicleUsageInterval( + sessionId, + driverKey, + intervalId, + from, + to, + to == null ? 0L : Duration.between(from, to).getSeconds(), + odometerBeginKm, + odometerEndKm, + registrationKey, + vehicleKey, + sourceKind, + sourceIntervalIds == null ? List.of() : List.copyOf(sourceIntervalIds) + ); + } +} \ No newline at end of file diff --git a/src/main/java/at/procon/eventhub/processing/service/RuntimeDriverVehicleEvidenceAttachmentService.java b/src/main/java/at/procon/eventhub/processing/service/RuntimeDriverVehicleEvidenceAttachmentService.java index 69ff7f0..87f59e0 100644 --- a/src/main/java/at/procon/eventhub/processing/service/RuntimeDriverVehicleEvidenceAttachmentService.java +++ b/src/main/java/at/procon/eventhub/processing/service/RuntimeDriverVehicleEvidenceAttachmentService.java @@ -7,12 +7,12 @@ import at.procon.eventhub.processing.dto.RuntimeVehicleEvidenceAttachmentDecisio import at.procon.eventhub.processing.dto.RuntimeVehicleUsageIntervalDebugDto; import at.procon.eventhub.processing.eventprocessing.partition.RuntimeEventScopeClassifier; import at.procon.eventhub.processing.eventprocessing.partition.RuntimeEventScopeType; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; import at.procon.eventhub.processing.model.RuntimeDriverVehicleEvidenceAttachmentResult; +import at.procon.eventhub.processing.model.RuntimeVehicleUsageInterval; +import at.procon.eventhub.processing.support.RuntimeDriverWorkingTimeAdapter; import at.procon.eventhub.processing.support.RuntimeEventIdentityResolver; -import at.procon.eventhub.processing.support.TachographRuntimeIdentityResolver; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; -import at.procon.eventhub.tachographfilesession.model.ResolvedVehicleUsageInterval; -import at.procon.eventhub.tachographfilesession.service.TachographDriverWorkingTimeAdapter; +import at.procon.eventhub.processing.support.RuntimeEntityReferenceResolver; import com.fasterxml.jackson.databind.JsonNode; import java.time.OffsetDateTime; import java.util.ArrayList; @@ -63,14 +63,14 @@ public class RuntimeDriverVehicleEvidenceAttachmentService { int vehicleEvidencePaddingMinutes, boolean includeDebug ) { - ResolvedDriverTimeline timeline = timelineReconstructor.reconstruct( + RuntimeDriverTimeline timeline = timelineReconstructor.reconstruct( null, driverKey, directDriverEvents == null ? List.of() : directDriverEvents ); List vehicleUsageIntervals = mergeVehicleUsageIntervals(timeline.vehicleUsageIntervals()) .stream() - .map(TachographDriverWorkingTimeAdapter::toVehicleUsageInterval) + .map(RuntimeDriverWorkingTimeAdapter::toVehicleUsageInterval) .filter(Objects::nonNull) .toList(); return attachVehicleEvidence( @@ -277,8 +277,8 @@ public class RuntimeDriverVehicleEvidenceAttachmentService { private Set vehicleKeys(EventHubEventDto event) { LinkedHashSet result = new LinkedHashSet<>(); - String vehicleKey = TachographRuntimeIdentityResolver.vehicleKey(event); - String registrationKey = TachographRuntimeIdentityResolver.registrationKey(event); + String vehicleKey = RuntimeEntityReferenceResolver.vehicleKey(event); + String registrationKey = RuntimeEntityReferenceResolver.registrationKey(event); add(result, vehicleKey); add(result, registrationKey); if (vehicleKey != null) { @@ -316,22 +316,22 @@ public class RuntimeDriverVehicleEvidenceAttachmentService { } } - private List mergeVehicleUsageIntervals(List intervals) { + private List mergeVehicleUsageIntervals(List intervals) { if (intervals == null || intervals.isEmpty()) { return List.of(); } - List sorted = intervals.stream() - .sorted(Comparator.comparing(ResolvedVehicleUsageInterval::from, Comparator.nullsLast(Comparator.naturalOrder())) - .thenComparing(ResolvedVehicleUsageInterval::to, Comparator.nullsLast(Comparator.naturalOrder())) - .thenComparing(ResolvedVehicleUsageInterval::intervalId, Comparator.nullsLast(String::compareTo))) + List sorted = intervals.stream() + .sorted(Comparator.comparing(RuntimeVehicleUsageInterval::from, Comparator.nullsLast(Comparator.naturalOrder())) + .thenComparing(RuntimeVehicleUsageInterval::to, Comparator.nullsLast(Comparator.naturalOrder())) + .thenComparing(RuntimeVehicleUsageInterval::intervalId, Comparator.nullsLast(String::compareTo))) .toList(); - List merged = new ArrayList<>(); - for (ResolvedVehicleUsageInterval next : sorted) { + List merged = new ArrayList<>(); + for (RuntimeVehicleUsageInterval next : sorted) { if (merged.isEmpty()) { merged.add(next); continue; } - ResolvedVehicleUsageInterval current = merged.get(merged.size() - 1); + RuntimeVehicleUsageInterval current = merged.get(merged.size() - 1); if (canMerge(current, next)) { merged.set(merged.size() - 1, merge(current, next)); } else { @@ -341,7 +341,7 @@ public class RuntimeDriverVehicleEvidenceAttachmentService { return List.copyOf(merged); } - private boolean canMerge(ResolvedVehicleUsageInterval left, ResolvedVehicleUsageInterval right) { + private boolean canMerge(RuntimeVehicleUsageInterval left, RuntimeVehicleUsageInterval right) { if (left == null || right == null || left.to() == null || right.from() == null) { return false; } @@ -351,7 +351,7 @@ public class RuntimeDriverVehicleEvidenceAttachmentService { && !right.from().isAfter(left.to().plusSeconds(1)); } - private ResolvedVehicleUsageInterval merge(ResolvedVehicleUsageInterval left, ResolvedVehicleUsageInterval right) { + private RuntimeVehicleUsageInterval merge(RuntimeVehicleUsageInterval left, RuntimeVehicleUsageInterval right) { LinkedHashSet sourceIntervalIds = new LinkedHashSet<>(); if (left.sourceIntervalIds() != null) { sourceIntervalIds.addAll(left.sourceIntervalIds()); @@ -363,7 +363,7 @@ public class RuntimeDriverVehicleEvidenceAttachmentService { if (right.to() != null && (end == null || right.to().isAfter(end))) { end = right.to(); } - return ResolvedVehicleUsageInterval.resolved( + return RuntimeVehicleUsageInterval.resolved( left.sessionId(), left.driverKey(), left.intervalId(), diff --git a/src/main/java/at/procon/eventhub/processing/service/RuntimeDriverWorkingTimeScopeProcessingService.java b/src/main/java/at/procon/eventhub/processing/service/RuntimeDriverWorkingTimeScopeProcessingService.java index 2901f1b..3628143 100644 --- a/src/main/java/at/procon/eventhub/processing/service/RuntimeDriverWorkingTimeScopeProcessingService.java +++ b/src/main/java/at/procon/eventhub/processing/service/RuntimeDriverWorkingTimeScopeProcessingService.java @@ -11,7 +11,7 @@ import at.procon.eventhub.processing.model.RuntimeDriverVehicleEvidenceAttachmen import at.procon.eventhub.processing.model.UnifiedRuntimeEventBundle; import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest; import at.procon.eventhub.processing.support.RuntimeEventIdentityResolver; -import at.procon.eventhub.processing.support.TachographRuntimeIdentityResolver; +import at.procon.eventhub.processing.support.RuntimeEntityReferenceResolver; import com.fasterxml.jackson.databind.JsonNode; import java.util.ArrayList; import java.util.Comparator; @@ -276,7 +276,7 @@ public class RuntimeDriverWorkingTimeScopeProcessingService { } private String driverKey(EventHubEventDto event) { - return TachographRuntimeIdentityResolver.driverKey(event); + return RuntimeEntityReferenceResolver.driverKey(event); } private JsonNode rawPayload(EventHubEventDto event) { diff --git a/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedDriverTimelineSource.java b/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedDriverTimelineSource.java index c105d79..96792d0 100644 --- a/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedDriverTimelineSource.java +++ b/src/main/java/at/procon/eventhub/processing/service/TachographFileSessionUnifiedDriverTimelineSource.java @@ -1,9 +1,10 @@ package at.procon.eventhub.processing.service; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; import at.procon.eventhub.processing.model.UnifiedDriverTimelineRequest; import at.procon.eventhub.processing.model.UnifiedEventSourceFamily; +import at.procon.eventhub.tachographfilesession.support.RuntimeTimelineCompatibilityAdapter; import at.procon.eventhub.tachographfilesession.model.DriverExtractionSession; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; import at.procon.eventhub.tachographfilesession.model.TachographFileSession; import at.procon.eventhub.tachographfilesession.service.DriverNotFoundInSessionException; import at.procon.eventhub.tachographfilesession.service.EventBackedDriverTimelineBuilder; @@ -31,13 +32,15 @@ public class TachographFileSessionUnifiedDriverTimelineSource implements Unified } @Override - public ResolvedDriverTimeline loadDriverTimeline(UnifiedDriverTimelineRequest request) { + public RuntimeDriverTimeline loadDriverTimeline(UnifiedDriverTimelineRequest request) { TachographFileSession session = repository.find(request.sessionId()) .orElseThrow(() -> new TachographFileSessionNotFoundException(request.sessionId())); DriverExtractionSession driver = session.driversByKey().get(request.driverKey()); if (driver == null) { throw new DriverNotFoundInSessionException(request.sessionId(), request.driverKey()); } - return eventBackedDriverTimelineBuilder.build(session, driver); + return RuntimeTimelineCompatibilityAdapter.fromResolvedDriverTimeline( + eventBackedDriverTimelineBuilder.build(session, driver) + ); } } diff --git a/src/main/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineService.java b/src/main/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineService.java index b1166a9..e213e1a 100644 --- a/src/main/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineService.java +++ b/src/main/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineService.java @@ -1,7 +1,7 @@ package at.procon.eventhub.processing.service; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; import at.procon.eventhub.processing.model.UnifiedDriverTimelineRequest; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; import java.util.List; import org.springframework.stereotype.Service; @@ -14,7 +14,7 @@ public class UnifiedDriverTimelineService { this.timelineSources = List.copyOf(timelineSources); } - public ResolvedDriverTimeline loadDriverTimeline(UnifiedDriverTimelineRequest request) { + public RuntimeDriverTimeline loadDriverTimeline(UnifiedDriverTimelineRequest request) { return timelineSources.stream() .filter(source -> source.supports(request)) .findFirst() diff --git a/src/main/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineSource.java b/src/main/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineSource.java index 0c94754..ce940dc 100644 --- a/src/main/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineSource.java +++ b/src/main/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineSource.java @@ -1,11 +1,11 @@ package at.procon.eventhub.processing.service; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; import at.procon.eventhub.processing.model.UnifiedDriverTimelineRequest; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; public interface UnifiedDriverTimelineSource { boolean supports(UnifiedDriverTimelineRequest request); - ResolvedDriverTimeline loadDriverTimeline(UnifiedDriverTimelineRequest request); + RuntimeDriverTimeline loadDriverTimeline(UnifiedDriverTimelineRequest request); } diff --git a/src/main/java/at/procon/eventhub/processing/service/UnifiedEventTimelineReconstructor.java b/src/main/java/at/procon/eventhub/processing/service/UnifiedEventTimelineReconstructor.java index 8238a5e..354b44f 100644 --- a/src/main/java/at/procon/eventhub/processing/service/UnifiedEventTimelineReconstructor.java +++ b/src/main/java/at/procon/eventhub/processing/service/UnifiedEventTimelineReconstructor.java @@ -4,13 +4,13 @@ import at.procon.eventhub.dto.EventDomain; import at.procon.eventhub.dto.EventHubEventDto; import at.procon.eventhub.dto.EventLifecycle; import at.procon.eventhub.dto.EventType; +import at.procon.eventhub.processing.model.RuntimeActivityInterval; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; +import at.procon.eventhub.processing.model.RuntimeExtractionWarning; +import at.procon.eventhub.processing.model.RuntimeSupportEvent; +import at.procon.eventhub.processing.model.RuntimeVehicleUsageInterval; import at.procon.eventhub.processing.support.RuntimeEventIdentityResolver; -import at.procon.eventhub.processing.support.TachographRuntimeIdentityResolver; -import at.procon.eventhub.tachographfilesession.model.ExtractedSupportEvent; -import at.procon.eventhub.tachographfilesession.model.ExtractionWarning; -import at.procon.eventhub.tachographfilesession.model.ResolvedActivityInterval; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; -import at.procon.eventhub.tachographfilesession.model.ResolvedVehicleUsageInterval; +import at.procon.eventhub.processing.support.RuntimeEntityReferenceResolver; import com.fasterxml.jackson.databind.JsonNode; import java.math.BigDecimal; import java.time.Duration; @@ -27,7 +27,7 @@ import org.springframework.stereotype.Service; @Service public class UnifiedEventTimelineReconstructor { - public ResolvedDriverTimeline reconstruct( + public RuntimeDriverTimeline reconstruct( UUID sessionId, String driverKey, List events @@ -35,23 +35,23 @@ public class UnifiedEventTimelineReconstructor { return reconstruct(sessionId, driverKey, events, List.of(), null); } - public ResolvedDriverTimeline reconstruct( + public RuntimeDriverTimeline reconstruct( UUID sessionId, String driverKey, List events, - List warnings, + List warnings, String sourceKind ) { List safeEvents = events == null ? List.of() : List.copyOf(events); - List activityIntervals = reconstructActivityIntervals(safeEvents); - List vehicleUsageIntervals = + List activityIntervals = reconstructActivityIntervals(safeEvents); + List vehicleUsageIntervals = reconstructVehicleUsageIntervals(sessionId, driverKey, safeEvents); - List supportEvents = reconstructSupportEvents(safeEvents); - List mergedWarnings = warnings == null ? List.of() : List.copyOf(new LinkedHashSet<>(warnings)); + List supportEvents = reconstructSupportEvents(safeEvents); + List mergedWarnings = warnings == null ? List.of() : List.copyOf(new LinkedHashSet<>(warnings)); OffsetDateTime loadedFrom = minTimestamp(activityIntervals, vehicleUsageIntervals, supportEvents); OffsetDateTime loadedTo = maxTimestamp(activityIntervals, vehicleUsageIntervals, supportEvents); - return new ResolvedDriverTimeline( + return new RuntimeDriverTimeline( resolveSourceKind(safeEvents, sourceKind), loadedFrom, loadedTo, @@ -62,7 +62,7 @@ public class UnifiedEventTimelineReconstructor { ); } - private List reconstructActivityIntervals(List events) { + private List reconstructActivityIntervals(List events) { Map byIntervalId = new LinkedHashMap<>(); for (EventHubEventDto event : events) { if (event.eventDomain() != EventDomain.DRIVER_ACTIVITY) { @@ -83,13 +83,13 @@ public class UnifiedEventTimelineReconstructor { return byIntervalId.values().stream() .map(ActivityAccumulator::finish) .filter(interval -> interval != null) - .sorted(Comparator.comparing(ResolvedActivityInterval::from) - .thenComparing(ResolvedActivityInterval::to) - .thenComparing(ResolvedActivityInterval::activityType, Comparator.nullsLast(String::compareTo))) + .sorted(Comparator.comparing(RuntimeActivityInterval::from) + .thenComparing(RuntimeActivityInterval::to) + .thenComparing(RuntimeActivityInterval::activityType, Comparator.nullsLast(String::compareTo))) .toList(); } - private List reconstructVehicleUsageIntervals( + private List reconstructVehicleUsageIntervals( UUID sessionId, String driverKey, List events @@ -117,13 +117,13 @@ public class UnifiedEventTimelineReconstructor { return byIntervalId.values().stream() .map(VehicleUsageAccumulator::finish) .filter(interval -> interval != null) - .sorted(Comparator.comparing(ResolvedVehicleUsageInterval::from) - .thenComparing(ResolvedVehicleUsageInterval::to, Comparator.nullsLast(Comparator.naturalOrder()))) + .sorted(Comparator.comparing(RuntimeVehicleUsageInterval::from) + .thenComparing(RuntimeVehicleUsageInterval::to, Comparator.nullsLast(Comparator.naturalOrder()))) .toList(); } - private List reconstructSupportEvents(List events) { - List result = new ArrayList<>(); + private List reconstructSupportEvents(List events) { + List result = new ArrayList<>(); for (EventHubEventDto event : events) { if (event.eventDomain() == EventDomain.DRIVER_ACTIVITY) { continue; @@ -136,16 +136,16 @@ public class UnifiedEventTimelineReconstructor { String eventId = firstNonBlank(text(raw, "supportEventId"), event.externalSourceEventId()); BigDecimal latitude = event.position() == null ? null : event.position().latitude(); BigDecimal longitude = event.position() == null ? null : event.position().longitude(); - result.add(new ExtractedSupportEvent( + result.add(new RuntimeSupportEvent( eventId, - TachographRuntimeIdentityResolver.driverKey(event), + RuntimeEntityReferenceResolver.driverKey(event), event.occurredAt(), event.eventDomain().name(), text(raw, "supportEventType") == null ? event.eventType().name() : text(raw, "supportEventType"), event.lifecycle().name(), text(raw, "slot"), - TachographRuntimeIdentityResolver.registrationKey(event), - TachographRuntimeIdentityResolver.vehicleKey(event), + RuntimeEntityReferenceResolver.registrationKey(event), + RuntimeEntityReferenceResolver.vehicleKey(event), firstNonBlank(text(raw, "country"), detailText(event, "country")), text(raw, "region"), firstNonBlank(text(raw, "countryFrom"), detailText(event, "countryFrom")), @@ -161,9 +161,9 @@ public class UnifiedEventTimelineReconstructor { text(raw, "rawRecordPath") )); } - result.sort(Comparator.comparing(ExtractedSupportEvent::occurredAt) - .thenComparing(ExtractedSupportEvent::eventDomain, Comparator.nullsLast(String::compareTo)) - .thenComparing(ExtractedSupportEvent::eventId, Comparator.nullsLast(String::compareTo))); + result.sort(Comparator.comparing(RuntimeSupportEvent::occurredAt) + .thenComparing(RuntimeSupportEvent::eventDomain, Comparator.nullsLast(String::compareTo)) + .thenComparing(RuntimeSupportEvent::eventId, Comparator.nullsLast(String::compareTo))); return List.copyOf(result); } @@ -189,36 +189,36 @@ public class UnifiedEventTimelineReconstructor { } private OffsetDateTime minTimestamp( - List activityIntervals, - List vehicleUsageIntervals, - List supportEvents + List activityIntervals, + List vehicleUsageIntervals, + List supportEvents ) { OffsetDateTime min = null; - for (ResolvedActivityInterval interval : activityIntervals) { + for (RuntimeActivityInterval interval : activityIntervals) { min = min(min, interval.from()); } - for (ResolvedVehicleUsageInterval interval : vehicleUsageIntervals) { + for (RuntimeVehicleUsageInterval interval : vehicleUsageIntervals) { min = min(min, interval.from()); } - for (ExtractedSupportEvent supportEvent : supportEvents) { + for (RuntimeSupportEvent supportEvent : supportEvents) { min = min(min, supportEvent.occurredAt()); } return min; } private OffsetDateTime maxTimestamp( - List activityIntervals, - List vehicleUsageIntervals, - List supportEvents + List activityIntervals, + List vehicleUsageIntervals, + List supportEvents ) { OffsetDateTime max = null; - for (ResolvedActivityInterval interval : activityIntervals) { + for (RuntimeActivityInterval interval : activityIntervals) { max = max(max, interval.to()); } - for (ResolvedVehicleUsageInterval interval : vehicleUsageIntervals) { + for (RuntimeVehicleUsageInterval interval : vehicleUsageIntervals) { max = max(max, interval.to()); } - for (ExtractedSupportEvent supportEvent : supportEvents) { + for (RuntimeSupportEvent supportEvent : supportEvents) { max = max(max, supportEvent.occurredAt()); } return max; @@ -370,11 +370,11 @@ public class UnifiedEventTimelineReconstructor { } } - private ResolvedActivityInterval finish() { + private RuntimeActivityInterval finish() { if (sample == null || startedAt == null || endedAt == null || !endedAt.isAfter(startedAt)) { return null; } - return new ResolvedActivityInterval( + return new RuntimeActivityInterval( intervalId, startedAt, endedAt, @@ -383,8 +383,8 @@ public class UnifiedEventTimelineReconstructor { detailText(sample, "cardSlot"), detailText(sample, "cardStatus"), detailText(sample, "drivingStatus"), - TachographRuntimeIdentityResolver.registrationKey(sample), - TachographRuntimeIdentityResolver.vehicleKey(sample), + RuntimeEntityReferenceResolver.registrationKey(sample), + RuntimeEntityReferenceResolver.vehicleKey(sample), text(raw, "sourceKind"), stringList(raw, "sourceRowIds"), booleanValue(raw, "synthetic"), @@ -427,11 +427,11 @@ public class UnifiedEventTimelineReconstructor { } } - private ResolvedVehicleUsageInterval finish() { + private RuntimeVehicleUsageInterval finish() { if (startedAt == null) { return null; } - return ResolvedVehicleUsageInterval.resolved( + return RuntimeVehicleUsageInterval.resolved( sessionId, driverKey, intervalId, @@ -439,8 +439,8 @@ public class UnifiedEventTimelineReconstructor { endedAt, odometerBeginKm, odometerEndKm, - sample == null ? null : TachographRuntimeIdentityResolver.registrationKey(sample), - sample == null ? null : TachographRuntimeIdentityResolver.vehicleKey(sample), + sample == null ? null : RuntimeEntityReferenceResolver.registrationKey(sample), + sample == null ? null : RuntimeEntityReferenceResolver.vehicleKey(sample), text(raw, "sourceKind"), stringList(raw, "sourceRowIds") ); diff --git a/src/main/java/at/procon/eventhub/processing/service/UnifiedRuntimeDerivedProjectionService.java b/src/main/java/at/procon/eventhub/processing/service/UnifiedRuntimeDerivedProjectionService.java index 63d20e0..9aecec3 100644 --- a/src/main/java/at/procon/eventhub/processing/service/UnifiedRuntimeDerivedProjectionService.java +++ b/src/main/java/at/procon/eventhub/processing/service/UnifiedRuntimeDerivedProjectionService.java @@ -13,14 +13,13 @@ import at.procon.eventhub.processing.driverworkingtime.service.DriverWorkingTime import at.procon.eventhub.processing.driverworkingtime.service.DriverWorkingTimeProcessingCore; import at.procon.eventhub.processing.driverworkingtime.service.DriverWorkingTimeReusableProjectionBuilder; import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceNormalizationResult; -import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceEvent; import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceNormalizer; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; +import at.procon.eventhub.processing.model.RuntimeSupportEvent; import at.procon.eventhub.processing.model.UnifiedRuntimeEventBundle; import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest; import at.procon.eventhub.processing.driverworkingtime.dto.DriverWorkingTimeProcessingResultDto; -import at.procon.eventhub.tachographfilesession.service.TachographDriverWorkingTimeAdapter; -import at.procon.eventhub.tachographfilesession.model.ExtractedSupportEvent; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; +import at.procon.eventhub.processing.support.RuntimeDriverWorkingTimeAdapter; import at.procon.eventhub.tachographfilesession.model.TachographEsperActivityIntervalEvent; import at.procon.eventhub.tachographfilesession.model.TachographEsperDailyWeeklyRestCandidateCoverageIntervalEvent; import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingDerivedProjectionBundle; @@ -31,7 +30,7 @@ import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialIn import at.procon.eventhub.tachographfilesession.model.TachographEsperSupportGeoEvent; import at.procon.eventhub.tachographfilesession.model.TachographEsperVehicleUsageIntervalEvent; import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent; -import at.procon.eventhub.processing.support.TachographRuntimeIdentityResolver; +import at.procon.eventhub.processing.support.RuntimeEntityReferenceResolver; import java.time.Duration; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -107,7 +106,7 @@ public class UnifiedRuntimeDerivedProjectionService { eventBundle.mergedEvents() ); List normalizedEvents = normalizationResult.normalizedEvents(); - ResolvedDriverTimeline timeline = timelineReconstructor.reconstruct( + RuntimeDriverTimeline timeline = timelineReconstructor.reconstruct( runtimeSessionId(request), driverKey, normalizedEvents @@ -150,7 +149,7 @@ public class UnifiedRuntimeDerivedProjectionService { significantDrivingMinutes, minimumRestPeriodMinutes, timeline.activityIntervals().stream() - .map(interval -> TachographDriverWorkingTimeAdapter.toActivityInterval( + .map(interval -> RuntimeDriverWorkingTimeAdapter.toActivityInterval( runtimeSessionId(request), driverKey, interval @@ -158,11 +157,11 @@ public class UnifiedRuntimeDerivedProjectionService { .filter(Objects::nonNull) .toList(), timeline.vehicleUsageIntervals().stream() - .map(TachographDriverWorkingTimeAdapter::toVehicleUsageInterval) + .map(RuntimeDriverWorkingTimeAdapter::toVehicleUsageInterval) .filter(Objects::nonNull) .toList(), timeline.supportEvents().stream() - .map(this::toSupportEvidenceEvent) + .map(RuntimeDriverWorkingTimeAdapter::toSupportEvidenceEvent) .filter(Objects::nonNull) .toList(), notes @@ -207,41 +206,11 @@ public class UnifiedRuntimeDerivedProjectionService { return request.sessionIds().size() == 1 ? request.sessionIds().get(0) : request.sessionId(); } - private RuntimeSupportEvidenceEvent toSupportEvidenceEvent(ExtractedSupportEvent supportEvent) { - if (supportEvent == null || supportEvent.occurredAt() == null) { - return null; - } - return new RuntimeSupportEvidenceEvent( - supportEvent.eventId(), - null, - null, - supportEvent.eventDomain(), - supportEvent.eventType(), - supportEvent.eventLifecycle(), - supportEvent.driverKey(), - supportEvent.vehicleKey(), - supportEvent.registrationKey(), - supportEvent.occurredAt(), - supportEvent.occurredAt().toEpochSecond(), - supportEvent.latitude(), - supportEvent.longitude(), - supportEvent.country(), - supportEvent.region(), - supportEvent.countryFrom(), - supportEvent.countryTo(), - supportEvent.operation(), - supportEvent.odometerKm(), - supportEvent.avgSpeedKmh(), - supportEvent.maxSpeedKmh(), - java.util.Map.of("rawRecordPath", supportEvent.rawRecordPath()) - ); - } - private String resolveDriverKey( UnifiedRuntimeProcessingRequest request, List events ) { - return TachographRuntimeIdentityResolver.requestDriverKey(request, events); + return RuntimeEntityReferenceResolver.requestDriverKey(request, events); } @@ -436,12 +405,12 @@ public class UnifiedRuntimeDerivedProjectionService { } private List clipSupportGeoEvents( - List supportEvents, + List supportEvents, String driverKey, OffsetDateTime requestedFrom, OffsetDateTime requestedTo ) { - return (supportEvents == null ? List.of() : supportEvents).stream() + return (supportEvents == null ? List.of() : supportEvents).stream() .filter(event -> event.occurredAt() != null) .filter(event -> driverKey == null || event.driverKey() == null || Objects.equals(driverKey, event.driverKey())) .filter(event -> requestedFrom == null || !event.occurredAt().isBefore(requestedFrom)) diff --git a/src/main/java/at/procon/eventhub/processing/service/UnifiedRuntimeDriverTimelineService.java b/src/main/java/at/procon/eventhub/processing/service/UnifiedRuntimeDriverTimelineService.java index c85f20e..54560e4 100644 --- a/src/main/java/at/procon/eventhub/processing/service/UnifiedRuntimeDriverTimelineService.java +++ b/src/main/java/at/procon/eventhub/processing/service/UnifiedRuntimeDriverTimelineService.java @@ -1,10 +1,10 @@ package at.procon.eventhub.processing.service; import at.procon.eventhub.dto.EventHubEventDto; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; import at.procon.eventhub.processing.model.UnifiedRuntimeEventBundle; import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest; -import at.procon.eventhub.processing.support.TachographRuntimeIdentityResolver; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; +import at.procon.eventhub.processing.support.RuntimeEntityReferenceResolver; import java.util.List; import org.springframework.stereotype.Service; @@ -22,7 +22,7 @@ public class UnifiedRuntimeDriverTimelineService { this.timelineReconstructor = timelineReconstructor; } - public ResolvedDriverTimeline loadDriverTimeline(UnifiedRuntimeProcessingRequest request) { + public RuntimeDriverTimeline loadDriverTimeline(UnifiedRuntimeProcessingRequest request) { UnifiedRuntimeEventBundle bundle = runtimeEventAssemblyService.assembleDriverScopedEvents(request); return timelineReconstructor.reconstruct( null, @@ -35,6 +35,6 @@ public class UnifiedRuntimeDriverTimelineService { UnifiedRuntimeProcessingRequest request, List events ) { - return TachographRuntimeIdentityResolver.requestDriverKey(request, events); + return RuntimeEntityReferenceResolver.requestDriverKey(request, events); } } diff --git a/src/main/java/at/procon/eventhub/processing/support/RuntimeDriverWorkingTimeAdapter.java b/src/main/java/at/procon/eventhub/processing/support/RuntimeDriverWorkingTimeAdapter.java new file mode 100644 index 0000000..bf0497c --- /dev/null +++ b/src/main/java/at/procon/eventhub/processing/support/RuntimeDriverWorkingTimeAdapter.java @@ -0,0 +1,123 @@ +package at.procon.eventhub.processing.support; + +import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeActivityInterval; +import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVehicleUsageInterval; +import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceEvent; +import at.procon.eventhub.processing.model.RuntimeActivityInterval; +import at.procon.eventhub.processing.model.RuntimeSupportEvent; +import at.procon.eventhub.processing.model.RuntimeVehicleUsageInterval; +import java.util.List; +import java.util.UUID; + +public final class RuntimeDriverWorkingTimeAdapter { + + private RuntimeDriverWorkingTimeAdapter() { + } + + public static DriverWorkingTimeActivityInterval toActivityInterval( + UUID sessionId, + String driverKey, + RuntimeActivityInterval interval + ) { + if (interval == null || interval.from() == null || interval.to() == null) { + return null; + } + return new DriverWorkingTimeActivityInterval( + sessionId, + driverKey, + interval.intervalId(), + interval.activityType(), + interval.slot(), + interval.cardStatus(), + interval.drivingStatus(), + interval.registrationKey(), + interval.vehicleKey(), + interval.sourceKind(), + firstSourceIntervalId(interval), + lastSourceIntervalId(interval), + interval.from(), + interval.to(), + interval.from().toEpochSecond(), + interval.to().toEpochSecond(), + interval.durationSeconds(), + interval.sourceIntervalIds(), + interval.synthetic(), + interval.clippedToRequestedPeriod(), + interval.level() + ); + } + + public static DriverWorkingTimeVehicleUsageInterval toVehicleUsageInterval(RuntimeVehicleUsageInterval interval) { + if (interval == null || interval.from() == null) { + return null; + } + return new DriverWorkingTimeVehicleUsageInterval( + interval.sessionId(), + interval.driverKey(), + interval.intervalId(), + firstSourceIntervalId(interval), + lastSourceIntervalId(interval), + interval.from(), + interval.to(), + interval.from().toEpochSecond(), + interval.to() == null ? null : interval.to().toEpochSecond(), + interval.durationSeconds(), + interval.odometerBeginKm(), + interval.odometerEndKm(), + interval.registrationKey(), + interval.vehicleKey(), + interval.sourceKind(), + interval.sourceIntervalIds() + ); + } + + public static RuntimeSupportEvidenceEvent toSupportEvidenceEvent(RuntimeSupportEvent supportEvent) { + if (supportEvent == null || supportEvent.occurredAt() == null) { + return null; + } + return new RuntimeSupportEvidenceEvent( + supportEvent.eventId(), + null, + null, + supportEvent.eventDomain(), + supportEvent.eventType(), + supportEvent.eventLifecycle(), + supportEvent.driverKey(), + supportEvent.vehicleKey(), + supportEvent.registrationKey(), + supportEvent.occurredAt(), + supportEvent.occurredAt().toEpochSecond(), + supportEvent.latitude(), + supportEvent.longitude(), + supportEvent.country(), + supportEvent.region(), + supportEvent.countryFrom(), + supportEvent.countryTo(), + supportEvent.operation(), + supportEvent.odometerKm(), + supportEvent.avgSpeedKmh(), + supportEvent.maxSpeedKmh(), + java.util.Map.of("rawRecordPath", supportEvent.rawRecordPath()) + ); + } + + private static String firstSourceIntervalId(RuntimeActivityInterval interval) { + return safe(interval.sourceIntervalIds()).isEmpty() ? interval.intervalId() : safe(interval.sourceIntervalIds()).getFirst(); + } + + private static String lastSourceIntervalId(RuntimeActivityInterval interval) { + return safe(interval.sourceIntervalIds()).isEmpty() ? interval.intervalId() : safe(interval.sourceIntervalIds()).getLast(); + } + + private static String firstSourceIntervalId(RuntimeVehicleUsageInterval interval) { + return safe(interval.sourceIntervalIds()).isEmpty() ? interval.intervalId() : safe(interval.sourceIntervalIds()).getFirst(); + } + + private static String lastSourceIntervalId(RuntimeVehicleUsageInterval interval) { + return safe(interval.sourceIntervalIds()).isEmpty() ? interval.intervalId() : safe(interval.sourceIntervalIds()).getLast(); + } + + private static List safe(List values) { + return values == null ? List.of() : values; + } +} \ No newline at end of file diff --git a/src/main/java/at/procon/eventhub/processing/support/TachographRuntimeIdentityResolver.java b/src/main/java/at/procon/eventhub/processing/support/RuntimeEntityReferenceResolver.java similarity index 98% rename from src/main/java/at/procon/eventhub/processing/support/TachographRuntimeIdentityResolver.java rename to src/main/java/at/procon/eventhub/processing/support/RuntimeEntityReferenceResolver.java index 62cbbbb..d617776 100644 --- a/src/main/java/at/procon/eventhub/processing/support/TachographRuntimeIdentityResolver.java +++ b/src/main/java/at/procon/eventhub/processing/support/RuntimeEntityReferenceResolver.java @@ -9,9 +9,9 @@ import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest; import com.fasterxml.jackson.databind.JsonNode; import java.util.List; -public final class TachographRuntimeIdentityResolver { +public final class RuntimeEntityReferenceResolver { - private TachographRuntimeIdentityResolver() { + private RuntimeEntityReferenceResolver() { } public static String driverKey(EventHubEventDto event) { diff --git a/src/main/java/at/procon/eventhub/processing/support/RuntimeEventIdentityResolver.java b/src/main/java/at/procon/eventhub/processing/support/RuntimeEventIdentityResolver.java index 8e90f8e..4ee4035 100644 --- a/src/main/java/at/procon/eventhub/processing/support/RuntimeEventIdentityResolver.java +++ b/src/main/java/at/procon/eventhub/processing/support/RuntimeEventIdentityResolver.java @@ -29,9 +29,9 @@ public final class RuntimeEventIdentityResolver { parts.add(nullToEmpty(event.eventType() == null ? null : event.eventType().name())); parts.add(nullToEmpty(event.lifecycle() == null ? null : event.lifecycle().name())); parts.add(normalizeTime(event.occurredAt())); - parts.add(nullToEmpty(TachographRuntimeIdentityResolver.driverKey(event))); - parts.add(nullToEmpty(TachographRuntimeIdentityResolver.registrationKey(event))); - parts.add(nullToEmpty(TachographRuntimeIdentityResolver.vehicleKey(event))); + parts.add(nullToEmpty(RuntimeEntityReferenceResolver.driverKey(event))); + parts.add(nullToEmpty(RuntimeEntityReferenceResolver.registrationKey(event))); + parts.add(nullToEmpty(RuntimeEntityReferenceResolver.vehicleKey(event))); parts.add(isIntervalPointEvent(event) ? nullToEmpty(runtimeIntervalKey(event)) : ""); parts.add(nullToEmpty(firstNonBlank(text(raw, "activityType"), event.eventType() == null ? null : event.eventType().name()))); parts.add(nullToEmpty(firstNonBlank(text(raw, "slot"), text(raw, "cardSlot"), text(details, "cardSlot")))); @@ -72,9 +72,9 @@ public final class RuntimeEventIdentityResolver { parts.add("INTERVAL"); parts.add(nullToEmpty(event.eventDomain() == null ? null : event.eventDomain().name())); parts.add(nullToEmpty(intervalSemanticType(event, raw))); - parts.add(nullToEmpty(TachographRuntimeIdentityResolver.driverKey(event))); - parts.add(nullToEmpty(TachographRuntimeIdentityResolver.registrationKey(event))); - parts.add(nullToEmpty(TachographRuntimeIdentityResolver.vehicleKey(event))); + parts.add(nullToEmpty(RuntimeEntityReferenceResolver.driverKey(event))); + parts.add(nullToEmpty(RuntimeEntityReferenceResolver.registrationKey(event))); + parts.add(nullToEmpty(RuntimeEntityReferenceResolver.vehicleKey(event))); parts.add(nullToEmpty(intervalCardSlot(event, raw, details))); parts.add(nullToEmpty(intervalCardStatus(event, raw, details))); parts.add(nullToEmpty(intervalDrivingStatus(event, raw, details))); @@ -152,7 +152,7 @@ public final class RuntimeEventIdentityResolver { } private static JsonNode rawPayload(EventHubEventDto event) { - return TachographRuntimeIdentityResolver.rawPayload(event); + return RuntimeEntityReferenceResolver.rawPayload(event); } private static JsonNode detailAttributes(EventHubEventDto event) { diff --git a/src/main/java/at/procon/eventhub/tachographfilesession/service/EventBackedDriverTimelineBuilder.java b/src/main/java/at/procon/eventhub/tachographfilesession/service/EventBackedDriverTimelineBuilder.java index 0df193b..061304f 100644 --- a/src/main/java/at/procon/eventhub/tachographfilesession/service/EventBackedDriverTimelineBuilder.java +++ b/src/main/java/at/procon/eventhub/tachographfilesession/service/EventBackedDriverTimelineBuilder.java @@ -1,5 +1,6 @@ package at.procon.eventhub.tachographfilesession.service; +import at.procon.eventhub.tachographfilesession.support.RuntimeTimelineCompatibilityAdapter; import at.procon.eventhub.processing.service.UnifiedEventTimelineReconstructor; import at.procon.eventhub.tachographfilesession.model.DriverExtractionSession; import at.procon.eventhub.tachographfilesession.model.ExtractionWarning; @@ -35,12 +36,16 @@ public class EventBackedDriverTimelineBuilder { DriverExtractionSession driverSession ) { TachographTimelineEventBundle bundle = eventBuilder.buildEventBundle(session, driverSession); - return timelineReconstructor.reconstruct( - session.sessionId(), - driverSession.driverKey(), - bundle.allEvents(), - mergeWarnings(session.warnings(), driverSession.warnings()), - fallbackSourceKind(session) + return RuntimeTimelineCompatibilityAdapter.toResolvedDriverTimeline( + timelineReconstructor.reconstruct( + session.sessionId(), + driverSession.driverKey(), + bundle.allEvents(), + mergeWarnings(session.warnings(), driverSession.warnings()).stream() + .map(RuntimeTimelineCompatibilityAdapter::fromExtractionWarning) + .toList(), + fallbackSourceKind(session) + ) ); } diff --git a/src/main/java/at/procon/eventhub/tachographfilesession/service/TachographCompositeSessionService.java b/src/main/java/at/procon/eventhub/tachographfilesession/service/TachographCompositeSessionService.java index 09fe45c..1b3a68b 100644 --- a/src/main/java/at/procon/eventhub/tachographfilesession/service/TachographCompositeSessionService.java +++ b/src/main/java/at/procon/eventhub/tachographfilesession/service/TachographCompositeSessionService.java @@ -2,6 +2,7 @@ package at.procon.eventhub.tachographfilesession.service; import at.procon.eventhub.dto.EventHubEventDto; import at.procon.eventhub.processing.service.UnifiedEventTimelineReconstructor; +import at.procon.eventhub.tachographfilesession.support.RuntimeTimelineCompatibilityAdapter; import at.procon.eventhub.service.EventAcquisitionRecordKeyService; import at.procon.eventhub.service.EventHubEventSorter; import at.procon.eventhub.tachographfilesession.dto.CreateTachographCompositeSessionRequest; @@ -119,12 +120,16 @@ public class TachographCompositeSessionService { throw new DriverNotFoundInCompositeSessionException(compositeSessionId, driverKey); } List mergedEvents = mergeDriverEvents(sourceSessions, driverKey); - return timelineReconstructor.reconstruct( - compositeSessionId, - driverKey, - mergedEvents, - mergeWarnings(sourceSessions, driverKey), - "COMPOSITE_TACHOGRAPH_FILE_SESSION" + return RuntimeTimelineCompatibilityAdapter.toResolvedDriverTimeline( + timelineReconstructor.reconstruct( + compositeSessionId, + driverKey, + mergedEvents, + mergeWarnings(sourceSessions, driverKey).stream() + .map(RuntimeTimelineCompatibilityAdapter::fromExtractionWarning) + .toList(), + "COMPOSITE_TACHOGRAPH_FILE_SESSION" + ) ); } diff --git a/src/main/java/at/procon/eventhub/tachographfilesession/service/TachographEventTimelineReconstructionHelper.java b/src/main/java/at/procon/eventhub/tachographfilesession/service/TachographEventTimelineReconstructionHelper.java index 70cfc23..4b66b1a 100644 --- a/src/main/java/at/procon/eventhub/tachographfilesession/service/TachographEventTimelineReconstructionHelper.java +++ b/src/main/java/at/procon/eventhub/tachographfilesession/service/TachographEventTimelineReconstructionHelper.java @@ -3,6 +3,7 @@ package at.procon.eventhub.tachographfilesession.service; import com.fasterxml.jackson.databind.JsonNode; import at.procon.eventhub.dto.EventHubEventDto; import at.procon.eventhub.processing.service.UnifiedEventTimelineReconstructor; +import at.procon.eventhub.tachographfilesession.support.RuntimeTimelineCompatibilityAdapter; import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; import at.procon.eventhub.tachographfilesession.model.ResolvedVehicleUsageInterval; import java.time.OffsetDateTime; @@ -51,10 +52,12 @@ public class TachographEventTimelineReconstructionHelper { String fallbackDriverKey, List events ) { - ResolvedDriverTimeline reconstructed = timelineReconstructor.reconstruct( - fallbackSessionId == null ? new UUID(0L, 0L) : fallbackSessionId, - fallbackDriverKey, - safe(events) + ResolvedDriverTimeline reconstructed = RuntimeTimelineCompatibilityAdapter.toResolvedDriverTimeline( + timelineReconstructor.reconstruct( + fallbackSessionId == null ? new UUID(0L, 0L) : fallbackSessionId, + fallbackDriverKey, + safe(events) + ) ); return new ResolvedDriverTimeline( reconstructed.sourceKind(), diff --git a/src/main/java/at/procon/eventhub/tachographfilesession/support/RuntimeTimelineCompatibilityAdapter.java b/src/main/java/at/procon/eventhub/tachographfilesession/support/RuntimeTimelineCompatibilityAdapter.java new file mode 100644 index 0000000..94275b4 --- /dev/null +++ b/src/main/java/at/procon/eventhub/tachographfilesession/support/RuntimeTimelineCompatibilityAdapter.java @@ -0,0 +1,237 @@ +package at.procon.eventhub.tachographfilesession.support; + +import at.procon.eventhub.processing.model.RuntimeActivityInterval; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; +import at.procon.eventhub.processing.model.RuntimeExtractionWarning; +import at.procon.eventhub.processing.model.RuntimeSupportEvent; +import at.procon.eventhub.processing.model.RuntimeVehicleUsageInterval; +import at.procon.eventhub.tachographfilesession.model.ExtractedSupportEvent; +import at.procon.eventhub.tachographfilesession.model.ExtractionWarning; +import at.procon.eventhub.tachographfilesession.model.ResolvedActivityInterval; +import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; +import at.procon.eventhub.tachographfilesession.model.ResolvedVehicleUsageInterval; +import java.util.List; + +public final class RuntimeTimelineCompatibilityAdapter { + + private RuntimeTimelineCompatibilityAdapter() { + } + + public static RuntimeDriverTimeline fromResolvedDriverTimeline(ResolvedDriverTimeline timeline) { + if (timeline == null) { + return null; + } + return new RuntimeDriverTimeline( + timeline.sourceKind(), + timeline.loadedFrom(), + timeline.loadedTo(), + safe(timeline.vehicleUsageIntervals()).stream() + .map(RuntimeTimelineCompatibilityAdapter::fromResolvedVehicleUsageInterval) + .toList(), + safe(timeline.activityIntervals()).stream() + .map(RuntimeTimelineCompatibilityAdapter::fromResolvedActivityInterval) + .toList(), + safe(timeline.supportEvents()).stream() + .map(RuntimeTimelineCompatibilityAdapter::fromExtractedSupportEvent) + .toList(), + safe(timeline.warnings()).stream() + .map(RuntimeTimelineCompatibilityAdapter::fromExtractionWarning) + .toList() + ); + } + + public static ResolvedDriverTimeline toResolvedDriverTimeline(RuntimeDriverTimeline timeline) { + if (timeline == null) { + return null; + } + return new ResolvedDriverTimeline( + timeline.sourceKind(), + timeline.loadedFrom(), + timeline.loadedTo(), + safe(timeline.vehicleUsageIntervals()).stream() + .map(RuntimeTimelineCompatibilityAdapter::toResolvedVehicleUsageInterval) + .toList(), + safe(timeline.activityIntervals()).stream() + .map(RuntimeTimelineCompatibilityAdapter::toResolvedActivityInterval) + .toList(), + safe(timeline.supportEvents()).stream() + .map(RuntimeTimelineCompatibilityAdapter::toExtractedSupportEvent) + .toList(), + safe(timeline.warnings()).stream() + .map(RuntimeTimelineCompatibilityAdapter::toExtractionWarning) + .toList() + ); + } + + public static RuntimeActivityInterval fromResolvedActivityInterval(ResolvedActivityInterval interval) { + if (interval == null) { + return null; + } + return new RuntimeActivityInterval( + interval.intervalId(), + interval.from(), + interval.to(), + interval.durationSeconds(), + interval.activityType(), + interval.slot(), + interval.cardStatus(), + interval.drivingStatus(), + interval.registrationKey(), + interval.vehicleKey(), + interval.sourceKind(), + interval.sourceIntervalIds(), + interval.synthetic(), + interval.clippedToRequestedPeriod(), + interval.level() + ); + } + + public static ResolvedActivityInterval toResolvedActivityInterval(RuntimeActivityInterval interval) { + if (interval == null) { + return null; + } + return new ResolvedActivityInterval( + interval.intervalId(), + interval.from(), + interval.to(), + interval.durationSeconds(), + interval.activityType(), + interval.slot(), + interval.cardStatus(), + interval.drivingStatus(), + interval.registrationKey(), + interval.vehicleKey(), + interval.sourceKind(), + interval.sourceIntervalIds(), + interval.synthetic(), + interval.clippedToRequestedPeriod(), + interval.level() + ); + } + + public static RuntimeVehicleUsageInterval fromResolvedVehicleUsageInterval(ResolvedVehicleUsageInterval interval) { + if (interval == null) { + return null; + } + return new RuntimeVehicleUsageInterval( + interval.sessionId(), + interval.driverKey(), + interval.intervalId(), + interval.from(), + interval.to(), + interval.durationSeconds(), + interval.odometerBeginKm(), + interval.odometerEndKm(), + interval.registrationKey(), + interval.vehicleKey(), + interval.sourceKind(), + interval.sourceIntervalIds() + ); + } + + public static ResolvedVehicleUsageInterval toResolvedVehicleUsageInterval(RuntimeVehicleUsageInterval interval) { + if (interval == null) { + return null; + } + return new ResolvedVehicleUsageInterval( + interval.sessionId(), + interval.driverKey(), + interval.intervalId(), + interval.from(), + interval.to(), + interval.durationSeconds(), + interval.odometerBeginKm(), + interval.odometerEndKm(), + interval.registrationKey(), + interval.vehicleKey(), + interval.sourceKind(), + interval.sourceIntervalIds() + ); + } + + public static RuntimeSupportEvent fromExtractedSupportEvent(ExtractedSupportEvent supportEvent) { + if (supportEvent == null) { + return null; + } + return new RuntimeSupportEvent( + supportEvent.eventId(), + supportEvent.driverKey(), + supportEvent.occurredAt(), + supportEvent.eventDomain(), + supportEvent.eventType(), + supportEvent.eventLifecycle(), + supportEvent.slot(), + supportEvent.registrationKey(), + supportEvent.vehicleKey(), + supportEvent.country(), + supportEvent.region(), + supportEvent.countryFrom(), + supportEvent.countryTo(), + supportEvent.operation(), + supportEvent.latitude(), + supportEvent.longitude(), + supportEvent.authenticationStatus(), + supportEvent.odometerKm(), + supportEvent.code(), + supportEvent.avgSpeedKmh(), + supportEvent.maxSpeedKmh(), + supportEvent.rawRecordPath() + ); + } + + public static ExtractedSupportEvent toExtractedSupportEvent(RuntimeSupportEvent supportEvent) { + if (supportEvent == null) { + return null; + } + return new ExtractedSupportEvent( + supportEvent.eventId(), + supportEvent.driverKey(), + supportEvent.occurredAt(), + supportEvent.eventDomain(), + supportEvent.eventType(), + supportEvent.eventLifecycle(), + supportEvent.slot(), + supportEvent.registrationKey(), + supportEvent.vehicleKey(), + supportEvent.country(), + supportEvent.region(), + supportEvent.countryFrom(), + supportEvent.countryTo(), + supportEvent.operation(), + supportEvent.latitude(), + supportEvent.longitude(), + supportEvent.authenticationStatus(), + supportEvent.odometerKm(), + supportEvent.code(), + supportEvent.avgSpeedKmh(), + supportEvent.maxSpeedKmh(), + supportEvent.rawRecordPath() + ); + } + + public static RuntimeExtractionWarning fromExtractionWarning(ExtractionWarning warning) { + if (warning == null) { + return null; + } + return new RuntimeExtractionWarning( + warning.code(), + warning.message(), + warning.rawRecordPath() + ); + } + + public static ExtractionWarning toExtractionWarning(RuntimeExtractionWarning warning) { + if (warning == null) { + return null; + } + return new ExtractionWarning( + warning.code(), + warning.message(), + warning.rawRecordPath() + ); + } + + private static List safe(List values) { + return values == null ? List.of() : values; + } +} diff --git a/src/test/java/at/procon/eventhub/processing/api/UnifiedRuntimeProcessingControllerTest.java b/src/test/java/at/procon/eventhub/processing/api/UnifiedRuntimeProcessingControllerTest.java index a801999..cb80e73 100644 --- a/src/test/java/at/procon/eventhub/processing/api/UnifiedRuntimeProcessingControllerTest.java +++ b/src/test/java/at/procon/eventhub/processing/api/UnifiedRuntimeProcessingControllerTest.java @@ -33,14 +33,14 @@ import at.procon.eventhub.processing.model.UnifiedDiscoveredVehicleRef; import at.procon.eventhub.processing.model.UnifiedEventSourceFamily; import at.procon.eventhub.processing.model.UnifiedRuntimeEventBackend; import at.procon.eventhub.processing.model.UnifiedRuntimeEventBundle; +import at.procon.eventhub.processing.model.RuntimeActivityInterval; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; +import at.procon.eventhub.processing.model.RuntimeVehicleUsageInterval; import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest; import at.procon.eventhub.processing.service.UnifiedRuntimeDerivedProjectionService; import at.procon.eventhub.processing.service.UnifiedRuntimeDriverTimelineService; import at.procon.eventhub.processing.service.UnifiedRuntimeEventAssemblyService; import at.procon.eventhub.tachographfilesession.dto.TachographEsperDriverProcessingResultDto; -import at.procon.eventhub.tachographfilesession.model.ResolvedActivityInterval; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; -import at.procon.eventhub.tachographfilesession.model.ResolvedVehicleUsageInterval; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.ObjectMapper; @@ -123,11 +123,11 @@ class UnifiedRuntimeProcessingControllerTest { .build(); when(timelineService.loadDriverTimeline(any())) - .thenReturn(new ResolvedDriverTimeline( + .thenReturn(new RuntimeDriverTimeline( "UNIFIED_EVENT_STREAM", OffsetDateTime.parse("2026-05-01T08:00:00Z"), OffsetDateTime.parse("2026-05-01T10:00:00Z"), - List.of(ResolvedVehicleUsageInterval.resolved( + List.of(RuntimeVehicleUsageInterval.resolved( null, "DRIVER:42", "CVU-1", @@ -140,7 +140,7 @@ class UnifiedRuntimeProcessingControllerTest { "DRIVER_CARD", List.of("CVU-1") )), - List.of(new ResolvedActivityInterval( + List.of(new RuntimeActivityInterval( "ACT-1", OffsetDateTime.parse("2026-05-01T08:30:00Z"), OffsetDateTime.parse("2026-05-01T09:00:00Z"), @@ -181,7 +181,6 @@ class UnifiedRuntimeProcessingControllerTest { .andExpect(jsonPath("$.vehicleUsageIntervals[0].intervalId").value("CVU-1")); } - @Test void loadsDriverDerivedProjectionsViaRuntimeApi() throws Exception { UnifiedRuntimeEventAssemblyService eventAssemblyService = org.mockito.Mockito.mock(UnifiedRuntimeEventAssemblyService.class); diff --git a/src/test/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineServiceTest.java b/src/test/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineServiceTest.java index 26b34f8..de007c0 100644 --- a/src/test/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineServiceTest.java +++ b/src/test/java/at/procon/eventhub/processing/service/UnifiedDriverTimelineServiceTest.java @@ -3,6 +3,7 @@ package at.procon.eventhub.processing.service; import static org.assertj.core.api.Assertions.assertThat; import at.procon.eventhub.config.EventHubProperties; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; import at.procon.eventhub.processing.model.UnifiedDriverTimelineRequest; import at.procon.eventhub.service.EventDetailsFactory; import at.procon.eventhub.tachographfilesession.model.DriverExtractionSession; @@ -14,7 +15,6 @@ import at.procon.eventhub.tachographfilesession.model.ExtractedSupportEvent; import at.procon.eventhub.tachographfilesession.model.ExtractedVehicle; import at.procon.eventhub.tachographfilesession.model.ExtractedVehicleRegistration; import at.procon.eventhub.tachographfilesession.model.ExtractionStats; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; import at.procon.eventhub.tachographfilesession.model.TachographFileSession; import at.procon.eventhub.tachographfilesession.model.TachographFileSessionMetadata; import at.procon.eventhub.tachographfilesession.service.DriverKeyFactory; @@ -55,7 +55,7 @@ class UnifiedDriverTimelineServiceTest { TachographFileSession session = session(driver); repository.save(session); - ResolvedDriverTimeline timeline = service.loadDriverTimeline( + RuntimeDriverTimeline timeline = service.loadDriverTimeline( UnifiedDriverTimelineRequest.forTachographFileSession(session.sessionId(), driver.driverKey()) ); diff --git a/src/test/java/at/procon/eventhub/processing/service/UnifiedEventTimelineReconstructorTest.java b/src/test/java/at/procon/eventhub/processing/service/UnifiedEventTimelineReconstructorTest.java index b110c4a..d90525c 100644 --- a/src/test/java/at/procon/eventhub/processing/service/UnifiedEventTimelineReconstructorTest.java +++ b/src/test/java/at/procon/eventhub/processing/service/UnifiedEventTimelineReconstructorTest.java @@ -14,7 +14,7 @@ import at.procon.eventhub.dto.GeoPointDto; import at.procon.eventhub.dto.ImportScopeDto; import at.procon.eventhub.dto.VehicleRefDto; import at.procon.eventhub.dto.VehicleRegistrationRefDto; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import java.math.BigDecimal; @@ -38,7 +38,7 @@ class UnifiedEventTimelineReconstructorTest { supportEvent("SUP-1", "2026-05-01T08:30:00Z") ); - ResolvedDriverTimeline timeline = reconstructor.reconstruct( + RuntimeDriverTimeline timeline = reconstructor.reconstruct( UUID.randomUUID(), "DRIVER:42", events @@ -68,7 +68,7 @@ class UnifiedEventTimelineReconstructorTest { activityEvent("VU-ACT-99", EventLifecycle.END, "2026-05-01T09:00:00Z", "2026-05-01T08:00:00Z", "2026-05-01T09:00:00Z") ); - ResolvedDriverTimeline timeline = reconstructor.reconstruct( + RuntimeDriverTimeline timeline = reconstructor.reconstruct( UUID.randomUUID(), "DRIVER:42", events @@ -105,7 +105,7 @@ class UnifiedEventTimelineReconstructorTest { ) ); - ResolvedDriverTimeline timeline = reconstructor.reconstruct( + RuntimeDriverTimeline timeline = reconstructor.reconstruct( UUID.randomUUID(), "DRIVER:42", events diff --git a/src/test/java/at/procon/eventhub/processing/service/UnifiedRuntimeDriverTimelineServiceTest.java b/src/test/java/at/procon/eventhub/processing/service/UnifiedRuntimeDriverTimelineServiceTest.java index 68692aa..c60ac72 100644 --- a/src/test/java/at/procon/eventhub/processing/service/UnifiedRuntimeDriverTimelineServiceTest.java +++ b/src/test/java/at/procon/eventhub/processing/service/UnifiedRuntimeDriverTimelineServiceTest.java @@ -16,8 +16,8 @@ import at.procon.eventhub.dto.VehicleRegistrationRefDto; import at.procon.eventhub.processing.model.UnifiedDiscoveredVehicleRef; import at.procon.eventhub.processing.model.UnifiedEventSourceFamily; import at.procon.eventhub.processing.model.UnifiedRuntimeEventBackend; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest; -import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import java.time.LocalDate; @@ -40,7 +40,7 @@ class UnifiedRuntimeDriverTimelineServiceTest { new UnifiedEventTimelineReconstructor() ); - ResolvedDriverTimeline timeline = service.loadDriverTimeline( + RuntimeDriverTimeline timeline = service.loadDriverTimeline( new UnifiedRuntimeProcessingRequest( null, List.of(), diff --git a/src/test/java/at/procon/eventhub/tachographfilesession/service/TachographCompositeSessionServiceTest.java b/src/test/java/at/procon/eventhub/tachographfilesession/service/TachographCompositeSessionServiceTest.java index 87e8511..8e2d012 100644 --- a/src/test/java/at/procon/eventhub/tachographfilesession/service/TachographCompositeSessionServiceTest.java +++ b/src/test/java/at/procon/eventhub/tachographfilesession/service/TachographCompositeSessionServiceTest.java @@ -15,6 +15,8 @@ import at.procon.eventhub.dto.EventLifecycle; import at.procon.eventhub.dto.EventType; import at.procon.eventhub.dto.VehicleRefDto; import at.procon.eventhub.dto.VehicleRegistrationRefDto; +import at.procon.eventhub.processing.model.RuntimeDriverTimeline; +import at.procon.eventhub.processing.model.RuntimeExtractionWarning; import at.procon.eventhub.processing.service.UnifiedEventTimelineReconstructor; import at.procon.eventhub.service.EventAcquisitionRecordKeyService; import at.procon.eventhub.service.EventHubEventSorter; @@ -175,7 +177,7 @@ class TachographCompositeSessionServiceTest { when(eventBuilder.buildEvents(first, firstDriver)).thenReturn(List.of(event("a", occurredAt, EventType.WORK))); when(eventBuilder.buildEvents(second, secondDriver)).thenReturn(List.of(event("b", occurredAt.plusHours(1), EventType.DRIVE))); - ResolvedDriverTimeline expected = new ResolvedDriverTimeline( + RuntimeDriverTimeline reconstructed = new RuntimeDriverTimeline( "COMPOSITE_TACHOGRAPH_FILE_SESSION", occurredAt, occurredAt.plusHours(1), @@ -185,14 +187,22 @@ class TachographCompositeSessionServiceTest { List.of() ); when(reconstructor.reconstruct(any(), eq("12:123"), any(), any(), eq("COMPOSITE_TACHOGRAPH_FILE_SESSION"))) - .thenReturn(expected); + .thenReturn(reconstructed); ResolvedDriverTimeline actual = service.getMergedDriverTimeline(created.session().compositeSessionId(), "12:123"); - assertThat(actual).isSameAs(expected); + assertThat(actual).isEqualTo(new ResolvedDriverTimeline( + "COMPOSITE_TACHOGRAPH_FILE_SESSION", + occurredAt, + occurredAt.plusHours(1), + List.of(), + List.of(), + List.of(), + List.of() + )); ArgumentCaptor> eventsCaptor = ArgumentCaptor.forClass(List.class); - ArgumentCaptor> warningsCaptor = ArgumentCaptor.forClass(List.class); + ArgumentCaptor> warningsCaptor = ArgumentCaptor.forClass(List.class); verify(reconstructor).reconstruct( eq(created.session().compositeSessionId()), eq("12:123"), @@ -203,10 +213,10 @@ class TachographCompositeSessionServiceTest { assertThat(eventsCaptor.getValue()).extracting(EventHubEventDto::externalSourceEventId) .containsExactly("a", "b"); assertThat(warningsCaptor.getValue()).containsExactly( - new ExtractionWarning("SESSION_A", "warn-a", "s1"), - new ExtractionWarning("CARD_GAP", "gap", "p1"), - new ExtractionWarning("SESSION_B", "warn-b", "s2"), - new ExtractionWarning("DUPLICATE", "duplicate", "p2") + new RuntimeExtractionWarning("SESSION_A", "warn-a", "s1"), + new RuntimeExtractionWarning("CARD_GAP", "gap", "p1"), + new RuntimeExtractionWarning("SESSION_B", "warn-b", "s2"), + new RuntimeExtractionWarning("DUPLICATE", "duplicate", "p2") ); }