    001/*****************************************************************************
    002 * Copyright by The HDF Group.                                               *
    003 * Copyright by the Board of Trustees of the University of Illinois.         *
    004 * All rights reserved.                                                      *
    005 *                                                                           *
    006 * This file is part of the HDF Java Products distribution.                  *
    007 * The full copyright notice, including terms governing use, modification,   *
    008 * and redistribution, is contained in the files COPYING and Copyright.html. *
    009 * COPYING can be found at the root of the source code distribution tree.    *
    010 * Or, see https://support.hdfgroup.org/products/licenses.html               *
    011 * If you do not have access to either file, you may request a copy from     *
    012 * help@hdfgroup.org.                                                        *
    013 ****************************************************************************/
    014
    015package hdf.object.nc2;
    016
    017import java.util.List;
    018
    019import hdf.object.Datatype;
    020import ucar.ma2.DataType;
    021
    022/**
    023 * Datatype encapsulates information of a datatype. Information includes the
    024 * class, size, endian of a datatype.
    025 *
    026 * @version 1.1 9/4/2007
    027 * @author Peter X. Cao
    028 */
    029public class NC2Datatype extends Datatype {
    030    private static final long serialVersionUID = 5399364372073889764L;
    031
    032    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NC2Datatype.class);
    033
    034    DataType nativeType = null;
    035
    036    /**
    037     * Create an Datatype with specified class, size, byte order and sign. The
    038     * following list a few example of how to create a Datatype.
    039     * <ol>
    040     * <li>to create unsigned native integer<br>
    041     * NC2Datatype type = new NC2Datatype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, Datatype.SIGN_NONE);</li>
    042     * <li>to create 16-bit signed integer with big endian<br>
    043     * NC2Datatype type = new NC2Datatype(Datatype.CLASS_INTEGER, 2, Datatype.ORDER_BE, Datatype.NATIVE);</li>
    044     * <li>to create native float<br>
    045     * NC2Datatype type = new NC2Datatype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE);</li>
    046     * <li>to create 64-bit double<br>
    047     * NC2Datatype type = new NC2Datatype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, Datatype.NATIVE);</li>
    048     * </ol>
    049     *
    050     * @param tclass
    051     *            the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc.
    052     * @param tsize
    053     *            the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4.
    054     *            Valid values are NATIVE or a positive value.
    055     * @param torder
    056     *            the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX,
    057     *            ORDER_NONE and NATIVE.
    058     * @param tsign
    059     *            the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE.
    060     *
    061     * @throws Exception
    062     *            if there is an error
    063     */
    064    public NC2Datatype(int tclass, int tsize, int torder, int tsign) throws Exception {
    065        super(tclass, tsize, torder, tsign);
    066        datatypeDescription = getDescription();
    067    }
    068
    069    /**
    070     * Constructs a NC2Datatype with a given NetCDF3 native datatype object.
    071     *
    072     * @param theType
    073     *            the netcdf native datatype.
    074     *
    075     * @throws Exception
    076     *            if there is an error
    077     */
    078    public NC2Datatype(DataType theType) throws Exception {
    079        super(null, -1);
    080        log.trace("NC2Datatype: start nc2 type = {}", theType);
    081        nativeType = theType;
    082        fromNative(0);
    083        datatypeDescription = getDescription();
    084    }
    085
    086    /*
    087     * (non-Javadoc)
    088     *
    089     * @see hdf.object.DataFormat#hasAttribute()
    090     */
    091    @Override
    092    public boolean hasAttribute() {
    093        return false;
    094    }
    095
    096    /*
    097     * (non-Javadoc)
    098     *
    099     * @see hdf.object.Datatype#fromNative(long)
    100     */
    101    /**
    102     * Translate NetCDF3 datatype object into NC2Datatype.
    103     *
    104     * @param tid the native ID
    105     *            UNUSED.
    106     */
    107    @Override
    108    public void fromNative(long tid)
    109    {
    110        if (nativeType == null) {
    111            return;
    112        }
    113
    114        datatypeOrder = NATIVE;
    115        if (nativeType.equals(DataType.CHAR)) {
    116            datatypeClass = CLASS_CHAR;
    117            datatypeSize = 1;
    118        }
    119        else if (nativeType.equals(DataType.BYTE)) {
    120            datatypeClass = CLASS_INTEGER;
    121            datatypeSize = 1;
    122        }
    123        else if (nativeType.equals(DataType.SHORT)) {
    124            datatypeClass = CLASS_INTEGER;
    125            datatypeSize = 2;
    126        }
    127        else if (nativeType.equals(DataType.INT)) {
    128            datatypeClass = CLASS_INTEGER;
    129            datatypeSize = 4;
    130        }
    131        else if (nativeType.equals(DataType.LONG)) {
    132            datatypeClass = CLASS_INTEGER;
    133            datatypeSize = 8;
    134        }
    135        else if (nativeType.equals(DataType.FLOAT)) {
    136            datatypeClass = CLASS_FLOAT;
    137            datatypeSize = 4;
    138        }
    139        else if (nativeType.equals(DataType.DOUBLE)) {
    140            datatypeClass = CLASS_FLOAT;
    141            datatypeSize = 8;
    142        }
    143        else if (nativeType.equals(DataType.STRING)) {
    144            datatypeClass = CLASS_STRING;
    145            datatypeSize = 80; // default length. need to figure out the actual length
    146        }
    147        else if (nativeType.equals(DataType.OPAQUE)) {
    148            datatypeClass = CLASS_OPAQUE;
    149            datatypeSize = 1;
    150        }
    151
    152        log.trace("Datatype class={} size={}", datatypeClass, datatypeSize);
    153    }
    154
    155    /**
    156     * Allocate an one-dimensional array of byte, short, int, long, float,
    157     * double, or String to store data retrieved from an NetCDF3 file based on
    158     * the given NetCDF3 datatype and dimension sizes.
    159     *
    160     * @param dtype
    161     *            the NetCDF3 datatype object.
    162     * @param datasize
    163     *            the size of the data array
    164     *
    165     * @return an array of 'datasize' numbers of datatype.
    166     *
    167     * @throws OutOfMemoryError
    168     *             if the array cannot be allocated
    169     */
    170    public static final Object allocateArray(DataType dtype, int datasize)
    171            throws OutOfMemoryError {
    172        if ((datasize <= 0) || (dtype == null)) {
    173            log.debug("datasize <= 0");
    174            return null;
    175        }
    176
    177        Object data = null;
    178
    179        if (dtype.equals(DataType.BYTE)) {
    180            data = new byte[datasize];
    181        }
    182        else if (dtype.equals(DataType.SHORT)) {
    183            data = new short[datasize];
    184        }
    185        else if (dtype.equals(DataType.INT)) {
    186            data = new int[datasize];
    187        }
    188        else if (dtype.equals(DataType.LONG)) {
    189            data = new long[datasize];
    190        }
    191        else if (dtype.equals(DataType.FLOAT)) {
    192            data = new float[datasize];
    193        }
    194        else if (dtype.equals(DataType.DOUBLE)) {
    195            data = new double[datasize];
    196        }
    197        else if (dtype.equals(DataType.STRING)) {
    198            data = new String[datasize];
    199        }
    200
    201        return data;
    202    }
    203
    204    /*
    205     * (non-Javadoc)
    206     *
    207     * @see hdf.object.Datatype#getDatatypeDescription()
    208     */
    209    @Override
    210    public String getDescription() {
    211        if (datatypeDescription != null) {
    212            return datatypeDescription;
    213        }
    214
    215        String description = null;
    216
    217        if (nativeType == null) {
    218            description = "Unknown data type.";
    219        }
    220
    221        description = nativeType.toString();
    222
    223        return description;
    224    }
    225
    226    /*
    227     * (non-Javadoc)
    228     *
    229     * @see hdf.object.Datatype#isUnsigned()
    230     */
    231    @Override
    232    public boolean isUnsigned() {
    233        if (nativeType.isNumeric())
    234            return false;
    235        else
    236            return false;
    237    }
    238
    239    @Override
    240    public boolean isText() {
    241        return (nativeType == DataType.CHAR);
    242    }
    243
    244    /*
    245     * (non-Javadoc)
    246     * @see hdf.object.Datatype#createNative()
    247     */
    248    @Override
    249    public long createNative()
    250    {
    251        if (datatypeClass == CLASS_INTEGER) {
    252            if (datatypeSize == 1) {
    253                nativeType = DataType.BYTE;
    254            }
    255            else if (datatypeSize == 2) {
    256                nativeType = DataType.SHORT;
    257            }
    258            else if (datatypeSize == 4) {
    259                nativeType = DataType.INT;
    260            }
    261            else if (datatypeSize == 8) {
    262                nativeType = DataType.LONG;
    263            }
    264        }
    265        else if (datatypeClass == CLASS_FLOAT) {
    266            if (datatypeSize == 4) {
    267                nativeType = DataType.FLOAT;
    268            }
    269            else if (datatypeSize == 8) {
    270                nativeType = DataType.DOUBLE;
    271            }
    272        }
    273        else if (datatypeClass == CLASS_STRING) {
    274            nativeType = DataType.STRING;
    275        }
    276        else {
    277            log.debug("createNative(): unknown datatype class {}", datatypeClass);
    278        }
    279
    280        return -1;
    281    }
    282
    283    /*
    284     * (non-Javadoc)
    285     *
    286     * @see hdf.object.Datatype#close(int)
    287     */
    288    @Override
    289    public void close(long id) {
    290        // No implementation
    291    }
    292
    293    // Implementing DataFormat
    294    @SuppressWarnings("rawtypes")
    295    public List getMetadata(int... attrPropList) throws Exception {
    296        throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported");
    297    }
    298}