001/* A token that contains an array of tokens. 002 003 Copyright (c) 1997-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.data; 029 030import ptolemy.data.type.TupleType; 031import ptolemy.data.type.Type; 032import ptolemy.kernel.util.IllegalActionException; 033 034/////////////////////////////////////////////////////////////////// 035//// TupleToken 036 037/** 038 A token that contains an ordered set of tokens. 039 040 @author Yang Zhao 041 @version $Id$ 042 @since Ptolemy II 10.0 043 @Pt.ProposedRating Yellow (neuendor) 044 @Pt.AcceptedRating Red (cxh) 045 */ 046public class TupleToken extends Token { 047 /** Construct a TupleToken with the specified token array as its value. 048 * @param value The value. 049 */ 050 public TupleToken(Token[] value) { 051 _initialize(value); 052 } 053 054 /////////////////////////////////////////////////////////////////// 055 //// public methods //// 056 057 /** Return an array of tokens populated with the contents of this 058 * array token. The returned array is a copy so the caller is 059 * free to modify it. 060 * @return An array of tokens. 061 */ 062 public Token[] tupleValue() { 063 Token[] result = new Token[_value.length]; 064 065 // This code will create a token array of a more specific type 066 // than token. Eventually, we would like to use this code 067 // since it will simplify writing some actors, but for the 068 // moment the code generator cannot deal with it. 069 // (Token[]) 070 // java.lang.reflect.Array.newInstance( 071 // getElementType().getTokenClass(), 072 // _value.length); 073 System.arraycopy(_value, 0, result, 0, _value.length); 074 return result; 075 } 076 077 /** Return true if the class of the argument is TupleToken and it 078 * has the same length and the elements are equal to that of this 079 * token. Equality of the contained elements is tested by their 080 * equals() method. 081 * @param object The object to compare with. 082 * @return True if the argument is a tuple token of the same length 083 * and the elements are equal to that of this token. 084 */ 085 @Override 086 public boolean equals(Object object) { 087 if (object == null) { 088 return false; 089 } 090 // This test rules out instances of a subclass. 091 if (object.getClass() != getClass()) { 092 return false; 093 } 094 095 TupleToken tupleArgument = (TupleToken) object; 096 int length = tupleArgument.length(); 097 098 if (_value.length != length) { 099 return false; 100 } 101 102 Token[] array = tupleArgument._value; 103 104 for (int i = 0; i < length; i++) { 105 if (!_value[i].equals(array[i])) { 106 return false; 107 } 108 } 109 110 return true; 111 } 112 113 /** Return the element at the specified index. 114 * @param index The index of the desired element. 115 * @return The token contained in this array token at the 116 * specified index. 117 * @exception ArrayIndexOutOfBoundsException If the specified index is 118 * outside the range of the token array. 119 */ 120 public Token getElement(int index) { 121 return _value[index]; 122 } 123 124 /** Return the element type at the specified index. 125 * @param index The index of the desired element. 126 * @return The type of the token contained in this array token at the 127 * specified index. 128 * @exception ArrayIndexOutOfBoundsException If the specified index is 129 * outside the range of the token array. 130 */ 131 public Type getElementType(int index) { 132 return _value[index].getType(); 133 } 134 135 /** Return the type of this token, which is a TupleType populated 136 * with the types of the value of this token. 137 * @return A TupleType. 138 */ 139 @Override 140 public Type getType() { 141 Type[] types = new Type[_value.length]; 142 143 for (int i = 0; i < _value.length; i++) { 144 types[i] = getElementType(i); 145 } 146 147 return new TupleType(types); 148 } 149 150 /** Return a hash code value for this token. This method returns the 151 * hash code length xored with the values of the tuples. 152 * @return A hash code value for this token. 153 */ 154 @Override 155 public int hashCode() { 156 int results = 0; 157 for (Token element : _value) { 158 results ^= element.hashCode(); 159 } 160 return results; 161 } 162 163 /** Return a true-valued token if the argument is equal to this one. 164 * The isEqualTo() method of the element tokens is used to make the 165 * comparison. It is assumed that the argument is a TupleToken. 166 * @param token The token to compare to this token. 167 * @exception IllegalActionException If the element types do not 168 * support this comparison. 169 * @return A true-valued token if the argument is equal. 170 */ 171 @Override 172 public BooleanToken isEqualTo(Token token) throws IllegalActionException { 173 if (getClass() != token.getClass()) { 174 throw new IllegalActionException("isEqualTo not supported" 175 + " between " + this.getType().toString() + " and " 176 + token.getType().toString()); 177 } 178 179 if (isNil() || token.isNil()) { 180 return BooleanToken.FALSE; 181 } 182 183 TupleToken rightTuple = (TupleToken) token; 184 if (length() != rightTuple.length()) { 185 return BooleanToken.FALSE; 186 } 187 188 for (int i = 0; i < _value.length; i++) { 189 BooleanToken result = _value[i].isEqualTo(rightTuple.getElement(i)); 190 191 if (result.booleanValue() == false) { 192 return BooleanToken.FALSE; 193 } 194 } 195 196 return BooleanToken.TRUE; 197 } 198 199 /** Return the length of the contained token array. 200 * @return The length of the contained token array. 201 */ 202 public int length() { 203 return _value.length; 204 } 205 206 /** Merge two tuple tokens into one by concatenating their tokens. 207 * @param first The first tuple token. 208 * @param second The second tuple token. 209 * @return The merged tuple token. 210 */ 211 public static TupleToken merge(TupleToken first, TupleToken second) { 212 if (first == VOID) { 213 return second; 214 } 215 216 if (second == VOID) { 217 return first; 218 } 219 220 Token[] firstTokens = first._value; 221 Token[] secondTokens = second._value; 222 Token[] result = new Token[firstTokens.length + secondTokens.length]; 223 System.arraycopy(firstTokens, 0, result, 0, firstTokens.length); 224 System.arraycopy(secondTokens, 0, result, firstTokens.length, 225 secondTokens.length); 226 return new TupleToken(result); 227 } 228 229 /** Return a new TupleToken representing the multiplicative 230 * identity. The returned token contains a tuple of the same 231 * size as the tuple contained by this token, where each element of 232 * the tuple in the returned token is the multiplicative identity 233 * of the corresponding element of this token. 234 * @return A TupleToken of multiplicative identities. 235 * @exception IllegalActionException If multiplicative identity is not 236 * supported by an element token. 237 */ 238 @Override 239 public Token one() throws IllegalActionException { 240 Token[] oneValueTuple = new Token[_value.length]; 241 242 for (int i = 0; i < _value.length; i++) { 243 oneValueTuple[i] = _value[i].one(); 244 } 245 246 return new TupleToken(oneValueTuple); 247 } 248 249 /** Return the value of this token as a string that can be parsed 250 * by the expression language to recover a token with the same value. 251 * FIXME: This is not currently supported by the expression language. 252 * @return A string beginning with "<" that contains expressions 253 * for every element in the tuple separated by commas, ending with ">". 254 */ 255 @Override 256 public String toString() { 257 StringBuffer buffer = new StringBuffer("<"); 258 259 for (int i = 0; i < _value.length; i++) { 260 buffer.append(_value[i].toString()); 261 262 if (i < _value.length - 1) { 263 buffer.append(", "); 264 } 265 } 266 267 buffer.append(">"); 268 return buffer.toString(); 269 } 270 271 /** Returns a new TupleToken representing the additive identity. 272 * The returned token contains a tuple of the same size as the 273 * tuple contained by this token, and each element of the tuple 274 * in the returned token is the additive identity of the 275 * corresponding element of this token. 276 * @return A TupleToken with additive identities. 277 * @exception IllegalActionException If the additive identity is not 278 * supported by an element token. 279 */ 280 @Override 281 public Token zero() throws IllegalActionException { 282 Token[] zeroValueTuple = new Token[_value.length]; 283 284 for (int i = 0; i < _value.length; i++) { 285 zeroValueTuple[i] = _value[i].zero(); 286 } 287 288 return new TupleToken(zeroValueTuple); 289 } 290 291 /////////////////////////////////////////////////////////////////// 292 //// public variables //// 293 294 /** An empty tuple token. */ 295 public static final TupleToken VOID = new TupleToken(new Token[0]); 296 297 /////////////////////////////////////////////////////////////////// 298 //// private methods //// 299 // Initialize this token using the specified array. 300 private void _initialize(Token[] value) { 301 int length = value.length; 302 _value = new Token[length]; 303 304 for (int i = 0; i < length; i++) { 305 _value[i] = value[i]; 306 } 307 } 308 309 /////////////////////////////////////////////////////////////////// 310 //// private variables //// 311 private Token[] _value; 312}