001/* An actor that reads a token from each input channel to 002 assemble an ArrayToken. 003 004 Copyright (c) 2003-2014 The Regents of the University of California. 005 All rights reserved. 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the above 009 copyright notice and the following two paragraphs appear in all copies 010 of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION_2 026 COPYRIGHTENDKEY 027 028 */ 029package ptolemy.actor.lib; 030 031import ptolemy.data.ArrayToken; 032import ptolemy.data.Token; 033import ptolemy.data.type.ArrayType; 034import ptolemy.kernel.CompositeEntity; 035import ptolemy.kernel.util.IllegalActionException; 036import ptolemy.kernel.util.InternalErrorException; 037import ptolemy.kernel.util.NameDuplicationException; 038import ptolemy.kernel.util.Workspace; 039 040/////////////////////////////////////////////////////////////////// 041//// ElementsToArray 042 043/** 044 <p>On each firing, this actor reads exactly one token from each channel 045 of the input port and assembles the tokens into an ArrayToken. The 046 ArrayToken is sent to the output port. If there is no input token 047 at any channel of the input port, the prefire() will return false. 048 </p><p> 049 This actor is polymorphic. It can accept inputs of any type, as long 050 as the type does not change, and will produce an array with elements 051 of the corresponding type. 052 </p> 053 054 @author Ye Zhou 055 @version $Id$ 056 @since Ptolemy II 4.0 057 @Pt.ProposedRating Red (zhouye) 058 @Pt.AcceptedRating Red (cxh) 059 */ 060public class ElementsToArray extends Transformer { 061 /** Construct an actor with the given container and name. 062 * @param container The container. 063 * @param name The name of this actor. 064 * @exception IllegalActionException If the actor cannot be 065 * contained by the proposed container. 066 * @exception NameDuplicationException If the container 067 * already has an actor with this name. 068 */ 069 public ElementsToArray(CompositeEntity container, String name) 070 throws NameDuplicationException, IllegalActionException { 071 super(container, name); 072 073 // set the output type to be an ArrayType. 074 output.setTypeAtLeast(ArrayType.arrayOf(input)); 075 input.setMultiport(true); 076 077 // Set the icon. 078 _attachText("_iconDescription", 079 "<svg>\n" + "<polygon points=\"-15,-15 15,15 15,-15 -15,15\" " 080 + "style=\"fill:white\"/>\n" + "</svg>\n"); 081 } 082 083 /////////////////////////////////////////////////////////////////// 084 //// public methods //// 085 086 /** Override the base class to set type constraints. 087 * @param workspace The workspace for the new object. 088 * @return A new instance of ArrayElement. 089 * @exception CloneNotSupportedException If a derived class contains 090 * an attribute that cannot be cloned. 091 */ 092 @Override 093 public Object clone(Workspace workspace) throws CloneNotSupportedException { 094 ElementsToArray newObject = (ElementsToArray) super.clone(workspace); 095 try { 096 newObject.output.setTypeAtLeast(ArrayType.arrayOf(newObject.input)); 097 } catch (IllegalActionException e) { 098 // Should have been caught before. 099 throw new InternalErrorException(e); 100 } 101 return newObject; 102 } 103 104 /** Consume one token from each channel of the input port, 105 * assemble those tokens into an ArrayToken, and send the 106 * result to the output. 107 * @exception IllegalActionException If not enough tokens 108 * are available. 109 */ 110 @Override 111 public void fire() throws IllegalActionException { 112 super.fire(); 113 int size = input.getWidth(); 114 Token[] valueArray = new Token[size]; 115 116 for (int i = 0; i < size; i++) { 117 valueArray[i] = input.get(i); 118 } 119 120 output.send(0, new ArrayToken(input.getType(), valueArray)); 121 } 122 123 /** Return true if all channels of the <i>input</i> port have 124 * tokens, false if any channel does not have a token. 125 * @return boolean True if all channels of the input port 126 * have tokens. 127 * @exception IllegalActionException If the hasToken() query 128 * to the input port throws it. 129 * @see ptolemy.actor.IOPort#hasToken(int) 130 */ 131 @Override 132 public boolean prefire() throws IllegalActionException { 133 for (int i = 0; i < input.getWidth(); i++) { 134 if (!input.hasToken(i)) { 135 return false; 136 } 137 } 138 139 return super.prefire(); 140 } 141}