001/* An actor that disassemble an ArrayToken to a multiport output. 002 003 Copyright (c) 2003-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.actor.lib; 029 030import java.util.HashSet; 031import java.util.Set; 032 033import ptolemy.actor.util.ArrayOfTypesFunction; 034import ptolemy.data.ArrayToken; 035import ptolemy.data.Token; 036import ptolemy.data.type.ArrayType; 037import ptolemy.graph.Inequality; 038import ptolemy.kernel.CompositeEntity; 039import ptolemy.kernel.util.IllegalActionException; 040import ptolemy.kernel.util.InternalErrorException; 041import ptolemy.kernel.util.NameDuplicationException; 042import ptolemy.kernel.util.Workspace; 043 044/////////////////////////////////////////////////////////////////// 045//// ArrayToElements 046 047/** 048 <p>An actor that disassembles an ArrayToken to a multiport output.</p> 049 <p>On each firing, this actor reads an ArrayToken from the input 050 port and send out each element token to each channel of the output 051 port. If the width of the output port (say, <i>n</i>) is less than 052 the number of elements in the array (say <i>m</i>), then the first 053 <i>n</i> elements in the array will be sent, and the remaining 054 tokens are discarded. If <i>n</i> is greater than <i>m</i>, then 055 the last <i>n-m</i> channels of the output port will never send 056 tokens out.</p> 057 <p> 058 This actor is polymorphic. It can accept ArrayTokens with any element 059 type and send out tokens corresponding to that type. 060 </p> 061 062 @author Ye Zhou 063 @version $Id$ 064 @since Ptolemy II 4.0 065 @Pt.ProposedRating Red (zhouye) 066 @Pt.AcceptedRating Red (cxh) 067 */ 068public class ArrayToElements extends Transformer { 069 /** Construct an actor with the given container and name. 070 * @param container The container. 071 * @param name The name of this actor. 072 * @exception IllegalActionException If the actor cannot be 073 * contained by the proposed container. 074 * @exception NameDuplicationException If the container 075 * already has an actor with this name. 076 */ 077 public ArrayToElements(CompositeEntity container, String name) 078 throws NameDuplicationException, IllegalActionException { 079 super(container, name); 080 081 // Set type constraints. 082 output.setTypeAtLeast(ArrayType.elementType(input)); 083 084 output.setMultiport(true); 085 086 // Set the icon. 087 _attachText("_iconDescription", 088 "<svg>\n" + "<polygon points=\"-15,-15 15,15 15,-15 -15,15\" " 089 + "style=\"fill:white\"/>\n" + "</svg>\n"); 090 } 091 092 /////////////////////////////////////////////////////////////////// 093 //// public methods //// 094 095 /** Clone the actor into the specified workspace. This calls the 096 * base class and then creates new ports and parameters. 097 * @param workspace The workspace for the new object. 098 * @return A new actor. 099 * @exception CloneNotSupportedException If a derived class 100 * contains an attribute that cannot be cloned. 101 */ 102 @Override 103 public Object clone(Workspace workspace) throws CloneNotSupportedException { 104 ArrayToElements newObject = (ArrayToElements) super.clone(workspace); 105 try { 106 newObject.output 107 .setTypeAtLeast(ArrayType.elementType(newObject.input)); 108 } catch (IllegalActionException e) { 109 // Should have been caught before. 110 throw new InternalErrorException(e); 111 } 112 return newObject; 113 } 114 115 /** If there is a token at the input, read the ArrayToken 116 * from the input port, and for each channel <i>i</i> of 117 * the output port, send the <i>i</i>-th element of this 118 * array to this channel. Otherwise, do nothing. 119 * @exception IllegalActionException If a runtime 120 * type conflict occurs. 121 */ 122 @Override 123 public void fire() throws IllegalActionException { 124 super.fire(); 125 if (input.hasToken(0)) { 126 ArrayToken token = (ArrayToken) input.get(0); 127 int size = token.length(); 128 129 int min = Math.min(size, output.getWidth()); 130 131 Token[] elements = token.arrayValue(); 132 133 for (int i = 0; i < min; i++) { 134 output.send(i, elements[i]); 135 } 136 } 137 } 138 139 /////////////////////////////////////////////////////////////////// 140 //// protected methods //// 141 142 /** Do not establish the usual default type constraints. Instead, the type 143 * of the output port is constrained to be no less than the type of the 144 * elements of the input array (set in the constructor of this class). 145 */ 146 @Override 147 protected Set<Inequality> _defaultTypeConstraints() { 148 return null; 149 } 150 151 /** Add a type constraint for backward type inference that forces 152 * the input to be an array of which the elements have a type 153 * greater than or equal to the output port. 154 * If backward type inference is disabled, this method returns 155 * an empty set. 156 * @see ArrayOfTypesFunction 157 * @return A set of inequalities. 158 */ 159 @Override 160 protected Set<Inequality> _customTypeConstraints() { 161 Set<Inequality> result = new HashSet<Inequality>(); 162 if (isBackwardTypeInferenceEnabled()) { 163 result.add(new Inequality(new ArrayOfTypesFunction(output), 164 input.getTypeTerm())); 165 } 166 return result; 167 } 168}