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