001/* An actor that outputs data read from a URL.
002
003 @Copyright (c) 1998-2015 The Regents of the University of California.
004 All rights reserved.
005
006 Permission is hereby granted, without written agreement and without
007 license or royalty fees, to use, copy, modify, and distribute this
008 software and its documentation for any purpose, provided that the
009 above copyright notice and the following two paragraphs appear in all
010 copies of this software.
011
012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
016 SUCH DAMAGE.
017
018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023 ENHANCEMENTS, OR MODIFICATIONS.
024
025 PT_COPYRIGHT_VERSION 2
026 COPYRIGHTENDKEY
027 */
028package ptolemy.actor.lib;
029
030import java.io.BufferedReader;
031import java.io.IOException;
032import java.io.InputStreamReader;
033import java.net.URL;
034import java.util.StringTokenizer;
035
036import ptolemy.data.BooleanToken;
037import ptolemy.data.DoubleToken;
038import ptolemy.data.StringToken;
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;
045
046//import java.io.Reader;
047///////////////////////////////////////////////////////////////////
048//// Reader
049
050/**
051 This actor reads tokens from an URL, and output them. Each entry in
052 the file corresponds to one iteration. If there are multiple fires in
053 the iteration, the same token will be repeated.  This actor has a
054 multiport, where each port corresponds to one column in the data file.
055
056 <p> The file format at the URL is assumed as the following.  A newline
057 character separates the rows, and a tab or a space character separates
058 the columns.
059
060 <p> The <i>sourceURL</i> parameter should be set to the name of the
061 file, specified as a fully qualified URL.  If the <i>sourceURL</i>
062 parameter is an empty string, then the System.in is used for input.
063
064 It is possible to load a file from the local file system by using the
065 prefix "file://" instead of "http://". Relative file paths are
066 allowed. To specify a file relative to the current directory, use
067 "../" or "./". For example, if the current directory contains a file
068 called "test.txt", then <i>sourceURL</i> should be set to
069 "file:./test.txt". If the parent directory contains a file called
070 "test.txt", then <i>sourceURL</i> should be set to
071 "file:../test.txt". To reference the file test.txt, located at
072 "/tmp/test.txt", <i>sourceURL</i> should be set to
073 "file:///tmp/test.txt" The default value is "file:///tmp/test.txt".
074
075 <p>FIXME: The type of the output ports is set to Double for now.
076 It should read a line in the prefire() and refer the type
077 from there.
078 <p>FIXME: Reader should read in expressions and serialized tokens
079
080 @author  Jie Liu
081 @deprecated Use ExpressionReader instead.
082 @version $Id$
083 @since Ptolemy II 1.0
084 @Pt.ProposedRating Red (liuj)
085 @Pt.AcceptedRating Red (liuj)
086 */
087@Deprecated
088public class Reader extends Source {
089    /** Construct an actor with the given container and name.
090     *  @param container The container.
091     *  @param name The name of this actor.
092     *  @exception IllegalActionException If the actor cannot be contained
093     *   by the proposed container.
094     *  @exception NameDuplicationException If the container already has an
095     *   actor with this name.
096     */
097    public Reader(CompositeEntity container, String name)
098            throws IllegalActionException, NameDuplicationException {
099        super(container, name);
100
101        // Set the type of the input port.
102        output.setMultiport(true);
103        output.setTypeEquals(BaseType.DOUBLE);
104        sourceURL = new Parameter(this, "sourceURL", new StringToken(""));
105        sourceURL.setTypeEquals(BaseType.STRING);
106
107        refresh = new Parameter(this, "refresh", new BooleanToken(false));
108        refresh.setTypeEquals(BaseType.BOOLEAN);
109
110        if (_stdIn == null) {
111            _stdIn = new BufferedReader(new InputStreamReader(System.in,
112                    java.nio.charset.Charset.defaultCharset()));
113        }
114
115        setReader(_stdIn);
116    }
117
118    ///////////////////////////////////////////////////////////////////
119    ////                     ports and parameters                  ////
120
121    /** The URL of the file to read from. This parameter contains
122     *  a StringToken.  By default, it contains an empty string, which
123     *  is interpreted to mean that input should be directed to the
124     *  standard input.
125     *  FIXME: Should this bring up a dialog box to type (or select) a URL?
126     */
127    public Parameter sourceURL;
128
129    /** Refresh between each readings. Default is false.
130     */
131    public Parameter refresh;
132
133    ///////////////////////////////////////////////////////////////////
134    ////                         public methods                    ////
135
136    /** If the specified attribute is <i>URL</i>, then close
137     *  the current file (if there is one) and open the new one.
138     *  @param attribute The attribute that has changed.
139     *  @exception IllegalActionException If the specified attribute
140     *   is <i>URL</i> and the file cannot be opened.
141     */
142    @Override
143    public void attributeChanged(Attribute attribute)
144            throws IllegalActionException {
145        if (attribute == sourceURL) {
146            try {
147                StringToken URLToken = (StringToken) sourceURL.getToken();
148
149                if (URLToken == null) {
150                    _source = null;
151                    setReader(null);
152                } else {
153                    _source = URLToken.stringValue();
154
155                    if (_source.equals("")) {
156                        setReader(null);
157                    } else {
158                        URL url = new URL(_source);
159                        java.io.BufferedReader reader = new BufferedReader(
160                                new InputStreamReader(url.openStream()));
161                        setReader(reader);
162                    }
163                }
164            } catch (IOException ex) {
165                throw new IllegalActionException(this, ex,
166                        "attributeChanged(" + attribute + ") failed");
167            }
168        }
169
170        super.attributeChanged(attribute);
171    }
172
173    /** Output the data read in the prefire.
174     *  @exception IllegalActionException If there's no director.
175     */
176    @Override
177    public void fire() throws IllegalActionException {
178        super.fire();
179
180        for (int i = 0; i < _dataSize; i++) {
181            output.send(i, new DoubleToken(_data[i]));
182        }
183    }
184
185    /** Open the file at the URL, and set the width of the output.
186     *  @exception IllegalActionException Not thrown in this base class
187     */
188    @Override
189    public void initialize() throws IllegalActionException {
190        super.initialize();
191        System.out.println("actor.lib.Reader is obsolete, "
192                + "use actor.lib.io.ExpressionReader instead");
193        _dataSize = output.getWidth();
194        _data = new double[_dataSize];
195        attributeChanged(sourceURL);
196    }
197
198    /** Read one row from the input and prepare for output them.
199     *  @exception IllegalActionException If an IO error occurs.
200     */
201    @Override
202    public boolean prefire() throws IllegalActionException {
203        try {
204            _dataSize = output.getWidth();
205
206            if (_data.length != _dataSize) {
207                _data = new double[_dataSize];
208            }
209
210            String oneRow = _reader.readLine();
211
212            if (oneRow == null) {
213                return false;
214            }
215
216            StringTokenizer tokenizer = new StringTokenizer(oneRow);
217            int columnCount = tokenizer.countTokens();
218
219            if (_dataSize > columnCount) {
220                _dataSize = columnCount;
221            }
222
223            for (int i = 0; i < _dataSize; i++) {
224                _data[i] = Double.valueOf(tokenizer.nextToken()).doubleValue();
225            }
226
227            return super.prefire();
228        } catch (IOException ex) {
229            throw new IllegalActionException(this, ex, "prefire() failed");
230        }
231    }
232
233    /** Set the reader.  If there was a previous reader, close it.
234     *  To set standard input, call this method with argument null.
235     *  @param reader The reader to read to.
236     *  @exception IllegalActionException If an IO error occurs.
237     */
238    public void setReader(java.io.BufferedReader reader)
239            throws IllegalActionException {
240        try {
241            if (_reader != null && _reader != _stdIn) {
242                _reader.close();
243            }
244        } catch (IOException ex) {
245            throw new IllegalActionException(this, ex,
246                    "setReader(" + reader + ") failed");
247        }
248
249        if (reader != null) {
250            _reader = reader;
251        } else {
252            _reader = _stdIn;
253        }
254    }
255
256    /** Close the reader if there is one.
257     *  @exception IllegalActionException If an IO error occurs.
258     */
259    @Override
260    public void wrapup() throws IllegalActionException {
261        try {
262            if (_reader != null && _reader != _stdIn) {
263                _reader.close();
264            }
265        } catch (IOException ex) {
266            throw new IllegalActionException(this, ex,
267                    "wrapup(" + _reader + ") failed");
268        }
269    }
270
271    ///////////////////////////////////////////////////////////////////
272    ////                         private members                   ////
273    // The writer to write to.
274    private java.io.BufferedReader _reader = null;
275
276    // Standard out as a writer.
277    private static java.io.BufferedReader _stdIn = null;
278
279    // String for the URL.
280    private String _source;
281
282    // Cache of one row.
283    private double[] _data;
284
285    // Valid enties in the data array.
286    private int _dataSize;
287}