/* Copyright (c) 2011 Danish Maritime Authority.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dk.dma.ais.tracker.targetTracker;
import dk.dma.ais.data.AisTarget;
import dk.dma.ais.data.AisVesselStatic;
import dk.dma.ais.data.AisVesselTarget;
import dk.dma.ais.message.AisMessage;
import dk.dma.ais.message.AisMessage5;
import dk.dma.ais.packet.AisPacket;
import dk.dma.ais.reader.AisReader;
import dk.dma.ais.reader.AisReaders;
import dk.dma.ais.tracker.targetTracker.TargetTracker.MmsiTarget;
import java.io.IOException;
import java.util.Collections;
import java.util.PriorityQueue;
import java.util.function.Consumer;
/**
* Necessary Evil for legacy resources and convenience
*
* @author Jens Tuxen
*
*/
public class TargetInfoToAisTarget {
static PriorityQueue<AisPacket> getPacketsInOrder(TargetInfo ti) {
// Min-Heap = Oldest first when creating AisTarget (natural)
PriorityQueue<AisPacket> messages = new PriorityQueue<>();
if (ti == null) {
return messages;
}
for (AisPacket p : ti.getStaticPackets()) {
if (p != null) {
messages.add(p);
}
}
if (ti.hasPositionInfo()) {
AisPacket p = ti.getPositionPacket();
if (p != null) {
messages.add(p);
}
}
return messages;
}
public static AisTarget generateAisTarget(TargetInfo ti) {
PriorityQueue<AisPacket> normal = getPacketsInOrder(ti);
// why reversed also? A workaround for AisTargets without static information for some reason
// TODO: this needs to be replaced with a proper fix
PriorityQueue<AisPacket> reversed = new PriorityQueue<>(normal.size(), Collections.reverseOrder());
reversed.addAll(normal);
AisTarget a = generateAisTarget(normal);
updateAisTarget(a, reversed);
return a;
}
/**
* Update aisTarget with messages (note that if the packets are of different class type,
*
* @param aisTarget
* @param messages
* @return
*/
static AisTarget updateAisTarget(AisTarget aisTarget, PriorityQueue<AisPacket> messages) {
while (!messages.isEmpty()) {
aisTarget = updateWithNewestTakingPrecedent(aisTarget, messages.poll());
}
return aisTarget;
}
/**
* Newest AisTarget takes precedent when sources have conflicting Class A/B packets.
*
* @param t
* @param m
* @return
*/
private static AisTarget updateWithNewestTakingPrecedent(AisTarget t, AisPacket m) {
try {
t.update(m.tryGetAisMessage());
} catch (NullPointerException e) {
// pass
} catch (IllegalArgumentException exc) {
// happens when we try to update ClassA with ClassB and visa
// versa
// the youngest (newest report) takes president
AisTarget tmp = AisTarget.createTarget(m.tryGetAisMessage());
if (tmp != null && tmp.getLastReport() != null) {
if (t != null && t.getLastReport() != null) {
return (tmp.getLastReport().after(t.getLastReport())) ? tmp : t;
}
return tmp;
}
}
return t;
}
static AisTarget generateAisTarget(PriorityQueue<AisPacket> messages) {
AisTarget aisTarget = null;
while (aisTarget == null && !messages.isEmpty()) {
aisTarget = AisTarget.createTarget(messages.poll().tryGetAisMessage());
}
return updateAisTarget(aisTarget, messages);
}
public static void main(String[] args) throws IOException, InterruptedException {
AisReader reader = AisReaders.createDirectoryReader("src/test", "s*.txt", true);
dk.dma.ais.tracker.targetTracker.TargetTracker tt = new TargetTracker();
tt.subscribeToPacketStream(reader.stream());
reader.start();
reader.join();
tt.targets.values().forEach(new Consumer<MmsiTarget>() {
@Override
public void accept(MmsiTarget t) {
System.out.println("TARGET " + t.mmsi);
TargetInfo ti = t.getLatest(ttt -> ttt != null);
AisTarget k = generateAisTarget(ti);
if (k != null && k instanceof AisVesselTarget) {
AisVesselStatic avs = ((AisVesselTarget) k).getVesselStatic();
if (avs != null) {
System.out.println(avs.getName());
}
}
for (AisPacket l : getPacketsInOrder(ti)) {
System.out.println(l.getBestTimestamp());
AisMessage m = l.tryGetAisMessage();
if (m instanceof AisMessage5) {
System.out.println("MY NAME IS " + ((AisMessage5) m).getName());
}
}
System.out.println("TARGET END " + t.mmsi);
}
});
}
}