001/* This actor implements a receiver that adds functionality to another receiver.
002
003@Copyright (c) 2011-2014 The Regents of the University of California.
004All rights reserved.
005
006Permission is hereby granted, without written agreement and without
007license or royalty fees, to use, copy, modify, and distribute this
008software and its documentation for any purpose, provided that the
009above copyright notice and the following two paragraphs appear in all
010copies of this software.
011
012IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
013FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
015THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
016SUCH DAMAGE.
017
018THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023ENHANCEMENTS, OR MODIFICATIONS.
024
025                                                PT_COPYRIGHT_VERSION_2
026                                                COPYRIGHTENDKEY
027
028
029 */
030
031package ptolemy.actor;
032
033import java.util.List;
034
035import ptolemy.data.Token;
036import ptolemy.kernel.util.IllegalActionException;
037
038/** A receiver that delegates to another receiver all method calls except
039 *  {@link #put(Token)} (and its variants), for which it delegates to a
040 *  communication aspect. The delegated receiver and the communication aspect are
041 *  specified as constructor arguments.
042 *  <p>
043 *  This can be used, for example, when multiple communication links share
044 *  resources. The communication aspect can, for example, delay the delivery
045 *  of tokens to the delegated receiver to take into account resource
046 *  availability. It could also be used to make a centralized record
047 *  of various communications.
048 *  <p>
049 *  Subclasses of this receiver may also intervene on method calls other
050 *  than put().
051 *  @author Patricia Derler, Edward A. Lee
052 *  @version $Id$
053 *  @since Ptolemy II 10.0
054 *  @Pt.ProposedRating Yellow (derler)
055 *  @Pt.AcceptedRating Red (derler)
056 */
057public class IntermediateReceiver extends AbstractReceiver {
058
059    /** Construct an intermediate receiver with no container that wraps the
060     *  specified receiver using the specified communication aspect.
061     *  @param aspect The communication aspect that receives tokens received by this receiver.
062     *  @param receiver The receiver wrapped by this intermediate receiver.
063     */
064    public IntermediateReceiver(CommunicationAspect aspect, Receiver receiver) {
065        _receiver = receiver;
066        communicationAspect = aspect;
067    }
068
069    /** Construct an intermediate receiver with no container that wraps the
070     *  specified receiver using the specified communication aspect.
071     *  @param aspect The communication aspect that receives tokens received by this receiver.
072     *  @param receiver The receiver wrapped by this intermediate receiver.
073     *  @param port The port wrapped by this intermediate receiver
074     */
075    public IntermediateReceiver(CommunicationAspect aspect, Receiver receiver,
076            IOPort port) {
077        _receiver = receiver;
078        communicationAspect = aspect;
079        _port = port;
080    }
081
082    ///////////////////////////////////////////////////////////////////
083    ////                         public variables                  ////
084
085    /** communication aspect that receives tokens from this receiver. */
086    public CommunicationAspect communicationAspect;
087
088    /** The source actor that sent a token to this receiver. */
089    public Actor source;
090
091    ///////////////////////////////////////////////////////////////////
092    ////                         public methods                    ////
093
094    /** Reset the communication aspect and the receiver that we delegate to.
095     */
096    @Override
097    public void clear() throws IllegalActionException {
098        communicationAspect.reset();
099    }
100
101    /** Delegate to the internal receiver and return whatever it returns.
102     *  @return A list of instances of Token.
103     *  @exception IllegalActionException Always thrown in this base class.
104     */
105    @Override
106    public List<Token> elementList() throws IllegalActionException {
107        return _receiver.elementList();
108    }
109
110    /** Delegate to the internal receiver and return whatever it returns.
111     *  @exception NoTokenException If the delegated receiver throws it.
112     */
113    @Override
114    public Token get() throws NoTokenException {
115        return _receiver.get();
116    }
117
118    /** Delegate to the internal receiver and return whatever it returns.
119     *  @return The port containing the internal receiver.
120     *  @see #setContainer(IOPort)
121     */
122    @Override
123    public IOPort getContainer() {
124        return _receiver.getContainer();
125    }
126
127    /** Delegate to the internal receiver and return whatever it returns.
128     */
129    @Override
130    public boolean hasRoom() {
131        return _receiver.hasRoom();
132    }
133
134    /** Delegate to the internal receiver and return whatever it returns.
135     */
136    @Override
137    public boolean hasRoom(int numberOfTokens) {
138        return _receiver.hasRoom(numberOfTokens);
139    }
140
141    /** Delegate to the internal receiver and return whatever it returns.
142     */
143    @Override
144    public boolean hasToken() {
145        return _receiver.hasToken();
146    }
147
148    /** Delegate to the internal receiver and return whatever it returns.
149     */
150    @Override
151    public boolean hasToken(int numberOfTokens) {
152        return _receiver.hasToken(numberOfTokens);
153    }
154
155    /** Delegate to the internal receiver and return whatever it returns.
156     */
157    @Override
158    public boolean isKnown() {
159        return _receiver.isKnown();
160    }
161
162    /** Forward the specified token to communication aspect specified in
163     *  the constructor.
164     */
165    @Override
166    public void put(Token token)
167            throws NoRoomException, IllegalActionException {
168        communicationAspect.sendToken(this, _receiver, token);
169        ((Actor) _receiver.getContainer().getContainer()).getDirector()
170                .notifyTokenSentToCommunicationAspect();
171    }
172
173    /** Reset this receiver to its initial state, which in this base
174     *  class is the same as calling clear().
175     *  @exception IllegalActionException If reset() is not supported by
176     *   the domain.
177     */
178    @Override
179    public void reset() throws IllegalActionException {
180        super.reset();
181        _receiver.reset();
182    }
183
184    /** Set the container of the internal receiver.
185     *  @param port The container.
186     *  @exception IllegalActionException If the container is not of
187     *   an appropriate subclass of IOPort. Not thrown in this base class,
188     *   but may be thrown in derived classes.
189     *  @see #getContainer()
190     */
191    @Override
192    public void setContainer(IOPort port) throws IllegalActionException {
193        _receiver.setContainer(port);
194    }
195
196    ///////////////////////////////////////////////////////////////////
197    ////                         protected variables               ////
198
199    /** Target receiver that is wrapped by this intermediate receiver.  */
200    public Receiver _receiver;
201
202    /** The port. */
203    protected IOPort _port;
204}