001/* An actor that outputs the previous event when it receives an event.
002
003 Copyright (c) 1998-2018 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.de.lib;
029
030import java.util.Set;
031
032import ptolemy.data.Token;
033import ptolemy.data.expr.Parameter;
034import ptolemy.graph.Inequality;
035import ptolemy.kernel.CompositeEntity;
036import ptolemy.kernel.util.IllegalActionException;
037import ptolemy.kernel.util.InternalErrorException;
038import ptolemy.kernel.util.NameDuplicationException;
039
040///////////////////////////////////////////////////////////////////
041//// Previous
042
043/**
044 On each iteration, this actor produces the token received on the previous
045 iteration. On the first iteration, it produces the token given by the
046 <i>initialValue</i> parameter, if such a value has been set.
047 <p>
048 Although it might be tempting to try, this actor is not very useful
049 for breaking precedences in a feedback loop in DE, the way the
050 TimedDelay actor in DE or the SampleDelay actor in SDF do.
051 Since it does not trigger until there is an input, it will not
052 actually break the precedences in a feedback loop.
053 <p>
054 The output data type is constrained to be at least as general
055 as both the input and the <i>initialValue</i> parameter.
056
057 @see ptolemy.domains.de.lib.TimedDelay
058 @see ptolemy.domains.sdf.lib.SampleDelay
059
060 @author Edward A. Lee
061 @version $Id$
062 @since Ptolemy II 2.0
063 @Pt.ProposedRating Red (eal)
064 @Pt.AcceptedRating Red (cxh)
065 */
066public class Previous extends DETransformer {
067    /** Construct an actor with the specified container and name.
068     *  @param container The composite actor to contain this one.
069     *  @param name The name of this actor.
070     *  @exception IllegalActionException If the entity cannot be contained
071     *   by the proposed container.
072     *  @exception NameDuplicationException If the container already has an
073     *   actor with this name.
074     */
075    public Previous(CompositeEntity container, String name)
076            throws NameDuplicationException, IllegalActionException {
077        super(container, name);
078        initialValue = new Parameter(this, "initialValue");
079    }
080
081    ///////////////////////////////////////////////////////////////////
082    ////                       ports and parameters                ////
083
084    /** The initial output value. If this is set, it specifies the
085     *  first output value produced when the first input arrives.
086     *  If it is not set, then no output is produced on the first
087     *  firing.
088     */
089    public Parameter initialValue;
090
091    ///////////////////////////////////////////////////////////////////
092    ////                         public methods                    ////
093
094    /** If there is a previous token, then produce it on the output,
095     *  and then read the input and record it for the next firing.
096     *  @exception IllegalActionException If getting token from input or
097     *  sending token to output throws it.
098     */
099    @Override
100    public void fire() throws IllegalActionException {
101        super.fire();
102
103        if (_previous != null) {
104            output.send(0, _previous);
105        }
106
107        if (input.hasToken(0)) {
108            _tempPrevious = input.get(0);
109        }
110    }
111
112    /** Initialize so that the initial token will be produced.
113     *  @exception IllegalActionException If the super class throws it
114     *  or can not get a valid token from the initializeValue parameter.
115     */
116    @Override
117    public void initialize() throws IllegalActionException {
118        super.initialize();
119
120        // Note that this might be null, if it has not been set.
121        _previous = initialValue.getToken();
122        _tempPrevious = null;
123    }
124
125    /** Update the state of the actor.
126     *  @exception IllegalActionException If the base class throws it.
127     */
128    @Override
129    public boolean postfire() throws IllegalActionException {
130        _previous = _tempPrevious;
131        _tempPrevious = null;
132        return super.postfire();
133    }
134
135    /** Override the method in the base class so that the type
136     *  constraint for the <i>initialValue</i> parameter will be set
137     *  if it contains a value.
138     *  @return a list of Inequality objects.
139     *  @see ptolemy.graph.Inequality
140     */
141    /*    public Set<Inequality> typeConstraints() {
142            Set<Inequality> typeConstraints = super.typeConstraints();
143
144            try {
145                if (initialValue.getToken() != null) {
146                    Inequality ineq = new Inequality(initialValue.getTypeTerm(),
147                            output.getTypeTerm());
148                    typeConstraints.add(ineq);
149                }
150
151                Inequality ineq2 = new Inequality(input.getTypeTerm(),
152                        output.getTypeTerm());
153                typeConstraints.add(ineq2);
154            } catch (IllegalActionException ex) {
155                // Errors in the initialValue parameter should
156                // already have been caught in getAttribute() method
157                // of the base class.
158                throw new InternalErrorException("Bad initialValue value!");
159            }
160
161            return typeConstraints;
162        }
163     */
164
165    /**
166     * Adds to the set of inequalities returned by the overridden method
167     * a constraint that requires the initial value to be less than or
168     * equal to the type of the output.
169     */
170    @Override
171    public Set<Inequality> _containedTypeConstraints() {
172        Set<Inequality> result = super._containedTypeConstraints();
173        try {
174            // type of initialValue <= type of output
175            if (initialValue.getToken() != null) {
176                result.add(new Inequality(initialValue.getTypeTerm(),
177                        output.getTypeTerm()));
178            }
179        } catch (IllegalActionException ex) {
180            // Errors in the initialValue parameter should already
181            // have been caught in getAttribute() method of the base
182            // class.
183            throw new InternalErrorException("Bad initialValue value!");
184        }
185
186        return result;
187    }
188
189    /** Reset the state variables.
190     *  @exception IllegalActionException If the base class throws it.
191     */
192    @Override
193    public void wrapup() throws IllegalActionException {
194        super.wrapup();
195        _tempPrevious = null;
196        _previous = null;
197    }
198
199    ///////////////////////////////////////////////////////////////////
200    ////                         private variables                 ////
201    // Previous input.
202    private Token _previous;
203
204    // Temporary previous input.
205    private Token _tempPrevious;
206}