package com.ruoyi.shadow.facts; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public final class ShadowFactBatch { private final Instant databaseCaptureStartedAt; private final Instant databaseCapturedAt; private final List sourceQueues; private final List queues; private final List vehicles; private final List maps; private ShadowFactBatch(Instant databaseCaptureStartedAt, Instant databaseCapturedAt, List sourceQueues, List vehicles, List maps) { this.databaseCaptureStartedAt = databaseCaptureStartedAt; this.databaseCapturedAt = databaseCapturedAt; this.sourceQueues = immutable(sourceQueues); this.queues = immutable(deduplicateAndSort(sourceQueues)); this.vehicles = immutable(sortVehicles(vehicles)); this.maps = immutable(sortMaps(maps)); } public static ShadowFactBatch create(Instant startedAt, Instant capturedAt, List queues, List vehicles, List maps) { return new ShadowFactBatch(startedAt, capturedAt, requiredList(queues, "queues"), requiredList(vehicles, "vehicles"), requiredList(maps, "maps")); } public Instant getDatabaseCaptureStartedAt() { return databaseCaptureStartedAt; } public Instant getDatabaseCapturedAt() { return databaseCapturedAt; } public List getSourceQueues() { return sourceQueues; } public List getQueues() { return queues; } public List getVehicles() { return vehicles; } public List getMaps() { return maps; } public ShadowQueueFact queue(String guid) { for (ShadowQueueFact fact : queues) { if (fact.isActive() && fact.getGuid().equals(guid)) { return fact; } } for (ShadowQueueFact fact : queues) { if (fact.getGuid().equals(guid)) { return fact; } } return null; } public ShadowVehicleFact vehicle(String deviceId) { for (ShadowVehicleFact fact : vehicles) { if (fact.getDeviceId().equals(deviceId)) { return fact; } } return null; } private static List deduplicateAndSort( List source) { Map unique = new LinkedHashMap(); for (ShadowQueueFact fact : source) { String key = fact.getTableName() + '\u0000' + fact.getGuid() + '\u0000' + fact.getContentHash(); unique.put(key, fact); } List result = new ArrayList(unique.values()); Collections.sort(result, Comparator .comparing(ShadowQueueFact::getCreatedAt, Comparator.nullsFirst(Comparator.naturalOrder())) .thenComparing(ShadowQueueFact::getGuid) .thenComparing(ShadowQueueFact::getContentHash)); return result; } private static List sortVehicles( List source) { List result = new ArrayList(source); Collections.sort(result, Comparator .comparing(ShadowVehicleFact::getDeviceId) .thenComparing(ShadowVehicleFact::getGuid) .thenComparing(ShadowVehicleFact::getContentHash)); return result; } private static List sortMaps(List source) { List result = new ArrayList(source); Collections.sort(result, Comparator .comparing(ShadowMapFact::getSiteId) .thenComparing(ShadowMapFact::getGuid)); return result; } private static List immutable(List source) { return Collections.unmodifiableList(new ArrayList(source)); } private static List requiredList(List source, String name) { if (source == null) { throw new IllegalArgumentException(name + " must not be null"); } for (T value : source) { if (value == null) { throw new IllegalArgumentException(name + " must not contain null"); } } return source; } }