001/* Utilities to convert between java types and Token types
002
003 Copyright (c) 1998-2015 The Regents of the University of California and
004 Research in Motion Limited.
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 OR RESEARCH IN MOTION
013 LIMITED BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
014 INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
015 SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA
016 OR RESEARCH IN MOTION LIMITED HAVE BEEN ADVISED OF THE POSSIBILITY OF
017 SUCH DAMAGE.
018
019 THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION LIMITED
020 SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
022 PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
023 BASIS, AND THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION
024 LIMITED HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
025 ENHANCEMENTS, OR MODIFICATIONS.
026
027 @ProposedRating Yellow (nsmyth)
028 @AcceptedRating Red (cxh)
029
030 Created : May 1998
031 */
032package ptolemy.data.expr;
033
034import ptolemy.data.ArrayToken;
035import ptolemy.data.BooleanMatrixToken;
036import ptolemy.data.BooleanToken;
037import ptolemy.data.ComplexMatrixToken;
038import ptolemy.data.ComplexToken;
039import ptolemy.data.DoubleMatrixToken;
040import ptolemy.data.DoubleToken;
041import ptolemy.data.FixMatrixToken;
042import ptolemy.data.FixToken;
043import ptolemy.data.FloatToken;
044import ptolemy.data.IntMatrixToken;
045import ptolemy.data.IntToken;
046import ptolemy.data.LongMatrixToken;
047import ptolemy.data.LongToken;
048import ptolemy.data.ObjectToken;
049import ptolemy.data.ShortToken;
050import ptolemy.data.StringToken;
051import ptolemy.data.UnsignedByteToken;
052import ptolemy.data.type.ArrayType;
053import ptolemy.data.type.BaseType;
054import ptolemy.data.type.FixType;
055import ptolemy.data.type.ObjectType;
056import ptolemy.data.type.RecordType;
057import ptolemy.data.type.Type;
058import ptolemy.kernel.util.IllegalActionException;
059import ptolemy.kernel.util.InternalErrorException;
060import ptolemy.math.Complex;
061import ptolemy.math.FixPoint;
062
063///////////////////////////////////////////////////////////////////
064//// ConversionUtilities
065
066/**
067 This class contains a series of static methods that facilitate the
068 runtime conversion of tokens to and from Java representations that are
069 not tokens.  One might call this "marshaling and unmarshaling" of
070 tokens.  Primarily this facility is used by the expression language to
071 properly type references to Java methods, and later invoke those
072 methods during expression evaluation.  Generally speaking this is
073 somewhat nasty from an Object-oriented point of view.  The nastiness
074 is fairly well encapsulated in this class.  The mapping is summarized
075 in the following table:
076
077 <pre>
078 Token type               Java type
079 ---------------------------------------------------
080 IntToken                 int
081 DoubleToken              double
082 LongToken                long
083 StringToken              java.lang.String
084 BooleanToken             boolean
085 ComplexToken             ptolemy.math.Complex
086 FixToken                 ptolemy.math.FixPoint
087 FixMatrixToken           ptolemy.math.FixPoint[][]
088 IntMatrixToken           int[][]
089 DoubleMatrixToken        double[][]
090 ComplexMatrixToken       ptolemy.math.Complex[][]
091 LongMatrixToken          long[][]
092 BooleanMatrixToken       boolean[][]
093 ArrayToken(FixToken)     ptolemy.math.FixPoint[]
094 ArrayToken(IntToken)     int[]
095 ArrayToken(LongToken)    long[]
096 ArrayToken(DoubleToken)  double[]
097 ArrayToken(ComplexToken) ptolemy.math.Complex[]
098 ArrayToken(StringToken)  java.lang.String[]
099 ArrayToken(BooleanToken) boolean[]
100 ArrayToken  (*)          Token[]
101 ---------------------------------------------------
102 (*) Only when converting from java to Token types
103 </pre>
104
105 @author Neil Smyth, Edward A. Lee, Steve Neuendorffer
106 @author Zoltan Kemenczy, Research in Motion Limited
107 @version $Id$
108 @see ptolemy.data.expr.ASTPtRootNode
109 @see ptolemy.data.expr.PtParser
110 @see ptolemy.data.Token
111 @see ptolemy.data.expr.UtilityFunctions
112 @see java.lang.Math
113 */
114public class ConversionUtilities {
115    ///////////////////////////////////////////////////////////////////
116    ////                         public methods                    ////
117
118    /** Convert a java object to a corresponding Token.  This method
119     * is called by the expression language to marshal numeric object
120     * into tokens.  If the argument is a token, this function returns
121     * it.  If the argument is an array, an array token will be
122     * returned.  If the argument is an array of array, then a matrix
123     * token will be returned.  If the argument is a Java numeric
124     * encapsulation object, e.g. java.lang.Double, then the number is
125     * extracted and re-encapsulated in a token.  If no other
126     * conversion is possible, then this method will simply return an
127     * ObjectToken wrapping the object.
128     * @param object The object that is a Java type to be converted.
129     * The value of this parameter might be null, in which case an
130     * ObjectToken with a null v
131     * @exception IllegalActionException If the selected conversion fails.
132     * @return A new token.
133     */
134    public static ptolemy.data.Token convertJavaTypeToToken(Object object)
135            throws ptolemy.kernel.util.IllegalActionException {
136        ptolemy.data.Token returnValue = null;
137
138        // FIXME: Object could be null. What to do here?
139        // Return null? Throw an exception?
140        if (object instanceof ptolemy.data.Token) {
141            returnValue = (ptolemy.data.Token) object;
142        } else if (object instanceof ptolemy.data.Token[]) {
143            returnValue = new ArrayToken((ptolemy.data.Token[]) object);
144        } else if (object instanceof Boolean) {
145            returnValue = new BooleanToken(((Boolean) object).booleanValue());
146        } else if (object instanceof Byte) {
147            // Note: This is technically not quite right, because of
148            // the sign involved...  In lieu of a signed byte token,
149            // we assume that methods that return byte should be
150            // interpreted unsigned.
151            returnValue = new UnsignedByteToken(((Byte) object).byteValue());
152        } else if (object instanceof Short) {
153            returnValue = new ShortToken(((Short) object).shortValue());
154        } else if (object instanceof Integer) {
155            returnValue = new IntToken(((Integer) object).intValue());
156        } else if (object instanceof Long) {
157            returnValue = new LongToken(((Long) object).longValue());
158        } else if (object instanceof Double) {
159            returnValue = new DoubleToken(((Double) object).doubleValue());
160        } else if (object instanceof Float) {
161            returnValue = new FloatToken(((Float) object).floatValue());
162        } else if (object instanceof Complex) {
163            returnValue = new ComplexToken((Complex) object);
164        } else if (object instanceof FixPoint) {
165            returnValue = new FixToken((FixPoint) object);
166        } else if (object instanceof String) {
167            returnValue = new StringToken((String) object);
168        } else if (object instanceof boolean[][]) {
169            returnValue = new BooleanMatrixToken((boolean[][]) object);
170        } else if (object instanceof int[][]) {
171            returnValue = new IntMatrixToken((int[][]) object);
172        } else if (object instanceof long[][]) {
173            returnValue = new LongMatrixToken((long[][]) object);
174        } else if (object instanceof double[][]) {
175            returnValue = new DoubleMatrixToken((double[][]) object);
176        } else if (object instanceof Complex[][]) {
177            returnValue = new ComplexMatrixToken((Complex[][]) object);
178        } else if (object instanceof FixPoint[][]) {
179            returnValue = new FixMatrixToken((FixPoint[][]) object);
180        } else if (object instanceof double[]) {
181            DoubleToken[] temp = new DoubleToken[((double[]) object).length];
182
183            for (int j = 0; j < temp.length; j++) {
184                temp[j] = new DoubleToken(((double[]) object)[j]);
185            }
186
187            returnValue = new ArrayToken(temp);
188        } else if (object instanceof Complex[]) {
189            ComplexToken[] temp = new ComplexToken[((Complex[]) object).length];
190
191            for (int j = 0; j < temp.length; j++) {
192                temp[j] = new ComplexToken(((Complex[]) object)[j]);
193            }
194
195            returnValue = new ArrayToken(temp);
196        } else if (object instanceof int[]) {
197            IntToken[] temp = new IntToken[((int[]) object).length];
198
199            for (int j = 0; j < temp.length; j++) {
200                temp[j] = new IntToken(((int[]) object)[j]);
201            }
202
203            returnValue = new ArrayToken(temp);
204        } else if (object instanceof long[]) {
205            LongToken[] temp = new LongToken[((long[]) object).length];
206
207            for (int j = 0; j < temp.length; j++) {
208                temp[j] = new LongToken(((long[]) object)[j]);
209            }
210
211            returnValue = new ArrayToken(temp);
212        } else if (object instanceof boolean[]) {
213            BooleanToken[] temp = new BooleanToken[((boolean[]) object).length];
214
215            for (int j = 0; j < temp.length; j++) {
216                temp[j] = new BooleanToken(((boolean[]) object)[j]);
217            }
218
219            returnValue = new ArrayToken(temp);
220        } else if (object instanceof String[]) {
221            StringToken[] temp = new StringToken[((String[]) object).length];
222
223            for (int j = 0; j < temp.length; j++) {
224                temp[j] = new StringToken(((String[]) object)[j]);
225            }
226
227            returnValue = new ArrayToken(temp);
228        } else if (object instanceof FixPoint[]) {
229            // Create back an ArrayToken containing FixTokens
230            FixToken[] temp = new FixToken[((FixPoint[]) object).length];
231
232            for (int j = 0; j < temp.length; j++) {
233                temp[j] = new FixToken(((FixPoint[]) object)[j]);
234            }
235
236            returnValue = new ArrayToken(temp);
237        } else if (object != null && object.getClass().isArray()) {
238            Class elementClass = object.getClass().getComponentType();
239            Type elementType = convertJavaTypeToTokenType(elementClass);
240
241            Object[] array = (Object[]) object;
242            ptolemy.data.Token[] tokens = new ptolemy.data.Token[array.length];
243            for (int i = 0; i < array.length; i++) {
244                tokens[i] = convertJavaTypeToToken(array[i]);
245            }
246
247            return new ArrayToken(elementType, tokens);
248        } else {
249            // Package into an ObjectToken.
250            returnValue = new ObjectToken(object);
251        }
252
253        return returnValue;
254    }
255
256    /** Convert a java class, representing a Java type, to a
257     *  corresponding instance of a ptolemy type object, as consistent
258     *  with the convertJavaTypeToToken method.
259     *  @param tokenClass the java class to be converted.
260     *  @return The corresponding Ptolemy type object.
261     *  @exception IllegalActionException If the token class is not
262     *  recognized, or creating the type fails.
263     */
264    public static Type convertJavaTypeToTokenType(Class tokenClass)
265            throws ptolemy.kernel.util.IllegalActionException {
266        try {
267            if (tokenClass.equals(ptolemy.data.Token.class)) {
268                return BaseType.GENERAL;
269            } else if (ptolemy.data.ArrayToken.class
270                    .isAssignableFrom(tokenClass)) {
271                Type type = new ArrayType(BaseType.GENERAL);
272                return type;
273            } else if (ptolemy.data.RecordToken.class
274                    .isAssignableFrom(tokenClass)) {
275                Type type = RecordType.EMPTY_RECORD;
276                return type;
277            } else if (ptolemy.data.Token.class.isAssignableFrom(tokenClass)) {
278                Type type = BaseType.forClassName(tokenClass.getName());
279
280                if (type == null) {
281                    throw new IllegalActionException(
282                            "Could not find return type for class "
283                                    + tokenClass);
284                }
285
286                return type;
287            } else if (tokenClass.equals(Boolean.class)
288                    || tokenClass.equals(Boolean.TYPE)) {
289                return BaseType.BOOLEAN;
290            } else if (tokenClass.equals(Byte.class)
291                    || tokenClass.equals(Byte.TYPE)) {
292                return BaseType.UNSIGNED_BYTE;
293            } else if (tokenClass.equals(Short.class)
294                    || tokenClass.equals(Short.TYPE)) {
295                return BaseType.SHORT;
296            } else if (tokenClass.equals(Integer.class)
297                    || tokenClass.equals(Integer.TYPE)) {
298                return BaseType.INT;
299            } else if (tokenClass.equals(Long.class)
300                    || tokenClass.equals(Long.TYPE)) {
301                return BaseType.LONG;
302            } else if (tokenClass.equals(Double.class)
303                    || tokenClass.equals(Double.TYPE)) {
304                return BaseType.DOUBLE;
305            } else if (tokenClass.equals(Float.class)
306                    || tokenClass.equals(Float.TYPE)) {
307                return BaseType.FLOAT;
308            } else if (tokenClass.equals(Complex.class)) {
309                return BaseType.COMPLEX;
310            } else if (tokenClass.equals(FixPoint.class)) {
311                return BaseType.UNSIZED_FIX;
312            } else if (tokenClass.equals(String.class)) {
313                return BaseType.STRING;
314            } else if (tokenClass.equals(Class.forName("[[Z"))) {
315                return BaseType.BOOLEAN_MATRIX;
316            } else if (tokenClass.equals(Class.forName("[[I"))) {
317                return BaseType.INT_MATRIX;
318            } else if (tokenClass.equals(Class.forName("[[J"))) {
319                return BaseType.LONG_MATRIX;
320            } else if (tokenClass.equals(Class.forName("[[D"))) {
321                return BaseType.DOUBLE_MATRIX;
322            } else if (tokenClass
323                    .equals(Class.forName("[[Lptolemy.math.Complex;"))) {
324                return BaseType.COMPLEX_MATRIX;
325            } else if (tokenClass
326                    .equals(Class.forName("[[Lptolemy.math.FixPoint;"))) {
327                return BaseType.FIX_MATRIX;
328            } else if (tokenClass.isArray()) {
329                return new ArrayType(convertJavaTypeToTokenType(
330                        tokenClass.getComponentType()));
331            } else if (java.lang.Object.class.isAssignableFrom(tokenClass)) {
332                return new ObjectType(tokenClass);
333            } else if (tokenClass.isArray()) {
334                Class elementClass = tokenClass.getComponentType();
335                Type elementType = convertJavaTypeToTokenType(elementClass);
336                return new ArrayType(elementType);
337            } else {
338                // This should really never happen, since every class
339                // should be caught by the isAssignable test above,
340                // but I don't like the dangling else if.
341                throw new InternalErrorException(
342                        "type not found: " + tokenClass);
343            }
344        } catch (ClassNotFoundException ex) {
345            throw new IllegalActionException(null, ex,
346                    "Could not find Class '" + tokenClass + "'");
347        }
348    }
349
350    /** Convert a Token to a corresponding Java object.  This method
351     * is called by the expression language to unmarshal numeric
352     * objects from tokens.  If the argument is an array token, this
353     * function returns an Java array of the correct type.  If the
354     * argument is a matrix token, this function returns a square Java
355     * array of arrays.  If the argument is another type of token,
356     * this function returns the encapsulated data, rewrapped in a
357     * Java numeric encapsulating object, e.g. java.lang.Double, if
358     * necessary.  If no conversion is possible, then this method
359     * throws an exception.
360     * @param token The token to be converted.
361     * @exception IllegalActionException If the selected conversion fails.
362     * @return An object that is not a ptolemy.data.Token or an array
363     * of ptolemy.data.Token.
364     */
365    public static Object convertTokenToJavaType(ptolemy.data.Token token)
366            throws ptolemy.kernel.util.IllegalActionException {
367        // Design note: it is arguable that this could be moved to the
368        // token interface for better object-oriented design, and to
369        // more easily support token types not explicitly listed here.
370        // We've opted instead to keep this code together with the
371        // previous method, in order to emphasize their complementary
372        // nature.  Hopefully this will also keep both conversions
373        // consistent as well.
374        Object returnValue;
375
376        if (token instanceof DoubleToken) {
377            returnValue = Double.valueOf(((DoubleToken) token).doubleValue());
378        } else if (token instanceof IntToken) {
379            returnValue = Integer.valueOf(((IntToken) token).intValue());
380        } else if (token instanceof UnsignedByteToken) {
381            returnValue = Byte.valueOf(((UnsignedByteToken) token).byteValue());
382        } else if (token instanceof LongToken) {
383            returnValue = Long.valueOf(((LongToken) token).longValue());
384        } else if (token instanceof StringToken) {
385            returnValue = ((StringToken) token).stringValue();
386        } else if (token instanceof BooleanToken) {
387
388            // FindBugs: "Creating new instances of java.lang.Boolean
389            // wastes memory, since Boolean objects are immutable and
390            // there are only two useful values of this type.  Use the
391            // Boolean.valueOf() method to create Boolean objects
392            // instead."
393            returnValue = Boolean
394                    .valueOf(((BooleanToken) token).booleanValue());
395        } else if (token instanceof ComplexToken) {
396            returnValue = ((ComplexToken) token).complexValue();
397        } else if (token instanceof FixToken) {
398            returnValue = ((FixToken) token).fixValue();
399        } else if (token instanceof FloatToken) {
400            returnValue = ((FloatToken) token).floatValue();
401        } else if (token instanceof ShortToken) {
402            returnValue = ((ShortToken) token).shortValue();
403        } else if (token instanceof FixMatrixToken) {
404            returnValue = ((FixMatrixToken) token).fixMatrix();
405        } else if (token instanceof IntMatrixToken) {
406            returnValue = ((IntMatrixToken) token).intMatrix();
407        } else if (token instanceof DoubleMatrixToken) {
408            returnValue = ((DoubleMatrixToken) token).doubleMatrix();
409        } else if (token instanceof ComplexMatrixToken) {
410            returnValue = ((ComplexMatrixToken) token).complexMatrix();
411        } else if (token instanceof LongMatrixToken) {
412            returnValue = ((LongMatrixToken) token).longMatrix();
413        } else if (token instanceof BooleanMatrixToken) {
414            returnValue = ((BooleanMatrixToken) token).booleanMatrix();
415        } else if (token instanceof ArrayToken) {
416            // This is frustrating... It would be nice if there
417            // was a Token.getValue() that would return the
418            // token element value in a polymorphic way...
419            if (((ArrayToken) token).getElement(0) instanceof FixToken) {
420                FixPoint[] array = new FixPoint[((ArrayToken) token).length()];
421
422                for (int j = 0; j < array.length; j++) {
423                    array[j] = ((FixToken) ((ArrayToken) token).getElement(j))
424                            .fixValue();
425                }
426
427                returnValue = array;
428            } else if (((ArrayToken) token).getElement(0) instanceof IntToken) {
429                int[] array = new int[((ArrayToken) token).length()];
430
431                for (int j = 0; j < array.length; j++) {
432                    array[j] = ((IntToken) ((ArrayToken) token).getElement(j))
433                            .intValue();
434                }
435
436                returnValue = array;
437            } else if (((ArrayToken) token)
438                    .getElement(0) instanceof LongToken) {
439                long[] array = new long[((ArrayToken) token).length()];
440
441                for (int j = 0; j < array.length; j++) {
442                    array[j] = ((LongToken) ((ArrayToken) token).getElement(j))
443                            .longValue();
444                }
445
446                returnValue = array;
447            } else if (((ArrayToken) token)
448                    .getElement(0) instanceof DoubleToken) {
449                double[] array = new double[((ArrayToken) token).length()];
450
451                for (int j = 0; j < array.length; j++) {
452                    array[j] = ((DoubleToken) ((ArrayToken) token)
453                            .getElement(j)).doubleValue();
454                }
455
456                returnValue = array;
457            } else if (((ArrayToken) token)
458                    .getElement(0) instanceof ComplexToken) {
459                Complex[] array = new Complex[((ArrayToken) token).length()];
460
461                for (int j = 0; j < array.length; j++) {
462                    array[j] = ((ComplexToken) ((ArrayToken) token)
463                            .getElement(j)).complexValue();
464                }
465
466                returnValue = array;
467            } else if (((ArrayToken) token)
468                    .getElement(0) instanceof StringToken) {
469                String[] array = new String[((ArrayToken) token).length()];
470
471                for (int j = 0; j < array.length; j++) {
472                    array[j] = ((StringToken) ((ArrayToken) token)
473                            .getElement(j)).stringValue();
474                }
475
476                returnValue = array;
477            } else if (((ArrayToken) token)
478                    .getElement(0) instanceof BooleanToken) {
479                boolean[] array = new boolean[((ArrayToken) token).length()];
480
481                for (int j = 0; j < array.length; j++) {
482                    array[j] = ((BooleanToken) ((ArrayToken) token)
483                            .getElement(j)).booleanValue();
484                }
485
486                returnValue = array;
487            } else {
488                throw new InternalErrorException(
489                        "token type not recognized: " + token);
490            }
491        } else {
492            throw new InternalErrorException(
493                    "token type not recognized: " + token);
494        }
495
496        return returnValue;
497    }
498
499    /** Convert the given ptolemy type object to a java class
500     * representing a java type.  The conversion is the complement of
501     * that provided by the convertJavaTypeToTokenType() method.  Note
502     * that, generally speaking the reverse is not true, since ptolemy
503     * types represent more information about data types than do java
504     * types.
505     * @param type the given type.
506     * @exception IllegalActionException If the token class is not
507     *  recognized, or creating the type fails.
508     * @return The class associated with the type.
509     */
510    public static Class convertTokenTypeToJavaType(Type type)
511            throws ptolemy.kernel.util.IllegalActionException {
512        try {
513            if (type.equals(BaseType.DOUBLE)) {
514                return Double.TYPE;
515            } else if (type.equals(BaseType.UNSIGNED_BYTE)) {
516                return Byte.TYPE;
517            } else if (type.equals(BaseType.INT)) {
518                return Integer.TYPE;
519            } else if (type.equals(BaseType.FLOAT)) {
520                return Short.TYPE;
521            } else if (type.equals(BaseType.LONG)) {
522                return Long.TYPE;
523            } else if (type.equals(BaseType.SHORT)) {
524                return Short.TYPE;
525            } else if (type.equals(BaseType.STRING)) {
526                return java.lang.String.class;
527            } else if (type.equals(BaseType.BOOLEAN)) {
528                return Boolean.TYPE;
529            } else if (type.equals(BaseType.COMPLEX)) {
530                return ptolemy.math.Complex.class;
531            } else if (type.equals(BaseType.UNSIZED_FIX)) {
532                return ptolemy.math.FixPoint.class;
533            } else if (type instanceof FixType) {
534                return ptolemy.math.FixPoint.class;
535            } else if (type.equals(BaseType.BOOLEAN)) {
536                return Class.forName("[[Lptolemy.math.FixPoint;");
537            } else if (type.equals(BaseType.INT_MATRIX)) {
538                return Class.forName("[[I");
539            } else if (type.equals(BaseType.DOUBLE_MATRIX)) {
540                return Class.forName("[[D");
541            } else if (type.equals(BaseType.COMPLEX_MATRIX)) {
542                return Class.forName("[[Lptolemy.math.Complex;");
543            } else if (type.equals(BaseType.LONG_MATRIX)) {
544                return Class.forName("[[J");
545            } else if (type.equals(BaseType.BOOLEAN_MATRIX)) {
546                return Class.forName("[[Z");
547            } else if (type instanceof ArrayType) {
548                ArrayType arrayType = (ArrayType) type;
549                Type elementType = arrayType.getElementType();
550
551                if (elementType.equals(BaseType.DOUBLE)) {
552                    return Class.forName("[D");
553                } else if (elementType.equals(BaseType.INT)) {
554                    return Class.forName("[I");
555                } else if (elementType.equals(BaseType.LONG)) {
556                    return Class.forName("[J");
557                } else if (elementType.equals(BaseType.BOOLEAN)) {
558                    return Class.forName("[Z");
559                } else {
560                    return java.lang.reflect.Array
561                            .newInstance(convertTokenTypeToJavaType(
562                                    arrayType.getElementType()), 0)
563                            .getClass();
564                }
565            } else {
566                // Bailout.  The type is not recognized, so defer to
567                // the type for some basic information.
568                return type.getTokenClass();
569            }
570        } catch (ClassNotFoundException ex) {
571            throw new IllegalActionException(null, ex,
572                    "Could not find Type '" + type + "'");
573        }
574    }
575}