001/* 002 * Copyright (c) 2003-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 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 */ 029 030package org.ecoinformatics.seek.gis.gdal; 031 032import java.io.File; 033 034import org.kepler.objectmanager.cache.DataCacheFileObject; 035import org.kepler.objectmanager.cache.DataCacheManager; 036 037import ptolemy.actor.TypedAtomicActor; 038import ptolemy.actor.TypedIOPort; 039import ptolemy.data.IntToken; 040import ptolemy.data.StringToken; 041import ptolemy.data.expr.Parameter; 042import ptolemy.data.expr.StringParameter; 043import ptolemy.data.type.BaseType; 044import ptolemy.kernel.CompositeEntity; 045import ptolemy.kernel.Port; 046import ptolemy.kernel.util.IllegalActionException; 047import ptolemy.kernel.util.InternalErrorException; 048import ptolemy.kernel.util.NameDuplicationException; 049 050/** 051 * <p> 052 * This actor provides translation capabilities provided through the GDAL GIS 053 * library. It attempts to find the translated file in the kepler file cache 054 * before doing the translation. If the file is found, the translation is not 055 * performed but the cached file is passed on. The file is cached by it's 056 * filename (minus the extension after the '.') and the output format so the 057 * cached result can be read from the cache with a tuple like 058 * {outputFilename.substring(0, outputFilename.lastIndexOf(".")), outputFormat}. 059 * </p> 060 * <p> 061 * Note that the 'cache options' parameter has a choice of 'no cache'. This 062 * option will not only not store files in the cache, but it will also ignore 063 * previously stored cache items. It can thus be used to force a new calculation 064 * even if the item was previousl cached (Dan Higgins) 065 * </p> 066 */ 067public class GDALTranslateActor extends TypedAtomicActor { 068 /** the type of output...byte, int, etc. **/ 069 public StringParameter outputType = new StringParameter(this, "output type"); 070 /** the format of the output...ascii, raw, binary, etc **/ 071 public StringParameter outputFormat = new StringParameter(this, 072 "output format"); 073 /** how to use the cache, if at all */ 074 public StringParameter cacheOutput = new StringParameter(this, 075 "Cache options"); 076 /** the filename of the input file **/ 077 public TypedIOPort inputFilename = new TypedIOPort(this, "inputFilename", 078 true, false); 079 /** trigger */ 080 public TypedIOPort trigger = new TypedIOPort(this, "trigger", true, false); 081 /** the filename (cacheid) of the outputfile **/ 082 public TypedIOPort outputFilename = new TypedIOPort(this, "outputFilename", 083 false, true); 084 public TypedIOPort outputCachename = new TypedIOPort(this, 085 "outputCachename", false, true); 086 public TypedIOPort outputCacheType = new TypedIOPort(this, 087 "outputCacheType", false, true); 088 /** production rate param to handle the multiport input **/ 089 public Parameter outputFilenameTokenProductionRate; 090 // cache manager 091 private DataCacheManager cacheManager; 092 093 /** 094 * Constructor 095 */ 096 public GDALTranslateActor(CompositeEntity container, String name) 097 throws NameDuplicationException, IllegalActionException { 098 super(container, name); 099 inputFilename.setTypeEquals(BaseType.STRING); 100 inputFilename.setMultiport(true); 101 outputFilename.setTypeEquals(BaseType.STRING); 102 outputCachename.setTypeEquals(BaseType.STRING); 103 outputCacheType.setTypeEquals(BaseType.STRING); 104 outputFilenameTokenProductionRate = new Parameter(outputFilename, 105 "tokenProductionRate"); 106 outputFilenameTokenProductionRate.setExpression("0"); 107 cacheManager = DataCacheManager.getInstance(); 108 } 109 110 /** 111 * Notify this entity that the links to the specified port have been 112 * altered. This sets the production rate of the output port and notifies 113 * the director that the schedule is invalid, if there is a director. 114 * 115 * @param port 116 */ 117 public void connectionsChanged(Port port) { 118 super.connectionsChanged(port); 119 if (port == inputFilename) { 120 try { 121 outputFilenameTokenProductionRate.setToken(new IntToken( 122 inputFilename.getWidth())); 123 // NOTE: schedule is invalidated automatically already 124 // by the changed connections. 125 } catch (IllegalActionException ex) { 126 throw new InternalErrorException(this, ex, 127 "Failed to set the token production rate of the " 128 + "outputFilename port"); 129 } 130 } 131 } 132 133 /** 134 * Initialize 135 */ 136 public void initialize() throws IllegalActionException { 137 } 138 139 /** 140 * Prefire 141 */ 142 public boolean prefire() throws IllegalActionException { 143 return super.prefire(); 144 } 145 146 /** 147 * Fire 148 */ 149 public void fire() throws IllegalActionException { 150 super.fire(); 151 if (trigger.getWidth() > 0 && !trigger.hasToken(0)) { // make sure we're 152 // ready to fire 153 return; 154 } 155 156 String outputTypeStr = outputType.stringValue(); 157 String outputFormatStr = outputFormat.stringValue(); 158 String cacheOutputStr = cacheOutput.stringValue(); 159 160 // what kind of cache should we use 161 int cacheOption = DataCacheFileObject.COPY_FILE_TO_CACHE; 162 if (cacheOutputStr.equals("Cache Files but Preserve Location")) { 163 cacheOption = DataCacheFileObject.EXTERNAL; 164 } else if (cacheOutputStr.equals("No Caching")) { 165 cacheOption = -666; 166 } 167 168 int inputFilenameWidth = inputFilename.getWidth(); 169 170 for (int i = 0; i < inputFilenameWidth; i++) { // loop through each 171 // input on the port 172 StringToken inputFilenameToken = (StringToken) inputFilename.get(i); 173 String inputFilenameStr = inputFilenameToken.stringValue(); 174 String outputFilenameStr; 175 if (inputFilenameStr.indexOf(".") != -1) { // get rid of the . and 176 // the extension on the 177 // filename 178 outputFilenameStr = inputFilenameStr.substring(0, 179 inputFilenameStr.lastIndexOf(".")); 180 } else { 181 outputFilenameStr = inputFilenameStr; 182 } 183 184 try { 185 // try to get the output file from the cache 186 if (cacheOption != -666) { 187 DataCacheFileObject fileItem = cacheManager.getFile( 188 outputFilenameStr, outputFormatStr); 189 outputFilename.broadcast(new StringToken(fileItem.getFile() 190 .getAbsolutePath())); 191 outputCachename 192 .broadcast(new StringToken(outputFilenameStr)); 193 outputCacheType.broadcast(new StringToken(outputFormatStr)); 194 } else { 195 throw new NullPointerException(); 196 } 197 } catch (NullPointerException npe) { // if the file doesn't exist in 198 // the cache, translate it. 199 try { 200 // add the new extension to the filename for output 201 String outFile = outputFilenameStr + "." + outputFormatStr; 202 File f = new File(outFile); 203 if (f.exists()) { // delete the old output file if there is 204 // one. 205 f.delete(); 206 } 207 GDALJniGlue g = new GDALJniGlue(); 208 String results = g.GDALTranslate(outputTypeStr, 209 outputFormatStr, inputFilenameStr, outFile); 210 if (results != null) { 211 throw new IllegalActionException(results); 212 } 213 214 if (cacheOption != -666) { 215 // put the output file into the cache 216 DataCacheFileObject fileItem = DataCacheManager 217 .putFile(outFile, outputFilenameStr, 218 outputFormatStr, cacheOption); 219 outputFilename.broadcast(new StringToken(fileItem 220 .getFile().getAbsolutePath())); 221 outputCachename.broadcast(new StringToken( 222 outputFilenameStr)); 223 outputCacheType.broadcast(new StringToken( 224 outputFormatStr)); 225 } else { 226 outputFilename.broadcast(new StringToken(outFile)); 227 } 228 } catch (Exception e) { 229 throw new IllegalActionException( 230 "Error running jni code for GDAL: " 231 + e.getMessage()); 232 } 233 } 234 } 235 } 236}