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 http://hdfgroup.org/products/hdf-java/doc/Copyright.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.List;
018
019/**
020 * Datatype is an abstract class that defines datatype characteristics and APIs
021 * for a data type.
022 * <p>
023 * A datatype has four basic characteristics: class, size, byte order and sign.
024 * These charactertics are defeined in the
025 * <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>.
026 * <p>
027 * These charactertics apply to all the sub-classes. The sub-classes may have
028 * different ways to describe a datatype. We here define the <strong> native
029 * datatype</strong> to the datatype used by the sub-class. For example,
030 * H5Datatype uses a datatype identifier (hid_t) to specify a datatype.
031 * NC2Datatype uses ucar.nc2.DataType object to describe its datatype. "Native"
032 * here is different from the "native" definition in the HDF5 library.
033 * <p>
034 * Two functions, toNative() and fromNative(), are defined to convert the
035 * general charactertics to/form the native datatype. Sub-classes must implement
036 * these functions so that the conversion will be done correctly.
037 * The values of the CLASS member are not identical to HDF5 values for a datatype class
038 * <p>
039 *
040 * @version 1.1 9/4/2007
041 * @author Peter X. Cao
042 */
043public abstract class Datatype extends HObject {
044    /**
045     *
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="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
058     */
059    public static final int CLASS_NO_CLASS = -1;
060
061    /**
062     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
063     */
064    public static final int CLASS_INTEGER = 0;
065
066    /**
067     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
068     */
069    public static final int CLASS_FLOAT = 1;
070
071    /**
072     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
073     */
074    public static final int CLASS_CHAR = 2;
075
076    /**
077     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
078     */
079    public static final int CLASS_STRING = 3;
080
081    /**
082     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
083     */
084    public static final int CLASS_BITFIELD = 4;
085
086    /**
087     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
088     */
089    public static final int CLASS_OPAQUE = 5;
090
091    /**
092     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
093     */
094    public static final int CLASS_COMPOUND = 6;
095
096    /**
097     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
098     */
099    public static final int CLASS_REFERENCE = 7;
100
101    /**
102     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
103     */
104    public static final int CLASS_ENUM = 8;
105
106    /**
107     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
108     */
109    public static final int CLASS_VLEN = 9;
110
111    /**
112     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
113     */
114    public static final int CLASS_ARRAY = 10;
115
116    /**
117     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
118     */
119    public static final int CLASS_TIME = 11;
120
121    /**
122     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
123     */
124    public static final int ORDER_LE = 0;
125
126    /**
127     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
128     */
129    public static final int ORDER_BE = 1;
130
131    /**
132     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
133     */
134    public static final int ORDER_VAX = 2;
135
136    /**
137     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
138     */
139    public static final int ORDER_NONE = 3;
140
141    // sign
142    /**
143     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
144     */
145    public static final int SIGN_NONE = 0;
146
147    /**
148     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
149     */
150    public static final int SIGN_2 = 1;
151
152    /**
153     * See <a href="http://hdfgroup.org/HDF5/doc/UG/index.html">HDF5 User's Guide</a>
154     */
155    public static final int NSGN = 2;
156
157    /**
158     * The class of the datatype.
159     */
160    protected int datatypeClass;
161
162    /**
163     * The size (in bytes) of the datatype.
164     */
165    protected int datatypeSize;
166
167    /**
168     * The byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, and
169     * ORDER_VAX.
170     */
171    protected int datatypeOrder;
172
173    /**
174     * The sign of the datatype.
175     */
176    protected int datatypeSign;
177
178    /**
179     * The (name, value) pairs of enum members
180     */
181    protected String enumMembers;
182    
183    /**
184     * The list of names of members of a compound Datatype
185     */
186    protected List<String> compoundMemberNames;
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 dimension of the ARRAY element. For ARRAY datatype only
206     */
207    protected long[] dims;
208
209
210    /**
211     * Constructs a named datatype with a given file, name and path.
212     *
213     * @param theFile
214     *            the HDF file.
215     * @param name
216     *            the name of the datatype, e.g "12-bit Integer".
217     * @param path
218     *            the full group path of the datatype, e.g. "/datatypes/".
219     */
220    public Datatype(FileFormat theFile, String name, String path) {
221        this(theFile, name, path, null);
222    }
223
224    /**
225     * @deprecated Not for public use in the future.<br>
226     *             Using {@link #Datatype(FileFormat, String, String)}
227     *
228     * @param theFile
229     *            the HDF file.
230     * @param name
231     *            the name of the datatype, e.g "12-bit Integer".
232     * @param path
233     *            the full group path of the datatype, e.g. "/datatypes/".
234     * @param oid
235     *            the oidof the datatype.
236     */
237    @Deprecated
238    public Datatype(FileFormat theFile, String name, String path, long[] oid) {
239        super(theFile, name, path, oid);
240    }
241
242    /**
243     * Constructs a Datatype with specified class, size, byte order and sign.
244     * <p>
245     * The following is a list of a few example of H5Datatype.
246     * <ol>
247     * <li>to create unsigned native integer<br>
248     * H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE,
249     * SIGN_NONE);
250     * <li>to create 16-bit signed integer with big endian<br>
251     * H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE);
252     * <li>to create native float<br>
253     * H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1);
254     * <li>to create 64-bit double<br>
255     * H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1);
256     * </ol>
257     *
258     * @param tclass
259     *            the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and
260     *            etc.
261     * @param tsize
262     *            the size of the datatype in bytes, e.g. for a 32-bit integer,
263     *            the size is 4.
264     * @param torder
265     *            the byte order of the datatype. Valid values are ORDER_LE,
266     *            ORDER_BE, ORDER_VAX and ORDER_NONE
267     * @param tsign
268     *            the sign of the datatype. Valid values are SIGN_NONE, SIGN_2
269     *            and MSGN
270     */
271    public Datatype(int tclass, int tsize, int torder, int tsign) {
272        this(tclass, tsize, torder, tsign, null);
273    }
274
275    /**
276     * Constructs a Datatype with specified class, size, byte order and sign.
277     * <p>
278     * The following is a list of a few example of H5Datatype.
279     * <ol>
280     * <li>to create unsigned native integer<br>
281     * H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE,
282     * SIGN_NONE);
283     * <li>to create 16-bit signed integer with big endian<br>
284     * H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE);
285     * <li>to create native float<br>
286     * H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1);
287     * <li>to create 64-bit double<br>
288     * H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1);
289     * </ol>
290     *
291     * @param tclass
292     *            the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and
293     *            etc.
294     * @param tsize
295     *            the size of the datatype in bytes, e.g. for a 32-bit integer,
296     *            the size is 4.
297     * @param torder
298     *            the byte order of the datatype. Valid values are ORDER_LE,
299     *            ORDER_BE, ORDER_VAX and ORDER_NONE
300     * @param tsign
301     *            the sign of the datatype. Valid values are SIGN_NONE, SIGN_2
302     *            and MSGN
303     * @param tbase
304     *            the base datatype of the new datatype
305     */
306    public Datatype(int tclass, int tsize, int torder, int tsign, Datatype tbase) {
307        datatypeClass = tclass;
308        datatypeSize = tsize;
309        datatypeOrder = torder;
310        datatypeSign = tsign;
311        enumMembers = null;
312        baseType = tbase;
313        dims = null;
314        log.trace("datatypeClass={} datatypeSize={} datatypeOrder={} datatypeSign={} baseType={}", datatypeClass, datatypeSize, datatypeOrder, datatypeSign, baseType);
315    }
316
317    /**
318     * Constructs a Datatype with a given native datatype identifier.
319     * <p>
320     * For example, if the datatype identifier is a 32-bit unsigned integer
321     * created from HDF5,
322     *
323     * <pre>
324     * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32);
325     * Datatype dtype = new Datatype(tid);
326     * </pre>
327     *
328     * will construct a datatype equivalent to new Datatype(CLASS_INTEGER, 4,
329     * NATIVE, SIGN_NONE);
330     *
331     * @see #fromNative(int tid)
332     * @param tid
333     *            the native datatype identifier.
334     */
335    public Datatype(int tid) {
336        this(CLASS_NO_CLASS, NATIVE, NATIVE, NATIVE);
337    }
338
339    /**
340     * Returns the class of the datatype. Valid values are:
341     * <ul>
342     * <li>CLASS_NO_CLASS
343     * <li>CLASS_INTEGER
344     * <li>CLASS_FLOAT
345     * <li>CLASS_CHAR
346     * <li>CLASS_STRING
347     * <li>CLASS_BITFIELD
348     * <li>CLASS_OPAQUE
349     * <li>CLASS_COMPOUND
350     * <li>CLASS_REFERENCE
351     * <li>CLASS_ENUM
352     * <li>CLASS_VLEN
353     * <li>CLASS_ARRAY
354     * </ul>
355     *
356     * @return the class of the datatype.
357     */
358    public int getDatatypeClass() {
359        return datatypeClass;
360    }
361
362    /**
363     * Returns the size of the datatype in bytes. For example, for a 32-bit
364     * integer, the size is 4 (bytes).
365     *
366     * @return the size of the datatype.
367     */
368    public int getDatatypeSize() {
369        return datatypeSize;
370    }
371
372    /**
373     * Returns the byte order of the datatype. Valid values are
374     * <ul>
375     * <li>ORDER_LE
376     * <li>ORDER_BE
377     * <li>ORDER_VAX
378     * <li>ORDER_NONE
379     * </ul>
380     *
381     * @return the byte order of the datatype.
382     */
383    public int getDatatypeOrder() {
384        return datatypeOrder;
385    }
386
387    /**
388     * Returns the sign (SIGN_NONE, SIGN_2 or NSGN) of an integer datatype.
389     *
390     * @return the sign of the datatype.
391     */
392    public int getDatatypeSign() {
393        return datatypeSign;
394    }
395
396    /**
397     * Returns the datatype of array element for ARRAY datatype.
398     * <p>
399     * For example, a dataset set of ARRAY of integer, The datatype of the
400     * dataset is ARRAY. The datatype of the base type is integer.
401     *
402     * @return the the datatype of array element for ARRAY datatype.
403     */
404    public Datatype getBasetype() {
405        return baseType;
406    }
407
408    /**
409     * Sets the (name, value) pairs of enum members for enum datatype.
410     * <p>
411     * For Example,
412     * <dl>
413     * <dt>setEnumMembers("lowTemp=-40, highTemp=90")</dt>
414     * <dd>sets the value of enum member lowTemp to -40 and highTemp to 90.</dd>
415     * <dt>setEnumMembers("lowTemp, highTemp")</dt>
416     * <dd>sets enum members to defaults, i.e. lowTemp=0 and highTemp=1</dd>
417     * <dt>setEnumMembers("lowTemp=10, highTemp")</dt>
418     * <dd>sets enum member lowTemp to 10 and highTemp to 11.</dd>
419     * </dl>
420     *
421     * @param enumStr
422     *            the (name, value) pairs of enum members
423     */
424    public final void setEnumMembers(String enumStr) {
425        enumMembers = enumStr;
426    }
427
428    /**
429     * Returns the "name=value" pairs of enum members for enum datatype.
430     * <p>
431     * For Example,
432     * <dl>
433     * <dt>setEnumMembers("lowTemp=-40, highTemp=90")</dt>
434     * <dd>sets the value of enum member lowTemp to -40 and highTemp to 90.</dd>
435     * <dt>setEnumMembers("lowTemp, highTemp")</dt>
436     * <dd>sets enum members to defaults, i.e. lowTemp=0 and highTemp=1</dd>
437     * <dt>setEnumMembers("lowTemp=10, highTemp")</dt>
438     * <dd>sets enum member lowTemp to 10 and highTemp to 11.</dd>
439     * </dl>
440     *
441     * @return enumStr the (name, value) pairs of enum members
442     */
443    public final String getEnumMembers() {
444        return enumMembers;
445    }
446    
447    /**
448     * Returns the dimensions of an Array Datatype.
449     * 
450     * @return dims the dimensions of the Array Datatype
451     */
452    public final long[] getArrayDims() {
453        return dims;
454    }
455
456    /**
457     * Converts the datatype object to a native datatype.
458     *
459     * Subclasses must implement it so that this datatype will be converted
460     * accordingly. Use close() to close the native identifier; otherwise, the
461     * datatype will be left open.
462     * <p>
463     * For example, a HDF5 datatype created from<br>
464     *
465     * <pre>
466     * H5Dataype dtype = new H5Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE);
467     * int tid = dtype.toNative();
468     * </pre>
469     *
470     * There "tid" will be the HDF5 datatype id of a 32-bit unsigned integer,
471     * which is equivalent to
472     *
473     * <pre>
474     * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32);
475     * </pre>
476     *
477     * @return the identifier of the native datatype.
478     */
479    public abstract int toNative();
480
481    /**
482     * Set datatype characteristics (class, size, byte order and sign) from a
483     * given datatye identifier.
484     * <p>
485     * Sub-classes must implement it so that this datatype will be converted
486     * accordingly.
487     * <p>
488     * For example, if the type identifier is a 32-bit unsigned integer created
489     * from HDF5,
490     *
491     * <pre>
492     * H5Datatype dtype = new H5Datatype();
493     * dtype.fromNative(HDF5Constants.H5T_NATIVE_UNINT32);
494     * </pre>
495     *
496     * Where dtype is equivalent to <br>
497     * new H5Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE);
498     *
499     * @param nativeID
500     *            the datatype identifier.
501     */
502    public abstract void fromNative(int nativeID);
503
504    /**
505     * Returns a short text description of this datatype.
506     *
507     * @return a short text description of this datatype
508     */
509    public String getDatatypeDescription() {
510        String description = "Unknown";
511
512        switch (datatypeClass) {
513        case CLASS_INTEGER:
514            if (datatypeSign == SIGN_NONE) {
515                description = String.valueOf(datatypeSize * 8)
516                        + "-bit unsigned integer";
517            }
518            else {
519                description = String.valueOf(datatypeSize * 8) + "-bit integer";
520            }
521            break;
522        case CLASS_FLOAT:
523            description = String.valueOf(datatypeSize * 8)
524                    + "-bit floating-point";
525            break;
526        case CLASS_STRING:
527            description = "String";
528            break;
529        case CLASS_REFERENCE:
530            description = "Object reference";
531            break;
532        case CLASS_BITFIELD:
533            description = "Bitfield";
534            break;
535        case CLASS_ENUM:
536            description = String.valueOf(datatypeSize * 8) + "-bit enum";
537            break;
538        case CLASS_ARRAY:
539            description = "Array";
540            break;
541        case CLASS_COMPOUND:
542            description = "Compound ";
543            break;
544        case CLASS_VLEN:
545            description = "Variable-length";
546            break;
547        default:
548            description = "Unknown";
549            break;
550        }
551
552        log.trace("description={}", description);
553        return description;
554    }
555
556    /**
557     * Checks if this datatype is an unsigned integer.
558     *
559     * @return true if the datatype is an unsigned integer; otherwise, returns
560     *         false.
561     */
562    public abstract boolean isUnsigned();
563
564    /**
565     * Opens access to this named datatype. Sub-clases must replace this default
566     * implementation. For example, in H5Datatype, open() function
567     * H5.H5Topen(loc_id, name) to get the datatype identifier.
568     *
569     * @return the datatype identifier if successful; otherwise returns negative
570     *         value.
571     */
572    @Override
573    public int open() {
574        return -1;
575    }
576
577    /**
578     * Closes a datatype identifier.
579     * <p>
580     * Sub-clases must replace this default implementation.
581     *
582     * @param id
583     *            the datatype identifier to close.
584     */
585    @Override
586    public abstract void close(int id);
587
588    /*
589     * (non-Javadoc)
590     *
591     * @see hdf.object.DataFormat#getMetadata()
592     */
593    public List getMetadata() throws Exception {
594        return null;
595    }
596
597    /*
598     * (non-Javadoc)
599     *
600     * @see hdf.object.DataFormat#writeMetadata(java.lang.Object)
601     */
602    public void writeMetadata(Object info) throws Exception {
603        ;
604    }
605
606    /*
607     * (non-Javadoc)
608     *
609     * @see hdf.object.DataFormat#removeMetadata(java.lang.Object)
610     */
611    public void removeMetadata(Object info) throws Exception {
612        ;
613    }
614
615    /*
616     * (non-Javadoc)
617     *
618     * @see hdf.object.DataFormat#updateMetadata(java.lang.Object)
619     */
620    public void updateMetadata(Object info) throws Exception {
621        ;
622    }
623}