001/////////////////////////////////////////////////////////////////////////////
002// Copyright (c) 2009 OPeNDAP, Inc.
003// All rights reserved.
004// Permission is hereby granted, without written agreement and without
005// license or royalty fees, to use, copy, modify, and distribute this
006// software and its documentation for any purpose, provided that the above
007// copyright notice and the following two paragraphs appear in all copies
008// of this software.
009//
010// IN NO EVENT SHALL OPeNDAP BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
011// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
012// THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF OPeNDAP HAS BEEN ADVISED
013// OF THE POSSIBILITY OF SUCH DAMAGE.
014//
015// OPeNDAP SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
016// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
017// PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
018// BASIS, AND OPeNDAP HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
019// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
020//
021// Author: Nathan David Potter  <ndp@opendap.org>
022// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
023//
024/////////////////////////////////////////////////////////////////////////////
025
026package org.kepler.dataproxy.datasource.opendap;
027
028import java.util.Enumeration;
029import java.util.Vector;
030
031import org.apache.commons.logging.Log;
032import org.apache.commons.logging.LogFactory;
033
034import opendap.dap.DArray;
035import opendap.dap.DArrayDimension;
036import opendap.dap.DByte;
037import opendap.dap.DConstructor;
038import opendap.dap.DFloat32;
039import opendap.dap.DFloat64;
040import opendap.dap.DGrid;
041import opendap.dap.DInt16;
042import opendap.dap.DInt32;
043import opendap.dap.DSequence;
044import opendap.dap.DString;
045import opendap.dap.DStructure;
046import opendap.dap.DUInt16;
047import opendap.dap.DUInt32;
048import opendap.dap.DURL;
049import opendap.dap.PrimitiveVector;
050import opendap.dap.Server.InvalidParameterException;
051import ptolemy.data.ArrayToken;
052import ptolemy.data.DoubleMatrixToken;
053import ptolemy.data.DoubleToken;
054import ptolemy.data.IntMatrixToken;
055import ptolemy.data.IntToken;
056import ptolemy.data.LongMatrixToken;
057import ptolemy.data.LongToken;
058import ptolemy.data.RecordToken;
059import ptolemy.data.StringToken;
060import ptolemy.data.Token;
061import ptolemy.data.UnsignedByteToken;
062import ptolemy.kernel.util.IllegalActionException;
063
064public class TokenMapper {
065
066        static Log log;
067        static {
068                log = LogFactory
069                                .getLog("org.kepler.dataproxy.datasource.opendap.CombinedMetaDataActorTest");
070        }
071
072        public static String metadataName = "metadata";
073        public static String valueName = "value";
074
075        /**
076         * Maps a DAP data object to a ptII Token object.
077         * 
078         * @param dapBT
079         *            The DAP obect to map.
080         * @param addMetadataRecord
081         *            controls whether or not dap Attribute metadata is added to the
082         *            returned kepler records.
083         * @return A new ptII Token that contains the value(s) of the passed DAP
084         *         object.
085         * @throws IllegalActionException
086         *             When bad things happen.
087         */
088        public static ptolemy.data.Token mapDapObjectToToken(
089                        opendap.dap.BaseType dapBT, boolean addMetadataRecord)
090                        throws IllegalActionException {
091
092                return mapDapObjectToToken(dapBT, null, 0, addMetadataRecord);
093
094        }
095
096        /**
097         * This helper method translates a single member of a DAP array to a ptII
098         * Token object.
099         * 
100         * @param pv
101         *            The array storage component of the DAP array.
102         * @param index
103         *            The index of the desired value in the PrimitiveVector.
104         * @return A new ptII Token that contains the value of the PrimitiveVector
105         *         located at index.
106         * @throws IllegalActionException
107         *             When bad things happen.
108         */
109        private static ptolemy.data.Token mapPrimtiveVectorMemberToToken(
110                        PrimitiveVector pv, int index) throws IllegalActionException {
111
112                return mapDapObjectToToken(pv.getTemplate(), pv.getInternalStorage(),
113                                index, false);
114
115        }
116
117        /**
118         * Provides the core mapping of DAP objects to ptII tokens. This method
119         * creates the ptII token and sets it's value to that of the passed DAP
120         * object. If the DAP object to be mapped was a memeber of a DAP array, then
121         * <code>primitiveArray</code> is cast to the appropriate type and the
122         * <code>index</code> parameter is used to pluck the correct value from the
123         * <code>primitiveArray</code>.
124         * 
125         * @param dapBT
126         *            BaseType that needs it's value mapped to a ptII Token object.
127         * @param primitiveArray
128         *            If the item to be mapped came from an DAP array then this is
129         *            the internal storage of the Dap array class. This should be a
130         *            null if not used.
131         * @param index
132         *            The index in the internal storage array of the value to map.
133         * @param addMetadataRecord
134         *            controls whether or not dap Attribute metadata is added to the
135         *            returned kepler records.
136         * @return A ptII Token object loaded with the data values help in the
137         *         parameter dapBT
138         * @throws IllegalActionException
139         *             When bad things happen.
140         */
141        private static ptolemy.data.Token mapDapObjectToToken(
142                        opendap.dap.BaseType dapBT, Object primitiveArray, int index,
143                        boolean addMetadataRecord) throws IllegalActionException {
144
145                ptolemy.data.Token token = null;
146                ptolemy.data.Token valueToken = null;
147                ptolemy.data.Token attToken;
148
149                if (dapBT instanceof DConstructor) {
150
151                        if (dapBT instanceof DStructure) {
152                                DStructure struct = (DStructure) dapBT;
153                                if (primitiveArray != null) {
154                                        struct = (DStructure) (((opendap.dap.BaseType[]) primitiveArray)[index]);
155                                }
156                                token = dapStructureToRecordToken(struct, addMetadataRecord);
157
158                        } else if (dapBT instanceof DGrid) {
159                                DGrid grid = (DGrid) dapBT;
160                                if (primitiveArray != null) {
161                                        grid = (DGrid) (((opendap.dap.BaseType[]) primitiveArray)[index]);
162                                }
163
164                                token = dapGridToRecordToken(grid, addMetadataRecord);
165
166                        } else if (dapBT instanceof DSequence) {
167                                DSequence seq = (DSequence) dapBT;
168                                if (primitiveArray != null) {
169                                        seq = (DSequence) (((opendap.dap.BaseType[]) primitiveArray)[index]);
170                                }
171                                token = dapSequenceToArrayOfRecordTokens(seq, addMetadataRecord);
172
173                        }
174
175                } else if (dapBT instanceof DArray) {
176
177                        if (primitiveArray != null) {
178                                throw new IllegalActionException(
179                                                "ERROR: OPeNDAP Should never allow nested Arrays!");
180                        }
181
182                        log.debug("DArray to be converted to tokens: "
183                                        + dapBT.getLongName());
184
185                        token = dapArrayToPtIIToken((DArray) dapBT, addMetadataRecord);
186
187                        log.debug("PtII Array is of type: " + token.getType()
188                                        + "  ClassName: " + token.getType().getClass().getName());
189                } else {
190                        if (dapBT instanceof DByte) {
191                                DByte dbyte = (DByte) dapBT;
192                                if (primitiveArray != null) {
193                                        dbyte.setValue(((byte[]) primitiveArray)[index]);
194                                }
195                                long tmp = ((long) dbyte.getValue()) & 0xFFL; // Mask for
196                                                                                                                                // unsigned
197                                                                                                                                // behavior
198                                valueToken = new UnsignedByteToken((byte) tmp);
199
200                        } else if (dapBT instanceof DUInt16) {
201                                DUInt16 ui16 = (DUInt16) dapBT;
202                                if (primitiveArray != null) {
203                                        ui16.setValue(((short[]) primitiveArray)[index]);
204                                }
205                                long tmp = ((long) ui16.getValue()) & 0xFFFFL; // Mask for
206                                                                                                                                // unsigned
207                                                                                                                                // behavior
208
209                                valueToken = new IntToken((int) tmp);
210
211                        } else if (dapBT instanceof DInt16) {
212                                DInt16 i16 = (DInt16) dapBT;
213                                if (primitiveArray != null) {
214                                        i16.setValue(((short[]) primitiveArray)[index]);
215                                }
216                                valueToken = new IntToken(i16.getValue());
217
218                        } else if (dapBT instanceof DUInt32) {
219                                DUInt32 ui32 = (DUInt32) dapBT;
220                                if (primitiveArray != null) {
221                                        ui32.setValue(((int[]) primitiveArray)[index]);
222                                }
223                                long tmp = ((long) ui32.getValue()) & 0xFFFFFFFFL; // Mask for
224                                                                                                                                        // unsigned
225                                                                                                                                        // behavior
226
227                                valueToken = new LongToken(tmp);
228
229                        } else if (dapBT instanceof DInt32) {
230                                DInt32 i32 = (DInt32) dapBT;
231                                if (primitiveArray != null) {
232                                        i32.setValue(((int[]) primitiveArray)[index]);
233                                }
234                                valueToken = new LongToken(i32.getValue());
235
236                        } else if (dapBT instanceof DFloat32) {
237                                DFloat32 f32 = (DFloat32) dapBT;
238                                if (primitiveArray != null) {
239                                        f32.setValue(((float[]) primitiveArray)[index]);
240                                }
241                                valueToken = new DoubleToken(f32.getValue());
242
243                        } else if (dapBT instanceof DFloat64) {
244                                DFloat64 f64 = (DFloat64) dapBT;
245                                if (primitiveArray != null) {
246                                        f64.setValue(((double[]) primitiveArray)[index]);
247                                }
248                                valueToken = new DoubleToken(f64.getValue());
249
250                        } else if (dapBT instanceof DURL) {
251                                DURL url = (DURL) dapBT;
252                                if (primitiveArray != null) {
253                                        url
254                                                        .setValue(((DURL) ((opendap.dap.BaseType[]) primitiveArray)[index])
255                                                                        .getValue());
256                                }
257                                valueToken = new StringToken(url.getValue());
258
259                        } else if (dapBT instanceof DString) {
260                                DString s = (DString) dapBT;
261                                if (primitiveArray != null) {
262                                        s
263                                                        .setValue(((DString) ((opendap.dap.BaseType[]) primitiveArray)[index])
264                                                                        .getValue());
265                                }
266                                valueToken = new StringToken(s.getValue());
267                        }
268
269                        if (valueToken == null)
270                                throw new IllegalActionException("Unrecognized DAP2 type. "
271                                                + "TypeName=" + dapBT.getTypeName() + "  VariableName="
272                                                + dapBT.getName());
273
274                        if (addMetadataRecord) {
275                                attToken = AttTypeMapper.convertAttributeToToken(dapBT
276                                                .getAttribute());
277                                token = new RecordToken(
278                                                new String[] { metadataName, valueName }, new Token[] {
279                                                                attToken, valueToken });
280                        } else
281                                token = valueToken;
282                }
283
284                if (token == null)
285                        throw new IllegalActionException("Unrecognized DAP2 type. "
286                                        + "TypeName=" + dapBT.getTypeName() + "  VariableName="
287                                        + dapBT.getName());
288
289                return token;
290
291        }
292
293        /**
294         * Helper method maps a DAP Structure to a ptII RecordToken.
295         * 
296         * @param s
297         *            The DAP Structure to map.
298         * @param addMetadataRecord
299         *            controls whether or not dap Attribute metadata is added to the
300         *            returned kepler records.
301         * @return The RecordToken containing the values of the DAP Structure.
302         * @throws IllegalActionException
303         *             When bad things happen.
304         */
305        private static RecordToken dapStructureToRecordToken(DStructure s,
306                        boolean addMetadataRecord) throws IllegalActionException {
307
308                RecordToken rt;
309                RecordToken token;
310
311                Enumeration e = s.getVariables();
312
313                Token[] tokens = new Token[s.elementCount()];
314                String[] names = new String[s.elementCount()];
315
316                opendap.dap.BaseType dapBT;
317                int i = 0;
318                while (e.hasMoreElements()) {
319                        dapBT = (opendap.dap.BaseType) e.nextElement();
320                        names[i] = TypeMapper.replacePeriods(dapBT.getName());
321                        tokens[i] = mapDapObjectToToken(dapBT, addMetadataRecord);
322                        i++;
323                }
324
325                rt = new RecordToken(names, tokens);
326
327                if (addMetadataRecord) {
328                        Token attToken = AttTypeMapper.convertAttributeToToken(s
329                                        .getAttribute());
330                        token = new RecordToken(new String[] { metadataName, valueName },
331                                        new Token[] { attToken, rt });
332                } else
333                        token = rt;
334
335                return token;
336        }
337
338        /**
339         * Helper method maps a DAP Sequence to a ptII ArrayToken of RecordTokens.
340         * 
341         * @param s
342         *            The DAP Sequence to map.
343         * @param addMetadataRecord
344         *            controls whether or not dap Attribute metadata is added to the
345         *            returned kepler records.
346         * @return The ArrayToken containing the values of the DAP Sequence.
347         * @throws IllegalActionException
348         *             When bad things happen.
349         */
350        private static Token dapSequenceToArrayOfRecordTokens(DSequence s,
351                        boolean addMetadataRecord) throws IllegalActionException {
352
353                int rowCount = s.getRowCount();
354                RecordToken[] rt = new RecordToken[rowCount];
355
356                String[] names = new String[s.elementCount()];
357                Token[] elements = new Token[s.elementCount()];
358                Token token;
359                Vector row;
360                opendap.dap.BaseType bt;
361                for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
362
363                        row = s.getRow(rowIndex);
364                        for (int i = 0; i < row.size(); i++) {
365                                bt = (opendap.dap.BaseType) row.get(i);
366                                elements[i] = mapDapObjectToToken(bt, addMetadataRecord);
367                                names[i] = TypeMapper.replacePeriods(bt.getName());
368                        }
369
370                        rt[rowIndex] = new RecordToken(names, elements);
371
372                }
373                Token value = new ArrayToken(rt);
374
375                if (addMetadataRecord) {
376                        Token attToken = AttTypeMapper.convertAttributeToToken(s
377                                        .getAttribute());
378                        token = new RecordToken(new String[] { metadataName, valueName },
379                                        new Token[] { attToken, value });
380                } else
381                        token = value;
382
383                return token;
384        }
385
386        /**
387         * Helper method maps a DAP Grid to a ptII RecordToken.
388         * 
389         * @param g
390         *            The DAP Grid to map.
391         * @param addMetadataRecord
392         *            controls whether or not dap Attribute metadata is added to the
393         *            returned kepler records.
394         * @return The RecordToken containing the values of the DAP Grid.
395         * @throws IllegalActionException
396         *             When bad things happen.
397         */
398        private static RecordToken dapGridToRecordToken(DGrid g,
399                        boolean addMetadataRecord) throws IllegalActionException {
400
401                RecordToken rt;
402                RecordToken token;
403
404                Enumeration e = g.getVariables();
405
406                Token[] tokens = new Token[g.elementCount()];
407                String[] names = new String[g.elementCount()];
408
409                DArray array = (DArray) e.nextElement();
410                tokens[0] = dapArrayToPtIIToken(array, addMetadataRecord);
411                names[0] = TypeMapper.replacePeriods(array.getName());
412
413                int i = 1;
414                while (e.hasMoreElements()) {
415                        array = (DArray) e.nextElement();
416                        names[i] = TypeMapper.replacePeriods(array.getName());
417                        tokens[i] = dapArrayToPtIIToken(array, addMetadataRecord);
418                        i++;
419                }
420
421                rt = new RecordToken(names, tokens);
422
423                if (addMetadataRecord) {
424                        Token attToken = AttTypeMapper.convertAttributeToToken(g
425                                        .getAttribute());
426                        token = new RecordToken(new String[] { metadataName, valueName },
427                                        new Token[] { attToken, rt });
428                } else
429                        token = rt;
430
431                return token;
432        }
433
434        /**
435         * Helper method maps a DAP arrays to a ptII Tokens. IF the DAP array is a
436         * 2D array then it is mapped to a MatrixToken. Otherwise it is mapped to a
437         * (possibly nested set of) ArrayToken(s).
438         * 
439         * @param a
440         *            The DAP Grid to map.
441         * @param addMetadataRecord
442         *            controls whether or not dap Attribute metadata is added to the
443         *            returned kepler records.
444         * @return The Token containing the values of the DAP array.
445         * @throws IllegalActionException
446         *             When bad things happen.
447         */
448        private static Token dapArrayToPtIIToken(DArray a, boolean addMetadataRecord)
449                        throws IllegalActionException {
450
451                if (a.numDimensions() == 1) {
452
453                        // if(a.getFirstDimension().getSize() == 1) {
454                        // return map1x1DapArray2Scalar(a);
455                        // }
456
457                        return mapDapArrayToMatrix(a, addMetadataRecord);
458
459                }
460
461                if (a.numDimensions() == 2)
462                        return mapDapArrayToMatrix(a, addMetadataRecord);
463
464                Token[] values;
465                try {
466                        values = buildArrayTokens(a);
467                } catch (InvalidParameterException e) {
468                        throw new IllegalActionException("Can't build Array Tokens!");
469                }
470
471                Token valueToken = new ArrayToken(values);
472                Token token = valueToken;
473                if (addMetadataRecord) {
474                        Token attToken = AttTypeMapper.convertAttributeToToken(a
475                                        .getAttribute());
476                        token = new RecordToken(new String[] { metadataName, valueName },
477                                        new Token[] { attToken, valueToken });
478                }
479
480                return token;
481
482        }
483
484        private static Token[] buildArrayTokens(DArray a)
485                        throws InvalidParameterException, IllegalActionException {
486
487                return buildArrayTokensRecurs(a, 0, null);
488        }
489
490        private static Token[] buildArrayTokensRecurs(DArray a, int dimension,
491                        int[] indices) throws InvalidParameterException,
492                        IllegalActionException {
493
494                if (dimension == 0) {
495                        // log.debug("Array Map Starting.");
496                        indices = new int[a.numDimensions() - 1];
497
498                        for (int i = 0; i < a.numDimensions() - 1; i++)
499                                indices[i] = 0;
500                }
501
502                // log.debug("dimension: "+dimension);
503
504                DArrayDimension thisAD = a.getDimension(dimension);
505                int thisADSize = thisAD.getSize();
506                Token[] values;
507
508                if (dimension == a.numDimensions() - 1) {
509                        // log.debug("Building inner Row Tokens.");
510                        // showArray(indices);
511                        values = innerRowToTokens(a, indices);
512
513                } else {
514                        // log.debug("Building new ArrayToken array.");
515
516                        values = new ArrayToken[thisADSize];
517
518                        for (int i = 0; i < thisADSize; i++) {
519                                indices[dimension] = i;
520                                // showArray(indices);
521                                values[i] = new ArrayToken(buildArrayTokensRecurs(a,
522                                                dimension + 1, indices));
523                        }
524
525                        // log.debug("ArrayToken array built.");
526                        // showArray(indices);
527
528                }
529
530                return values;
531        }
532
533        public static void showArray(int[] a) {
534                System.out.print("array={");
535                for (int i = 0; i < a.length; i++) {
536                        if (i > 0)
537                                System.out.print(",");
538                        System.out.print(a[i]);
539                }
540                log.debug("}");
541
542        }
543
544        private static Token[] innerRowToTokens(DArray a, int[] indices)
545                        throws InvalidParameterException, IllegalActionException {
546
547                int startIndex = 0;
548                int innerRowSize = a.getDimension(a.numDimensions() - 1).getSize();
549                long blockSize;
550
551                // log.debug("begin  -  startIndex: "+startIndex);
552                for (int i = 0; i < a.numDimensions() - 1; i++) {
553                        blockSize = 1;
554
555                        for (int j = i + 1; j < a.numDimensions(); j++)
556                                blockSize *= a.getDimension(j).getSize();
557
558                        startIndex += indices[i] * blockSize;
559                        // log.debug("process  -  startIndex: "+startIndex+
560                        // "   indices["+i+"]: "+indices[i]+ "   blockSize: "+blockSize);
561
562                }
563                // log.debug("FINAL  -  startIndex: "+startIndex);
564
565                Token[] values = new Token[innerRowSize];
566                PrimitiveVector pv = a.getPrimitiveVector();
567
568                log.debug("Primitive Vector is: " + pv.getClass().getName());
569                log.debug("Primitive Vector Internal Storage is: "
570                                + pv.getInternalStorage().getClass().getName());
571
572                int j = 0;
573                for (int i = startIndex; i < startIndex + innerRowSize; i++) {
574                        values[j] = mapPrimtiveVectorMemberToToken(pv, i);
575                        j++;
576                }
577
578                return values;
579
580        }
581
582        private static Token mapDapArrayToMatrix(opendap.dap.DArray a,
583                        boolean addMetadataRecord) throws IllegalActionException {
584
585                Token mtoken;
586                long tmp;
587
588                int numDims = a.numDimensions();
589
590                if (numDims != 1 && numDims != 2)
591                        throw new IllegalActionException("Only 1D and 2D DAP arrays may "
592                                        + "be converted to a Matrix datatype.");
593
594                try {
595
596                        PrimitiveVector pv = a.getPrimitiveVector();
597                        opendap.dap.BaseType dapBT = pv.getTemplate();
598                        Object is = pv.getInternalStorage();
599
600                        if (dapBT instanceof DByte) {
601
602                                byte[] dbyte = (byte[]) is;
603                                log
604                                                .debug("Building a IntMatrixToken from a 2D DAP Byte array.");
605
606                                int dim0 = a.getDimension(0).getSize();
607                                int dim1 = 1;
608
609                                if (numDims == 2)
610                                        dim1 = a.getDimension(1).getSize();
611
612                                int mvals[][] = new int[dim0][dim1];
613                                int k = 0;
614                                for (int i = 0; i < dim0; i++) {
615                                        for (int j = 0; j < dim1; j++) {
616                                                tmp = ((long) dbyte[k]) & 0xFFL; // Mask for unsigned
617                                                                                                                        // behavior
618                                                mvals[i][j] = (int) tmp;
619                                                k++;
620                                        }
621                                }
622                                mtoken = new IntMatrixToken(mvals);
623
624                        } else if (dapBT instanceof DUInt16) {
625                                short[] ui16 = (short[]) is;
626                                log
627                                                .debug("Building a IntMatrixToken from a 2D DAP UInt16 array.");
628
629                                int dim0 = a.getDimension(0).getSize();
630                                int dim1 = 1;
631
632                                if (numDims == 2)
633                                        dim1 = a.getDimension(1).getSize();
634
635                                int mvals[][] = new int[dim0][dim1];
636                                int k = 0;
637                                for (int i = 0; i < dim0; i++) {
638                                        for (int j = 0; j < dim1; j++) {
639                                                tmp = ((long) ui16[k]) & 0xFFFFL; // Mask for unsigned
640                                                                                                                        // behavior
641                                                mvals[i][j] = (int) tmp;
642                                                k++;
643                                        }
644                                }
645                                mtoken = new IntMatrixToken(mvals);
646
647                        } else if (dapBT instanceof DInt16) {
648                                short[] i16 = (short[]) is;
649                                log
650                                                .debug("Building a IntMatrixToken from a 2D DAP Int16 array.");
651
652                                int dim0 = a.getDimension(0).getSize();
653                                int dim1 = 1;
654
655                                if (numDims == 2)
656                                        dim1 = a.getDimension(1).getSize();
657
658                                int mvals[][] = new int[dim0][dim1];
659                                int k = 0;
660                                for (int i = 0; i < dim0; i++) {
661                                        for (int j = 0; j < dim1; j++) {
662                                                tmp = ((long) i16[k]);
663                                                mvals[i][j] = (int) tmp;
664                                                k++;
665                                        }
666                                }
667                                mtoken = new IntMatrixToken(mvals);
668
669                        } else if (dapBT instanceof DUInt32) {
670                                int[] ui32 = (int[]) is;
671                                log
672                                                .debug("Building a LongMatrixToken from a 2D DAP UInt32 array.");
673
674                                int dim0 = a.getDimension(0).getSize();
675                                int dim1 = 1;
676
677                                if (numDims == 2)
678                                        dim1 = a.getDimension(1).getSize();
679
680                                long mvals[][] = new long[dim0][dim1];
681                                int k = 0;
682                                for (int i = 0; i < dim0; i++) {
683                                        for (int j = 0; j < dim1; j++) {
684                                                tmp = ((long) ui32[k]) & 0xFFFFFFFFL; // Mask for
685                                                                                                                                // unsigned
686                                                                                                                                // behavior
687                                                mvals[i][j] = tmp;
688                                                k++;
689                                        }
690                                }
691                                mtoken = new LongMatrixToken(mvals);
692
693                        } else if (dapBT instanceof DInt32) {
694                                int[] i32 = (int[]) is;
695                                log
696                                                .debug("Building a LongMatrixToken from a 2D DAP Int32 array.");
697
698                                int dim0 = a.getDimension(0).getSize();
699                                int dim1 = 1;
700
701                                if (numDims == 2)
702                                        dim1 = a.getDimension(1).getSize();
703
704                                long mvals[][] = new long[dim0][dim1];
705                                int k = 0;
706                                for (int i = 0; i < dim0; i++) {
707                                        for (int j = 0; j < dim1; j++) {
708                                                tmp = ((long) i32[k]);
709                                                mvals[i][j] = tmp;
710                                                k++;
711                                        }
712                                }
713                                mtoken = new LongMatrixToken(mvals);
714
715                        } else if (dapBT instanceof DFloat32) {
716                                float[] f32 = (float[]) is;
717                                log
718                                                .debug("Building a DoubleMatrixToken from a 2D DAP Float32 array.");
719
720                                int dim0 = a.getDimension(0).getSize();
721                                int dim1 = 1;
722
723                                if (numDims == 2)
724                                        dim1 = a.getDimension(1).getSize();
725
726                                double mvals[][] = new double[dim0][dim1];
727                                int k = 0;
728                                for (int i = 0; i < dim0; i++) {
729                                        for (int j = 0; j < dim1; j++) {
730                                                mvals[i][j] = f32[k];
731                                                k++;
732                                        }
733                                }
734                                mtoken = new DoubleMatrixToken(mvals);
735
736                        } else if (dapBT instanceof DFloat64) {
737                                double[] f64 = (double[]) is;
738                                log
739                                                .debug("Building a DoubleMatrixToken from a 2D DAP Float32 array.");
740
741                                int dim0 = a.getDimension(0).getSize();
742                                int dim1 = 1;
743
744                                if (numDims == 2)
745                                        dim1 = a.getDimension(1).getSize();
746
747                                double mvals[][] = new double[dim0][dim1];
748                                int k = 0;
749                                for (int i = 0; i < dim0; i++) {
750                                        for (int j = 0; j < dim1; j++) {
751                                                mvals[i][j] = f64[k];
752                                                k++;
753                                        }
754                                }
755                                mtoken = new DoubleMatrixToken(mvals);
756
757                        } else {
758                                // Other DAP data types have no reasonable corresponding
759                                // MatrixToken data type in ptII. So DString, DStructure,
760                                // DGrid, and DSequence all get stuffed in to non-optimized
761                                // arrays of arrays of ptII Tokens.
762
763                                mtoken = dapArrayToPtIIToken(a, addMetadataRecord);
764                        }
765
766                        Token token = mtoken;
767                        if (addMetadataRecord) {
768                                Token attToken = AttTypeMapper.convertAttributeToToken(a
769                                                .getAttribute());
770                                token = new RecordToken(
771                                                new String[] { metadataName, valueName }, new Token[] {
772                                                                attToken, mtoken });
773                        }
774
775                        return token;
776
777                } catch (InvalidParameterException e) {
778                        throw new IllegalActionException("Failed to determine the size "
779                                        + "of a dimension of the DAP array \"" + a.getLongName()
780                                        + "\"");
781                }
782        }
783
784}