001/* A Token holder with a capacity of one token. 002 003 Copyright (c) 1997-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.domains.modal.kernel; 029 030import java.util.LinkedList; 031import java.util.List; 032 033import ptolemy.actor.AbstractReceiver; 034import ptolemy.actor.IOPort; 035import ptolemy.actor.NoRoomException; 036import ptolemy.actor.NoTokenException; 037import ptolemy.data.Token; 038import ptolemy.kernel.util.IllegalActionException; 039import ptolemy.kernel.util.InternalErrorException; 040 041/////////////////////////////////////////////////////////////////// 042//// FSMReceiver 043 044/** 045 A receiver with capacity one for which one can explicitly set the status. 046 047 @author Edward A. Lee 048 @version $Id$ 049 @since Ptolemy II 8.0 050 @Pt.ProposedRating Yellow (eal) 051 @Pt.AcceptedRating Red (cxh) 052 */ 053public class FSMReceiver extends AbstractReceiver { 054 055 /** Construct an empty receiver with no container. 056 * The initial status is unknown. 057 */ 058 public FSMReceiver() { 059 super(); 060 } 061 062 /** Construct an empty receiver with the specified container. 063 * The initial status is unknown. 064 * @param container The container. 065 * @exception IllegalActionException If the container does 066 * not accept this receiver. 067 */ 068 public FSMReceiver(IOPort container) throws IllegalActionException { 069 super(container); 070 } 071 072 /////////////////////////////////////////////////////////////////// 073 //// public methods //// 074 075 /** Clear this receiver of any contained token and set the known 076 * status to true. 077 */ 078 @Override 079 public void clear() { 080 _token = null; 081 _isKnown = true; 082 } 083 084 /** Return a list with the token currently in the receiver, or 085 * an empty list if there is no such token. 086 * @return A list of instances of Token. 087 * @exception IllegalActionException If the status is unknown. 088 */ 089 @Override 090 public List<Token> elementList() throws IllegalActionException { 091 if (!_isKnown) { 092 throw new IllegalActionException(getContainer(), 093 "Receiver status is unknown."); 094 } 095 List<Token> result = new LinkedList<Token>(); 096 if (_token != null) { 097 result.add(_token); 098 } 099 return result; 100 } 101 102 /** Get the contained Token. If there is none, throw an exception. 103 * The token is not removed. It can be repeatedly read. 104 * @return The token contained by this receiver. 105 * @exception NoTokenException If this receiver is empty or unknown 106 */ 107 @Override 108 public Token get() throws NoTokenException { 109 if (_token == null) { 110 throw new NoTokenException(getContainer(), 111 "Attempt to get data from an empty recever."); 112 } 113 if (!_isKnown) { 114 throw new NoTokenException(getContainer(), 115 "Receiver status is unknown."); 116 } 117 return _token; 118 } 119 120 /** If the argument is 1, there is a token, and the status is known, 121 * then return an array containing the one token. Otherwise, throw 122 * an exception. 123 * @exception NoTokenException If the status is unknown, if there is 124 * no token, or if the argument is not 1. 125 */ 126 @Override 127 public Token[] getArray(int numberOfTokens) throws NoTokenException { 128 if (!_isKnown) { 129 throw new NoTokenException(getContainer(), 130 "Receiver status is unknown."); 131 } 132 if (numberOfTokens <= 0) { 133 throw new IllegalArgumentException( 134 "Illegal argument to getArray():" + numberOfTokens); 135 } 136 if (numberOfTokens > 1) { 137 throw new NoTokenException(getContainer(), 138 "Receiver can only contain one token, but request is for " 139 + numberOfTokens); 140 } 141 if (_token == null) { 142 throw new NoTokenException(getContainer(), "Receiver is empty."); 143 } 144 // Check whether we need allocate the cached token array. 145 if (_tokenCache == null) { 146 _tokenCache = new Token[1]; 147 } 148 _tokenCache[0] = _token; 149 return _tokenCache; 150 } 151 152 /** Return true. 153 * @return True. 154 */ 155 @Override 156 public boolean hasRoom() { 157 return true; 158 } 159 160 /** Return true if the argument is 1, and otherwise return false. 161 * @param numberOfTokens The number of tokens to put into the receiver. 162 * @return True if the argument is 1, and otherwise return false. 163 * @exception IllegalArgumentException If the argument is not positive. 164 * This is a runtime exception, so it does not need to be declared 165 * explicitly. 166 */ 167 @Override 168 public boolean hasRoom(int numberOfTokens) throws IllegalArgumentException { 169 if (numberOfTokens < 1) { 170 throw new IllegalArgumentException( 171 "hasRoom() requires a positive argument."); 172 } 173 if (numberOfTokens > 1) { 174 return false; 175 } 176 return true; 177 } 178 179 /** Return true if this mailbox is not empty. 180 * @return True if this mailbox is not empty. 181 * @exception InternalErrorException If the status is not known. 182 */ 183 @Override 184 public boolean hasToken() { 185 if (!_isKnown) { 186 throw new InternalErrorException(getContainer(), null, 187 "Receiver status is not known."); 188 } 189 return _token != null; 190 } 191 192 /** Return true if the argument is 1 and this receiver is not empty, 193 * and otherwise return false. 194 * @param numberOfTokens The number of tokens to get from the receiver. 195 * @return True if the argument is 1 and this receiver is not empty. 196 * @exception InternalErrorException If the status is not known. 197 * @exception IllegalArgumentException If the argument is not positive. 198 * This is a runtime exception, so it does not need to be declared 199 * explicitly. 200 */ 201 @Override 202 public boolean hasToken(int numberOfTokens) 203 throws IllegalArgumentException { 204 if (!_isKnown) { 205 throw new InternalErrorException(getContainer(), null, 206 "Receiver status is not known."); 207 } 208 if (numberOfTokens < 1) { 209 throw new IllegalArgumentException( 210 "hasToken() requires a positive argument."); 211 } 212 213 if (numberOfTokens == 1) { 214 return _token != null; 215 } 216 217 return false; 218 } 219 220 /** Return whether the state of the receiver is known. 221 * @return True if the state of the receiver is known. 222 * @see #clear() 223 * @see #put(Token) 224 */ 225 @Override 226 public boolean isKnown() { 227 return _isKnown; 228 } 229 230 /** Put a token into this receiver. If the argument is null, then the 231 * receiver will not contain a token after this returns, getting the 232 * same effect as calling clear(). If there was previously a token 233 * in the receiver, this overwrites that token. 234 * Set the known status of the receiver to true. 235 * @param token The token to be put into the mailbox. 236 * @exception NoRoomException If this mailbox is not empty. 237 */ 238 @Override 239 public void put(Token token) throws NoRoomException { 240 _token = token; 241 _isKnown = true; 242 } 243 244 /** If the argument has one token, then put that token in 245 * the receiver. Otherwise, throw an exception. 246 */ 247 @Override 248 public void putArray(Token[] tokenArray, int numberOfTokens) 249 throws NoRoomException, IllegalActionException { 250 if (numberOfTokens != 1 || tokenArray.length < 1) { 251 throw new IllegalActionException(getContainer(), 252 "Receiver cannot accept more than one token."); 253 } 254 put(tokenArray[0]); 255 } 256 257 /** Set the receiver to unknown. */ 258 @Override 259 public void reset() throws IllegalActionException { 260 _isKnown = false; 261 _token = null; 262 } 263 264 /////////////////////////////////////////////////////////////////// 265 //// private variables //// 266 267 /** Flag indicating whether the state of the receiver is known. */ 268 private boolean _isKnown = false; 269 270 /** The token held. */ 271 private Token _token = null; 272 273 /** The cache used by the getArray() method to avoid reallocating. */ 274 private Token[] _tokenCache; 275}