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