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 file COPYING.                     *
009 * COPYING can be found at the root of the source code distribution tree.    *
010 * If you do not have access to this file, you may request a copy from       *
011 * help@hdfgroup.org.                                                        *
012 ****************************************************************************/
013
014package hdf.object;
015
016import java.util.List;
017
018/**
019 * Datatype is an abstract class that defines datatype characteristics and APIs
020 * for a data type.
021 * <p>
022 * A datatype has four basic characteristics: class, size, byte order and sign.
023 * These characteristics are defined in the
024 * <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>.
025 * <p>
026 * These characteristics apply to all the sub-classes. The sub-classes may have
027 * different ways to describe a datatype. We here define the <strong> native
028 * datatype</strong> to the datatype used by the sub-class. For example,
029 * H5Datatype uses a datatype identifier (hid_t) to specify a datatype.
030 * NC2Datatype uses ucar.nc2.DataType object to describe its datatype. "Native"
031 * here is different from the "native" definition in the HDF5 library.
032 * <p>
033 * Two functions, toNative() and fromNative(), are defined to convert the
034 * general characteristics to/from the native datatype. Sub-classes must implement
035 * these functions so that the conversion will be done correctly.
036 * The values of the CLASS member are not identical to HDF5 values for a datatype class.
037 * <p>
038 *
039 * @version 1.1 9/4/2007
040 * @author Peter X. Cao
041 */
042public abstract class Datatype extends HObject {
043    private static final long serialVersionUID = -581324710549963177L;
044
045    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Datatype.class);
046
047    /**
048     * The default definition for datatype size, order, and sign.
049     */
050    public static final int NATIVE = -1;
051
052    /**
053     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
054     */
055    public static final int CLASS_NO_CLASS = -1;
056
057    /**
058     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
059     */
060    public static final int CLASS_INTEGER = 0;
061
062    /**
063     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
064     */
065    public static final int CLASS_FLOAT = 1;
066
067    /**
068     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
069     */
070    public static final int CLASS_CHAR = 2;
071
072    /**
073     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
074     */
075    public static final int CLASS_STRING = 3;
076
077    /**
078     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
079     */
080    public static final int CLASS_BITFIELD = 4;
081
082    /**
083     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
084     */
085    public static final int CLASS_OPAQUE = 5;
086
087    /**
088     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
089     */
090    public static final int CLASS_COMPOUND = 6;
091
092    /**
093     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
094     */
095    public static final int CLASS_REFERENCE = 7;
096
097    /**
098     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
099     */
100    public static final int CLASS_ENUM = 8;
101
102    /**
103     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
104     */
105    public static final int CLASS_VLEN = 9;
106
107    /**
108     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
109     */
110    public static final int CLASS_ARRAY = 10;
111
112    /**
113     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
114     */
115    public static final int CLASS_TIME = 11;
116
117    /**
118     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
119     */
120    public static final int ORDER_LE = 0;
121
122    /**
123     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
124     */
125    public static final int ORDER_BE = 1;
126
127    /**
128     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
129     */
130    public static final int ORDER_VAX = 2;
131
132    /**
133     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
134     */
135    public static final int ORDER_NONE = 3;
136
137    /**
138     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
139     */
140    public static final int SIGN_NONE = 0;
141
142    /**
143     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
144     */
145    public static final int SIGN_2 = 1;
146
147    /**
148     * See <a href="https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a>
149     */
150    public static final int NSGN = 2;
151
152    /**
153     * The class of the datatype.
154     */
155    protected int datatypeClass;
156
157    /**
158     * The size (in bytes) of the datatype.
159     */
160    protected int datatypeSize;
161
162    /**
163     * The byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, and
164     * ORDER_VAX.
165     */
166    protected int datatypeOrder;
167
168    /**
169     * The sign of the datatype.
170     */
171    protected int datatypeSign;
172
173    /**
174     * The (name, value) pairs of enum members.
175     */
176    protected String enumMembers;
177
178    /**
179     * The list of names of members of a compound Datatype.
180     */
181    protected List<String> compoundMemberNames;
182
183    /**
184     * The list of types of members of a compound Datatype
185     */
186    protected List<Datatype> compoundMemberTypes;
187
188    /**
189     * The list of offsets of members of a compound Datatype.
190     */
191    protected List<Long> compoundMemberOffsets;
192
193    /**
194     * The list of field IDs of members of a compound Datatype.
195     */
196    protected List<Integer> compoundMemberFieldIDs;
197
198    /**
199     * The base datatype of every element of the array (for CLASS_ARRAY
200     * datatype).
201     */
202    protected Datatype baseType;
203
204    /**
205     * The dimensions of the ARRAY element of an ARRAY datatype.
206     */
207    protected long[] dims;
208
209    /**
210     * Determines whether this datatype is a variable-length type.
211     */
212    protected boolean isVLEN = false;
213
214
215    /**
216     * Constructs a named datatype with a given file, name and path.
217     *
218     * @param theFile
219     *            the HDF file.
220     * @param name
221     *            the name of the datatype, e.g "12-bit Integer".
222     * @param path
223     *            the full group path of the datatype, e.g. "/datatypes/".
224     */
225    public Datatype(FileFormat theFile, String name, String path) {
226        this(theFile, name, path, 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 name
236     *            the name of the datatype, e.g "12-bit Integer".
237     * @param path
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 name, String path, long[] oid) {
244        super(theFile, name, path, 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        datatypeClass = tclass;
313        datatypeSize = tsize;
314        datatypeOrder = torder;
315        datatypeSign = tsign;
316        enumMembers = null;
317        baseType = tbase;
318        dims = null;
319        log.trace("datatypeClass={} datatypeSize={} datatypeOrder={} datatypeSign={} baseType={}", datatypeClass, datatypeSize, datatypeOrder, datatypeSign, baseType);
320    }
321
322    /**
323     * Constructs a Datatype with a given native datatype identifier.
324     * <p>
325     * For example, if the datatype identifier is a 32-bit unsigned integer
326     * created from HDF5,
327     *
328     * <pre>
329     * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32);
330     * Datatype dtype = new Datatype(tid);
331     * </pre>
332     *
333     * will construct a datatype equivalent to new Datatype(CLASS_INTEGER, 4,
334     * NATIVE, SIGN_NONE);
335     *
336     * @see #fromNative(int tid)
337     * @param tid
338     *            the native datatype identifier.
339     */
340    public Datatype(int tid) {
341        this(CLASS_NO_CLASS, NATIVE, NATIVE, NATIVE);
342    }
343
344    /**
345     * Returns the class of the datatype. Valid values are:
346     * <ul>
347     * <li>CLASS_NO_CLASS
348     * <li>CLASS_INTEGER
349     * <li>CLASS_FLOAT
350     * <li>CLASS_CHAR
351     * <li>CLASS_STRING
352     * <li>CLASS_BITFIELD
353     * <li>CLASS_OPAQUE
354     * <li>CLASS_COMPOUND
355     * <li>CLASS_REFERENCE
356     * <li>CLASS_ENUM
357     * <li>CLASS_VLEN
358     * <li>CLASS_ARRAY
359     * </ul>
360     *
361     * @return the class of the datatype.
362     */
363    public int getDatatypeClass() {
364        return datatypeClass;
365    }
366
367    /**
368     * Returns the size of the datatype in bytes. For example, for a 32-bit
369     * integer, the size is 4 (bytes).
370     *
371     * @return the size of the datatype.
372     */
373    public int getDatatypeSize() {
374        return datatypeSize;
375    }
376
377    /**
378     * Returns the byte order of the datatype. Valid values are
379     * <ul>
380     * <li>ORDER_LE
381     * <li>ORDER_BE
382     * <li>ORDER_VAX
383     * <li>ORDER_NONE
384     * </ul>
385     *
386     * @return the byte order of the datatype.
387     */
388    public int getDatatypeOrder() {
389        return datatypeOrder;
390    }
391
392    /**
393     * Returns the sign (SIGN_NONE, SIGN_2 or NSGN) of an integer datatype.
394     *
395     * @return the sign of the datatype.
396     */
397    public int getDatatypeSign() {
398        return datatypeSign;
399    }
400
401    /**
402     * Returns the datatype of array elements for an ARRAY datatype.
403     * <p>
404     * For example, in a dataset of type ARRAY of integer, the datatype of the
405     * dataset is ARRAY. The datatype of the base type is integer.
406     *
407     * @return the datatype of array elements for an ARRAY datatype.
408     */
409    public Datatype getBasetype() {
410        return baseType;
411    }
412
413    /**
414     * Sets the (name, value) pairs of enum members for enum datatype.
415     * <p>
416     * For Example,
417     * <dl>
418     * <dt>setEnumMembers("lowTemp=-40, highTemp=90")</dt>
419     * <dd>sets the value of enum member lowTemp to -40 and highTemp to 90.</dd>
420     * <dt>setEnumMembers("lowTemp, highTemp")</dt>
421     * <dd>sets enum members to defaults, i.e. lowTemp=0 and highTemp=1</dd>
422     * <dt>setEnumMembers("lowTemp=10, highTemp")</dt>
423     * <dd>sets enum member lowTemp to 10 and highTemp to 11.</dd>
424     * </dl>
425     *
426     * @param enumStr
427     *            the (name, value) pairs of enum members
428     */
429    public final void setEnumMembers(String enumStr) {
430        enumMembers = enumStr;
431    }
432
433    /**
434     * Returns the "name=value" pairs of enum members for enum datatype.
435     * <p>
436     * For Example,
437     * <dl>
438     * <dt>setEnumMembers("lowTemp=-40, highTemp=90")</dt>
439     * <dd>sets the value of enum member lowTemp to -40 and highTemp to 90.</dd>
440     * <dt>setEnumMembers("lowTemp, highTemp")</dt>
441     * <dd>sets enum members to defaults, i.e. lowTemp=0 and highTemp=1</dd>
442     * <dt>setEnumMembers("lowTemp=10, highTemp")</dt>
443     * <dd>sets enum member lowTemp to 10 and highTemp to 11.</dd>
444     * </dl>
445     *
446     * @return enumStr the (name, value) pairs of enum members
447     */
448    public final String getEnumMembers() {
449        return enumMembers;
450    }
451
452    /**
453     * Returns the dimensions of an Array Datatype.
454     *
455     * @return dims the dimensions of the Array Datatype
456     */
457    public final long[] getArrayDims() {
458        return dims;
459    }
460
461    public final List<String> getCompoundMemberNames() {
462        return compoundMemberNames;
463    }
464
465    public final List<Datatype> getCompoundMemberTypes() {
466        return compoundMemberTypes;
467    }
468
469    /**
470     * Converts the datatype object to a native datatype.
471     *
472     * Subclasses must implement it so that this datatype will be converted
473     * accordingly. Use close() to close the native identifier; otherwise, the
474     * datatype will be left open.
475     * <p>
476     * For example, a HDF5 datatype created from<br>
477     *
478     * <pre>
479     * H5Dataype dtype = new H5Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE);
480     * int tid = dtype.toNative();
481     * </pre>
482     *
483     * There "tid" will be the HDF5 datatype id of a 32-bit unsigned integer,
484     * which is equivalent to
485     *
486     * <pre>
487     * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32);
488     * </pre>
489     *
490     * @return the identifier of the native datatype.
491     */
492    public abstract int toNative();
493
494    /**
495     * Set datatype characteristics (class, size, byte order and sign) from a
496     * given datatype identifier.
497     * <p>
498     * Sub-classes must implement it so that this datatype will be converted
499     * accordingly.
500     * <p>
501     * For example, if the type identifier is a 32-bit unsigned integer created
502     * from HDF5,
503     *
504     * <pre>
505     * H5Datatype dtype = new H5Datatype();
506     * dtype.fromNative(HDF5Constants.H5T_NATIVE_UNINT32);
507     * </pre>
508     *
509     * Where dtype is equivalent to <br>
510     * new H5Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE);
511     *
512     * @param nativeID
513     *            the datatype identifier.
514     */
515    public abstract void fromNative(int nativeID);
516
517    /**
518     * Returns a short text description of this datatype.
519     *
520     * @return a short text description of this datatype
521     */
522    public String getDatatypeDescription() {
523        log.trace("getDatatypeDescription(): start");
524
525        String description = "Unknown";
526
527        switch (datatypeClass) {
528        case CLASS_INTEGER:
529            if (datatypeSign == SIGN_NONE) {
530                description = String.valueOf(datatypeSize * 8)
531                        + "-bit unsigned integer";
532            }
533            else {
534                description = String.valueOf(datatypeSize * 8) + "-bit integer";
535            }
536            break;
537        case CLASS_FLOAT:
538            description = String.valueOf(datatypeSize * 8)
539                    + "-bit floating-point";
540            break;
541        case CLASS_STRING:
542            description = "String";
543            break;
544        case CLASS_REFERENCE:
545            description = "Object reference";
546            break;
547        case CLASS_BITFIELD:
548            description = "Bitfield";
549            break;
550        case CLASS_ENUM:
551            description = String.valueOf(datatypeSize * 8) + "-bit enum";
552            break;
553        case CLASS_ARRAY:
554            description = "Array";
555            break;
556        case CLASS_COMPOUND:
557            description = "Compound ";
558            break;
559        case CLASS_VLEN:
560            description = "Variable-length";
561            break;
562        default:
563            description = "Unknown";
564            break;
565        }
566
567        log.trace("description={}", description);
568        log.trace("getDatatypeDescription(): finish");
569        return description;
570    }
571
572    /**
573     * Checks if this datatype is an unsigned integer.
574     *
575     * @return true if the datatype is an unsigned integer; otherwise, returns
576     *         false.
577     */
578    public abstract boolean isUnsigned();
579
580    /**
581     * Checks if this datatype is a variable-length type.
582     *
583     * @return true if the datatype is variable-length; false otherwise
584     */
585    public boolean isVLEN() {
586        return isVLEN;
587    }
588
589    /**
590     * Opens access to this named datatype. Sub-classes must replace this default
591     * implementation. For example, in H5Datatype, open() function
592     * H5.H5Topen(loc_id, name) to get the datatype identifier.
593     *
594     * @return the datatype identifier if successful; otherwise returns negative
595     *         value.
596     */
597    @Override
598    public int open() {
599        return -1;
600    }
601
602    /**
603     * Closes a datatype identifier.
604     * <p>
605     * Sub-classes must replace this default implementation.
606     *
607     * @param id
608     *            the datatype identifier to close.
609     */
610    @Override
611    public abstract void close(int id);
612
613    /*
614     * (non-Javadoc)
615     *
616     * @see hdf.object.DataFormat#getMetadata()
617     */
618    @SuppressWarnings("rawtypes")
619    public List getMetadata() throws Exception {
620        return null;
621    }
622
623    /*
624     * (non-Javadoc)
625     *
626     * @see hdf.object.DataFormat#writeMetadata(java.lang.Object)
627     */
628    public void writeMetadata(Object info) throws Exception {
629        log.trace("writeMetadata(): disabled");
630    }
631
632    /*
633     * (non-Javadoc)
634     *
635     * @see hdf.object.DataFormat#removeMetadata(java.lang.Object)
636     */
637    public void removeMetadata(Object info) throws Exception {
638        log.trace("removeMetadata(): disabled");
639    }
640
641    /*
642     * (non-Javadoc)
643     *
644     * @see hdf.object.DataFormat#updateMetadata(java.lang.Object)
645     */
646    public void updateMetadata(Object info) throws Exception {
647        log.trace("updateMetadata(): disabled");
648    }
649}