/* * This source is part of the * _____ ___ ____ * __ / / _ \/ _ | / __/___ _______ _ * / // / , _/ __ |/ _/_/ _ \/ __/ _ `/ * \___/_/|_/_/ |_/_/ (_)___/_/ \_, / * /___/ * repository. * * Copyright (C) 2014-2015 Carmen Alvarez (c@rmen.ca) * * 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 ca.rmen.android.networkmonitor.app.dbops.backend.export.kml; import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import android.text.TextUtils; /** * Writes a KML document with styles and placemarks. */ class KMLWriter extends PrintWriter { private static final String STYLEMAP_RED = "#stylemap_red"; private static final String STYLEMAP_GREEN = "#stylemap_green"; private static final String STYLEMAP_YELLOW = "#stylemap_yellow"; private static final SimpleDateFormat TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); private final KMLStyle mKmlStyle; private final String mEmptyLabel; private final String mTitle; private final Map<String, String> mFieldDisplayNames; /** * @param file the kml file to create * @param emptyLabel when the placemark name has no value, use this label instead of a blank value * @param fieldDisplayNames mapping between the names of the placemark fields and the user-friendly names to display for these fields */ public KMLWriter(File file, String title, KMLStyle kmlStyle, String emptyLabel, Map<String, String> fieldDisplayNames) throws FileNotFoundException { super(file); mKmlStyle = kmlStyle; mEmptyLabel = emptyLabel; mFieldDisplayNames = fieldDisplayNames; mTitle = title; TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); } public void writeHeader() { println("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); println("<kml xmlns=\"http://earth.google.com/kml/2.1\">"); println(" <Document>"); print(" <name>"); print(mTitle); println("</name>"); writeStyles(); } /** * Write a single Placemark * * @param values map of field name to value */ public void writePlacemark(String name, Map<String, String> values, String latitude, String longitude, long timestamp) { println(" <Placemark>"); writePlacemarkName(name); writePlacemarkCoordinates(longitude, latitude); if (timestamp > 0) writePlacemarkTimestamp(timestamp); writePlacemarkStyleUrl(values); writePlacemarkExtendedData(values); println(" </Placemark>"); flush(); } public void writeFooter() { println(" </Document>"); println("</kml>"); flush(); } /** * To make the output file a bit smaller, we use KML styles: one style for pass (green), one for slow (yellow) and one for fail (red). */ private void writeStyles() { // KML colors are of the format aabbggrr: https://developers.google.com/kml/documentation/kmlreference#color writeStyle("red", "ff0000ff"); writeStyle("green", "ff00ff00"); writeStyle("yellow", "ff00ffff"); } /** * Write the style xml for the given color. * * @param colorName the name of the color: used for the name of the kml style and stylemap * @param colorCode the aabbggrr color code for this color. */ private void writeStyle(String colorName, String colorCode) { println(" <StyleMap id=\"stylemap_" + colorName + "\">"); // Write the style map String[] keys = new String[] { "normal", "highlight" }; for (String key : keys) { println(" <Pair>"); println(" <key>" + key + "</key>"); println(" <styleUrl>#style_" + colorName + "</styleUrl>"); println(" </Pair>"); } println(" </StyleMap>"); // Write the style println(" <Style id=\"style_" + colorName + "\">"); // The icon style println(" <IconStyle>"); print(" <color>"); print(colorCode); println("</color>"); println(" <Icon>"); print(" <href>"); String iconUrl = "http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png"; print(iconUrl); println("</href>"); println(" </Icon>"); println(" </IconStyle>"); // The label style println(" <LabelStyle>"); println(" <scale>1.0</scale>"); println(" </LabelStyle>"); println(" </Style>"); } /** * Write the label of this placemark. This is the value for the column the user chose to export. */ private void writePlacemarkName(String label) { print(" <name>"); if (TextUtils.isEmpty(label)) label = mEmptyLabel; print(label); println("</name>"); } /** * Refer to the correct style, depending on the value of the data point for this record. */ private void writePlacemarkStyleUrl(Map<String, String> values) { final String styleUrl; KMLStyle.IconColor iconColor = mKmlStyle.getColor(values); if (iconColor == KMLStyle.IconColor.GREEN) styleUrl = STYLEMAP_GREEN; else if (iconColor == KMLStyle.IconColor.RED) styleUrl = STYLEMAP_RED; else styleUrl = STYLEMAP_YELLOW; print(" <styleUrl>"); print(styleUrl); println("</styleUrl>"); } /** * Write the device coordinates for this record. */ private void writePlacemarkCoordinates(String longitude, String latitude) { // Write the device coordinates. println(" <Point>"); print(" <coordinates>"); print(longitude + "," + latitude); println("</coordinates>"); println(" </Point>"); } /** * Write the timestamp. */ private void writePlacemarkTimestamp(long timestamp) { Date date = new Date(timestamp); String timestampString = TIMESTAMP_FORMAT.format(date); print(" <when>"); print(timestampString); println("</when>>"); } /** * Write all the attributes we were able to retrieve for this record. */ private void writePlacemarkExtendedData(Map<String, String> values) { println(" <ExtendedData>"); for (String columnName : values.keySet()) { String displayName = mFieldDisplayNames.get(columnName); String value = values.get(columnName); if (!TextUtils.isEmpty(value)) { println(" <Data name=\"" + displayName + "\">"); print(" <value>"); print(value); println("</value>"); println(" </Data>"); } } println(" </ExtendedData>"); } }