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