Compare commits
3 Commits
ff12953e05
...
84922f6c44
| Author | SHA1 | Date |
|---|---|---|
|
|
84922f6c44 | |
|
|
5cf0cedc41 | |
|
|
aa360c9f02 |
|
|
@ -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<ResolvedDriverTimeline> loadDriverTimeline(
|
||||
public ResponseEntity<RuntimeDriverTimeline> loadDriverTimeline(
|
||||
@RequestBody UnifiedRuntimeProcessingApiRequest request
|
||||
) {
|
||||
return ResponseEntity.ok(runtimeDriverTimelineService.loadDriverTimeline(request.toRuntimeRequest()));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package at.procon.eventhub.processing.dto;
|
|||
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
|
||||
import at.procon.eventhub.processing.model.UnifiedRuntimeEventBackend;
|
||||
import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest;
|
||||
import at.procon.eventhub.processing.model.UnifiedTachographSourceKind;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
|
@ -16,7 +15,7 @@ public record UnifiedRuntimeProcessingApiRequest(
|
|||
String tenantKey,
|
||||
Set<UnifiedEventSourceFamily> sourceFamilies,
|
||||
UnifiedRuntimeEventBackend eventBackend,
|
||||
Set<UnifiedTachographSourceKind> tachographSourceKinds,
|
||||
Set<String> sourceKinds,
|
||||
String driverKey,
|
||||
Set<String> driverKeys,
|
||||
Boolean includeAllDrivers,
|
||||
|
|
@ -43,7 +42,7 @@ public record UnifiedRuntimeProcessingApiRequest(
|
|||
String tenantKey,
|
||||
Set<UnifiedEventSourceFamily> sourceFamilies,
|
||||
UnifiedRuntimeEventBackend eventBackend,
|
||||
Set<UnifiedTachographSourceKind> tachographSourceKinds,
|
||||
Set<String> sourceKinds,
|
||||
String driverKey,
|
||||
Set<String> driverKeys,
|
||||
Boolean includeAllDrivers,
|
||||
|
|
@ -69,7 +68,7 @@ public record UnifiedRuntimeProcessingApiRequest(
|
|||
tenantKey,
|
||||
sourceFamilies,
|
||||
eventBackend,
|
||||
tachographSourceKinds,
|
||||
sourceKinds,
|
||||
driverKey,
|
||||
driverKeys,
|
||||
includeAllDrivers,
|
||||
|
|
@ -99,7 +98,7 @@ public record UnifiedRuntimeProcessingApiRequest(
|
|||
tenantKey,
|
||||
sourceFamilies,
|
||||
eventBackend,
|
||||
tachographSourceKinds,
|
||||
sourceKinds,
|
||||
driverKey,
|
||||
driverKeys,
|
||||
includeAllDrivers != null && includeAllDrivers,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ public class DriverWorkingTimeRuntimeProcessingPlan implements RuntimeProcessing
|
|||
sourceSelection.tenantKey(),
|
||||
sourceSelection.sourceFamilies(),
|
||||
sourceSelection.eventBackend(),
|
||||
sourceSelection.tachographSourceKinds(),
|
||||
sourceSelection.sourceKinds(),
|
||||
sourceSelection.driverKey(),
|
||||
driverKeys,
|
||||
includeAllDrivers,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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<String> 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<String> 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<String> 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"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<RuntimeVehicleUsageInterval> vehicleUsageIntervals,
|
||||
List<RuntimeActivityInterval> activityIntervals,
|
||||
List<RuntimeSupportEvent> supportEvents,
|
||||
List<RuntimeExtractionWarning> warnings
|
||||
) {
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package at.procon.eventhub.processing.model;
|
||||
|
||||
public record RuntimeExtractionWarning(
|
||||
String code,
|
||||
String message,
|
||||
String rawRecordPath
|
||||
) {
|
||||
}
|
||||
|
|
@ -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
|
||||
) {
|
||||
}
|
||||
|
|
@ -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<EventHubEventDto> activityEvents,
|
||||
List<EventHubEventDto> vehicleUsageEvents,
|
||||
List<EventHubEventDto> 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<EventHubEventDto> allEvents() {
|
||||
List<EventHubEventDto> 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<EventHubEventDto> copy(List<EventHubEventDto> events) {
|
||||
return events == null ? List.of() : List.copyOf(events);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String> 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<String> 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package at.procon.eventhub.processing.model;
|
|||
import at.procon.eventhub.reference.DriverCardNumberNormalizer;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
|
@ -17,7 +16,7 @@ public record UnifiedRuntimeProcessingRequest(
|
|||
String tenantKey,
|
||||
Set<UnifiedEventSourceFamily> sourceFamilies,
|
||||
UnifiedRuntimeEventBackend eventBackend,
|
||||
Set<UnifiedTachographSourceKind> tachographSourceKinds,
|
||||
Set<String> sourceKinds,
|
||||
String driverKey,
|
||||
Set<String> driverKeys,
|
||||
boolean includeAllDrivers,
|
||||
|
|
@ -40,7 +39,7 @@ public record UnifiedRuntimeProcessingRequest(
|
|||
String tenantKey,
|
||||
Set<UnifiedEventSourceFamily> sourceFamilies,
|
||||
UnifiedRuntimeEventBackend eventBackend,
|
||||
Set<UnifiedTachographSourceKind> tachographSourceKinds,
|
||||
Set<String> sourceKinds,
|
||||
String driverKey,
|
||||
Set<String> driverKeys,
|
||||
boolean includeAllDrivers,
|
||||
|
|
@ -62,7 +61,7 @@ public record UnifiedRuntimeProcessingRequest(
|
|||
tenantKey,
|
||||
sourceFamilies,
|
||||
eventBackend,
|
||||
tachographSourceKinds,
|
||||
sourceKinds,
|
||||
driverKey,
|
||||
driverKeys,
|
||||
includeAllDrivers,
|
||||
|
|
@ -87,7 +86,7 @@ public record UnifiedRuntimeProcessingRequest(
|
|||
throw new IllegalArgumentException("sourceFamilies must not be empty");
|
||||
}
|
||||
eventBackend = eventBackend == null ? UnifiedRuntimeEventBackend.SOURCE_DB : eventBackend;
|
||||
tachographSourceKinds = normalizeTachographSourceKinds(tachographSourceKinds);
|
||||
sourceKinds = normalizeSourceKinds(sourceKinds);
|
||||
sessionIds = normalizeSessionIds(sessionId, sessionIds);
|
||||
if (sessionId == null && !sessionIds.isEmpty()) {
|
||||
sessionId = sessionIds.get(0);
|
||||
|
|
@ -448,7 +447,7 @@ public record UnifiedRuntimeProcessingRequest(
|
|||
tenantKey,
|
||||
Set.of(sourceInput.sourceFamily()),
|
||||
sourceInput.eventBackend(),
|
||||
tachographSourceKinds,
|
||||
sourceKinds,
|
||||
driverKey,
|
||||
driverKeys,
|
||||
includeAllDrivers,
|
||||
|
|
@ -485,7 +484,7 @@ public record UnifiedRuntimeProcessingRequest(
|
|||
tenantKey,
|
||||
sourceFamilies,
|
||||
eventBackend,
|
||||
tachographSourceKinds,
|
||||
sourceKinds,
|
||||
value,
|
||||
Set.of(),
|
||||
false,
|
||||
|
|
@ -507,21 +506,15 @@ public record UnifiedRuntimeProcessingRequest(
|
|||
return includeAllDrivers || driverKeys.size() > 1 || (driverKey == null && !driverKeys.isEmpty());
|
||||
}
|
||||
|
||||
public boolean includesTachographSourceKind(String sourceKind) {
|
||||
public boolean includesSourceKind(String sourceKind) {
|
||||
if (sourceKind == null || sourceKind.isBlank()) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
return tachographSourceKinds.contains(UnifiedTachographSourceKind.valueOf(sourceKind.trim().toUpperCase()));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return false;
|
||||
}
|
||||
return sourceKinds.contains(sourceKind.trim().toUpperCase());
|
||||
}
|
||||
|
||||
public List<String> tachographSourceKindNames() {
|
||||
return tachographSourceKinds.stream()
|
||||
.map(UnifiedTachographSourceKind::name)
|
||||
.toList();
|
||||
public List<String> sourceKindNames() {
|
||||
return sourceKinds.stream().toList();
|
||||
}
|
||||
|
||||
private static Set<UnifiedEventSourceFamily> normalizeSourceFamilies(
|
||||
|
|
@ -600,13 +593,20 @@ public record UnifiedRuntimeProcessingRequest(
|
|||
return Set.copyOf(normalized);
|
||||
}
|
||||
|
||||
private static Set<UnifiedTachographSourceKind> normalizeTachographSourceKinds(
|
||||
Set<UnifiedTachographSourceKind> values
|
||||
private static Set<String> normalizeSourceKinds(
|
||||
Set<String> values
|
||||
) {
|
||||
if (values == null || values.isEmpty()) {
|
||||
return Set.copyOf(Arrays.asList(UnifiedTachographSourceKind.values()));
|
||||
return Set.of("DRIVER_CARD", "VEHICLE_UNIT");
|
||||
}
|
||||
return Set.copyOf(values);
|
||||
LinkedHashSet<String> normalized = new LinkedHashSet<>();
|
||||
for (String value : values) {
|
||||
String normalizedValue = normalizeUpper(value);
|
||||
if (normalizedValue != null) {
|
||||
normalized.add(normalizedValue);
|
||||
}
|
||||
}
|
||||
return normalized.isEmpty() ? Set.of("DRIVER_CARD", "VEHICLE_UNIT") : Set.copyOf(normalized);
|
||||
}
|
||||
|
||||
private static boolean isExternalDbFamily(UnifiedEventSourceFamily family) {
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
package at.procon.eventhub.processing.model;
|
||||
|
||||
public enum UnifiedTachographSourceKind {
|
||||
DRIVER_CARD,
|
||||
VEHICLE_UNIT
|
||||
}
|
||||
|
|
@ -71,7 +71,7 @@ public class EventHubRuntimeEventLoader implements RuntimeDriverEventLoader, Run
|
|||
request.driverCardNumber(),
|
||||
request.occurredFrom(),
|
||||
request.occurredTo(),
|
||||
request.tachographSourceKindNames(),
|
||||
request.sourceKindNames(),
|
||||
request.includeIntersectingIntervals()
|
||||
);
|
||||
case YELLOWFOX_DB -> UnifiedDriverEventsRequest.forYellowFoxDbDriver(
|
||||
|
|
@ -100,7 +100,7 @@ public class EventHubRuntimeEventLoader implements RuntimeDriverEventLoader, Run
|
|||
vehicleRef.registrationNumber(),
|
||||
request.vehicleOccurredFrom(),
|
||||
request.vehicleOccurredTo(),
|
||||
request.tachographSourceKindNames(),
|
||||
request.sourceKindNames(),
|
||||
request.includeIntersectingIntervals()
|
||||
);
|
||||
case YELLOWFOX_DB -> UnifiedVehicleEventsRequest.forYellowFoxDb(
|
||||
|
|
|
|||
|
|
@ -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<DriverWorkingTimeVehicleUsageInterval> 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<String> vehicleKeys(EventHubEventDto event) {
|
||||
LinkedHashSet<String> 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<ResolvedVehicleUsageInterval> mergeVehicleUsageIntervals(List<ResolvedVehicleUsageInterval> intervals) {
|
||||
private List<RuntimeVehicleUsageInterval> mergeVehicleUsageIntervals(List<RuntimeVehicleUsageInterval> intervals) {
|
||||
if (intervals == null || intervals.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
List<ResolvedVehicleUsageInterval> 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<RuntimeVehicleUsageInterval> 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<ResolvedVehicleUsageInterval> merged = new ArrayList<>();
|
||||
for (ResolvedVehicleUsageInterval next : sorted) {
|
||||
List<RuntimeVehicleUsageInterval> 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<String> 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(),
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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<EventHubEventDto> filterIntervalEvents(
|
||||
static List<EventHubEventDto> filterIntervalEvents(
|
||||
List<EventHubEventDto> events,
|
||||
OffsetDateTime occurredFrom,
|
||||
OffsetDateTime occurredTo,
|
||||
|
|
@ -59,11 +58,14 @@ final class RuntimeIntervalEventWindowSelector {
|
|||
return List.copyOf(result);
|
||||
}
|
||||
|
||||
private static List<EventHubEventDto> filterPointEvents(
|
||||
static List<EventHubEventDto> filterPointEvents(
|
||||
List<EventHubEventDto> 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<EventHubEventDto> events = new ArrayList<>();
|
||||
private OffsetDateTime startedAt;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ public class TachographDbRuntimeEventLoader implements RuntimeDriverEventLoader,
|
|||
) {
|
||||
return definitionRegistry.definitions().stream()
|
||||
.filter(definition -> !"VEHICLE".equals(definition.entityAxis()))
|
||||
.filter(definition -> request.includesTachographSourceKind(definition.sourceKind()))
|
||||
.filter(definition -> request.includesSourceKind(definition.sourceKind()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ public class TachographDbRuntimeEventLoader implements RuntimeDriverEventLoader,
|
|||
) {
|
||||
return definitionRegistry.definitions().stream()
|
||||
.filter(definition -> !"DRIVER".equals(definition.entityAxis()))
|
||||
.filter(definition -> request.includesTachographSourceKind(definition.sourceKind()))
|
||||
.filter(definition -> request.includesSourceKind(definition.sourceKind()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<EventHubEventDto> 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<EventHubEventDto> events,
|
||||
List<ExtractionWarning> warnings,
|
||||
List<RuntimeExtractionWarning> warnings,
|
||||
String sourceKind
|
||||
) {
|
||||
List<EventHubEventDto> safeEvents = events == null ? List.of() : List.copyOf(events);
|
||||
List<ResolvedActivityInterval> activityIntervals = reconstructActivityIntervals(safeEvents);
|
||||
List<ResolvedVehicleUsageInterval> vehicleUsageIntervals =
|
||||
List<RuntimeActivityInterval> activityIntervals = reconstructActivityIntervals(safeEvents);
|
||||
List<RuntimeVehicleUsageInterval> vehicleUsageIntervals =
|
||||
reconstructVehicleUsageIntervals(sessionId, driverKey, safeEvents);
|
||||
List<ExtractedSupportEvent> supportEvents = reconstructSupportEvents(safeEvents);
|
||||
List<ExtractionWarning> mergedWarnings = warnings == null ? List.of() : List.copyOf(new LinkedHashSet<>(warnings));
|
||||
List<RuntimeSupportEvent> supportEvents = reconstructSupportEvents(safeEvents);
|
||||
List<RuntimeExtractionWarning> 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<ResolvedActivityInterval> reconstructActivityIntervals(List<EventHubEventDto> events) {
|
||||
private List<RuntimeActivityInterval> reconstructActivityIntervals(List<EventHubEventDto> events) {
|
||||
Map<String, ActivityAccumulator> 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<ResolvedVehicleUsageInterval> reconstructVehicleUsageIntervals(
|
||||
private List<RuntimeVehicleUsageInterval> reconstructVehicleUsageIntervals(
|
||||
UUID sessionId,
|
||||
String driverKey,
|
||||
List<EventHubEventDto> 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<ExtractedSupportEvent> reconstructSupportEvents(List<EventHubEventDto> events) {
|
||||
List<ExtractedSupportEvent> result = new ArrayList<>();
|
||||
private List<RuntimeSupportEvent> reconstructSupportEvents(List<EventHubEventDto> events) {
|
||||
List<RuntimeSupportEvent> 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<ResolvedActivityInterval> activityIntervals,
|
||||
List<ResolvedVehicleUsageInterval> vehicleUsageIntervals,
|
||||
List<ExtractedSupportEvent> supportEvents
|
||||
List<RuntimeActivityInterval> activityIntervals,
|
||||
List<RuntimeVehicleUsageInterval> vehicleUsageIntervals,
|
||||
List<RuntimeSupportEvent> 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<ResolvedActivityInterval> activityIntervals,
|
||||
List<ResolvedVehicleUsageInterval> vehicleUsageIntervals,
|
||||
List<ExtractedSupportEvent> supportEvents
|
||||
List<RuntimeActivityInterval> activityIntervals,
|
||||
List<RuntimeVehicleUsageInterval> vehicleUsageIntervals,
|
||||
List<RuntimeSupportEvent> 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")
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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<EventHubEventDto> 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<EventHubEventDto> events
|
||||
) {
|
||||
return TachographRuntimeIdentityResolver.requestDriverKey(request, events);
|
||||
return RuntimeEntityReferenceResolver.requestDriverKey(request, events);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -436,12 +405,12 @@ public class UnifiedRuntimeDerivedProjectionService {
|
|||
}
|
||||
|
||||
private List<TachographEsperSupportGeoEvent> clipSupportGeoEvents(
|
||||
List<ExtractedSupportEvent> supportEvents,
|
||||
List<RuntimeSupportEvent> supportEvents,
|
||||
String driverKey,
|
||||
OffsetDateTime requestedFrom,
|
||||
OffsetDateTime requestedTo
|
||||
) {
|
||||
return (supportEvents == null ? List.<ExtractedSupportEvent>of() : supportEvents).stream()
|
||||
return (supportEvents == null ? List.<RuntimeSupportEvent>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))
|
||||
|
|
|
|||
|
|
@ -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<EventHubEventDto> events
|
||||
) {
|
||||
return TachographRuntimeIdentityResolver.requestDriverKey(request, events);
|
||||
return RuntimeEntityReferenceResolver.requestDriverKey(request, events);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <T> List<T> safe(List<T> values) {
|
||||
return values == null ? List.of() : values;
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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<EventHubEventDto> copy(List<EventHubEventDto> events) {
|
||||
return events == null ? List.of() : List.copyOf(events);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<EventHubEventDto> 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"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<EventHubEventDto> 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(),
|
||||
|
|
|
|||
|
|
@ -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 <T> List<T> safe(List<T> values) {
|
||||
return values == null ? List.of() : values;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -67,12 +67,12 @@ class UnifiedRuntimeProcessingRequestTest {
|
|||
OffsetDateTime.parse("2026-05-02T00:00:00Z")
|
||||
);
|
||||
|
||||
assertThat(defaultRequest.tachographSourceKinds()).containsExactlyInAnyOrder(
|
||||
UnifiedTachographSourceKind.DRIVER_CARD,
|
||||
UnifiedTachographSourceKind.VEHICLE_UNIT
|
||||
assertThat(defaultRequest.sourceKinds()).containsExactlyInAnyOrder(
|
||||
"DRIVER_CARD",
|
||||
"VEHICLE_UNIT"
|
||||
);
|
||||
assertThat(defaultRequest.includesTachographSourceKind("DRIVER_CARD")).isTrue();
|
||||
assertThat(defaultRequest.includesTachographSourceKind("VEHICLE_UNIT")).isTrue();
|
||||
assertThat(defaultRequest.includesSourceKind("DRIVER_CARD")).isTrue();
|
||||
assertThat(defaultRequest.includesSourceKind("VEHICLE_UNIT")).isTrue();
|
||||
|
||||
UnifiedRuntimeProcessingRequest driverCardOnlyRequest = new UnifiedRuntimeProcessingRequest(
|
||||
null,
|
||||
|
|
@ -81,7 +81,7 @@ class UnifiedRuntimeProcessingRequestTest {
|
|||
"default",
|
||||
Set.of(UnifiedEventSourceFamily.TACHOGRAPH_DB),
|
||||
UnifiedRuntimeEventBackend.SOURCE_DB,
|
||||
Set.of(UnifiedTachographSourceKind.DRIVER_CARD),
|
||||
Set.of("DRIVER_CARD"),
|
||||
null,
|
||||
Set.of(),
|
||||
false,
|
||||
|
|
@ -97,9 +97,9 @@ class UnifiedRuntimeProcessingRequestTest {
|
|||
true
|
||||
);
|
||||
|
||||
assertThat(driverCardOnlyRequest.tachographSourceKinds()).containsExactly(UnifiedTachographSourceKind.DRIVER_CARD);
|
||||
assertThat(driverCardOnlyRequest.includesTachographSourceKind("DRIVER_CARD")).isTrue();
|
||||
assertThat(driverCardOnlyRequest.includesTachographSourceKind("VEHICLE_UNIT")).isFalse();
|
||||
assertThat(driverCardOnlyRequest.sourceKinds()).containsExactly("DRIVER_CARD");
|
||||
assertThat(driverCardOnlyRequest.includesSourceKind("DRIVER_CARD")).isTrue();
|
||||
assertThat(driverCardOnlyRequest.includesSourceKind("VEHICLE_UNIT")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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<List<EventHubEventDto>> eventsCaptor = ArgumentCaptor.forClass(List.class);
|
||||
ArgumentCaptor<List<ExtractionWarning>> warningsCaptor = ArgumentCaptor.forClass(List.class);
|
||||
ArgumentCaptor<List<RuntimeExtractionWarning>> 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")
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue