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