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 * If the datatype is a reference, then return the type. 707 * 708 * @return the datatype reference type if successful; otherwise returns negative value. 709 */ 710 public long getReferenceType() { 711 return -1; 712 } 713 714 /** 715 * Returns a short text description of this datatype. 716 * 717 * @return a short text description of this datatype 718 */ 719 public String getDescription() { 720 721 if (datatypeDescription != null) { 722 return datatypeDescription; 723 } 724 725 StringBuilder description = new StringBuilder(); 726 727 switch (datatypeClass) { 728 case CLASS_CHAR: 729 description.append("8-bit ").append((isUnsigned() ? "unsigned " : "")).append("integer"); 730 break; 731 case CLASS_INTEGER: 732 if (datatypeSize == NATIVE) 733 description.append("native ").append((isUnsigned() ? "unsigned " : "")).append("integer"); 734 else 735 description.append(String.valueOf(datatypeSize * 8)).append("-bit ") 736 .append((isUnsigned() ? "unsigned " : "")).append("integer"); 737 break; 738 case CLASS_FLOAT: 739 if (datatypeSize == NATIVE) 740 description.append("native floating-point"); 741 else 742 description.append(String.valueOf(datatypeSize * 8)).append("-bit floating-point"); 743 break; 744 case CLASS_STRING: 745 description.append("String"); 746 break; 747 case CLASS_REFERENCE: 748 description.append("Object reference"); 749 break; 750 case CLASS_OPAQUE: 751 if (datatypeSize == NATIVE) 752 description.append("native opaque"); 753 else 754 description.append(String.valueOf(datatypeSize * 8)).append("-bit opaque"); 755 break; 756 case CLASS_BITFIELD: 757 if (datatypeSize == NATIVE) 758 description.append("native bitfield"); 759 else 760 description.append(String.valueOf(datatypeSize * 8)).append("-bit bitfield"); 761 break; 762 case CLASS_ENUM: 763 if (datatypeSize == NATIVE) 764 description.append("native enum"); 765 else 766 description.append(String.valueOf(datatypeSize * 8)).append("-bit enum"); 767 break; 768 case CLASS_ARRAY: 769 description.append("Array"); 770 771 if (arrayDims != null) { 772 description.append(" ["); 773 for (int i = 0; i < arrayDims.length; i++) { 774 description.append(arrayDims[i]); 775 if (i < arrayDims.length - 1) 776 description.append(" x "); 777 } 778 description.append("]"); 779 } 780 781 break; 782 case CLASS_COMPOUND: 783 description.append("Compound"); 784 break; 785 case CLASS_VLEN: 786 description.append("Variable-length"); 787 break; 788 default: 789 description.append("Unknown"); 790 break; 791 } 792 793 if (baseType != null) { 794 description.append(" of " + baseType.getDescription()); 795 } 796 797 return description.toString(); 798 } 799 800 /** 801 * Checks if this datatype is unsigned. 802 * 803 * @return true if the datatype is unsigned; 804 * otherwise, returns false. 805 */ 806 public boolean isUnsigned() { 807 if (baseType != null) 808 return baseType.isUnsigned(); 809 else { 810 if (isCompound()) { 811 if ((compoundMemberTypes != null) && !compoundMemberTypes.isEmpty()) { 812 boolean allMembersUnsigned = true; 813 814 Iterator<Datatype> cmpdTypeListIT = compoundMemberTypes.iterator(); 815 while (cmpdTypeListIT.hasNext()) { 816 Datatype next = cmpdTypeListIT.next(); 817 818 allMembersUnsigned = allMembersUnsigned && next.isUnsigned(); 819 } 820 821 return allMembersUnsigned; 822 } 823 else { 824 log.debug("isUnsigned(): compoundMemberTypes is null"); 825 return false; 826 } 827 } 828 else { 829 return (datatypeSign == Datatype.SIGN_NONE); 830 } 831 } 832 } 833 834 public abstract boolean isText(); 835 836 /** 837 * Checks if this datatype is an integer type. 838 * 839 * @return true if the datatype is integer; false otherwise 840 */ 841 public boolean isInteger() { 842 return (datatypeClass == Datatype.CLASS_INTEGER); 843 } 844 845 /** 846 * Checks if this datatype is a floating-point type. 847 * 848 * @return true if the datatype is floating-point; false otherwise 849 */ 850 public boolean isFloat() { 851 return (datatypeClass == Datatype.CLASS_FLOAT); 852 } 853 854 /** 855 * Checks if this datatype is a named type. 856 * 857 * @return true if the datatype is named; false otherwise 858 */ 859 public boolean isNamed() { 860 return isNamed; 861 } 862 863 /** 864 * Checks if this datatype is a variable-length string type. 865 * 866 * @return true if the datatype is variable-length string; false otherwise 867 */ 868 public boolean isVarStr() { 869 return isVariableStr; 870 } 871 872 /** 873 * Checks if this datatype is a variable-length type. 874 * 875 * @return true if the datatype is variable-length; false otherwise 876 */ 877 public boolean isVLEN() { 878 return isVLEN; 879 } 880 881 /** 882 * Checks if this datatype is an compound type. 883 * 884 * @return true if the datatype is compound; false otherwise 885 */ 886 public boolean isCompound() { 887 return (datatypeClass == Datatype.CLASS_COMPOUND); 888 } 889 890 /** 891 * Checks if this datatype is an array type. 892 * 893 * @return true if the datatype is array; false otherwise 894 */ 895 public boolean isArray() { 896 return (datatypeClass == Datatype.CLASS_ARRAY); 897 } 898 899 /** 900 * Checks if this datatype is a string type. 901 * 902 * @return true if the datatype is string; false otherwise 903 */ 904 public boolean isString() { 905 return (datatypeClass == Datatype.CLASS_STRING); 906 } 907 908 /** 909 * Checks if this datatype is a character type. 910 * 911 * @return true if the datatype is character; false otherwise 912 */ 913 public boolean isChar() { 914 return (datatypeClass == Datatype.CLASS_CHAR); 915 } 916 917 /** 918 * Checks if this datatype is a reference type. 919 * 920 * @return true if the datatype is reference; false otherwise 921 */ 922 public boolean isRef() { 923 return (datatypeClass == Datatype.CLASS_REFERENCE); 924 } 925 926 /** 927 * Checks if this datatype is a enum type. 928 * 929 * @return true if the datatype is enum; false otherwise 930 */ 931 public boolean isEnum() { 932 return (datatypeClass == Datatype.CLASS_ENUM); 933 } 934 935 /** 936 * Checks if this datatype is a opaque type. 937 * 938 * @return true if the datatype is opaque; false otherwise 939 */ 940 public boolean isOpaque() { 941 return (datatypeClass == Datatype.CLASS_OPAQUE); 942 } 943 944 /** 945 * Checks if this datatype is a bitfield type. 946 * 947 * @return true if the datatype is bitfield; false otherwise 948 */ 949 public boolean isBitField() { 950 return (datatypeClass == Datatype.CLASS_BITFIELD); 951 } 952 953 /* 954 * (non-Javadoc) 955 * 956 * @see hdf.object.DataFormat#getMetadata() 957 */ 958 @Override 959 @SuppressWarnings("rawtypes") 960 public List getMetadata() throws Exception { 961 return null; 962 } 963 964 /* 965 * (non-Javadoc) 966 * 967 * @see hdf.object.DataFormat#writeMetadata(java.lang.Object) 968 */ 969 @Override 970 public void writeMetadata(Object info) throws Exception { 971 throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement Datatype:writeMetadata."); 972 } 973 974 /* 975 * (non-Javadoc) 976 * 977 * @see hdf.object.DataFormat#removeMetadata(java.lang.Object) 978 */ 979 @Override 980 public void removeMetadata(Object info) throws Exception { 981 throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement Datatype:removeMetadata."); 982 } 983 984 /* 985 * (non-Javadoc) 986 * 987 * @see hdf.object.DataFormat#updateMetadata(java.lang.Object) 988 */ 989 @Override 990 public void updateMetadata(Object info) throws Exception { 991 throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement Datatype:updateMetadata."); 992 } 993 994 @Override 995 public String toString() { 996 return getDescription(); 997 } 998}