001/*
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
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
030/* Input a sequence of N input tokens and then output a trigger
031   after the Nth token
032 */
033
034package org.ecoinformatics.seek.util;
035
036import ptolemy.actor.parameters.PortParameter;
037import ptolemy.data.IntToken;
038import ptolemy.data.StringToken;
039import ptolemy.data.type.BaseType;
040import ptolemy.domains.sdf.lib.SDFTransformer;
041import ptolemy.kernel.CompositeEntity;
042import ptolemy.kernel.util.Attribute;
043import ptolemy.kernel.util.IllegalActionException;
044import ptolemy.kernel.util.NameDuplicationException;
045
046//////////////////////////////////////////////////////////////////////////
047//// SequenceToTrigger
048
049/**
050 * This actor bundles a specified number of input tokens into a single array.
051 * The number of tokens to be bundled is specified by the <i>sequenceLength</i>
052 * parameter.
053 * <p>
054 * This actor is polymorphic. It can accept inputs of any type, as long as the
055 * type does not change, and will produce an array with elements of the
056 * corresponding type.
057 * <p>
058 */
059public class SequenceToTrigger extends SDFTransformer {
060        /**
061         * Construct an actor with the given container and name.
062         * 
063         * @param container
064         *            The container.
065         * @param name
066         *            The name of this actor.
067         * @exception IllegalActionException
068         *                If the actor cannot be contained by the proposed
069         *                container.
070         * @exception NameDuplicationException
071         *                If the container already has an actor with this name.
072         */
073        public SequenceToTrigger(CompositeEntity container, String name)
074                        throws NameDuplicationException, IllegalActionException {
075                super(container, name);
076
077                input_tokenConsumptionRate.setExpression("sequenceLength");
078
079                // set the output type to be an ArrayType.
080                output.setTypeEquals(BaseType.STRING);
081
082                // Set parameters.
083                sequenceLength = new PortParameter(this, "sequenceLength");
084                sequenceLength.setExpression("1");
085
086                // Set the icon.
087                _attachText("_iconDescription", "<svg>\n"
088                                + "<polygon points=\"-15,-15 15,15 15,-15 -15,15\" "
089                                + "style=\"fill:white\"/>\n" + "</svg>\n");
090        }
091
092        // /////////////////////////////////////////////////////////////////
093        // // parameters ////
094
095        /**
096         * The size of the output array. This is an integer that defaults to 1.
097         */
098        public PortParameter sequenceLength;
099
100        // /////////////////////////////////////////////////////////////////
101        // // public methods ////
102
103        /**
104         * Ensure that the sequenceLength parameter is not negative.
105         * 
106         * @param attribute
107         *            The attribute that has changed.
108         * @exception IllegalActionException
109         *                If the parameters are out of range.
110         */
111        public void attributeChanged(Attribute attribute)
112                        throws IllegalActionException {
113                if (attribute == sequenceLength) {
114                        int rate = ((IntToken) sequenceLength.getToken()).intValue();
115
116                        if (rate < 0) {
117                                throw new IllegalActionException(this,
118                                                "Invalid sequenceLength: " + rate);
119                        }
120                } else {
121                        super.attributeChanged(attribute);
122                }
123        }
124
125        /**
126         * Consume the inputs and produce the output ArrayToken.
127         * 
128         * @exception IllegalActionException
129         *                If not enough tokens are available.
130         */
131        public void fire() throws IllegalActionException {
132                super.fire();
133                sequenceLength.update();
134
135                int length = ((IntToken) sequenceLength.getToken()).intValue();
136
137                output.send(0, new StringToken("fire"));
138        }
139
140        /**
141         * Return true if the input port has enough tokens for this actor to fire.
142         * The number of tokens required is determined by the value of the
143         * <i>arrayLength</i> parameter.
144         * 
145         * @return boolean True if there are enough tokens at the input port for
146         *         this actor to fire.
147         * @exception IllegalActionException
148         *                If the hasToken() query to the input port throws it.
149         * @see ptolemy.actor.IOPort#hasToken(int, int)
150         */
151        public boolean prefire() throws IllegalActionException {
152                int length = ((IntToken) sequenceLength.getToken()).intValue();
153
154                if (!input.hasToken(0, length)) {
155                        if (_debugging) {
156                                _debug("Called prefire(), which returns false.");
157                        }
158
159                        return false;
160                } else {
161                        return super.prefire();
162                }
163        }
164
165}