001/* An event that represents a token or tokens sent or received by an IOPort.
002
003 Copyright (c) 2006-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.actor;
029
030import ptolemy.data.Token;
031import ptolemy.kernel.util.DebugEvent;
032import ptolemy.kernel.util.NamedObj;
033
034///////////////////////////////////////////////////////////////////
035//// PortEvent
036
037/**
038 An event that is published by an IOPort when a token or tokens are sent or
039 received.
040
041 <p>In Kepler the provenance recorder and the activity monitor use
042 these events to save intermediate results / show status of the
043 workflow.  In the future these events could be used for "smart"
044 reruns or a fault tolerance mechanism.
045
046 @author  Oscar Barney, Norbert Podhorszki
047 @version $Id$
048 @since Ptolemy II 7.0
049 @Pt.ProposedRating Red (barney)
050 @Pt.AcceptedRating Red (barney)
051 */
052public class IOPortEvent implements DebugEvent {
053    /** Create a new port event with the given parameters.  This
054     *  constructor is used when an array of tokens is sent or received.
055     *  @param port The IOPort where the event occurred.
056     *  @param event The type of event.
057     *  @param channel Channel the token was sent/received on. Use
058     *  IOPortEvent.ALLCHANNELS to indicate a broadcast event.
059     *  @param outside True if the event is related the port's outside
060     *  activity, false if the event is related to the port's inside
061     *  activity.
062     *  @param tokens The token array used for the send/receive.
063     *  @param vectorLength The number of tokens sent/received.
064     */
065    public IOPortEvent(IOPort port, int event, int channel, boolean outside,
066            Token[] tokens, int vectorLength) {
067        _port = port;
068        _event = event;
069        _channel = channel;
070        _outside = outside;
071        _tokenArray = tokens;
072        _token = null;
073        _vectorLength = vectorLength;
074        _receiverPort = null;
075    }
076
077    /** Create a new port event with the given parameters.  This
078     *  constructor is used when a token is sent or sent inside,
079     *  received or received inside.
080     *  @param port The IOPort where the event occurred
081     *  @param event The type of event.
082     *  @param channel Channel the token was sent/received on. Use
083     *  IOPortEvent.ALLCHANNELS to indicate a broadcast event.
084     *  @param outside True if the event is related the port's outside
085     *  activity, false if the event is related to the port's inside
086     *  activity.
087     *  @param token The token that was sent/received.
088     */
089    public IOPortEvent(IOPort port, int event, int channel, boolean outside,
090            Token token) {
091        _port = port;
092        _event = event;
093        _channel = channel;
094        _outside = outside;
095        _tokenArray = null;
096        _token = token;
097        _vectorLength = SINGLETOKEN;
098        _receiverPort = null;
099    }
100
101    /** Create a new port event with the given parameters.  This
102     *  constructor is used when a token is directly put in a
103     *  receiver instead of transferred with IOPort's send() or
104     *  sendInside() methods.
105     *  @param port The IOPort where the event occurred
106     *  @param receiverPort The IOPort of the receiver.
107     *  @param isBegin True if this event is the start.
108     *  @param channel Channel the token was transferred on.
109     *  @param outside True if the event is related the port's outside
110     *  activity, false if the event is related to the port's inside
111     *  activity.
112     *  @param token The token that was transferred.
113     */
114    public IOPortEvent(IOPort port, IOPort receiverPort, boolean isBegin,
115            int channel, boolean outside, Token token) {
116        _port = port;
117        if (isBegin) {
118            _event = SEND_BEGIN;
119        } else {
120            _event = SEND_END;
121        }
122        _receiverPort = receiverPort;
123        _channel = channel;
124        _outside = outside;
125        _tokenArray = null;
126        _token = token;
127        _vectorLength = SINGLETOKEN;
128    }
129
130    ///////////////////////////////////////////////////////////////////
131    ////                         public methods                    ////
132
133    /** Return the port that caused this event.
134     * @return The port.
135     */
136    @Override
137    public NamedObj getSource() {
138        return _port;
139    }
140
141    /** Return the channel on which the token was sent or received.
142     *  @return The channel number.
143     */
144    public int getChannel() {
145        return _channel;
146    }
147
148    /**
149     * Return the receiver's port if this event represents a token put directly
150     * into a receiver instead of transferred via IOPort send or sendInside.
151     * @return Return the receiver's port or null if token was transferred in IOPort.
152     */
153    public IOPort getReceiverPort() {
154        return _receiverPort;
155    }
156
157    /**
158     * Return the type of event.
159     * @return The int event.
160     */
161    public int getEventType() {
162        return _event;
163    }
164
165    /** Return the flag indicating that the event related to the port's outside
166     *  activity (true) or to its inside activity.
167     *  @return The int event.
168     */
169    public boolean getOutsideFlag() {
170        return _outside;
171    }
172
173    /** Return the port where the event occurred.
174     *  @return An instance of IOPort.
175     */
176    public IOPort getPort() {
177        return _port;
178    }
179
180    /** Return the token that was sent or received by the IOPort.
181     *  Return null if the event was for an array of tokens. To get
182     *  the tokens that were sent use getTokenArray() instead.  The
183     *  condition (getVectorLength == IOPortEvent.SINGLETOKEN) is true
184     *  if there was a single token involved.  It returns null if it
185     *  was GET_BEGIN event, since that has no related token at all.
186     *  @return The token sent/received by the IOPort.
187     */
188    public Token getToken() {
189        return _token;
190    }
191
192    /** Return the array of tokens that the IOPort sent or received.
193     *  Return null if an individual token was sent or received
194     *  instead of an array.
195     *  @return The array of tokens which were sent/received.
196     */
197    public Token[] getTokenArray() {
198        //may want to return the array shortened to be vector length long?
199        return _tokenArray;
200    }
201
202    /** Return the number of tokens in the array sent by the IOPort.
203     *  Return IOPortEvent.SINGLETOKEN if an individual token
204     *  was sent instead of an array of tokens.
205     *  @return The number of tokens sent by the port.
206     */
207    public int getVectorLength() {
208        return _vectorLength;
209    }
210
211    /** Return a string representation of this event.
212     *  @return A user-readable string describing the event.
213     */
214    @Override
215    public String toString() {
216        StringBuilder buffer = new StringBuilder("The port " + _port);
217        if (_event == SEND_BEGIN) {
218            buffer.append(" began sending ");
219        } else if (_event == GET_BEGIN) {
220            buffer.append(" began reading ");
221        } else if (_event == GET_END) {
222            buffer.append(" read ");
223        } else if (_event == SEND_END) {
224            buffer.append(" wrote ");
225        }
226        if (_vectorLength != SINGLETOKEN) {
227            buffer.append(_vectorLength);
228            if (_vectorLength == 1) {
229                buffer.append(" token");
230            } else {
231                buffer.append(" tokens");
232            }
233        } else if (_token == null) {
234            buffer.append("a null token");
235        } else {
236            buffer.append(_token.toString());
237        }
238        if (_channel != ALLCHANNELS) {
239            buffer.append(" on channel " + _channel + ".");
240        } else {
241            buffer.append(" on all channels");
242        }
243
244        return buffer.toString();
245    }
246
247    // FIXME change to typesafe enum.
248
249    /** An event corresponding with a token being sent.
250     *  @deprecated Use SEND_BEGIN or SEND_END instead.
251     */
252    @Deprecated
253    public final static int SEND = 1;
254
255    /** An event corresponding with the beginning of a token being sent. */
256    public final static int SEND_BEGIN = 1;
257
258    /** An event corresponding with the beginning of a token being received. */
259    public final static int GET_BEGIN = 2;
260
261    /** An event corresponding with the ending of a token being received. */
262    public final static int GET_END = 3;
263
264    /** An event corresponding with the ending of a token being sent. */
265    public final static int SEND_END = 4;
266
267    /** The token was broadcast on all channels. */
268    public final static int ALLCHANNELS = -1;
269
270    /** A single token related event in getVectorLength(). */
271    public final static int SINGLETOKEN = -1;
272
273    ///////////////////////////////////////////////////////////////////
274    ////                         private variables                 ////
275
276    /** The channel on which the token was sent. */
277    private int _channel;
278
279    /** The receiver's port if this event represents a token put directly
280     * into a receiver instead of transferred via IOPort send or sendInside.
281     */
282    private IOPort _receiverPort;
283
284    /** The IOPort that was activated. */
285    private IOPort _port;
286
287    /** The event type. */
288    // FIXME: we should use a type safe enumeration here.
289    private int _event;
290
291    /** The direction of the event (outside vs inside). */
292    private boolean _outside;
293
294    /** The token sent by the IOPort. */
295    private Token _token;
296
297    /** The array of tokens sent by the IOPort. */
298    private Token[] _tokenArray;
299
300    /** The number of tokens from the array that were sent by the IOPort. */
301    private int _vectorLength;
302}