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