//$Id: CDFData.java,v 1.1.1.1 2025/09/11 12:24:45 mhliu Exp $
/*
 * Copyright 1996-2014 United States Government as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gsfc.nssdc.cdf;

import java.lang.*;
import java.lang.reflect.*;
import java.util.*;
import gsfc.nssdc.cdf.util.*;
import gsfc.nssdc.cdf.*;

/** 
 * This class acts as the glue between the Java code and the Java Native
 * Interface (JNI) code.  This class applies only to the Variable object.
 * It handles its data.  This class translates a multi-dimensional array
 * data into a 1-dimensional (1D) array prior to sending data to the JNI
 * code for processing.  Similarly, data retrieved in 1D array from the 
 * JNI code is properly dimensioned for usage or further manipulation.
 *
 * @version 1.0
 * @version 2.0 03/18/05  Selection of current CDF and variable are done as
 *                        part of operations passed to JNI.
 *                        JNI call is synchronized so only one process is
 *                        allowed in a JVM, due to multi-thread safety.
 *                        The select method will never be called.
 * @version 3.0 06/09/09  The number of dimesions returned from the get method
 *                        depends on the variable dimensions and dimesional 
 *                        elements: e.g., 2-dim (2x1 or 1x2) will have a 2-dim,
 *                        not 1-dim, object returned, while 2-dim (1x1) 
 *                        returns an object of a single item, not an array. 
 * @author Phil Williams, QSS Group Inc/RITSS <BR>
 *         Mike Liu, RSTX
 *
 * @see gsfc.nssdc.cdf.Variable
 * @see gsfc.nssdc.cdf.CDFException
 */
public class CDFData implements CDFObject, CDFConstants {

    /**
     * The Variable to which the data belongs.
     */
    private Variable _myVar;

    /**
     * The data returned from the CDFlib call.  This will always be 
     * a 1D array of the correct primitive or String data
     */
    private Object _data;

    /**
     * The data after _dataArray has been unwrapped to the proper
     * array dimensions.
     */
    private Object _dataArray;

    /**
     * Returns an object that is properly dimensioned.  The returned 
     * object can be casted in an application for usage or further 
     * manipulation.  <P>
     *
     * The following example retrieves the Temperature data.  The user
     * should know how the data was stored before casting the generic
     * object to a variable.  
     * <PRE>
     *    Variable var = cdf.getVariable("Temperature");
     *    CDFData data = var.getHyperDataObject (recNum, 
     *                                           recCount, 
     *                                           recInterval, 
     *                                           dimIndicies, 
     *                                           dimSizes, 
     *                                           dimCounts);
     *    long[][] temperature = (long [][]) data.getData(); 
     * </PRE>
     *
     * @return a generic Object that is properly dimensioned
     */ 
    public Object getData() { 

         return _dataArray; 
    }

    /**
     * Returns an object of a 1-dimensional array, which presents a sequence
     * of raw data values retrieved and presented by JNI from a CDF file.
     * The data stream may or may not reflect how the data is stored in the
     * file, depending the file majority. It is up to the calling application
     * to decipher the data stream. Note: for column-major CDF files, the 
     * sequence of the returned data stream is reordered so data can be 
     * properly assigned into Java's arrays. Normally, getData method
     * should be called so the retrieved data are properly dimensioned.  <P>
     *
     * The following example retrieves the 2-D Temperature data.  The user
     * should know how to organize the data, e.g., number of records, 
     * row/column major, data type, data value sequence, etc. 
     * <PRE>
     *    Variable var = cdf.getVariable("Temperature");
     *    CDFData data = var.getHyperDataObject (recNum,
     *                                           recCount,
     *                                           recInterval,
     *                                           dimIndicies,
     *                                           dimSizes,
     *                                           dimCounts);
     *    long[] temperature = (long []) data.getRawData();
     * </PRE>
     *
     * @return a generic Object that is properly dimensioned
     */
    public Object getRawData() {

         return _data;
    }

    /**
     * Variable id. 
     */
    private long id;

    /**
     * CDF id.
     */
    private long cdfID;

    /**
     * How many data values a data get/put action involves.  Note that for
     * CDF_CHAR and CDF_UCHAR, this is the total number of characters.
     */
    private long numValues;

    /**
     * Mirror _myVar.getNumElements(). numElements = 1 or the string length
     * for CDF_CHAR and CDF_UCHAR data.  
     */
    private long numElements;

    /**
     * The number of dimensions for this variable. 
     */
    private long numDims;

    /**
     * The dimension sizes for this variable.
     */
    private long[] varDimSizes;

     /**
     * Used in the JNI. This is the "real" signature of _data.
     */
    private String dataSignature;

    /**
     * Mirrors _myVar.getDataType().  
     */
    private long dataType;

    /**
     * The dimensionality of the actual passed data or retrieved data.
     */
    private int nDims = 0;

    /**
     * Gets the dimensionality of this variable. 
     * <PRE>
     *    Variable var = cdf.getVariable("Temperature");
     *    CDFData data = var.getHyperDataObject (recNum,
     *                                           recCount,
     *                                           recInterval,
     *                                           dimIndicies,
     *                                           dimSizes,
     *                                           dimCounts);
     *    long[][] temperature = (long [][]) data.getData();
     *    nDims = data.getnDims();   // Gives the dimenionality of temperature
     * </PRE> <P>
     *
     * @return the dimensionality of this variable 
     */
    public int getnDims() { 

         return nDims; 
    }

    /**
     * The dimension sizes of this variable. 
     */
    private int [] dimSizes;

    /**
     * Gets the dimension sizes of this variable.  For example, 3 X 10 
     * (3 rows and 10 columns) two-dimentional array is returned as an 
     * one-dimensional integer array, containing 3 in the first element 
     * and 10 in the second element. 
     *
     * @return the dimension sizes of this variable 
     */
    public int [] getDimSizes() { 

         return dimSizes;
    }

    /**
     * At which record does this hyper get/put function starts.
     */
    private long recStart;
    
    /**
     * Gets the record number at which a hyper get/put function starts. 
     *
     * @return the starting record number for a hyper get/put function
     */
    public long getRecStart() {

         return recStart;
    }
    
    /**
     * The number of records a hyper get/put function involves.
     */
    private long recCount;
    
    /**
     * Gets the number of records to read or write for a hyper get/put function.
     *
     * @return the number of records involved for a hyper get/put 
     *         function involves
     */
    public long getRecCount() {

         return recCount;
    }
    
    /**
     * What is the spacing between records for a hyper get/put function.
     */
    private long recInterval;
    
    /**
     * Gets the number of records to skip for a hyper get/put function.  
     * The record interval of 1 represents every record.  The value of 2 
     * represents every other record, the value of 3 represents every 
     * third record and so on. 
     *
     * @return the value of record interval
     */
    public long getRecInterval() {

         return recInterval;
    }
    
    /**
     * What are the starting dimension indices within a record for a 
     * hyper get/put function.
     */
    private long [] dimIndices;
    
    /**
     * Gets the starting dimension index within a record for a hyper 
     * get/put function.  Dimension index indicates where the data search 
     * started from within a record.  
     * Let's say a record is comprised of a 2x5 two-dimensional array 
     * (2 rows and 5 columns).  If the index returned from this method has  
     * a value of {1,0}, then the data search was performed starting at the 
     * first element of the second row.  Similarly, the value of {0,0} 
     * represents that the data search search was performed starting at the
     * first element of the first record. 
     *
     * @return the dimension index for this variable 
     */
    public long [] getDimIndices() {

         return dimIndices;
    }
    
    /**
     * How many values in each dimension within a record for a 
     * hyper get/put function.
     */
    private long [] dimCounts;
    
    /**
     * Gets the value of the dimension counts that represents the number of 
     * elements read or write starting at the location &lt;dimension index&gt;
     * for a hyper get/put function. 
     *
     * @return the dimension counts for this variable 
     */
    public long [] getDimCounts() {

         return dimCounts;
    }
    
    /**
     * The dimension intervals. 
     */
    private long [] dimIntervals;
    
    /**
     * Gets the value of the dimension intervals that represent the number of
     * elements to skip between reads or writes for a hyper get/put function.
     * The value of 1 represents every element.  The value of 2 represents
     * every other element, and the value of 3 represents every third 
     * element and so on.
     *
     * @return the dimension intervals for this variable
     */
    public long [] getDimIntervals() {

         return dimIntervals;
    }
    
