001/* 002 * Copyright (c) 2015 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-12-16 21:30:37 +0000 (Wed, 16 Dec 2015) $' 007 * '$Revision: 34341 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029package org.kepler.gis.actor.kml; 030 031import java.io.File; 032import java.io.FileNotFoundException; 033import java.io.IOException; 034import java.text.SimpleDateFormat; 035import java.util.Date; 036 037import de.micromata.opengis.kml.v_2_2_0.Kml; 038import ptolemy.actor.TypedAtomicActor; 039import ptolemy.actor.TypedIOPort; 040import ptolemy.actor.parameters.PortParameter; 041import ptolemy.data.DateToken; 042import ptolemy.data.StringToken; 043import ptolemy.data.Token; 044import ptolemy.data.type.BaseType; 045import ptolemy.kernel.CompositeEntity; 046import ptolemy.kernel.util.IllegalActionException; 047import ptolemy.kernel.util.NameDuplicationException; 048 049/** Add a timestamp to a KML file. 050 * 051 * @author Daniel Crawl 052 * @version $Id: WriteTimestampToKML.java 34341 2015-12-16 21:30:37Z crawl $ 053 */ 054public class WriteTimestampToKML extends TypedAtomicActor { 055 056 public WriteTimestampToKML(CompositeEntity container, String name) 057 throws IllegalActionException, NameDuplicationException { 058 super(container, name); 059 060 input = new TypedIOPort(this, "input", true, false); 061 input.setTypeEquals(BaseType.STRING); 062 063 filename = new PortParameter(this, "filename"); 064 filename.setTypeEquals(BaseType.STRING); 065 filename.getPort().setTypeEquals(BaseType.STRING); 066 067 date = new TypedIOPort(this, "date", true, false); 068 date.setTypeEquals(BaseType.DATE); 069 070 output = new TypedIOPort(this, "output", false, true); 071 output.setTypeEquals(BaseType.STRING); 072 } 073 074 @Override 075 public void fire() throws IllegalActionException { 076 077 super.fire(); 078 079 String inKMLNameStr = ((StringToken)input.get(0)).stringValue(); 080 if(inKMLNameStr.trim().isEmpty()) { 081 throw new IllegalActionException(this, "Input KML is empty."); 082 } 083 084 File inKML = new File(inKMLNameStr); 085 if(!inKML.exists()) { 086 throw new IllegalActionException(this, "Input KML does not exist: " + inKML); 087 } 088 089 filename.update(); 090 File outKML = null; 091 Token token = filename.getToken(); 092 if(token != null) { 093 String outKMLNameStr = ((StringToken)token).stringValue(); 094 if(outKMLNameStr.trim().isEmpty()) { 095 throw new IllegalActionException(this, "Output KML name is empty."); 096 } 097 outKML = new File(outKMLNameStr); 098 } else { 099 outKML = inKML; 100 } 101 102 Date dateVal = new Date(((DateToken)date.get(0)).getValue()); 103 String formattedDateStr; 104 synchronized(KML_TIMESTAMP_FORMAT) { 105 formattedDateStr = KML_TIMESTAMP_FORMAT.format(dateVal); 106 } 107 108 Kml[] kmls = null; 109 if(inKMLNameStr.toLowerCase().endsWith(".kmz")) { 110 try { 111 kmls = Kml.unmarshalFromKmz(inKML); 112 } catch (IOException e) { 113 throw new IllegalActionException(this, e, "Error unmarshalling KMZ."); 114 } 115 // TODO 116 throw new IllegalActionException(this, "Reading from KMZ not supported."); 117 } else { 118 kmls = new Kml[1]; 119 kmls[0] = Kml.unmarshal(inKML); 120 } 121 122 for(Kml kml: kmls) { 123 //_addTimestampToFeature(kml.getFeature(), formattedDateStr); 124 kml.getFeature().createAndSetTimeStamp().setWhen(formattedDateStr); 125 } 126 127 if(outKML.getName().toLowerCase().endsWith("kmz") || kmls.length > 1) { 128 try { 129 Kml[] otherKMLs = new Kml[kmls.length - 1]; 130 System.arraycopy(kmls, 1, otherKMLs, 0, otherKMLs.length); 131 kmls[0].marshalAsKmz(outKML.getAbsolutePath(), otherKMLs); 132 } catch (IOException e) { 133 throw new IllegalActionException(this, e, "Error writing KMZ to " + outKML); 134 } 135 } else { 136 try { 137 kmls[0].marshal(outKML); 138 } catch (FileNotFoundException e) { 139 throw new IllegalActionException(this, e, "Error writing to " + outKML); 140 } 141 } 142 143 output.broadcast(new StringToken(outKML.getAbsolutePath())); 144 } 145 146 /** The KML to read. */ 147 public TypedIOPort input; 148 149 /** The name of the KML file to write. If not specified, then the input KML 150 * will be overwritten. If the input file is a KMZ containing more than 151 * one KML, then the output is written as a KMZ. 152 */ 153 public PortParameter filename; 154 155 /** The timestamp to set. */ 156 public TypedIOPort date; 157 158 /** The name of the updated KML file. */ 159 public TypedIOPort output; 160 161 /** Format for KML timestamps. */ 162 public final static SimpleDateFormat KML_TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmXXX"); 163 164 /** Set the timestamp to a Feature and all contained Features. */ 165 /* 166 private void _addTimestampToFeature(Feature feature, String formattedDateStr) { 167 if(feature instanceof Placemark) { 168 ((Placemark)feature).createAndSetTimeStamp().setWhen(formattedDateStr); 169 } else { 170 List<Feature> subFeatures = null; 171 if(feature instanceof Document) { 172 subFeatures = ((Document)feature).getFeature(); 173 } else if(feature instanceof Folder) { 174 subFeatures = ((Folder)feature).getFeature(); 175 } 176 177 if(subFeatures != null) { 178 for(Feature subFeature : subFeatures) { 179 _addTimestampToFeature(subFeature, formattedDateStr); 180 } 181 } 182 } 183 } 184 */ 185 186}