    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;
    016
    017import java.util.HashMap;
    018import java.util.Iterator;
    019import java.util.List;
    020import java.util.Map;
    021import java.util.Map.Entry;
    022
    023/**
    024 * Datatype is an abstract class that defines datatype characteristics and APIs for a data type.
    025 * <p>
    026 * A datatype has four basic characteristics: class, size, byte order and sign. These
    027 * characteristics are defined in the
    028 * <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>.
    029 * <p>
    030 * These characteristics apply to all the sub-classes. The sub-classes may have different ways to
    031 * describe a datatype. We here define the <strong> native datatype</strong> to the datatype used by
    032 * the sub-class. For example, H5Datatype uses a datatype identifier (hid_t) to specify a datatype.
    033 * NC2Datatype uses ucar.nc2.DataType object to describe its datatype. "Native" here is different
    034 * from the "native" definition in the HDF5 library.
    035 * <p>
    036 * Two functions, createNative() and fromNative(), are defined to convert the general
    037 * characteristics to/from the native datatype. Sub-classes must implement these functions so that
    038 * the conversion will be done correctly. The values of the CLASS member are not identical to HDF5
    039 * values for a datatype class.
    040 * <p>
    041 *
    042 * @version 1.1 9/4/2007
    043 * @author Peter X. Cao
    044 */
    045public abstract class Datatype extends HObject implements MetaDataContainer {
    046
    047    private static final long serialVersionUID = -581324710549963177L;
    048
    049    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Datatype.class);
    050
    051    /**
    052     * The default definition for datatype size, order, and sign.
    053     */
    054    public static final int NATIVE = -1;
    055
    056    /**
    057     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    058     */
    059    public static final int CLASS_NO_CLASS = -1;
    060
    061    /**
    062     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    063     */
    064    public static final int CLASS_INTEGER = 0;
    065
    066    /**
    067     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    068     */
    069    public static final int CLASS_FLOAT = 1;
    070
    071    /**
    072     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    073     */
    074    public static final int CLASS_CHAR = 2;
    075
    076    /**
    077     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    078     */
    079    public static final int CLASS_STRING = 3;
    080
    081    /**
    082     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    083     */
    084    public static final int CLASS_BITFIELD = 4;
    085
    086    /**
    087     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    088     */
    089    public static final int CLASS_OPAQUE = 5;
    090
    091    /**
    092     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    093     */
    094    public static final int CLASS_COMPOUND = 6;
    095
    096    /**
    097     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    098     */
    099    public static final int CLASS_REFERENCE = 7;
    100
    101    /**
    102     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    103     */
    104    public static final int CLASS_ENUM = 8;
    105
    106    /**
    107     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    108     */
    109    public static final int CLASS_VLEN = 9;
    110
    111    /**
    112     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    113     */
    114    public static final int CLASS_ARRAY = 10;
    115
    116    /**
    117     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    118     */
    119    public static final int CLASS_TIME = 11;
    120
    121    /**
    122     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    123     */
    124    public static final int ORDER_LE = 0;
    125
    126    /**
    127     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    128     */
    129    public static final int ORDER_BE = 1;
    130
    131    /**
    132     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    133     */
    134    public static final int ORDER_VAX = 2;
    135
    136    /**
    137     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    138     */
    139    public static final int ORDER_NONE = 3;
    140
    141    /**
    142     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    143     */
    144    public static final int SIGN_NONE = 0;
    145
    146    /**
    147     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    148     */
    149    public static final int SIGN_2 = 1;
    150
    151    /**
    152     * See <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
    153     */
    154    public static final int NSGN = 2;
    155
    156    protected String datatypeDescription = null;
    157
    158    /**
    159     * The class of the datatype.
    160     */
    161    protected int datatypeClass;
    162
    163    /**
    164     * The size (in bytes) of the datatype.
    165     */
    166    protected long datatypeSize;
    167
    168    /**
    169     * The byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, and
    170     * ORDER_VAX.
    171     */
    172    protected int datatypeOrder;
    173
    174    /**
    175     * The sign of the datatype.
    176     */
    177    protected int datatypeSign;
    178
    179    /**
    180     * The base datatype of this datatype (null if this datatype is atomic).
    181     */
    182    protected Datatype baseType;
    183
    184    /**
    185     * The dimensions of the ARRAY element of an ARRAY datatype.
    186     */
    187    protected long[] arrayDims;
    188
    189    /**
    190     * Determines whether this datatype is a variable-length type.
    191     */
    192    protected boolean is_VLEN = false;
    193    protected boolean is_variable_str = false;
    194
    195    /**
    196     * The (name, value) pairs of enum members.
    197     */
    198    protected Map<String, String> enumMembers;
    199
    200    /**
    201     * The list of names of members of a compound Datatype.
    202     */
    203    protected List<String> compoundMemberNames;
    204
    205    /**
    206     * The list of types of members of a compound Datatype.
    207     */
    208    protected List<Datatype> compoundMemberTypes;
    209
    210    /**
    211     * The list of offsets of members of a compound Datatype.
    212     */
    213    protected List<Long> compoundMemberOffsets;
    214
    215    /**
    216     * Constructs a named datatype with a given file, name and path.
    217     *
    218     * @param theFile
    219     *            the HDF file.
    220     * @param typeName
    221     *            the name of the datatype, e.g "12-bit Integer".
    222     * @param typePath
    223     *            the full group path of the datatype, e.g. "/datatypes/".
    224     */
    225    public Datatype(FileFormat theFile, String typeName, String typePath) {
    226        this(theFile, typeName, typePath, null);
    227    }
    228
    229    /**
    230     * @deprecated Not for public use in the future.<br>
    231     *             Using {@link #Datatype(FileFormat, String, String)}
    232     *
    233     * @param theFile
    234     *            the HDF file.
    235     * @param typeName
    236     *            the name of the datatype, e.g "12-bit Integer".
    237     * @param typePath
    238     *            the full group path of the datatype, e.g. "/datatypes/".
    239     * @param oid
    240     *            the oidof the datatype.
    241     */
    242    @Deprecated
    243    public Datatype(FileFormat theFile, String typeName, String typePath, long[] oid) {
    244        super(theFile, typeName, typePath, oid);
    245    }
    246
    247    /**
    248     * Constructs a Datatype with specified class, size, byte order and sign.
    249     * <p>
    250     * The following is a list of a few example of H5Datatype.
    251     * <ol>
    252     * <li>to create unsigned native integer<br>
    253     * H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE,
    254     * SIGN_NONE);
    255     * <li>to create 16-bit signed integer with big endian<br>
    256     * H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE);
    257     * <li>to create native float<br>
    258     * H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1);
    259     * <li>to create 64-bit double<br>
    260     * H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1);
    261     * </ol>
    262     *
    263     * @param tclass
    264     *            the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and
    265     *            etc.
    266     * @param tsize
    267     *            the size of the datatype in bytes, e.g. for a 32-bit integer,
    268     *            the size is 4.
    269     * @param torder
    270     *            the byte order of the datatype. Valid values are ORDER_LE,
    271     *            ORDER_BE, ORDER_VAX and ORDER_NONE
    272     * @param tsign
    273     *            the sign of the datatype. Valid values are SIGN_NONE, SIGN_2
    274     *            and MSGN
    275     */
    276    public Datatype(int tclass, int tsize, int torder, int tsign) {
    277        this(tclass, tsize, torder, tsign, null);
    278    }
    279
    280    /**
    281     * Constructs a Datatype with specified class, size, byte order and sign.
    282     * <p>
    283     * The following is a list of a few example of H5Datatype.
    284     * <ol>
    285     * <li>to create unsigned native integer<br>
    286     * H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE,
    287     * SIGN_NONE);
    288     * <li>to create 16-bit signed integer with big endian<br>
    289     * H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE);
    290     * <li>to create native float<br>
    291     * H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1);
    292     * <li>to create 64-bit double<br>
    293     * H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1);
    294     * </ol>
    295     *
    296     * @param tclass
    297     *            the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and
    298     *            etc.
    299     * @param tsize
    300     *            the size of the datatype in bytes, e.g. for a 32-bit integer,
    301     *            the size is 4.
    302     * @param torder
    303     *            the byte order of the datatype. Valid values are ORDER_LE,
    304     *            ORDER_BE, ORDER_VAX and ORDER_NONE
    305     * @param tsign
    306     *            the sign of the datatype. Valid values are SIGN_NONE, SIGN_2
    307     *            and MSGN
    308     * @param tbase
    309     *            the base datatype of the new datatype
    310     */
    311    public Datatype(int tclass, int tsize, int torder, int tsign, Datatype tbase) {
    312        this(tclass, tsize, torder, tsign, tbase, null);
    313    }
    314
    315    /**
    316     * Constructs a Datatype with specified class, size, byte order and sign.
    317     * <p>
    318     * The following is a list of a few example of H5Datatype.
    319     * <ol>
    320     * <li>to create unsigned native integer<br>
    321     * H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE, SIGN_NONE);
    322     * <li>to create 16-bit signed integer with big endian<br>
    323     * H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE);
    324     * <li>to create native float<br>
    325     * H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1);
    326     * <li>to create 64-bit double<br>
    327     * H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1);
    328     * </ol>
    329     *
    330     * @param tclass
    331     *            the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc.
    332     * @param tsize
    333     *            the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4.
    334     * @param torder
    335     *            the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX and
    336     *            ORDER_NONE
    337     * @param tsign
    338     *            the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and MSGN
    339     * @param tbase
    340     *            the base datatype of the new datatype
    341     * @param pbase
    342     *            the parent datatype of the new datatype
    343     */
    344    public Datatype(int tclass, int tsize, int torder, int tsign, Datatype tbase, Datatype pbase) {
    345        datatypeClass = tclass;
    346        datatypeSize = tsize;
    347        datatypeOrder = torder;
    348        datatypeSign = tsign;
    349        enumMembers = null;
    350        baseType = tbase;
    351        arrayDims = null;
    352        is_variable_str = (datatypeClass == Datatype.CLASS_STRING) && (tsize < 0);
    353        is_VLEN = (datatypeClass == Datatype.CLASS_VLEN) || is_variable_str;
    354
    355        log.trace("datatypeClass={} datatypeSize={} datatypeOrder={} datatypeSign={} baseType={}",
    356                datatypeClass, datatypeSize, datatypeOrder, datatypeSign, baseType);
    357    }
    358
    359    /**
    360     * Constructs a Datatype with a given native datatype identifier.
    361     * <p>
    362     * For example, if the datatype identifier is a 32-bit unsigned integer created from HDF5,
    363     *
    364     * <pre>
    365     * long tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32);
    366     * Datatype dtype = new Datatype(tid);
    367     * </pre>
    368     *
    369     * will construct a datatype equivalent to new Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE);
    370     *
    371     * @see #fromNative(long tid)
    372     * @param tid
    373     *            the native datatype identifier.
    374     */
    375    public Datatype(long tid) {
    376        this(tid, null);
    377    }
    378
    379    /**
    380     * Constructs a Datatype with a given native datatype identifier.
    381     * <p>
    382     * For example, if the datatype identifier is a 32-bit unsigned integer created
    383     * from HDF5,
    384     *
    385     * <pre>
    386     * long tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32);
    387     * Datatype dtype = new Datatype(tid);
    388     * </pre>
    389     *
    390     * will construct a datatype equivalent to new Datatype(CLASS_INTEGER, 4,
    391     * NATIVE, SIGN_NONE);
    392     *
    393     * @see #fromNative(long tid)
    394     * @param tid
    395     *            the native datatype identifier.
    396     * @param pbase
    397     *            the parent datatype of the new datatype
    398     */
    399    public Datatype(long tid, Datatype pbase) {
    400        this(CLASS_NO_CLASS, NATIVE, NATIVE, NATIVE, null, pbase);
    401    }
    402
    403    /**
    404     * Opens access to this named datatype. Sub-classes must replace this default implementation. For
    405     * example, in H5Datatype, open() function H5.H5Topen(loc_id, name) to get the datatype identifier.
    406     *
    407     * @return the datatype identifier if successful; otherwise returns negative value.
    408     */
    409    @Override
    410    public long open() {
    411        return -1;
    412    }
    413
    414    /**
    415     * Closes a datatype identifier.
    416     * <p>
    417     * Sub-classes must replace this default implementation.
    418     *
    419     * @param id
    420     *            the datatype identifier to close.
    421     */
    422    @Override
    423    public abstract void close(long id);
    424
    425    /**
    426     * Returns the class of the datatype. Valid values are:
    427     * <ul>
    428     * <li>CLASS_NO_CLASS
    429     * <li>CLASS_INTEGER
    430     * <li>CLASS_FLOAT
    431     * <li>CLASS_CHAR
    432     * <li>CLASS_STRING
    433     * <li>CLASS_BITFIELD
    434     * <li>CLASS_OPAQUE
    435     * <li>CLASS_COMPOUND
    436     * <li>CLASS_REFERENCE
    437     * <li>CLASS_ENUM
    438     * <li>CLASS_VLEN
    439     * <li>CLASS_ARRAY
    440     * </ul>
    441     *
    442     * @return the class of the datatype.
    443     */
    444    public int getDatatypeClass() {
    445        return datatypeClass;
    446    }
    447
    448    /**
    449     * Returns the size of the datatype in bytes. For example, for a 32-bit
    450     * integer, the size is 4 (bytes).
    451     *
    452     * @return the size of the datatype.
    453     */
    454    public long getDatatypeSize() {
    455        return datatypeSize;
    456    }
    457
    458    /**
    459     * Returns the byte order of the datatype. Valid values are
    460     * <ul>
    461     * <li>ORDER_LE
    462     * <li>ORDER_BE
    463     * <li>ORDER_VAX
    464     * <li>ORDER_NONE
    465     * </ul>
    466     *
    467     * @return the byte order of the datatype.
    468     */
    469    public int getDatatypeOrder() {
    470        return datatypeOrder;
    471    }
    472
    473    /**
    474     * Returns the sign (SIGN_NONE, SIGN_2 or NSGN) of an integer datatype.
    475     *
    476     * @return the sign of the datatype.
    477     */
    478    public int getDatatypeSign() {
    479        return datatypeSign;
    480    }
    481
    482    /**
    483     * Returns the datatype of the elements for this datatype.
    484     * <p>
    485     * For example, in a dataset of type ARRAY of integer, the datatype of the dataset is ARRAY. The
    486     * datatype of the base type is integer.
    487     *
    488     * @return the datatype of the contained datatype.
    489     */
    490    public Datatype getDatatypeBase() {
    491        return baseType;
    492    }
    493
    494    /**
    495     * Sets the (name, value) pairs of enum members for enum datatype.
    496     * <p>
    497     * For Example,
    498     * <dl>
    499     * <dt>setEnumMembers("lowTemp=-40, highTemp=90")</dt>
    500     * <dd>sets the value of enum member lowTemp to -40 and highTemp to 90.</dd>
    501     * <dt>setEnumMembers("lowTemp, highTemp")</dt>
    502     * <dd>sets enum members to defaults, i.e. lowTemp=0 and highTemp=1</dd>
    503     * <dt>setEnumMembers("lowTemp=10, highTemp")</dt>
    504     * <dd>sets enum member lowTemp to 10 and highTemp to 11.</dd>
    505     * </dl>
    506     *
    507     * @param enumStr
    508     *            the (name, value) pairs of enum members
    509     */
    510    public final void setEnumMembers(String enumStr) {
    511        log.trace("setEnumMembers: is_enum enum_members={}", enumStr);
    512        enumMembers = new HashMap<>();
    513        String[] entries = enumStr.split(",");
    514        for (String entry : entries) {
    515            String[] keyValue = entry.split("=");
    516            enumMembers.put(keyValue[1].trim(), keyValue[0].trim());
    517            log.trace("setEnumMembers: is_enum value={} name={}", keyValue[1].trim(), keyValue[0].trim());
    518        }
    519    }
    520
    521    /**
    522     * Returns the Map&lt;String,String&gt; pairs of enum members for enum datatype.
    523     *
    524     * @return enumStr Map&lt;String,String%gt; pairs of enum members
    525     */
    526    public final Map<String, String> getEnumMembers() {
    527        if (enumMembers == null) {
    528            enumMembers = new HashMap<>();
    529            enumMembers.put("1", "0");
    530            enumMembers.put("2", "1");
    531        }
    532
    533        return enumMembers;
    534    }
    535
    536    /**
    537     * Returns the HashMap pairs of enum members for enum datatype.
    538     * <p>
    539     * For Example,
    540     * <dl>
    541     * <dt>getEnumMembersAsString()</dt>
    542     * <dd>returns "lowTemp=10, highTemp=40"</dd>
    543     * </dl>
    544     *
    545     * @return enumStr the (name, value) pairs of enum members
    546     */
    547    @SuppressWarnings("rawtypes")
    548    public final String getEnumMembersAsString() {
    549        if (enumMembers == null) {
    550            enumMembers = new HashMap<>();
    551            enumMembers.put("1", "0");
    552            enumMembers.put("2", "1");
    553        }
    554
    555        String enumStr = new String();
    556        Iterator<Entry<String, String>> entries = enumMembers.entrySet().iterator();
    557        int i = enumMembers.size();
    558        while (entries.hasNext()) {
    559            Entry thisEntry = entries.next();
    560            String memstr = (String) thisEntry.getKey();
    561            String memname = (String) thisEntry.getValue();
    562            enumStr += memname + "=" + memstr;
    563            i--;
    564            if (i > 0)
    565                enumStr += ", ";
    566        }
    567        return enumStr;
    568    }
    569
    570    /**
    571     * Returns the dimensions of an Array Datatype.
    572     *
    573     * @return dims the dimensions of the Array Datatype
    574     */
    575    public final long[] getArrayDims() {
    576        return arrayDims;
    577    }
    578
    579    public final List<String> getCompoundMemberNames() {
    580        return compoundMemberNames;
    581    }
    582
    583    public final List<Datatype> getCompoundMemberTypes() {
    584        return compoundMemberTypes;
    585    }
    586
    587    /**
    588     * Converts the datatype object to a native datatype.
    589     *
    590     * Subclasses must implement it so that this datatype will be converted accordingly. Use close() to
    591     * close the native identifier; otherwise, the datatype will be left open.
    592     * <p>
    593     * For example, a HDF5 datatype created from<br>
    594     *
    595     * <pre>
    596     * H5Dataype dtype = new H5Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE);
    597     * int tid = dtype.createNative();
    598     * </pre>
    599     *
    600     * The "tid" will be the HDF5 datatype id of a 64-bit unsigned integer, which is equivalent to
    601     *
    602     * <pre>
    603     * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32);
    604     * </pre>
    605     *
    606     * @return the identifier of the native datatype.
    607     */
    608    public abstract long createNative();
    609
    610    /**
    611     * Set datatype characteristics (class, size, byte order and sign) from a given datatype identifier.
    612     * <p>
    613     * Sub-classes must implement it so that this datatype will be converted accordingly.
    614     * <p>
    615     * For example, if the type identifier is a 64-bit unsigned integer created from HDF5,
    616     *
    617     * <pre>
    618     * H5Datatype dtype = new H5Datatype();
    619     * dtype.fromNative(HDF5Constants.H5T_NATIVE_UNINT32);
    620     * </pre>
    621     *
    622     * Where dtype is equivalent to <br>
    623     * new H5Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE);
    624     *
    625     * @param nativeID
    626     *            the datatype identifier.
    627     */
    628    public abstract void fromNative(long nativeID);
    629
    630    /**
    631     * Returns a short text description of this datatype.
    632     *
    633     * @return a short text description of this datatype
    634     */
    635    public String getDescription() {
    636        log.trace("getDescription(): start");
    637
    638        if (datatypeDescription != null) {
    639            log.trace("getDescription(): finish");
    640            return datatypeDescription;
    641        }
    642
    643        String description = null;
    644
    645        switch (datatypeClass) {
    646            case CLASS_CHAR:
    647                description = "8-bit " + (isUnsigned() ? "unsigned " : "") + "integer";
    648                break;
    649            case CLASS_INTEGER:
    650                description = String.valueOf(datatypeSize * 8) + "-bit " + (isUnsigned() ? "unsigned " : "") + "integer";
    651                break;
    652            case CLASS_FLOAT:
    653                description = String.valueOf(datatypeSize * 8) + "-bit floating-point";
    654                break;
    655            case CLASS_STRING:
    656                description = "String";
    657                break;
    658            case CLASS_REFERENCE:
    659                description = "Object reference";
    660                break;
    661            case CLASS_BITFIELD:
    662                description = String.valueOf(datatypeSize * 8) + "-bit bitfield";
    663                break;
    664            case CLASS_ENUM:
    665                description = String.valueOf(datatypeSize * 8) + "-bit enum";
    666                break;
    667            case CLASS_ARRAY:
    668                description = "Array";
    669                break;
    670            case CLASS_COMPOUND:
    671                description = "Compound";
    672                break;
    673            case CLASS_VLEN:
    674                description = "Variable-length";
    675                break;
    676            default:
    677                description = "Unknown";
    678                break;
    679        }
    680
    681        if (baseType != null) {
    682            description += " of " + baseType.getDescription();
    683        }
    684
    685        log.trace("getDescription(): finish");
    686        return description;
    687    }
    688
    689    /**
    690     * Checks if this datatype is unsigned.
    691     *
    692     * @return true if the datatype is unsigned;
    693     *         otherwise, returns false.
    694     */
    695    public boolean isUnsigned() {
    696        if (baseType != null)
    697            return baseType.isUnsigned();
    698        else {
    699            if (isCompound()) {
    700                if ((compoundMemberTypes != null) && (compoundMemberTypes.size() > 0)) {
    701                    boolean all_members_unsigned = true;
    702
    703                    Iterator<Datatype> cmpd_type_list_it = compoundMemberTypes.iterator();
    704                    while (cmpd_type_list_it.hasNext()) {
    705                        Datatype next = cmpd_type_list_it.next();
    706
    707                        all_members_unsigned = all_members_unsigned && next.isUnsigned();
    708                    }
    709
    710                    return all_members_unsigned;
    711                }
    712                else {
    713                    log.debug("isUnsigned(): compoundMemberTypes is null");
    714                    return false;
    715                }
    716            }
    717            else {
    718                return (datatypeSign == Datatype.SIGN_NONE);
    719            }
    720        }
    721    }
    722
    723    public abstract boolean isText();
    724
    725    /**
    726     * Checks if this datatype is an integer type.
    727     *
    728     * @return true if the datatype is integer; false otherwise
    729     */
    730    public boolean isInteger() {
    731        return (datatypeClass == Datatype.CLASS_INTEGER);
    732    }
    733
    734    /**
    735     * Checks if this datatype is a floating-point type.
    736     *
    737     * @return true if the datatype is floating-point; false otherwise
    738     */
    739    public boolean isFloat() {
    740        return (datatypeClass == Datatype.CLASS_FLOAT);
    741    }
    742
    743    /**
    744     * Checks if this datatype is a variable-length string type.
    745     *
    746     * @return true if the datatype is variable-length string; false otherwise
    747     */
    748    public boolean isVarStr() {
    749        return is_variable_str;
    750    }
    751
    752    /**
    753     * Checks if this datatype is a variable-length type.
    754     *
    755     * @return true if the datatype is variable-length; false otherwise
    756     */
    757    public boolean isVLEN() {
    758        return is_VLEN;
    759    }
    760
    761    /**
    762     * Checks if this datatype is an compound type.
    763     *
    764     * @return true if the datatype is compound; false otherwise
    765     */
    766    public boolean isCompound() {
    767        return (datatypeClass == Datatype.CLASS_COMPOUND);
    768    }
    769
    770    /**
    771     * Checks if this datatype is an array type.
    772     *
    773     * @return true if the datatype is array; false otherwise
    774     */
    775    public boolean isArray() {
    776        return (datatypeClass == Datatype.CLASS_ARRAY);
    777    }
    778
    779    /**
    780     * Checks if this datatype is a string type.
    781     *
    782     * @return true if the datatype is string; false otherwise
    783     */
    784    public boolean isString() {
    785        return (datatypeClass == Datatype.CLASS_STRING);
    786    }
    787
    788    /**
    789     * Checks if this datatype is a character type.
    790     *
    791     * @return true if the datatype is character; false otherwise
    792     */
    793    public boolean isChar() {
    794        return (datatypeClass == Datatype.CLASS_CHAR);
    795    }
    796
    797    /**
    798     * Checks if this datatype is a reference type.
    799     *
    800     * @return true if the datatype is reference; false otherwise
    801     */
    802    public boolean isRef() {
    803        return (datatypeClass == Datatype.CLASS_REFERENCE);
    804    }
    805
    806    /**
    807     * Checks if this datatype is a enum type.
    808     *
    809     * @return true if the datatype is enum; false otherwise
    810     */
    811    public boolean isEnum() {
    812        return (datatypeClass == Datatype.CLASS_ENUM);
    813    }
    814
    815    /**
    816     * Checks if this datatype is a opaque type.
    817     *
    818     * @return true if the datatype is opaque; false otherwise
    819     */
    820    public boolean isOpaque() {
    821        return (datatypeClass == Datatype.CLASS_OPAQUE);
    822    }
    823
    824    /**
    825     * Checks if this datatype is a bitfield type.
    826     *
    827     * @return true if the datatype is bitfield; false otherwise
    828     */
    829    public boolean isBitField() {
    830        return (datatypeClass == Datatype.CLASS_BITFIELD);
    831    }
    832
    833    /*
    834     * (non-Javadoc)
    835     *
    836     * @see hdf.object.DataFormat#getMetadata()
    837     */
    838    @Override
    839    @SuppressWarnings("rawtypes")
    840    public List getMetadata() throws Exception {
    841        return null;
    842    }
    843
    844    /*
    845     * (non-Javadoc)
    846     *
    847     * @see hdf.object.DataFormat#writeMetadata(java.lang.Object)
    848     */
    849    @Override
    850    public void writeMetadata(Object info) throws Exception {
    851        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement Datatype:writeMetadata.");
    852    }
    853
    854    /*
    855     * (non-Javadoc)
    856     *
    857     * @see hdf.object.DataFormat#removeMetadata(java.lang.Object)
    858     */
    859    @Override
    860    public void removeMetadata(Object info) throws Exception {
    861        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement Datatype:removeMetadata.");
    862    }
    863
    864    /*
    865     * (non-Javadoc)
    866     *
    867     * @see hdf.object.DataFormat#updateMetadata(java.lang.Object)
    868     */
    869    @Override
    870    public void updateMetadata(Object info) throws Exception {
    871        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement Datatype:updateMetadata.");
    872    }
    873
    874    @Override
    875    public String toString() {
    876        return getDescription();
    877    }
    878}