   /**
    * Constructor for CDFData.
    *
    * @param v the variable from which this CDFData object is created <P>
    */
    private CDFData (Variable v) {
	_dataArray  = null;
	_data       = null;
	_myVar      = v;
	id          = _myVar.getID();
	cdfID	    = _myVar.getMyCDF().getID();
	dataType    = _myVar.getDataType();
	numElements = _myVar.getNumElements();
	numDims     = _myVar.getNumDims();
        varDimSizes = _myVar.getDimSizes();
    }

    /**
     * Read data and metadata from the given variable.  This method allows 
     * to read one or more records at once.
     *
     * @param v Variable from which to retrieve data from
     * @param recStart Record number at which data search begins 
     * @param recCount The number of records to read 
     * @param recInterval The number of records to skip between reads 
     * @param dimIndices Dimension index within a record at which data
     *                   search begins 
     * @param dimCounts The number of elements to read from dimIndicies 
     * @param dimIntervals The number of elements to skip between reads <P> 
     *
     * @return An CDFData object that contains the requested variable's 
     *         data <P>
     * @exception CDFException If there was a problem in retrieving 
     *                         variable's data and metadata
     */ 
//    final synchronized static protected CDFData get(Variable v,
    final static protected CDFData get(Variable v,
				       long recStart, 
				       long recCount, 
				       long recInterval,
				       long[] dimIndices,
				       long[] dimCounts, 
				       long[] dimIntervals)
	throws CDFException
    {

synchronized(v) {

	CDFData theData      = new CDFData(v);
	theData.recStart     = recStart;
	theData.recCount     = recCount;
	theData.recInterval  = recInterval;
        if (v.getNumDims() > 0) { // one dimensional and above
          theData.dimIndices   = dimIndices;
          theData.dimCounts    = dimCounts;
          theData.dimIntervals = dimIntervals;
        } else { // for 0 dimensional, we set it to dummy 1 dimensional
          theData.dimIndices   = new long[] {0L};
          theData.dimCounts    = new long[] {1L};
          theData.dimIntervals = new long[] {1L};
        }

	// Determine the dimensionality and sizes of this data
	theData.initDimAndSizes();

        Vector cmds = new Vector();
        Vector item0 = new Vector();
	Vector item1 = new Vector();
	Vector item2 = new Vector();
	Vector item3 = new Vector();
	Vector item4 = new Vector();
	Vector item5 = new Vector();
	Vector item6 = new Vector();
	Vector item7 = new Vector();
	Vector itemA = new Vector();

        // Create the 1D _data object
        theData.buildDataObject();
	// Select the variable and the correct record etc.

        cmds.addElement(Long.valueOf(SELECT_));
          cmds.addElement(Long.valueOf(CDF_));
            itemA.addElement("cdfID");
            itemA.addElement("J");
          cmds.addElement(itemA);
          cmds.addElement(Long.valueOf(zVAR_));
            item0.addElement("id");
            item0.addElement("J");
          cmds.addElement(item0);
          cmds.addElement(Long.valueOf(zVAR_RECNUMBER_));
            item1.addElement("recStart");
            item1.addElement("J");
          cmds.addElement(item1);
          cmds.addElement(Long.valueOf(zVAR_RECCOUNT_));
            item2.addElement("recCount");
            item2.addElement("J");
          cmds.addElement(item2);
          cmds.addElement(Long.valueOf(zVAR_RECINTERVAL_));
            item3.addElement("recInterval");
            item3.addElement("J");
          cmds.addElement(item3);
          cmds.addElement(Long.valueOf(zVAR_DIMINDICES_));
            item4.addElement("dimIndices");
            item4.addElement("[J");
          cmds.addElement(item4);
          cmds.addElement(Long.valueOf(zVAR_DIMCOUNTS_));
            item5.addElement("dimCounts");
            item5.addElement("[J");
          cmds.addElement(item5);
          cmds.addElement(Long.valueOf(zVAR_DIMINTERVALS_));
            item6.addElement("dimIntervals");
            item6.addElement("[J");
          cmds.addElement(item6);

        cmds.addElement(Long.valueOf(GET_));
          cmds.addElement(Long.valueOf(zVAR_HYPERDATA_));
            item7.addElement("_data");
            item7.addElement("Ljava/lang/Object;");
          cmds.addElement(item7);
        cmds.addElement(Long.valueOf(NULL_));

	theData._myVar.getMyCDF().executeCommand((CDFObject)theData, cmds);
	// unwrap the data
	theData.arrayify();

        return theData;
}
    }

    /**
     * Store data from the given variable to the current CDF file.  
     * This method allows to write one or more records at once. Albeit this
     * method returns a CDFData object, it's not required make use of the
     * returned object.  In other words, one can simply call this method
     * as a subroutine instead of a function. 
     * 
     * @param v Variable to which data should be written   
     * @param recStart Record number at which data write begins
     * @param recCount The number of records to write
     * @param recInterval The number of records to skip between writes
     * @param dimIndices Dimension index within a record at which data
     *                   write begins
     * @param dimCounts The number of elements to write starting at dimIndicies
     * @param dimIntervals The number of elements to skip between writes
     * @param data Data to be written to the destination variable <P>
     * 
     * @return An CDFData object that contains the data and metadata 
     *         written to the current CDF file <P>
     * @exception CDFException If there was a problem in writing
     *                         variable's data 
     */
//    final synchronized static protected CDFData put(Variable v,
    final static protected CDFData put(Variable v,
				       long recStart, 
				       long recCount,
				       long recInterval, 
				       long[] dimIndices, 
				       long[] dimCounts, 
				       long[] dimIntervals,
				       Object data) 
	throws CDFException
    {

synchronized(v) {
	// Make sure that the data is of the proper type
	String dataClassName = data.getClass().getName();
	switch ((int)v.getDataType()) {
	case (int)CDF_CHAR:
	case (int)CDF_UCHAR: 
	    if ((dataClassName.indexOf("java.lang.String") == -1) &&
		(dataClassName.indexOf("[B") == -1)) {
		throw new CDFException(DATATYPE_MISMATCH);
	    }
	    break;
	case (int)CDF_BYTE:
	case (int)CDF_INT1:
	    if ((dataClassName.indexOf("[B") == -1) &&
		(dataClassName.indexOf("Byte") == -1)) {
		throw new CDFException(DATATYPE_MISMATCH);
	    }
	    break;
	case (int)CDF_INT2:
	case (int)CDF_UINT1: 
	    if ((dataClassName.indexOf("[S") == -1) &&
		(dataClassName.indexOf("Short") == -1)) {
		throw new CDFException(DATATYPE_MISMATCH);
	    }
	    break;
	case (int)CDF_INT4:
	case (int)CDF_UINT2: 
	    if ((dataClassName.indexOf("[I") == -1) &&
		(dataClassName.indexOf("Integer") == -1)) {
		throw new CDFException(DATATYPE_MISMATCH);
	    }
	    break;
	case (int)CDF_UINT4: 
	    if ((dataClassName.indexOf("[J") == -1) &&
		(dataClassName.indexOf("Long") == -1)) {
		throw new CDFException(DATATYPE_MISMATCH);
	    }
	    break;
	case (int)CDF_INT8: 
	case (int)CDF_TIME_TT2000: 
	    if ((dataClassName.indexOf("[J") == -1) &&
		(dataClassName.indexOf("Long") == -1)) {
		throw new CDFException(DATATYPE_MISMATCH);
	    }
	    break;
	case (int)CDF_REAL4:
	case (int)CDF_FLOAT: 
	    if ((dataClassName.indexOf("[F") == -1) &&
		(dataClassName.indexOf("Float") == -1)) {
		throw new CDFException(DATATYPE_MISMATCH);
	    }
	    break;
	case (int)CDF_REAL8:
	case (int)CDF_DOUBLE:
	case (int)CDF_EPOCH: 
	    if ((dataClassName.indexOf("[D") == -1) &&
		(dataClassName.indexOf("Double") == -1)) {
		throw new CDFException(DATATYPE_MISMATCH);
	    }
	    break;
        case (int)CDF_EPOCH16:
            if (dataClassName.indexOf("[D") == -1) {
/*
                throw new CDFException(DATATYPE_MISMATCH);
*/
            }
            break;
	}

	CDFData theData = new CDFData(v);
	theData._dataArray   = data;
	theData.recStart     = recStart;
	theData.recCount     = recCount;
	theData.recInterval  = recInterval;
	theData.dimIndices   = dimIndices;
	theData.dimCounts    = dimCounts;
	theData.dimIntervals = dimIntervals;

	// Determine the dimensionality and sizes of this data
	theData.initDimAndSizes();

        // Convert the data to a 1D array to enable JNI
        // This will also build _data as needed
        theData.vectorize();
        // Get the signature
        theData.dataSignature = CDFUtils.getSignature(theData._data);

        Vector cmds = new Vector();
        Vector item0 = new Vector();
        Vector item1 = new Vector();
        Vector item2 = new Vector();
        Vector item3 = new Vector();
        Vector item4 = new Vector();
        Vector item5 = new Vector();
        Vector item6 = new Vector();
	Vector item7 = new Vector();
        Vector itemA = new Vector();

        cmds.addElement(Long.valueOf(SELECT_));
          cmds.addElement(Long.valueOf(CDF_));
            itemA.addElement("cdfID");
            itemA.addElement("J");
          cmds.addElement(itemA);
          cmds.addElement(Long.valueOf(zVAR_));
            item0.addElement("id");
            item0.addElement("J");
          cmds.addElement(item0);
          cmds.addElement(Long.valueOf(zVAR_RECNUMBER_));
            item1.addElement("recStart");
            item1.addElement("J");
          cmds.addElement(item1);
          cmds.addElement(Long.valueOf(zVAR_RECCOUNT_));
            item2.addElement("recCount");
            item2.addElement("J");
          cmds.addElement(item2);
          cmds.addElement(Long.valueOf(zVAR_RECINTERVAL_));
            item3.addElement("recInterval");
            item3.addElement("J");
          cmds.addElement(item3);
          cmds.addElement(Long.valueOf(zVAR_DIMINDICES_));
            item4.addElement("dimIndices");
            item4.addElement("[J");
          cmds.addElement(item4);
          cmds.addElement(Long.valueOf(zVAR_DIMCOUNTS_));
            item5.addElement("dimCounts");
            item5.addElement("[J");
          cmds.addElement(item5);
          cmds.addElement(Long.valueOf(zVAR_DIMINTERVALS_));
            item6.addElement("dimIntervals");
            item6.addElement("[J");
          cmds.addElement(item6);

        cmds.addElement(Long.valueOf(PUT_));
          cmds.addElement(Long.valueOf(zVAR_HYPERDATA_));
            item7.addElement("_data");
            item7.addElement("Ljava/lang/Object;");
          cmds.addElement(item7);
        cmds.addElement(Long.valueOf(NULL_));

	theData._myVar.getMyCDF().executeCommand((CDFObject)theData, cmds);
	
	return theData;
}
    }

