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