001/* 002 * Copyright (c) 2002-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.geon; 031 032import java.io.BufferedReader; 033import java.io.IOException; 034 035import ptolemy.actor.lib.Source; 036import ptolemy.data.IntToken; 037import ptolemy.data.StringToken; 038import ptolemy.data.expr.FileParameter; 039import ptolemy.data.expr.Parameter; 040import ptolemy.data.type.BaseType; 041import ptolemy.kernel.CompositeEntity; 042import ptolemy.kernel.util.Attribute; 043import ptolemy.kernel.util.IllegalActionException; 044import ptolemy.kernel.util.NameDuplicationException; 045import ptolemy.kernel.util.Workspace; 046 047////////////////////////////////////////////////////////////////////////// 048//// FileToString 049/** 050 * This actor reads a file or URL and outputs its content in a single string. 051 * The file or URL is specified using any form acceptable to FileParameter. 052 * <p> 053 * This actor can skip some lines at the beginning of the file or URL, with the 054 * number specified by the <i>numberOfLinesToSkip</i> parameter. The default 055 * value of this parameter is 0. 056 * 057 * @author Efrat Jaeger 058 * @version $Id: FileToString.java 24234 2010-05-06 05:21:26Z welker $ 059 * @since Ptolemy II 3.0.2 060 */ 061public class FileToString extends Source { 062 063 /** 064 * Construct an actor with the given container and name. 065 * 066 * @param container 067 * The container. 068 * @param name 069 * The name of this actor. 070 * @exception IllegalActionException 071 * If the actor cannot be contained by the proposed 072 * container. 073 * @exception NameDuplicationException 074 * If the container already has an actor with this name. 075 */ 076 public FileToString(CompositeEntity container, String name) 077 throws IllegalActionException, NameDuplicationException { 078 super(container, name); 079 080 output.setTypeEquals(BaseType.STRING); 081 082 fileOrURL = new FileParameter(this, "fileOrURL"); 083 084 numberOfLinesToSkip = new Parameter(this, "numberOfLinesToSkip", 085 new IntToken(0)); 086 numberOfLinesToSkip.setTypeEquals(BaseType.INT); 087 088 _attachText("_iconDescription", "<svg>\n" 089 + "<rect x=\"-25\" y=\"-20\" " + "width=\"50\" height=\"40\" " 090 + "style=\"fill:white\"/>\n" 091 + "<polygon points=\"-15,-10 -12,-10 -8,-14 -1,-14 3,-10" 092 + " 15,-10 15,10, -15,10\" " + "style=\"fill:red\"/>\n" 093 + "</svg>\n"); 094 } 095 096 // ///////////////////////////////////////////////////////////////// 097 // // ports and parameters //// 098 099 /** 100 * The file name or URL from which to read. This is a string with any form 101 * accepted by FileParameter. 102 * 103 * @see FileParameter 104 */ 105 public FileParameter fileOrURL; 106 107 /** 108 * The number of lines to skip at the beginning of the file or URL. This 109 * parameter contains an IntToken, initially with value 0. The value of this 110 * parameter must be non-negative. 111 */ 112 public Parameter numberOfLinesToSkip; 113 114 // ///////////////////////////////////////////////////////////////// 115 // // public methods //// 116 117 /** 118 * If the specified attribute is <i>fileOrURL</i> and there is an open file 119 * being read, then close that file and open the new one; if the attribute 120 * is <i>numberOfLinesToSkip</i> and its value is negative, then throw an 121 * exception. In the case of <i>fileOrURL</i>, do nothing if the file name 122 * is the same as the previous value of this attribute. 123 * 124 * @param attribute 125 * The attribute that has changed. 126 * @exception IllegalActionException 127 * If the specified attribute is <i>fileOrURL</i> and the 128 * file cannot be opened, or the previously opened file 129 * cannot be closed; or if the attribute is 130 * <i>numberOfLinesToSkip</i> and its value is negative. 131 */ 132 public void attributeChanged(Attribute attribute) 133 throws IllegalActionException { 134 if (attribute == fileOrURL) { 135 // NOTE: We do not want to close the file if the file 136 // has not in fact changed. We check this by just comparing 137 // name, which is not perfect... 138 if (_previousFileOrURL != null 139 && !fileOrURL.getExpression().equals(_previousFileOrURL)) { 140 _previousFileOrURL = fileOrURL.getExpression(); 141 fileOrURL.close(); 142 // Ignore if the fileOrUL is blank. 143 if (fileOrURL.getExpression().trim().equals("")) { 144 _reader = null; 145 } else { 146 _reader = fileOrURL.openForReading(); 147 } 148 } 149 } else if (attribute == numberOfLinesToSkip) { 150 int linesToSkip = ((IntToken) numberOfLinesToSkip.getToken()) 151 .intValue(); 152 if (linesToSkip < 0) { 153 throw new IllegalActionException(this, "The number of lines " 154 + "to skip cannot be negative."); 155 } 156 } else { 157 super.attributeChanged(attribute); 158 } 159 } 160 161 /** 162 * Clone the actor into the specified workspace. 163 * 164 * @return A new actor. 165 * @exception CloneNotSupportedException 166 * If a derived class contains an attribute that cannot be 167 * cloned. 168 */ 169 public Object clone(Workspace workspace) throws CloneNotSupportedException { 170 FileToString newObject = (FileToString) super.clone(workspace); 171 newObject._currentLine = null; 172 newObject._reader = null; 173 return newObject; 174 } 175 176 /** 177 * Output the data lines into a string. 178 * 179 * @exception IllegalActionException 180 * If there's no director. 181 */ 182 public void fire() throws IllegalActionException { 183 super.fire(); 184 _openAndReadFirstLine(); 185 while (_currentLine != null) { 186 _result += _currentLine; 187 _result += "\n"; 188 try { 189 _currentLine = _reader.readLine(); 190 } catch (IOException ex) { 191 throw new IllegalActionException(this, ex, 192 "fire failed reading line"); 193 } 194 } 195 output.broadcast(new StringToken(_result)); 196 } 197 198 /** 199 * Post fire the actor. Return false to indicate that the process has 200 * finished. If it returns true, the process will continue indefinitely. 201 */ 202 public boolean postfire() { 203 _result = ""; 204 return false; 205 } 206 207 /** 208 * Open the file or URL and read the first line, and use the first line to 209 * set the type of the output. 210 * 211 * @exception IllegalActionException 212 * If the file or URL cannot be opened, or if the first line 213 * cannot be read. 214 */ 215 public void preinitialize() throws IllegalActionException { 216 super.preinitialize(); 217 // _openAndReadFirstLine(); 218 } 219 220 /** 221 * Close the reader if there is one. 222 * 223 * @exception IllegalActionException 224 * If an IO error occurs. 225 */ 226 public void wrapup() throws IllegalActionException { 227 fileOrURL.close(); 228 _reader = null; 229 } 230 231 // ///////////////////////////////////////////////////////////////// 232 // // protected members //// 233 234 /** Cache of most recently read data. */ 235 protected String _currentLine; 236 237 /** The current reader for the input file. */ 238 protected BufferedReader _reader; 239 240 // ///////////////////////////////////////////////////////////////// 241 // // private methods //// 242 243 /** 244 * Open the file and read the first line. 245 */ 246 private void _openAndReadFirstLine() throws IllegalActionException { 247 _reader = fileOrURL.openForReading(); 248 try { 249 // Read (numberOfLinesToSkip + 1) lines 250 int numberOfLines = ((IntToken) numberOfLinesToSkip.getToken()) 251 .intValue(); 252 for (int i = 0; i <= numberOfLines; i++) { 253 _currentLine = _reader.readLine(); 254 if (_currentLine == null) { 255 throw new IllegalActionException(this, "The file does not " 256 + "have enough lines."); 257 } 258 } 259 } catch (IOException ex) { 260 throw new IllegalActionException(this, ex, "Preinitialize failed."); 261 } 262 } 263 264 // ///////////////////////////////////////////////////////////////// 265 // // private members //// 266 267 /** Previous value of fileOrURL parameter. */ 268 private String _previousFileOrURL; 269 270 /** Result string Variable. */ 271 private String _result = new String(""); 272 273}