    // used to determine the boundaries
    private long product(int [] array, int start, int stop) {

	long product = 1;
	for (int i=start; i<stop; i++)
	    if (array[i] > 1) product *= array[i];

	return product;
    }

    /**
     * Translate a 1D array into a proper dimension.
     */
    private void arrayify() throws CDFException {
	if (nDims <= 1 || numValues == 1) {
	    if ((dataType == CDF_CHAR) || (dataType == CDF_UCHAR)) {
		if (nDims == 0) {
                    int i, iend;
                    iend = ((byte [])_data).length;
                    for (i = 0; i < ((byte [])_data).length; ++i) {
                      if (((byte [])_data)[i] == 0) {
                         iend = i;
                         break;
                      }
		    }
//		    _dataArray = new String((byte [])_data);
		    try {
		      _dataArray = new String((byte [])_data, 0, iend, "UTF-8");
		    } catch (Exception ee) {
		      _dataArray = new String((byte [])_data, 0, iend);
		    }  
		}		else {
		    buildDataArray();
		    int n = 0;
		    byte [] aByteArray = new byte[(int)numElements];
		    for (int i=0; i<dimSizes[0]; i++) {
			System.arraycopy(_data, n, aByteArray, 0, 
					 (int)numElements);
                        int iend = (int)numElements;
                        for (int j=0; j<(int)numElements; j++) {
                          if (aByteArray[j] == 0) {
                            iend = j;
                            break;
                          }
                        }
//			Array.set(_dataArray, i, new String(aByteArray, 0, iend));
			try {
			  Array.set(_dataArray, i, new String(aByteArray, 0, iend,
                                                              "UTF-8"));
                        } catch (Exception ee) {
			  Array.set(_dataArray, i, new String(aByteArray, 0, iend));
                        }
			n += numElements;
		    }
		}
	    } else {
		_dataArray = _data;
	    }
	} else {
	    // First need to build the _dataArray
	    buildDataArray();

	    /* 
	     * Setup the subArrays array
	     * cIndex is the holds the index for the current subarray
	     * boundary is the # of values in the subarray
	     */
	    Object aRow = null;  // Holder for a single row of data
	    Object [] subArrays = new Object[(int)nDims-1];
	    int [] cIndex   = new int[(int)nDims-1];
	    long [] boundary = new long[(int)nDims-1];

	    subArrays[0] = _dataArray;
	    cIndex[0] = 0;
	    boundary[0] = product(dimSizes,0,(int)nDims);

	    for (int i=1; i<(int)nDims-1; i++) {
		subArrays[i] = Array.get(subArrays[i-1], 0);
		boundary[i] = product(dimSizes,i,(int)nDims);
		cIndex[i] = 0;
	    }

	    int n = 0; // The current element in the _data
	    Object cObject = _dataArray;  // A temp object to hold a subarray
	    boolean boundaryCrossed;
	    // Unwrap the 1D array to the multidimensional array.
	    // Note that if the user wanted a 1D array then this will not
	    // be used since _dataArray = _data
	    while (n < numValues) {
		// Get the correct 2D subarray to fill
		if (n != 0) {
		    for (int i = 0; i < (int)nDims-1; i++) {
//			boundaryCrossed = ((n % boundary[i]) == 0);
			boundaryCrossed = (((n/numElements) % boundary[i]) == 0);
			if (boundaryCrossed) {
			    // Get the next sub array
			    cIndex[i] += 1;
			    cObject = Array.get(cObject, (int)cIndex[i]);
			    subArrays[i] = cObject;

			    // Get the first element of each subsequent subarray
			    for (int j=i+1; j<(int)nDims-1; j++) {
				cIndex[j] = 0;
				subArrays[j] = Array.get(subArrays[j-1], 0);
			    }
			    break;
			   
			} else {
			    cObject = subArrays[i];
			}
		    }
		}
		// Fill the rows of the 2D subarray
		for (int i=0; i<dimSizes[(int)nDims-2]; i++) {
		    switch ((int)_myVar.getDataType()) {
		    case (int)CDF_CHAR:
		    case (int)CDF_UCHAR:
			byte [] aByteArray = new byte[(int)numElements];
			aRow = new String[(int)dimSizes[(int)nDims-1]];
			// Need to loop for each value for strings
			for (int j=0; j<dimSizes[nDims-1]; j++) {
			    System.arraycopy(_data, n, 
					     aByteArray, 0, (int)numElements);
                            int iend = (int)numElements;
                            for (int k=0; k<(int)numElements; k++) {
                              if (aByteArray[k] == 0) {
                                iend = k;
                                break;
                              }
                            }
//			    ((String [])aRow)[j] = new String(aByteArray, 0, iend);
			    try {
			      ((String [])aRow)[j] = new String(aByteArray, 0, iend,
							        "UTF-8");
			    } catch (Exception ee) {
			      ((String [])aRow)[j] = new String(aByteArray, 0, iend);
			    }
			    n += numElements;
			}
			break;
		    case (int)CDF_BYTE:
		    case (int)CDF_INT1:
			aRow = new byte[(int)dimSizes[(int)nDims-1]];
			System.arraycopy(_data, n, aRow, 0, 
					 (int)dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_INT2:
		    case (int)CDF_UINT1:
			aRow = new short[(int)dimSizes[(int)nDims-1]];
			System.arraycopy(_data, n, aRow, 0, 
					 (int)dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_INT4:
		    case (int)CDF_UINT2: 
			aRow = new int[(int)dimSizes[(int)nDims-1]];
			System.arraycopy(_data, n, aRow, 0, 
					 (int)dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_UINT4:
			aRow = new long[(int)dimSizes[(int)nDims-1]];
			System.arraycopy(_data, n, aRow, 0, 
					 (int)dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_INT8:
		    case (int)CDF_TIME_TT2000:
			aRow = new long[(int)dimSizes[(int)nDims-1]];
			System.arraycopy(_data, n, aRow, 0, 
					 (int)dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_REAL4:
		    case (int)CDF_FLOAT:
			aRow = new float[(int)dimSizes[(int)nDims-1]];
			System.arraycopy(_data, n, aRow, 0, 
					 (int)dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_REAL8:
		    case (int)CDF_DOUBLE:
		    case (int)CDF_EPOCH:
			aRow = new double[(int)dimSizes[(int)nDims-1]];
			System.arraycopy(_data, n, aRow, 0, 
					 (int)dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
                    case (int)CDF_EPOCH16:
                        aRow = new double[2*(int)dimSizes[(int)nDims-1]];
                        System.arraycopy(_data, n, aRow, 0,
                                         2*(int)dimSizes[(int)nDims-1]);
                        n += 2*dimSizes[(int)nDims-1];
                        break;
		    default:
			break;
		    } /* switch (dataType) */
		    Array.set(subArrays[(int)nDims - 2], i, aRow);
		}
	    }
	}
    }
	
    /**
     * Called by put.  Converts the _dataArray to _data (a 1D array)
     * for handling by the JNI
     */
    private void vectorize() throws CDFException {

	if (nDims <= 1 || numValues == 1)
	    if ((dataType == CDF_CHAR) || (dataType == CDF_UCHAR)) {
                int lenx;
		String dataClassName = _dataArray.getClass().getName();
		if (dataClassName.indexOf("[B") == -1) {
		  int n = 0;
		  if (nDims == 0) {
		    _data = new byte [(int)numElements];
		    for (int i=0; i<numElements; i++)	// fill with spaces or 0
			((byte [])_data)[i] = 0;
                    if (((String)_dataArray).length() != 0) {
                      String oneStr = (String)_dataArray;
                      byte[] bytes = oneStr.getBytes();
                      lenx = bytes.length;
		      System.arraycopy(bytes, 0, _data, 0,
				       (int)((lenx>numElements)?numElements:
                                                                lenx));
		    }
		  } else {
		    buildDataObject();
		    for (int i=0; i<dimSizes[0]; i++) {
                        for (int j=0; j<numElements; j++)
                            ((byte [])_data)[n+j] = 0;
                        if (((String [])_dataArray)[i].length() != 0) {
                          String oneStr = ((String [])_dataArray)[i];  
                          byte[] bytes = oneStr.getBytes();   
                          lenx = bytes.length;
		          System.arraycopy(bytes, 0, _data, n,
				           (int)((lenx>numElements)?numElements:
                                                                    lenx));
			}
			n += numElements;
		    }
		  } 
		} else
		  _data = _dataArray;
	    } else
		_data = _dataArray;
	else {
	    buildDataObject();

	    /* 
	     * Setup the subArrays array
	     * cIndex is the holds the index for the current subarray
	     * boundary is the # of values in the subarray
	     */
	    Object aRow = null;
	    Object [] subArrays = new Object[(int)nDims-1];
	    int [] cIndex   = new int[(int)nDims-1];
	    long [] boundary = new long[(int)nDims-1];
	    
	    subArrays[0] = _dataArray;
	    cIndex[0] = 0;
	    boundary[0] = product(dimSizes,0,(int)nDims);

	    for (int i=1; i<(int)nDims-1;i++) {
		subArrays[i] = Array.get(subArrays[i-1], 0);
		boundary[i] = product(dimSizes,i,(int)nDims);
		cIndex[i] = 0;
	    }

	    int n = 0; // The current element in the _data
	    Object cObject = _dataArray;  // A temp object to hold a subarray
	    boolean boundaryCrossed;

	    // Convert the multidimensional array into a 1D array.
	    // Note that if the user passed a 1D array then this will not
	    // be used since _dataArray = _data

	    while (n < numValues) {
		// Get the correct 2D subarray to fill
		if (n!=0) {
		    for (int i = 0; i < (int)nDims-1; i++) {
			boundaryCrossed = ((n % boundary[i]) == 0);
			if (boundaryCrossed) {
			    // Get the next sub array
			    cIndex[i]+=1;
			    cObject = Array.get(cObject, cIndex[i]);
			    subArrays[i] = cObject;

			    // Get the first element of each 
			    // subsequent subarray
			    for (int j=i+1;j<(int)nDims-1;j++) {
				cIndex[j] = 0;
				subArrays[j] = Array.get(subArrays[j-1],
                                                         cIndex[j]);
			    }
			    break;
			    
			} else {
			    cObject = subArrays[i];
			}
		    }
		}

		// Fill the correct elements of _data
		for (int i=0; i<dimSizes[(int)nDims-2]; i++) {
		    switch ((int)_myVar.getDataType()) {
		    case (int)CDF_CHAR:
		    case (int)CDF_UCHAR:
			aRow = (String [])Array.get(subArrays[(int)nDims - 2],
                                                    i);
			for (int j=0; j<dimSizes[nDims - 1]; j++) {
                          for (int k=0; k<numElements; k++)
                             ((byte [])_data)[n+k] = 0;
			  if (((String [])aRow)[j] != null) {
                             String oneStr = ((String [])aRow)[j];
			  byte[] bytes = oneStr.getBytes();
			  int lenx = bytes.length;
			  System.arraycopy(bytes, 0, _data, n,
                                           (int)((lenx>numElements)?numElements:
                                                                    lenx));
			  }
			  n += numElements;
			}
			break;
		    case (int)CDF_BYTE:
		    case (int)CDF_INT1:
			aRow = (byte [])Array.get(subArrays[(int)nDims - 2], i);
			System.arraycopy(aRow, 0, _data, n, 
					 dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_INT2:
		    case (int)CDF_UINT1:
			aRow = new short[dimSizes[(int)nDims-1]];
			aRow = (short [])Array.get(subArrays[(int)nDims - 2], i);
			System.arraycopy(aRow, 0, _data, n, 
					 dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_INT4:
		    case (int)CDF_UINT2: 
			aRow = (int [])Array.get(subArrays[(int)nDims - 2], i);
			System.arraycopy(aRow, 0, _data, n, 
					 dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_UINT4:
			aRow = (long [])Array.get(subArrays[(int)nDims - 2], i);
			System.arraycopy(aRow, 0, _data, n, 
					 dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_INT8:
		    case (int)CDF_TIME_TT2000:
			aRow = (long [])Array.get(subArrays[(int)nDims - 2], i);
			System.arraycopy(aRow, 0, _data, n, 
					 dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_REAL4:
		    case (int)CDF_FLOAT:
			aRow = (float [])Array.get(subArrays[(int)nDims - 2], i);
			System.arraycopy(aRow, 0, _data, n, 
					 dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
		    case (int)CDF_REAL8:
		    case (int)CDF_DOUBLE:
		    case (int)CDF_EPOCH:
			aRow = (double [])Array.get(subArrays[(int)nDims - 2], i);
			System.arraycopy(aRow, 0, _data, n, 
					 dimSizes[(int)nDims-1]);
			n += dimSizes[(int)nDims-1];
			break;
                    case (int)CDF_EPOCH16:
                        aRow = (double [])Array.get(subArrays[(int)nDims - 2], i);
                        System.arraycopy(aRow, 0, _data, n,
                                         2*dimSizes[(int)nDims-1]);
                        n += 2*dimSizes[(int)nDims-1];
                        break;
		    default:
			break;
		    } /* switch (dataType) */
		}
	    }
	}
    }

    /**
     * Initialize the nDims, dimSizes and numValues of this CDFData.
     */
    private void initDimAndSizes() {

	Object tempArray;

	numValues = 1;
	
	/*
	 * This was called from put.  In that case we can get the 
	 * nDims and sizes directly from the _dataArray
	 */
	if (_dataArray != null) {	// Called from put
	    nDims = _dataArray.getClass().getName().lastIndexOf("[") + 1;
	    // Is the _dataArray an array?
	    if (_dataArray.getClass().isArray()) { 
		tempArray = _dataArray;
		dimSizes = new int[nDims];
		for (int i = 0;i < nDims; i++) {
		    dimSizes[i] = Array.getLength(tempArray);
		    numValues *= dimSizes[i];
		    tempArray = Array.get(tempArray, 0);
		}
	    } else {                     // Just an object => nDims == 1
		dimSizes = new int[1];
		dimSizes[0] = 1;
	    }
	    numValues *= numElements;
	} else {                         // Called from get
	    // Get the nDims
	    nDims = ((recCount > 1) ? 1 : 0);
	    int len = dimCounts.length;
	    if (len == 1) {
              if (dimCounts[0] > 1 || (numDims > 0 && varDimSizes[0] == 1))
		    nDims ++;
	    } else {
		boolean multi=false;
		for (int i=0; i<len; i++)
                  if (dimCounts[i] > 1 || varDimSizes[i] == 1)
			nDims ++;
	    }
	    // Get the dimSizes
	    if (nDims > 0) {
	      dimSizes = new int[nDims];
	      if (nDims == 1) {
		dimSizes[0] = ((recCount > 1) ? (int)recCount : (int)dimCounts[0]);
	      } else {
		if (recCount > 1) {
		    int j = 0;
		    dimSizes[0] = (int)recCount;
		    for (int i=0; i<numDims; i++) {
                      if (dimCounts[i] > 1 || varDimSizes[i] == 1) {
			   j++;
			   dimSizes[j] = (int)dimCounts[i];
                      }
		    }
		} else {
		    int j = -1;
		    for (int i=0; i<numDims; i++) {
                      if (dimCounts[i] > 1 || varDimSizes[i] == 1) {
			   j++;
			   dimSizes[j] = (int)dimCounts[i];
                      }
		    }
		}
	      }
              for (int dimN = 0; dimN < nDims; dimN++)
                 numValues *= dimSizes[dimN];
	    } else {
              dimSizes = new int[1];
	      dimSizes[0] = 1;
	    }
	    numValues *= numElements;
	}
    }
    
    /**
     * Build the _dataArray object
     */
    private void buildDataArray() throws CDFException {

	int [] tempSizes = new int[nDims-1];
	System.arraycopy(dimSizes,0,tempSizes,0,(int)nDims-1);

	String className = null;
	switch ((int)_myVar.getDataType()) {
	case (int)CDF_CHAR:
	case (int)CDF_UCHAR: 
	    className = "java.lang.String";  
	    tempSizes = dimSizes;
	    break;
	case (int)CDF_BYTE:
	case (int)CDF_INT1:  className = "[B";                 break;
	case (int)CDF_INT2:
	case (int)CDF_UINT1: className = "[S";                 break;
	case (int)CDF_INT4:
	case (int)CDF_UINT2: className = "[I";                 break;
	case (int)CDF_UINT4:
	case (int)CDF_INT8:
	case (int)CDF_TIME_TT2000: className = "[J";           break;
	case (int)CDF_REAL4:
	case (int)CDF_FLOAT: className = "[F";                 break;
	case (int)CDF_REAL8:
	case (int)CDF_DOUBLE:
	case (int)CDF_EPOCH: className = "[D";                 break;
	case (int)CDF_EPOCH16: className = "[D";               break;
	default:
	    break;
	} /* switch (dataType) */
	
	Class arrayClass;
	try {
	    arrayClass = Class.forName(className);
	    _dataArray = Array.newInstance(arrayClass, tempSizes);
	} catch (ClassNotFoundException e) {
	    throw new CDFException(BAD_ARGUMENT);
	}
    }

    /*****************************************************************/
    /*  Build the _data object and its signature so that the         */
    /*  JNI code can allocate appropriate amount of space.           */
    /*****************************************************************/

    private void buildDataObject() throws CDFException
    {

	int dataTypeX = (int)_myVar.getDataType();
	Object padValue = null;
	if (_myVar.checkPadValueExistence()) 
	  padValue = (Object) _myVar.getPadValue();
	switch (dataTypeX) {
	case (int)CDF_CHAR:
	case (int)CDF_UCHAR:
	    dataSignature = "[B";
	    _data = new byte [(int)numValues];
            for (int i=0; i<(int)numValues; i++) ((byte [])_data)[i] = 0;
	    if (padValue == null) {
              if (dataTypeX == (int)CDF_CHAR) {
                ((byte [])_data)[0] = (((new Character(DEFAULT_CHAR_PADVALUE))
                                        .toString()).getBytes())[0];
	      } else {
		((byte [])_data)[0] = (((new Character(DEFAULT_UCHAR_PADVALUE))
		  		        .toString()).getBytes())[0];
              }
              for (int i=1; i<numValues; i++)
                  ((byte [])_data)[i] = 0; 
	    } else {
              int i, j;
	      byte[] myBytes = ((String)padValue).getBytes();
	      int ilen = myBytes.length;
              if (ilen > 0) {
                int itotal = ilen;
                int numElms = (int) _myVar.getNumElements();
                int numItems;
                numItems = (int)numValues / numElms;
                if (itotal > numElms) itotal = numElms;
                for (j=0; j<numItems; j++) {
                  for (i=0; i<itotal; i++)
                    ((byte [])_data)[j*numElms+i] = myBytes[i];
                }
              } 
	    }
	    break;
	case (int)CDF_BYTE:
	case (int)CDF_INT1:
	    if (numValues > 1) {
		dataSignature = "[B";
		_data = new byte [(int)numValues];
		if (padValue == null)
		  for (int i=0; i<numValues; i++)
		    if (dataTypeX == (int)CDF_INT1)
			((byte [])_data)[i] = (byte)DEFAULT_INT1_PADVALUE;
		    else
			((byte [])_data)[i] = (byte)DEFAULT_BYTE_PADVALUE;
		else
		    for (int i=0; i<numValues; i++)
			((byte [])_data)[i] = ((Byte)padValue).byteValue();
	    } else {
		dataSignature = "Ljava/lang/Byte;";
		if (padValue == null) 
		  if (dataTypeX == (int)CDF_INT1)
		       _data = Byte.valueOf((byte)DEFAULT_INT1_PADVALUE);
		  else _data = Byte.valueOf((byte)DEFAULT_BYTE_PADVALUE);
		else 
		  _data = Byte.valueOf(((Byte)padValue).byteValue());
	    }
	    break;
	case (int)CDF_INT2:
	case (int)CDF_UINT1:
	    if (numValues > 1) {
		dataSignature = "[S";
		_data = new short [(int)numValues];
                if (padValue == null)
		  for (int i=0; i<numValues; i++)
                    if (dataTypeX == (int)CDF_INT2)
                        ((short [])_data)[i] = (short)DEFAULT_INT2_PADVALUE;
                    else
                        ((short [])_data)[i] = (short)DEFAULT_UINT1_PADVALUE;
                else
                    for (int i=0; i<numValues; i++)
                        ((short [])_data)[i] = ((Short)padValue).shortValue();
	    } else {
		dataSignature = "Ljava/lang/Short;";
		if (padValue == null)
		  if (dataTypeX == (int)CDF_INT2) 
		       _data = Short.valueOf((short)DEFAULT_INT2_PADVALUE);
		  else _data = Short.valueOf((short)DEFAULT_UINT1_PADVALUE);
		else
		  _data = Short.valueOf(((Short)padValue).shortValue());
	    }
	    break;
	case (int)CDF_INT4:
	case (int)CDF_UINT2:
	    if (numValues > 1) {
		dataSignature = "[I";
		_data = new int [(int)numValues];
                if (padValue == null)
		  for (int i=0; i<numValues; i++)
                    if (dataTypeX == (int)CDF_INT4)
                        ((int [])_data)[i] = (int)DEFAULT_INT4_PADVALUE;
                    else
                        ((int [])_data)[i] = (int)DEFAULT_UINT2_PADVALUE;
                else
                    for (int i=0; i<numValues; i++)
                        ((int [])_data)[i] = ((Integer)padValue).intValue();
 	    } else {
		dataSignature = "Ljava/lang/Integer;";
		if (padValue == null)
		  if (dataTypeX == (int)CDF_INT4)
		       _data = Integer.valueOf((int)DEFAULT_INT4_PADVALUE);
		  else _data = Integer.valueOf((int)DEFAULT_UINT2_PADVALUE);
		else
		  _data = Integer.valueOf(((Integer)padValue).intValue());
	    }
	    break;
	case (int)CDF_UINT4:
	case (int)CDF_INT8:
	case (int)CDF_TIME_TT2000:
	    if (numValues > 1) {
		dataSignature = "[J";
		_data = new long [(int)numValues];
                if (padValue == null)
                  for (int i=0; i<numValues; i++)
                     ((long [])_data)[i] = 
                      (long)((dataTypeX == (int) CDF_UINT4) ? 
                             DEFAULT_UINT4_PADVALUE :
                             ((dataTypeX == (int) CDF_INT8) ?
                               DEFAULT_INT8_PADVALUE :
                               DEFAULT_TT2000_PADVALUE));
                else
                    for (int i=0; i<numValues; i++)
                        ((long [])_data)[i] = ((Long)padValue).longValue();
	    } else {
		dataSignature = "Ljava/lang/Long;";
		if (padValue == null)
		  _data = Long.valueOf((dataTypeX == (int) CDF_UINT4) ?
                                   DEFAULT_UINT4_PADVALUE :
                                   ((dataTypeX == (int) CDF_INT8) ?
                                     DEFAULT_INT8_PADVALUE :
                                     DEFAULT_TT2000_PADVALUE));
		else
		  _data = Long.valueOf(((Long)padValue).longValue());
	    }
	    break;
	case (int)CDF_REAL4:
	case (int)CDF_FLOAT:
	    if (numValues > 1) {
		dataSignature = "[F";
		_data = new float [(int)numValues];
                if (padValue == null)
		  for (int i=0; i<numValues; i++)
                    if (dataTypeX == (int)CDF_REAL4)
                        ((float [])_data)[i] = (float)DEFAULT_REAL4_PADVALUE;
                    else
                        ((float [])_data)[i] = (float)DEFAULT_FLOAT_PADVALUE;
                else
		  for (int i=0; i<numValues; i++)
                    ((float [])_data)[i] = ((Float)padValue).floatValue();
	    } else {
		dataSignature = "Ljava/lang/Float;";
		if (padValue == null) {
		  if (dataTypeX == (int)CDF_REAL4)
		       _data = Float.valueOf((float)DEFAULT_REAL4_PADVALUE);
		  else _data = Float.valueOf((float)DEFAULT_FLOAT_PADVALUE);
		} else
		  _data = Float.valueOf(((Float)padValue).floatValue());
	    }
	    break;
	case (int)CDF_REAL8:
	case (int)CDF_DOUBLE:
	case (int)CDF_EPOCH:
	    if (numValues > 1) {
		dataSignature = "[D";
		_data = new double [(int)numValues];
                if (padValue == null)
		  for (int i=0; i<numValues; i++)
                    if (dataTypeX == (int)CDF_REAL8)
                        ((double [])_data)[i] = (double)DEFAULT_REAL8_PADVALUE;
                    else if (dataTypeX == (int)CDF_DOUBLE)
                        ((double [])_data)[i] = (double)DEFAULT_DOUBLE_PADVALUE;
		    else
			((double [])_data)[i] = (double)DEFAULT_EPOCH_PADVALUE;
                else
                    for (int i=0; i<numValues; i++)
                        ((double [])_data)[i] = ((Double)padValue).doubleValue();
	    } else {
		dataSignature = "Ljava/lang/Double;";
		if (padValue == null)
		  if (dataTypeX == (int)CDF_REAL8)
			_data = Double.valueOf((double)DEFAULT_REAL8_PADVALUE);
		  else if (dataTypeX == (int)CDF_DOUBLE)
			_data = Double.valueOf((double)DEFAULT_DOUBLE_PADVALUE);
		  else	_data = Double.valueOf((double)DEFAULT_EPOCH_PADVALUE);
		else
		  _data = Double.valueOf(((Double)padValue).doubleValue());
	    }
	    break;
        case (int)CDF_EPOCH16:
            dataSignature = "[D";
            _data = new double [2*(int)numValues];
            if (padValue == null)
              for (int i=0; i<numValues; i++) {
                 ((double [])_data)[2*i] = (double)DEFAULT_EPOCH16_PADVALUE;
                 ((double [])_data)[2*i+1] = (double)DEFAULT_EPOCH16_PADVALUE;
              }
            else
                for (int i=0; i<numValues; i++) {
                    ((double [])_data)[2*i] = ((double[])padValue)[0];
                    ((double [])_data)[2*i+1] = ((double[])padValue)[1];
                }
            break;
	default:
	    break;
	} /* switch (dataTypeX) */
    }


    /**
     * Dumps variable data, one row at a time per record.  This is a generic
     * utility for dumping data to a screen.  Data can be scalar or 
     * 1-dimensional or multi-dimensional array of any data type. This
     * method dumps the data without using format.<P>
     *
     * The following example retrieves the first record, comprised of
     * 3x5 (3 rows and 5 columns) array, into a generic object and dumps 
     * its contents to screen one row at a time.  In this case three rows
     *  will be displayed on a screen, each row containing 5 elements. 
     * <PRE>
     *     CDFData data;
     *     long[] dimIndices   = {0,0};
     *     long[] dimIntervals = {3,5};
     *     long[] dimSizes     = {1,1}; 
     *     data = var.getHyperDataObject(0L,         // record start
     *                                   1,          // record counts 
     *                                   1,          // record interval
     *                                   dimIndices,
     *                                   dimSizes,
     *                                   dimIntervals);
     *     data.dumpData();
     * </PRE>
     *
     */
    public void dumpData() {

        /////////////////////////////////////////////////////////////
        //                                                         //
        //                    Dump 1D Arrays                       //
        //                                                         //
        /////////////////////////////////////////////////////////////

        if (nDims <= 1 || numValues == 1) {
            if (nDims == 0 || numValues == 1) {
                if (_myVar.getDataType() == CDF_EPOCH) {
                    Double lEpoch = (Double) _dataArray;
                    System.out.println (Epoch.encode4(lEpoch.doubleValue()));
                } else if (_myVar.getDataType() == CDF_EPOCH16) {
                    double[] lEpoch16 = (double[]) _dataArray;
                    System.out.println (Epoch16.encode4(lEpoch16));
                } else if (_myVar.getDataType() == CDF_TIME_TT2000) {
                    Long lEpoch = (Long) _dataArray;
                    System.out.println (CDFTT2000.encode(lEpoch.longValue()));
                } else if (_myVar.getDataType() == CDF_CHAR ||
                           _myVar.getDataType() == CDF_UCHAR) {
                    System.out.println ("\""+_dataArray.toString()+"\"");
                }
                else
                    System.out.println (_dataArray.toString());
            }
            else {
                System.out.print("[");
                int dataTypeX = (int)_myVar.getDataType();
                switch (dataTypeX) {
                case (int)CDF_CHAR:
                case (int)CDF_UCHAR:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print("\""+((String [])_dataArray)[j]+"\"");
                    }
                    break;
                case (int)CDF_BYTE:
                case (int)CDF_INT1:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print(((byte [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_INT2:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print(((short [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_UINT1:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (((short [])_dataArray)[j] >=0) 
			  System.out.print(((short [])_dataArray)[j]);
			else {
			  short tmp = (short)(((short [])_dataArray)[j]+256); 
			  System.out.print(tmp);
			}
                    }
                    break;
                case (int)CDF_INT4:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print(((int [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_UINT2:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (((int [])_dataArray)[j] >=0)
                          System.out.print(((int [])_dataArray)[j]);
                        else {
			  int tmp = (int)(((int [])_dataArray)[j]+65536);
                          System.out.print(tmp);
			}
                    }
                    break;

                case (int)CDF_UINT4:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (((long [])_dataArray)[j] >=0)
                          System.out.print(((long [])_dataArray)[j]);
                        else {
			  long tmp = (long)(((long [])_dataArray)[j]+
					    4294967296L);
                          System.out.print(tmp);
			}
                    }
                    break;
                case (int)CDF_INT8:
                case (int)CDF_TIME_TT2000:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (dataTypeX == (int)CDF_INT8)
                          System.out.print(((long [])_dataArray)[j]);
                        else
                          System.out.print(CDFTT2000.encode(((long [])_dataArray)[j]));
                    }
                    break;
                case (int)CDF_REAL4:
                case (int)CDF_FLOAT:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print(((float [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_REAL8:
                case (int)CDF_DOUBLE:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print(((double [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_EPOCH:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
			System.out.print(
                                   Epoch.encode4(((double [])_dataArray)[j]));
                    }
                    break;
                case (int)CDF_EPOCH16:
		    double[] tmp = new double[2];
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        tmp[0] = ((double [])_dataArray)[2*j];
                        tmp[1] = ((double [])_dataArray)[2*j+1];
                        System.out.print(Epoch16.encode4(tmp));
                    }
                    break;
                default:
                    break;
                } /* switch (dataType) */
                System.out.println ("]");
            }

        /////////////////////////////////////////////////////////////
        //                                                         //
        //              Dump Multidimensional Arrays               //
        //                                                         //
        /////////////////////////////////////////////////////////////

        } else {
            /*
             * Setup the subArrays array
             * cIndex is the holds the index for the current subarray
             * boundary is the # of values in the subarray
             */
            Object aRow = null;
            Object [] subArrays = new Object[(int)nDims-1];
            int [] cIndex   = new int[(int)nDims-1];
            long [] boundary = new long[(int)nDims-1];

            subArrays[0] = _dataArray;
            cIndex[0] = 0;
	    boundary[0] = product(dimSizes,0,(int)nDims);

            for (int i=1; i<(int)nDims-1;i++) {
                subArrays[i] = Array.get(subArrays[i-1], 0);
                boundary[i] = product(dimSizes,i,(int)nDims);
                cIndex[i] = 0;
            }

            int n = 0; // The current element in the _data
            Object cObject = _dataArray;  // A temp object to hold a subarray
            boolean boundaryCrossed;
            while (n < boundary[0]) {
                // Get the correct 2D subarray to print
                if (n != 0) {
                    for (int i = 0; i < (int)nDims-1; i++) {
                        boundaryCrossed = ((n % boundary[i]) == 0);
                        if (boundaryCrossed) {
                            // Get the next sub array
                            cIndex[i]+=1;
                            cObject = Array.get(cObject, cIndex[i]);
                            subArrays[i] = cObject;

                            // Get the first element of each
                            // subsequent subarray
                            for (int j=i+1;j<(int)nDims-1;j++) {
                                cIndex[j] = 0;
                                subArrays[j] =
                                    Array.get(subArrays[j-1],cIndex[j]);
                            }
                            break;

                        } else {
                            cObject = subArrays[i];
                        }
                    }
                }

                // Fill the correct elements of _data
                for (int i=0;i<dimSizes[(int)nDims-2];i++) {
                    System.out.print("[");
                    int dataTypeX = (int)_myVar.getDataType();
                    switch (dataTypeX) {
                    case (int)CDF_CHAR:
                    case (int)CDF_UCHAR:
                        aRow =
                            (String [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print("\""+((String [])aRow)[j]+"\"");
                        }
                        break;
                    case (int)CDF_BYTE:
                    case (int)CDF_INT1:
                        aRow = (byte [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print(((byte [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_INT2:
                        aRow = (short [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print(((short [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_UINT1:
                        aRow = (short [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (((short [])aRow)[j] >=0) 
				System.out.print(((short [])aRow)[j]);
			    else {
				short tmp = (short) (((short [])aRow)[j] + 256);
				System.out.print(tmp);
			    }
                        }
                        break;
                    case (int)CDF_INT4:
                        aRow = (int [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print(((int [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_UINT2:
                        aRow = (int [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (((int [])aRow)[j] >=0)
                                System.out.print(((int [])aRow)[j]);
                            else {
                                int tmp = (int) (((int [])aRow)[j] + 65536);
                                System.out.print(tmp);
                            }
                        }
                        break;
                    case (int)CDF_UINT4:
                        aRow = (long [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (((long [])aRow)[j] >=0)
                                System.out.print(((long [])aRow)[j]);
                            else {
                                long tmp = (long) (((long [])aRow)[j]+
						   4294967296L);
                                System.out.print(tmp);
                            }
                        }
                        break;
                    case (int)CDF_INT8:
                    case (int)CDF_TIME_TT2000:
                        aRow = (long [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (dataTypeX == (int)CDF_INT8)
                              System.out.print(((long [])aRow)[j]);
                            else
                              System.out.print(CDFTT2000.encode(((long [])aRow)[j]));
                        }
                        break;
                    case (int)CDF_REAL4:
                    case (int)CDF_FLOAT:
                        aRow = (float [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print(((float [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_REAL8:
                    case (int)CDF_DOUBLE:
                        aRow = (double [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print(((double [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_EPOCH:
                        aRow = (double [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
			    System.out.print(
                                       Epoch.encode4(((double [])aRow)[j]));
                        }
                        break;
                    case (int)CDF_EPOCH16:
			double tmp[] = new double[2];
                        aRow = (double [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            tmp[0] = ((double [])aRow)[2*j];
                            tmp[1] = ((double [])aRow)[2*j+1];
                            System.out.print(Epoch16.encode4(tmp));
                        }
                        break;
                    default:
                        break;
                    } /* switch (dataType) */
                    System.out.println ("]");
                    n += dimSizes[nDims - 1];
                }
            }
        }
    }

    /**
     * Dumps variable data, one row at a time per record, with format.  This
     * is a generic * utility for dumping data to a screen.  Data can be scalar
     * or 1-dimensional or multi-dimensional array of any data type. The format
     * is only applicable to variables of numerical data type. the format comes
     * from variable's FORMAT attribute entry. Note: The FORMAT might be
     * in original C or Fortran format form. This format is mainly used for
     * floating point data. 
     *
     * The following example retrieves the first record, comprised of
     * 3x5 (3 rows and 5 columns) array, into a generic object and dumps 
     * its contents to screen one row at a time.  In this case three rows
     *  will be displayed on a screen, each row containing 5 elements. 
     * <PRE>
     *     CDFData data;
     *     String format = (String) var.getEntryData("FORMAT");
     *     long[] dimIndices   = {0,0};
     *     long[] dimIntervals = {3,5};
     *     long[] dimSizes     = {1,1}; 
     *     data = var.getHyperDataObject(0L,         // record start
     *                                   1,          // record counts 
     *                                   1,          // record interval
     *                                   dimIndices,
     *                                   dimSizes,
     *                                   dimIntervals);
     *     data.dumpDataWithFormat(format);
     * </PRE>
     *
     * @param format A string format
     *
     */
    public void dumpDataWithFormat(String format) {

	if (format == null) {
            dumpData();
            return;
        }
        String jFormat = CDFUtils.CFtoJformat (format);
        if (jFormat == null) {
            dumpData();
            return;
        } 
        
        /////////////////////////////////////////////////////////////
        //                                                         //
        //                    Dump 1D Arrays                       //
        //                                                         //
        /////////////////////////////////////////////////////////////
        long dataTYpe = _myVar.getDataType();
        if (nDims <= 1 || numValues == 1) {
            if (nDims == 0 || numValues == 1) {
                if (dataTYpe == CDF_EPOCH) {
                    Double lEpoch = (Double) _dataArray;
                    System.out.println (Epoch.encode4(lEpoch.doubleValue()));
                } else if (dataTYpe == CDF_EPOCH16) {
                    double[] lEpoch16 = (double[]) _dataArray;
                    System.out.println (Epoch16.encode4(lEpoch16));
                } else if (dataTYpe == CDF_TIME_TT2000) {
                    Long lEpoch = (Long) _dataArray;
                    System.out.println (CDFTT2000.encode(lEpoch.longValue()));
                } else if (dataTYpe == CDF_CHAR || dataTYpe == CDF_UCHAR) {
                    System.out.println ("\""+_dataArray.toString()+"\"");
                }
                else {
                    if ((dataTYpe != CDF_REAL4 && dataTYpe != CDF_REAL8 &&
                         dataTYpe != CDF_FLOAT && dataTYpe != CDF_DOUBLE) ||
                        CDFUtils.isFloatingPadValue (dataTYpe, _dataArray) == 1)
                       System.out.println (_dataArray.toString());
                    else
                       System.out.format(jFormat+"%n", _dataArray);
                }
            }
            else {
                System.out.print("[");
                int dataTypeX = (int)_myVar.getDataType();
                switch (dataTypeX) {
                case (int)CDF_CHAR:
                case (int)CDF_UCHAR:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print("\""+((String [])_dataArray)[j]+"\"");
                    }
                    break;
                case (int)CDF_BYTE:
                case (int)CDF_INT1:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print(((byte [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_INT2:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print(((short [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_UINT1:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (((short [])_dataArray)[j] >=0) {
                          System.out.print(((short [])_dataArray)[j]);
			} else {
			  short tmp = (short)(((short [])_dataArray)[j]+256); 
                          System.out.print(tmp);
			}
                    }
                    break;
                case (int)CDF_INT4:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        System.out.print(((int [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_UINT2:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (((int [])_dataArray)[j] >=0) {
                          System.out.print(((int [])_dataArray)[j]);
                        } else {
			  int tmp = (int)(((int [])_dataArray)[j]+65536);
                          System.out.print(tmp);
			}
                    }
                    break;

                case (int)CDF_UINT4:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (((long [])_dataArray)[j] >=0) {
                          System.out.print(((long [])_dataArray)[j]);
                        } else {
			  long tmp = (long)(((long [])_dataArray)[j]+
					    4294967296L);
                          System.out.print(tmp);
			}
                    }
                    break;
                case (int)CDF_INT8:
                case (int)CDF_TIME_TT2000:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (dataTypeX == (int)CDF_INT8) {
                          System.out.print(((long [])_dataArray)[j]);
                        } else
                          System.out.print(CDFTT2000.encode(((long [])_dataArray)[j]));
                    }
                    break;
                case (int)CDF_REAL4:
                case (int)CDF_FLOAT:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (CDFUtils.isFloatingPadValue (dataType, ((float [])_dataArray)[j]) != 1)
                           System.out.print(((float [])_dataArray)[j]);
                        else
                           System.out.format(jFormat, ((float [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_REAL8:
                case (int)CDF_DOUBLE:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        if (CDFUtils.isFloatingPadValue (dataType, ((double [])_dataArray)[j]) != 1)
                           System.out.print(((double [])_dataArray)[j]);
                        else
                           System.out.format(jFormat, ((double [])_dataArray)[j]);
                    }
                    break;
                case (int)CDF_EPOCH:
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
			System.out.print(
                                   Epoch.encode4(((double [])_dataArray)[j]));
                    }
                    break;
                case (int)CDF_EPOCH16:
		    double[] tmp = new double[2];
                    for (int j=0; j<dimSizes[nDims - 1]; j++) {
                        if (j>0) System.out.print(",");
                        tmp[0] = ((double [])_dataArray)[2*j];
                        tmp[1] = ((double [])_dataArray)[2*j+1];
                        System.out.print(Epoch16.encode4(tmp));
                    }
                    break;
                default:
                    break;
                } /* switch (dataType) */
                System.out.println ("]");
            }

        /////////////////////////////////////////////////////////////
        //                                                         //
        //              Dump Multidimensional Arrays               //
        //                                                         //
        /////////////////////////////////////////////////////////////

        } else {
            /*
             * Setup the subArrays array
             * cIndex is the holds the index for the current subarray
             * boundary is the # of values in the subarray
             */
            Object aRow = null;
            Object [] subArrays = new Object[(int)nDims-1];
            int [] cIndex   = new int[(int)nDims-1];
            long [] boundary = new long[(int)nDims-1];

            subArrays[0] = _dataArray;
            cIndex[0] = 0;
	    boundary[0] = product(dimSizes,0,(int)nDims);

            for (int i=1; i<(int)nDims-1;i++) {
                subArrays[i] = Array.get(subArrays[i-1], 0);
                boundary[i] = product(dimSizes,i,(int)nDims);
                cIndex[i] = 0;
            }

            int n = 0; // The current element in the _data
            Object cObject = _dataArray;  // A temp object to hold a subarray
            boolean boundaryCrossed;
            while (n < boundary[0]) {
                // Get the correct 2D subarray to print
                if (n != 0) {
                    for (int i = 0; i < (int)nDims-1; i++) {
                        boundaryCrossed = ((n % boundary[i]) == 0);
                        if (boundaryCrossed) {
                            // Get the next sub array
                            cIndex[i]+=1;
                            cObject = Array.get(cObject, cIndex[i]);
                            subArrays[i] = cObject;

                            // Get the first element of each
                            // subsequent subarray
                            for (int j=i+1;j<(int)nDims-1;j++) {
                                cIndex[j] = 0;
                                subArrays[j] =
                                    Array.get(subArrays[j-1],cIndex[j]);
                            }
                            break;

                        } else {
                            cObject = subArrays[i];
                        }
                    }
                }

                // Fill the correct elements of _data
                for (int i=0;i<dimSizes[(int)nDims-2];i++) {
                    System.out.print("[");
                    int dataTypeX = (int)_myVar.getDataType();
                    switch (dataTypeX) {
                    case (int)CDF_CHAR:
                    case (int)CDF_UCHAR:
                        aRow =
                            (String [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print("\""+((String [])aRow)[j]+"\"");
                        }
                        break;
                    case (int)CDF_BYTE:
                    case (int)CDF_INT1:
                        aRow = (byte [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print(((short [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_INT2:
                        aRow = (short [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print(((short [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_UINT1:
                        aRow = (short [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (((short [])aRow)[j] >=0) {
                                System.out.print(((short [])aRow)[j]);
			    } else {
				short tmp = (short) (((short [])aRow)[j] + 256);
                                System.out.print(tmp);
			    }
                        }
                        break;
                    case (int)CDF_INT4:
                        aRow = (int [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            System.out.print(((int [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_UINT2:
                        aRow = (int [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (((int [])aRow)[j] >=0) {
                                System.out.print(((long [])aRow)[j]);
                            } else {
                                int tmp = (int) (((int [])aRow)[j] + 65536);
                                System.out.print(tmp);
                            }
                        }
                        break;
                    case (int)CDF_UINT4:
                        aRow = (long [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (((long [])aRow)[j] >=0) {
                                System.out.print(((long [])aRow)[j]);
                            } else {
                                long tmp = (long) (((long [])aRow)[j]+
						   4294967296L);
                                System.out.print(((long [])aRow)[j]);
                            }
                        }
                        break;
                    case (int)CDF_INT8:
                    case (int)CDF_TIME_TT2000:
                        aRow = (long [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (dataTypeX == (int)CDF_INT8) {
                              System.out.print(((long [])aRow)[j]);
                            } else
                              System.out.print(CDFTT2000.encode(((long [])aRow)[j]));
                        }
                        break;
                    case (int)CDF_REAL4:
                    case (int)CDF_FLOAT:
                        aRow = (float [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (CDFUtils.isFloatingPadValue (dataType, ((float [])aRow)[j]) != 1)
                               System.out.print(((float [])aRow)[j]);
                            else
                               System.out.format(format, ((float [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_REAL8:
                    case (int)CDF_DOUBLE:
                        aRow = (double [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            if (CDFUtils.isFloatingPadValue (dataType, ((double [])aRow)[j]) != 1)
                               System.out.print(((double [])aRow)[j]);
                            else
                               System.out.format(format, ((double [])aRow)[j]);
                        }
                        break;
                    case (int)CDF_EPOCH:
                        aRow = (double [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
			    System.out.print(
                                       Epoch.encode4(((double [])aRow)[j]));
                        }
                        break;
                    case (int)CDF_EPOCH16:
			double tmp[] = new double[2];
                        aRow = (double [])Array.get(subArrays[(int)nDims - 2], i);
                        for (int j=0; j<dimSizes[nDims - 1]; j++) {
                            if (j>0) System.out.print(",");
                            tmp[0] = ((double [])aRow)[2*j];
                            tmp[1] = ((double [])aRow)[2*j+1];
                            System.out.print(Epoch16.encode4(tmp));
                        }
                        break;
                    default:
                        break;
                    } /* switch (dataType) */
                    System.out.println ("]");
                    n += dimSizes[nDims - 1];
                }
            }
        }
    }

    /**
     * Dump data information and values, one row at a time, to the stdErr.
     * This method is provided for debugging purposes only.
     *
     * The information is printed in the following manner:
     * &lt;VAR_TYPE&gt;/&lt;VAR_#Elements&gt;    nDims:[sizes]  
     * recStart/recCount/recInterval/dimIndices/dimsSizes/dimIntervals/dataArraySignature
     * &lt;values row-by-row&gt;
     */
    public void dump() {

	StringBuffer 
	    sb = new StringBuffer(), 
	    specs = new StringBuffer();
	int nSpaces;

	System.err.println ("Data dump for "+_myVar+": ");

	// Get the Data type in a human form
	sb.append(CDFUtils.getStringDataType(_myVar.getDataType()));
	sb.append("/");
	sb.append(_myVar.getNumElements());
	nSpaces = 12 - sb.length();
	for (int i=0;i<nSpaces;i++)
             sb.append(" "); 
	specs.append(sb.toString());
	sb.setLength(0);

	specs.append(String.valueOf(nDims));
	specs.append(":[");
	for (int i=0;i<nDims;i++) {
	    if (i>0) specs.append(",");
	    specs.append(String.valueOf(dimSizes[i]));
	}
	specs.append("]\t");

	// Print the record, dim, etc info
	specs.append(String.valueOf(recStart));
	specs.append("/");
	specs.append(String.valueOf(recCount));
	specs.append("/");
	specs.append(String.valueOf(recInterval));
	specs.append("/[");
	for (int i=0;i<dimIndices.length;i++) {
	    if (i>0) specs.append(",");
	    specs.append(String.valueOf(dimIndices[i]));
	}
	specs.append("]/[");
	for (int i=0;i<dimCounts.length;i++) {
	    if (i>0) specs.append(",");
	    specs.append(String.valueOf(dimCounts[i]));
	}
	specs.append("]/[");
	for (int i=0;i<dimIntervals.length;i++) {
	    if (i>0) specs.append(",");
	    specs.append(String.valueOf(dimIntervals[i]));
	}
	specs.append("]/");
	specs.append(_dataArray.getClass().getName());
	System.err.println (specs.toString());

	/////////////////////////////////////////////////////////////
	//                                                         //
	//                    Dump 1D Arrays                       //
	//                                                         //
	/////////////////////////////////////////////////////////////

        dumpData();
    }

    /**
     * CDFData implements CDFObject to enable CDFDelegate calls.  CDFObject
     * specifies the following three methods: getName(), rename(String), and
     * delete().  Since CDFData implements CDFObject, it must have the methods
     * defined in CDFObject.  That's why this method is here; it doesn't do
     * anything. 
     */
    public String getName() {

	return "Data";
    }

    /**
     * See the description of the getName() method in this class.
     * @exception CDFException No exception is thrown since this method is a
     *                      placeholder
     */
    public void   rename(String name) throws CDFException {}

    /**
     * See the description of the getName() method in this class.
     * @exception CDFException No exception is thrown since this method is a
     *                      placeholder
     */
    public void   delete() throws CDFException {}

}


