/* Copyright (c) 2011 Danish Maritime Authority * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library. If not, see <http://www.gnu.org/licenses/>. */ package dk.dma.ais.packet; import static dk.dma.commons.util.io.IoUtil.writeAscii; import static java.util.Objects.requireNonNull; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.text.DecimalFormat; import dk.dma.ais.message.AisMessage; import dk.dma.ais.message.AisPositionMessage; import dk.dma.ais.message.AisStaticCommon; import dk.dma.ais.message.ShipTypeCargo; import dk.dma.commons.util.io.IoUtil; import dk.dma.commons.util.io.OutputStreamSink; import dk.dma.enav.model.geometry.Position; /** * Transform AisPackets into json objects with only specific columns * @author Jens Tuxen * */ public class AisPacketOutputSinkJsonObject extends OutputStreamSink<AisPacket> { /** The column we are writing. */ private final String[] columns; final byte[] separator; private DecimalFormat df = new DecimalFormat("###.#####"); private boolean first = true; public static final String ALLCOLUMNS = "mmsi;timestamp;lat;lon;sog;cog;name;dimBow;dimPort;dimStarboard;dimStern;shipType;shipCargo;callsign;targetType"; private String objectName; public AisPacketOutputSinkJsonObject(String format) { this(format,";","data"); } public AisPacketOutputSinkJsonObject(String format, String separator, String objectName) { columns = format.split(separator); this.objectName = objectName; this.separator = requireNonNull(separator).getBytes(StandardCharsets.US_ASCII); } @Override public void process(OutputStream stream, AisPacket message, long count) throws IOException { AisMessage m = message.tryGetAisMessage(); if (m != null) { StringBuilder sb = new StringBuilder(); if (!first) { sb.append(",\n"); } first = false; sb.append('['); AisStaticCommon common = null; ShipTypeCargo stc = null; if (m instanceof AisStaticCommon) { common = (AisStaticCommon)m; stc = new ShipTypeCargo(common.getShipType()); } AisPositionMessage im = null; Position pos = m.getValidPosition(); if (m instanceof AisPositionMessage) { im = (AisPositionMessage)m; } for (int i= 0; i< columns.length; i++) { String c = columns[i]; switch(c) { case "mmsi": sb.append('\"').append(m.getUserId()).append('\"'); break; case "lat": if (im != null && pos != null) { sb.append(df.format(pos.getLatitude())); } else { sb.append("null"); } break; case "lon": if (im != null && pos != null) { sb.append(df.format(pos.getLongitude())); } else { sb.append("null"); } break; case "targetType": sb.append('\"').append(m.getTargetType().toString()).append("\""); break; case "sog": if (im != null) { sb.append(im.getSog()); } else { sb.append("null"); } break; case "cog": if (im != null) { sb.append(im.getCog()); } else { sb.append("null"); } break; case "trueHeading": if (im != null) { sb.append(im.getTrueHeading()); break; } else { sb.append("null"); } case "timestamp": sb.append(message.getBestTimestamp()); break; case "name": if (common != null) { sb.append("\"").append(AisMessage.trimText(common.getName())).append("\""); } else { sb.append("null"); } break; case "dimBow": if (common != null) { sb.append(common.getDimBow()); } else { sb.append("null"); } break; case "dimPort": if (common != null) { sb.append(common.getDimPort()); } else { sb.append("null"); } break; case "dimStarboard": if (common != null) { sb.append(common.getDimStarboard()); } else { sb.append("null"); } break; case "dimStern": if (common != null) { sb.append(common.getDimStern()); } else { sb.append("null"); } break; case "shipType": if (stc != null) { sb.append('\"').append(stc.getShipType().toString()).append("\""); } else { sb.append("null"); } break; case "shipCargo": if (stc != null) { sb.append('\"').append(stc.getShipCargo().toString()).append("\""); } else { sb.append("null"); } break; case "callsign": if (common != null) { sb.append("\"").append(AisMessage.trimText(common.getCallsign())).append("\""); } else { sb.append("null"); } break; default: sb.append("null"); } if (i < (columns.length-1)) { sb.append(','); } } sb.append("]"); IoUtil.writeAscii(sb, stream); } } /** {@inheritDoc} */ @Override public void header(OutputStream stream) throws IOException { // Writes the name of each column as the header StringBuilder sb = new StringBuilder(); sb.append("{\"").append(objectName).append("\": {\n \"headers\": ["); for (int i = 0; i < columns.length-1; i++) { sb.append('\"').append(columns[i]).append("\","); } // no "," on last element sb.append('\"').append(columns[columns.length-1]).append('\"'); sb.append("],\n \"targets\": ["); IoUtil.writeAscii(sb, stream); } /** {@inheritDoc} */ @Override public void footer(OutputStream stream, long count) throws IOException { writeAscii("]\n}}", stream); } }