001/*
002 * Copyright (c) 2008-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: berkley $'
006 * '$Date: 2010-04-28 00:12:36 +0000 (Wed, 28 Apr 2010) $' 
007 * '$Revision: 24000 $'
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.kepler.provenance;
031
032import java.util.HashMap;
033import java.util.Map;
034
035import ptolemy.actor.Actor;
036import ptolemy.actor.FiringEvent;
037
038/**
039 *
040 * A utility class to keep track of an actor's firing.
041 *
042 * @author Daniel Crawl
043 * @version $Id: FireState.java 24000 2010-04-28 00:12:36Z berkley $
044 *
045 */
046    
047public class FireState<FireIdType>
048{
049    /** Construct a FireState with an actor and its id. */
050    public FireState(Actor actor, int id)
051    {
052        _actor = actor;
053        _actorId = id;
054        _typesIndicesMap = new HashMap<String,FireIdType>();
055        _portLastAccess = PortAccessType.Uninitialized;
056        
057        _currentFireType = null;
058        _lastStartFireType = null;
059
060        _firings = 0;
061    }
062
063    /** Get the actor. */
064    public Actor getActor()
065    {
066        return _actor;
067    }
068
069    /** Get the actor's id. */
070    public int getActorId()
071    {
072        return _actorId;
073    }
074
075    
076    /** Record the start of a firing for this actor. 
077     *
078     * @param type type of firing.
079     * @param fireId fire id.
080     * 
081     */
082    public void fireStart(FiringEvent.FiringEventType type, FireIdType fireId)
083    {
084        _typesIndicesMap.put(type.getTypeName(), fireId);
085
086        /*
087        _debug("fire started " + _getName() + " " + type.getTypeName() + 
088            " -> " + fireId);
089        */
090
091        // record the type if not rw
092        if(type.isStart() && type != FiringEvent.BEFORE_RW_FIRE)
093        {
094            _currentFireType = type;
095            _lastStartFireType = type;
096        }
097    }
098
099    /** Record the stop of a firing, and get the fire index 
100     *  for a type of fire. 
101     *
102     *  @param type the current type of fire that running
103     *  @return the firing id
104     */
105    public FireIdType fireStop(FiringEvent.FiringEventType type)
106    {
107        //_debug("fire stopped " + _getName() + " " + type.getTypeName());
108
109        FireIdType retval = _typesIndicesMap.remove(type.getTypeName());
110
111        // if not rw, remove last fire type.
112        if(! type.isStart() && type != FiringEvent.AFTER_RW_FIRE)
113        {
114            _currentFireType = null;
115            _lastStartFireType = type;
116        }
117
118        _firings++;
119
120        return retval;
121    }
122
123    /** Get the current (non-rw) firing index. */
124    public FireIdType getCurFireId()
125    {
126        return getCurFireId(false);
127    }
128
129    /** Get the current firing index.
130     *
131     * @param wantRWFireId If true, return current rw fire id, else
132     * return current non-rw fire id. In the latter case, it returns
133     * the id of the most recent prefire, fire, or postfire to start.
134     * If none of those three types of fire are currently running,
135     * it returns the id of the currently "iterate" firing. If no
136     * "iterate" is currently running, returns UNKNOWN_FIRE_ID.
137     */
138    public FireIdType getCurFireId(boolean wantRWFireId)
139    {
140        FireIdType retval = null;
141
142        // see if we should return rw fire id.
143        if(wantRWFireId)
144        {
145            retval = _typesIndicesMap.get(FiringEvent.BEFORE_RW_FIRE.getTypeName());
146            //_Debug(_getName() + " rw fire id: " + id);
147        }
148        else if(_currentFireType != null)
149        {
150            retval = _typesIndicesMap.get(_currentFireType.getTypeName());
151            //_Debug(_getName() + " " + _currentFireType + " id: " + id);
152        }
153
154        return retval;
155    }
156
157    /** Get the last starting firing type seen. */
158    public FiringEvent.FiringEventType getLastStartFireType()
159    {
160        return _lastStartFireType;
161    }
162
163    /** Get the expected firing type for stopping the firing iteration. */
164    public FiringEvent.FiringEventType getNextStopFiringType()
165        throws RecordingException
166    {
167        FiringEvent.FiringEventType retval = null;
168       
169        // see if firing iteration started with iterate
170        if(_currentFireType == FiringEvent.BEFORE_ITERATE)
171        {
172            retval = FiringEvent.AFTER_ITERATE;
173        }
174        // see if it started with prefire or postfire
175        else if(_currentFireType == FiringEvent.BEFORE_PREFIRE ||
176            _currentFireType == FiringEvent.BEFORE_POSTFIRE)
177        {
178            retval = FiringEvent.AFTER_POSTFIRE;
179        }
180        else if(_currentFireType == FiringEvent.BEFORE_FIRE)
181        {
182            retval = FiringEvent.AFTER_FIRE;
183        }
184        else if(_currentFireType != null)
185        {
186            throw new RecordingException("ERROR: unexpected current fire " +
187                "type: " + _currentFireType + " for actor " +
188                _actor.getFullName());
189        }
190
191        return retval;
192    }
193
194    /** Return the number of firings seen. The number is incremented each
195     *  time fireStop() is called.
196     */
197    public int getNumberOfFirings()
198    {
199        return _firings; 
200    }
201
202    /** Get the last port access for the actor. */
203    public PortAccessType getPortLastAccess()
204    {
205        return _portLastAccess;
206    }
207
208    /** Set the last port access for the actor. */
209    public void setPortLastAccess(PortAccessType type)
210    {
211        _portLastAccess = type;
212    }
213
214    ////////////////////////////////////////////////////////////////////////
215    //// public variables
216
217    /** The types of port accesses. */
218    public enum PortAccessType
219    {
220        Read,
221        Write,
222        Uninitialized
223    };
224
225    ////////////////////////////////////////////////////////////////////////
226    //// private methods
227
228    /** Get the full name of the actor. */
229    private String _getName()
230    {
231        return _actor.getFullName();
232    }
233
234    ////////////////////////////////////////////////////////////////////////
235    //// private variables
236
237    /** The actor. */
238    private Actor _actor;
239
240    /** The actor id. */
241    private int _actorId;
242
243    /** A mapping of firing types to fire indices. */
244    private Map<String,FireIdType> _typesIndicesMap;
245
246    /** The type of firing currently executing. */
247    private FiringEvent.FiringEventType _currentFireType;
248    
249    /** The type of starting firing last seen. */
250    private FiringEvent.FiringEventType _lastStartFireType;
251
252    /** The last kind of access to a port contained by this actor. */
253    private PortAccessType _portLastAccess;
254
255    /** The number of firings. */
256    private int _firings;
257}