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 http://hdfgroup.org/products/hdf-java/doc/Copyright.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.h5; 016 017import java.lang.reflect.Array; 018import java.util.List; 019import java.util.StringTokenizer; 020 021import hdf.hdf5lib.H5; 022import hdf.hdf5lib.HDF5Constants; 023import hdf.hdf5lib.HDFNativeData; 024import hdf.hdf5lib.exceptions.HDF5Exception; 025import hdf.hdf5lib.structs.H5O_info_t; 026import hdf.object.Attribute; 027import hdf.object.Datatype; 028import hdf.object.FileFormat; 029 030/** 031 * This class defines HDF5 data type characteristics and APIs for a data type. 032 * <p> 033 * This class provides several methods to convert an HDF5 dataype identifier to a dataype object, and vice versa. A 034 * dataype object is described by four basic fields: datatype class, size, byte order, and sign, while an HDF5 dataype 035 * is presented by a datetype identifier. 036 * <p> 037 * 038 * @version 1.1 9/4/2007 039 * @author Peter X. Cao 040 */ 041public class H5Datatype extends Datatype { 042 /** 043 * 044 */ 045 private static final long serialVersionUID = -750546422258749792L; 046 047 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H5Datatype.class); 048 049 /** 050 * The list of attributes of this data object. 051 */ 052 private List<Attribute> attributeList; 053 054 /** Flag to indicate if this datatype is a named datatype */ 055 private boolean isNamed = false; 056 057 private int nAttributes = -1; 058 059 private H5O_info_t obj_info; 060 061 private boolean isVLEN = false; 062 063 private String description = null; 064 065 /** 066 * Constructs an named HDF5 data type object for a given file, dataset name and group path. 067 * <p> 068 * The datatype object represents an existing named datatype in file. For example, new H5Datatype(file, "dtype1", 069 * "/g0") constructs a datatype object that corresponds to the dataset,"dset1", at group "/g0". 070 * <p> 071 * 072 * @param theFile 073 * the file that contains the dataset. 074 * @param name 075 * the name of the dataset such as "dset1". 076 * @param path 077 * the group path to the dataset such as "/g0/". 078 */ 079 public H5Datatype(FileFormat theFile, String name, String path) { 080 this(theFile, name, path, null); 081 } 082 083 /** 084 * @deprecated Not for public use in the future. <br> 085 * Using {@link #H5Datatype(FileFormat, String, String)} 086 */ 087 @Deprecated 088 public H5Datatype(FileFormat theFile, String name, String path, long[] oid) { 089 super(theFile, name, path, oid); 090 obj_info = new H5O_info_t(-1L, -1L, 0, 0, -1L, 0L, 0L, 0L, 0L, null, null, null); 091 092 if ((oid == null) && (theFile != null)) { 093 // retrieve the object ID 094 try { 095 byte[] ref_buf = H5.H5Rcreate(theFile.getFID(), this.getFullName(), HDF5Constants.H5R_OBJECT, -1); 096 this.oid = new long[1]; 097 this.oid[0] = HDFNativeData.byteToLong(ref_buf, 0); 098 } 099 catch (Exception ex) { 100 log.debug("constructor ID {} for {} failed H5Rcreate", theFile.getFID(), this.getFullName()); 101 } 102 } 103 } 104 105 /** 106 * Constructs a Datatype with specified class, size, byte order and sign. 107 * <p> 108 * The following is a list of a few example of H5Datatype. 109 * <OL> 110 * <LI>to create unsigned native integer<br> 111 * H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE, SIGN_NONE); 112 * <LI>to create 16-bit signed integer with big endian<br> 113 * H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE); 114 * <LI>to create native float<br> 115 * H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1); 116 * <LI>to create 64-bit double<br> 117 * H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1); 118 * </OL> 119 * 120 * @param tclass 121 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 122 * @param tsize 123 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. 124 * @param torder 125 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX and ORDER_NONE 126 * @param tsign 127 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and MSGN 128 */ 129 public H5Datatype(int tclass, int tsize, int torder, int tsign) { 130 super(tclass, tsize, torder, tsign); 131 } 132 133 /** 134 * Constructs a Datatype with specified class, size, byte order and sign. 135 * <p> 136 * The following is a list of a few example of H5Datatype. 137 * <OL> 138 * <LI>to create unsigned native integer<br> 139 * H5Datatype type = new H5Dataype(CLASS_INTEGER, NATIVE, NATIVE, SIGN_NONE); 140 * <LI>to create 16-bit signed integer with big endian<br> 141 * H5Datatype type = new H5Dataype(CLASS_INTEGER, 2, ORDER_BE, NATIVE); 142 * <LI>to create native float<br> 143 * H5Datatype type = new H5Dataype(CLASS_FLOAT, NATIVE, NATIVE, -1); 144 * <LI>to create 64-bit double<br> 145 * H5Datatype type = new H5Dataype(CLASS_FLOAT, 8, NATIVE, -1); 146 * </OL> 147 * 148 * @param tclass 149 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 150 * @param tsize 151 * the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4. 152 * @param torder 153 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX and ORDER_NONE 154 * @param tsign 155 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and MSGN 156 * @param tbase 157 * the base datatype of the new datatype 158 */ 159 public H5Datatype(int tclass, int tsize, int torder, int tsign, Datatype tbase) { 160 super(tclass, tsize, torder, tsign, tbase); 161 } 162 163 /** 164 * Constructs a Datatype with a given native datatype identifier. 165 * <p> 166 * For example, if the datatype identifier is a 32-bit unsigned integer created from HDF5, 167 * 168 * <pre> 169 * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UNINT32); 170 * Datatype dtype = new Datatype(tid); 171 * </pre> 172 * 173 * will construct a datatype equivalent to new Datatype(CLASS_INTEGER, 4, NATIVE, SIGN_NONE); 174 * <p> 175 * 176 * @see #fromNative(int nativeID) 177 * @param nativeID 178 * the native datatype identifier. 179 */ 180 public H5Datatype(int nativeID) { 181 super(nativeID); 182 183 description = getDatatypeDescription(nativeID); 184 log.trace("H5Datatype(int nativeID) description={}", description); 185 fromNative(nativeID); 186 } 187 188 /* 189 * (non-Javadoc) 190 * 191 * @see hdf.object.DataFormat#hasAttribute() 192 */ 193 public boolean hasAttribute() { 194 obj_info.num_attrs = nAttributes; 195 196 if (obj_info.num_attrs < 0) { 197 int tid = -1; 198 try { 199 tid = H5.H5Topen(getFID(), getPath() + getName(), HDF5Constants.H5P_DEFAULT); 200 fromNative(tid); 201 obj_info = H5.H5Oget_info(tid); 202 isNamed = true; 203 } 204 catch (Exception ex) { 205 obj_info.num_attrs = 0; 206 } 207 finally { 208 try { 209 H5.H5Tclose(tid); 210 } 211 catch (Exception ex) { 212 log.debug("hasAttribute() finally close:", ex); 213 } 214 } 215 } 216 217 return (obj_info.num_attrs > 0); 218 } 219 220 /** 221 * Converts values in an Enumeration Datatype to names. 222 * <p> 223 * This method searches the identified enumeration datatype for the values appearing in <code>inValues</code> and 224 * returns the names corresponding to those values. If a given value is not found in the enumeration datatype, the 225 * name corresponding to that value will be set to <code>null</code> in the string array that is returned. 226 * <p> 227 * If the method fails in general, null will be returned instead of a String array. An empty <code>inValues</code> 228 * parameter, an <code>outNames</code> array with a different number of entries than the <code>inValues</code> 229 * array, or an invalid <code>tid</code> would all cause general failure. 230 * 231 * @param tid 232 * The identifier of the enumeration datatype. 233 * @param inValues 234 * The array of enumerations values to be converted. 235 * @param outNames 236 * The array of names to be populated. If null, the array will be created. If <code>outNames</code> is 237 * not null, the number of entries must be the same as the number of values in <code>inValues</code>. 238 * @return The string array of names if successful; otherwise return null. 239 * @throws HDF5Exception 240 * If there is an error at the HDF5 library level. 241 * 242 */ 243 public static final String[] convertEnumValueToName(int tid, Object inValues, String[] outNames) 244 throws HDF5Exception { 245 int inSize = 0; 246 log.trace("convertEnumValueToName start"); 247 248 if ((inValues == null) || ((inSize = Array.getLength(inValues)) <= 0) 249 || ((outNames != null) && (inSize != Array.getLength(outNames)))) { 250 return null; 251 } 252 253 int nMembers = H5.H5Tget_nmembers(tid); 254 if (nMembers <= 0) { 255 return null; 256 } 257 258 log.trace("convertEnumValueToName inSize={} nMembers={}", inSize, nMembers); 259 if (outNames == null) { 260 outNames = new String[inSize]; 261 } 262 else { 263 // set values in existing array to null in case no match found 264 for (int i = 0; i < inSize; i++) { 265 outNames[i] = null; 266 } 267 } 268 269 String[] names = new String[nMembers]; 270 int[] values = new int[nMembers]; 271 int[] theValue = { 0 }; 272 273 // Loop through the enumeration datatype and extract the names and 274 // values. 275 for (int i = 0; i < nMembers; i++) { 276 names[i] = H5.H5Tget_member_name(tid, i); 277 H5.H5Tget_member_value(tid, i, theValue); 278 values[i] = theValue[0]; 279 log.trace("convertEnumValueToName: extract member[{}] names[i]={} values[i]={}", i, names[i], values[i]); 280 } 281 282 int val = -1; 283 284 // Look for matches 285 for (int i = 0; i < inSize; i++) { 286 val = Array.getInt(inValues, i); 287 for (int j = 0; j < nMembers; j++) { 288 if (val == values[j]) { 289 outNames[i] = names[j]; 290 break; 291 } 292 } 293 } 294 295 log.trace("convertEnumValueToName finish"); 296 return outNames; 297 } 298 299 /** 300 * Converts names in an Enumeration Datatype to values. 301 * <p> 302 * This method searches the identified enumeration datatype for the names appearing in <code>inValues</code> and 303 * returns the values corresponding to those names. 304 * 305 * @param tid 306 * The identifier of the enumeration datatype. 307 * @param in 308 * The array of enumerations names to be converted. 309 * @param out 310 * The array of values to be populated. 311 * 312 * @return The int array of values if successful; otherwise return null. 313 * @throws HDF5Exception 314 * If there is an error at the HDF5 library level. 315 * 316 */ 317 public static final int[] convertEnumNameToValue(int tid, String[] in, int[] out) throws HDF5Exception { 318 int size = 0; 319 log.trace("convertEnumNameToValue start"); 320 321 if ((in == null) || ((size = Array.getLength(in)) <= 0) || ((out != null) && (size != Array.getLength(out)))) { 322 return null; 323 } 324 325 int nMembers = H5.H5Tget_nmembers(tid); 326 if (nMembers <= 0) { 327 return null; 328 } 329 330 if (out == null) { 331 out = new int[size]; 332 } 333 else { 334 // set values in existing array to -1 in case no match found 335 for (int i = 0; i < size; i++) { 336 out[i] = -1; 337 } 338 } 339 340 String[] names = new String[nMembers]; 341 int[] values = new int[nMembers]; 342 int[] theValue = { 0 }; 343 344 // Loop through the enumeration datatype and extract the names and 345 // values. 346 for (int i = 0; i < nMembers; i++) { 347 names[i] = H5.H5Tget_member_name(tid, i); 348 H5.H5Tget_member_value(tid, i, theValue); 349 values[i] = theValue[0]; 350 } 351 352 for (int i = 0; i < size; i++) { 353 if (in[i] == null || in[i].length() <= 0) 354 continue; 355 356 for (int j = 0; j < nMembers; j++) { 357 if (in[i].equalsIgnoreCase(names[j])) { 358 out[i] = values[j]; 359 break; 360 } 361 } 362 } 363 364 log.trace("convertEnumNameToValue finish"); 365 return out; 366 } 367 368 /* 369 * (non-Javadoc) 370 * 371 * @see hdf.object.Datatype#fromNative(int) 372 */ 373 @Override 374 public void fromNative(int tid) { 375 int tclass = -1, tsize = -1, torder = -1; 376 boolean isChar = false, isUchar = false; 377 log.trace("fromNative start"); 378 379 if (tid < 0) { 380 datatypeClass = CLASS_NO_CLASS; 381 } 382 else { 383 try { 384 tclass = H5.H5Tget_class(tid); 385 tsize = H5.H5Tget_size(tid); 386 torder = H5.H5Tget_order(tid); 387 isVLEN = (tclass == HDF5Constants.H5T_VLEN); 388 } 389 catch (Exception ex) { 390 datatypeClass = CLASS_NO_CLASS; 391 } 392 393 if (torder == HDF5Constants.H5T_ORDER_BE) 394 datatypeOrder = ORDER_BE; 395 else 396 datatypeOrder = ORDER_LE; 397 398 try { 399 isUchar = H5.H5Tequal(tid, HDF5Constants.H5T_NATIVE_UCHAR); 400 isChar = (H5.H5Tequal(tid, HDF5Constants.H5T_NATIVE_CHAR) || isUchar); 401 } 402 catch (Exception ex) { 403 log.debug("native char type:", ex); 404 } 405 406 if (tclass == HDF5Constants.H5T_ARRAY) { 407 int tmptid = -1; 408 datatypeClass = CLASS_ARRAY; 409 try { 410 int ndims = H5.H5Tget_array_ndims(tid); 411 dims = new long[ndims]; 412 H5.H5Tget_array_dims(tid, dims); 413 tmptid = H5.H5Tget_super(tid); 414 baseType = new H5Datatype(tmptid); 415 } 416 catch (Exception ex) { 417 log.debug("array type:", ex); 418 } 419 finally { 420 try { 421 H5.H5Tclose(tmptid); 422 } 423 catch (Exception ex) { 424 log.debug("finally close:", ex); 425 } 426 } 427 } 428 else if (isChar) { 429 datatypeClass = CLASS_CHAR; 430 if (isUchar) 431 datatypeSign = SIGN_NONE; 432 else 433 datatypeSign = SIGN_2; 434 } 435 else if (tclass == HDF5Constants.H5T_INTEGER) { 436 datatypeClass = CLASS_INTEGER; 437 try { 438 int tsign = H5.H5Tget_sign(tid); 439 if (tsign == HDF5Constants.H5T_SGN_NONE) { 440 datatypeSign = SIGN_NONE; 441 } 442 else 443 datatypeSign = SIGN_2; 444 445 } 446 catch (Exception ex) { 447 log.debug("int type:", ex); 448 } 449 } 450 else if (tclass == HDF5Constants.H5T_FLOAT) { 451 datatypeClass = CLASS_FLOAT; 452 } 453 else if (tclass == HDF5Constants.H5T_STRING) { 454 try { 455 isVLEN = H5.H5Tis_variable_str(tid); 456 } 457 catch (Exception ex) { 458 log.debug("var str type:", ex); 459 } 460 461 datatypeClass = CLASS_STRING; 462 } 463 else if (tclass == HDF5Constants.H5T_REFERENCE) { 464 datatypeClass = CLASS_REFERENCE; 465 } 466 else if (tclass == HDF5Constants.H5T_ENUM) { 467 datatypeClass = CLASS_ENUM; 468 try { 469 int nMember = H5.H5Tget_nmembers(tid); 470 String name = null; 471 byte[] val = new byte[tsize]; 472 String enumStr = ""; 473 for (int i = 0; i < nMember; i++) { 474 name = H5.H5Tget_member_name(tid, i); 475 H5.H5Tget_member_value(tid, i, val); 476 enumStr += name + "="; 477 switch (H5.H5Tget_size(tid)) { 478 case 1: 479 enumStr += (HDFNativeData.byteToByte(val[0]))[0]; 480 break; 481 case 2: 482 enumStr += (HDFNativeData.byteToShort(val))[0]; 483 break; 484 case 4: 485 enumStr += (HDFNativeData.byteToInt(val))[0]; 486 break; 487 case 8: 488 enumStr += (HDFNativeData.byteToLong(val))[0]; 489 break; 490 default: 491 enumStr += "?"; 492 break; 493 } 494 if(i < nMember-1) 495 enumStr += ","; 496 } 497 enumMembers = enumStr; 498 } 499 catch (Exception ex) { 500 log.debug("enum type:", ex); 501 } 502 } 503 else if (tclass == HDF5Constants.H5T_VLEN) { 504 int tmptid = -1; 505 datatypeClass = CLASS_VLEN; 506 try { 507 tmptid = H5.H5Tget_super(tid); 508 baseType = new H5Datatype(tmptid); 509 } 510 catch (Exception ex) { 511 } 512 finally { 513 try { 514 H5.H5Tclose(tmptid); 515 } 516 catch (Exception ex) { 517 log.debug("vlen finally close:", ex); 518 } 519 } 520 } 521 else if (tclass == HDF5Constants.H5T_BITFIELD) { 522 datatypeClass = CLASS_BITFIELD; 523 } 524 else if (tclass == HDF5Constants.H5T_OPAQUE) { 525 datatypeClass = CLASS_OPAQUE; 526 } 527 else { 528 log.debug("fromNative datatypeClass is unknown"); 529 } 530 531 if (isVLEN) 532 datatypeSize = -1; 533 else 534 datatypeSize = tsize; 535 } 536 log.trace("fromNative datatypeClass={} baseType={} datatypeSize={}", datatypeClass, baseType, datatypeSize); 537 log.trace("fromNative start"); 538 } 539 540 /** 541 * @deprecated Not for public use in the future.<br> 542 * Using {@link hdf.hdf5lib.H5#H5Tget_native_type(int)} 543 * <p> 544 * Return the HDF5 memory datatype identifier based on the HDF5 datatype identifier on disk 545 * <p> 546 * @param tid 547 * the datatype identification disk. 548 * @return the memory datatype identifier if successful, and negative otherwise. 549 */ 550 @Deprecated 551 public static int toNative(int tid) { 552 // data type information 553 int native_type = -1; 554 555 try { 556 native_type = H5.H5Tget_native_type(tid); 557 } 558 catch (Exception ex) { 559 log.debug("toNative type:", ex); 560 } 561 562 try { 563 if (H5.H5Tis_variable_str(tid)) 564 H5.H5Tset_size(native_type, HDF5Constants.H5T_VARIABLE); 565 } 566 catch (Exception ex) { 567 log.debug("var str type size:", ex); 568 } 569 570 return native_type; 571 } 572 573 /* 574 * (non-Javadoc) 575 * 576 * @see hdf.object.Datatype#toNative() 577 */ 578 @Override 579 public int toNative() { 580 int tid = -1, tmptid = -1; 581 582 if (isNamed) { 583 try { 584 tid = H5.H5Topen(getFID(), getPath() + getName(), HDF5Constants.H5P_DEFAULT); 585 } 586 catch (Exception ex) { 587 log.debug("toNative name {} open failure:", getPath() + getName(), ex); 588 } 589 } 590 591 if (tid >= 0) { 592 return tid; 593 } 594 595 // figure the datatype 596 try { 597 log.trace("toNative datatypeClass={} baseType={} datatypeSize={}", datatypeClass, baseType, datatypeSize); 598 switch (datatypeClass) { 599 case CLASS_ARRAY: 600 if (baseType != null) { 601 if ((tmptid = baseType.toNative()) >= 0) { 602 try { 603 tid = H5.H5Tarray_create(tmptid, dims.length, dims); 604 } 605 finally { 606 close(tmptid); 607 } 608 } 609 } 610 else { 611 log.debug("CLASS_ARRAY base type is NULL"); 612 } 613 break; 614 case CLASS_INTEGER: 615 case CLASS_ENUM: 616 if (datatypeSize == 1) { 617 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT8"); 618 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT8); 619 } 620 else if (datatypeSize == 2) { 621 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT16"); 622 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT16); 623 } 624 else if (datatypeSize == 4) { 625 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT32"); 626 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32); 627 } 628 else if (datatypeSize == 8) { 629 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT64"); 630 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT64); 631 } 632 else { 633 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT"); 634 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT); 635 } 636 637 if (datatypeOrder == Datatype.ORDER_BE) { 638 log.trace("toNative CLASS_INT-ENUM is H5T_ORDER_BE"); 639 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 640 } 641 else if (datatypeOrder == Datatype.ORDER_LE) { 642 log.trace("toNative CLASS_INT-ENUM is H5T_ORDER_LE"); 643 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 644 } 645 646 if (datatypeSign == Datatype.SIGN_NONE) { 647 log.trace("toNative CLASS_INT-ENUM is H5T_SGN_NONE"); 648 H5.H5Tset_sign(tid, HDF5Constants.H5T_SGN_NONE); 649 } 650 break; 651 case CLASS_FLOAT: 652 if (datatypeSize == 8) { 653 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_DOUBLE); 654 } 655 else { 656 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_FLOAT); 657 } 658 659 if (datatypeOrder == Datatype.ORDER_BE) { 660 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 661 } 662 else if (datatypeOrder == Datatype.ORDER_LE) { 663 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 664 } 665 break; 666 case CLASS_CHAR: 667 if (datatypeSign == Datatype.SIGN_NONE) { 668 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_UCHAR); 669 } 670 else { 671 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_CHAR); 672 } 673 break; 674 case CLASS_STRING: 675 tid = H5.H5Tcopy(HDF5Constants.H5T_C_S1); 676 if (isVLEN || datatypeSize < 0) 677 H5.H5Tset_size(tid, HDF5Constants.H5T_VARIABLE); 678 else 679 H5.H5Tset_size(tid, datatypeSize); 680 681 // H5.H5Tset_strpad(tid, HDF5Constants.H5T_STR_NULLPAD); 682 break; 683 case CLASS_REFERENCE: 684 if (datatypeSize > H5.H5Tget_size(HDF5Constants.H5T_STD_REF_OBJ)) { 685 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_DSETREG); 686 } 687 else { 688 tid = H5.H5Tcopy(HDF5Constants.H5T_STD_REF_OBJ); 689 } 690 break; 691 case CLASS_VLEN: 692 if (baseType != null) { 693 if ((tmptid = baseType.toNative()) >= 0) { 694 try { 695 tid = H5.H5Tvlen_create(tmptid); 696 } 697 finally { 698 close(tmptid); 699 } 700 } 701 } 702 else { 703 log.debug("CLASS_VLEN base type is NULL"); 704 } 705 break; 706 case CLASS_BITFIELD: 707 case CLASS_OPAQUE: 708 if (datatypeSize == 1) { 709 log.trace("toNative CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT8"); 710 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT8); 711 } 712 else if (datatypeSize == 2) { 713 log.trace("toNative CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT16"); 714 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT16); 715 } 716 else if (datatypeSize == 4) { 717 log.trace("toNative CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT32"); 718 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32); 719 } 720 else if (datatypeSize == 8) { 721 log.trace("toNative CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT64"); 722 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT64); 723 } 724 else { 725 log.trace("toNative CLASS_BITFIELD-OPAQUE is H5T_NATIVE_INT"); 726 tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT); 727 } 728 729 if (datatypeOrder == Datatype.ORDER_BE) { 730 log.trace("toNative CLASS_BITFIELD-OPAQUE is H5T_ORDER_BE"); 731 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_BE); 732 } 733 else if (datatypeOrder == Datatype.ORDER_LE) { 734 log.trace("toNative CLASS_BITFIELD-OPAQUE is H5T_ORDER_LE"); 735 H5.H5Tset_order(tid, HDF5Constants.H5T_ORDER_LE); 736 } 737 break; 738 default: 739 log.debug("toNative Unknown class"); 740 break; 741 } // switch (tclass) 742 } 743 catch (Exception ex) { 744 log.debug("toNative figure the datatype", ex); 745 tid = -1; 746 } 747 748 // set up enum members 749 if (datatypeClass == CLASS_ENUM) { 750 int ptid = tid; 751 try { 752 tid = H5.H5Tenum_create(ptid); 753 datatypeSize = H5.H5Tget_size(tid); 754 } 755 catch (Exception ex) { 756 log.debug("toNative create members", ex); 757 tid = -1; 758 } 759 760 try { 761 String memstr, memname; 762 int idx; 763 byte[] memval = null; 764 if (datatypeSize == 1) { 765 memval = HDFNativeData.byteToByte(new Byte((byte) 0)); 766 } 767 else if (datatypeSize == 2) { 768 memval = HDFNativeData.shortToByte(new Short((short) 0)); 769 } 770 else if (datatypeSize == 4) { 771 memval = HDFNativeData.intToByte(new Integer((int) 0)); 772 } 773 else if (datatypeSize == 8) { 774 memval = HDFNativeData.longToByte(new Long((long) 0)); 775 } 776 StringTokenizer token; 777 778 // using "0" and "1" as default 779 if (enumMembers == null) { 780 token = new StringTokenizer("0,1", ","); 781 log.trace("toNative default string"); 782 } 783 else { 784 token = new StringTokenizer(enumMembers, ","); 785 log.trace("toNative string {}", enumMembers); 786 } 787 788 while (token.hasMoreTokens()) { 789 memstr = token.nextToken(); 790 791 if (memstr != null) { 792 memstr = memstr.trim(); 793 } 794 795 if ((memstr == null) || (memstr.length() < 1)) { 796 continue; 797 } 798 799 idx = memstr.indexOf('='); 800 if (idx > 0) { 801 memname = memstr.substring(0, idx); 802 if (datatypeSize == 1) { 803 log.trace("toNative ENUM is H5T_NATIVE_INT8"); 804 Byte tval = Byte.parseByte(memstr.substring(idx + 1)); 805 memval = HDFNativeData.byteToByte(tval); 806 } 807 else if (datatypeSize == 2) { 808 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT16"); 809 Short tval = Short.parseShort(memstr.substring(idx + 1)); 810 memval = HDFNativeData.shortToByte(tval); 811 } 812 else if (datatypeSize == 4) { 813 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT32"); 814 Integer tval = Integer.parseInt(memstr.substring(idx + 1)); 815 memval = HDFNativeData.intToByte(tval); 816 } 817 else if (datatypeSize == 8) { 818 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT64"); 819 Long tval = Long.parseLong(memstr.substring(idx + 1)); 820 memval = HDFNativeData.longToByte(tval); 821 } 822 else { 823 log.debug("toNative enum datatypeSize incorrect"); 824 } 825 } 826 else { 827 memname = memstr; 828 if (datatypeSize == 1) { 829 log.trace("toNative ENUM is H5T_NATIVE_INT8"); 830 Byte tval = new Byte(memval[0]); 831 tval++; 832 memval = HDFNativeData.byteToByte(tval); 833 } 834 else if (datatypeSize == 2) { 835 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT16"); 836 Short tval = (HDFNativeData.byteToShort(memval))[0]; 837 tval++; 838 memval = HDFNativeData.shortToByte(tval); 839 } 840 else if (datatypeSize == 4) { 841 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT32"); 842 Integer tval = (HDFNativeData.byteToInt(memval))[0]; 843 tval++; 844 memval = HDFNativeData.intToByte(tval); 845 } 846 else if (datatypeSize == 8) { 847 log.trace("toNative CLASS_INT-ENUM is H5T_NATIVE_INT64"); 848 Long tval = (HDFNativeData.byteToLong(memval))[0]; 849 tval++; 850 memval = HDFNativeData.longToByte(tval); 851 } 852 else { 853 log.debug("toNative enum datatypeSize incorrect"); 854 } 855 } 856 log.trace("toNative H5Tenum_insert {} {}", memname, memval); 857 H5.H5Tenum_insert(tid, memname, memval); 858 } 859 } 860 catch (Exception ex) { 861 log.debug("toNative set up enum members", ex); 862 } 863 864 try { 865 H5.H5Tclose(ptid); 866 } 867 catch (Exception ex) { 868 log.debug("toNative enum class:", ex); 869 } 870 } // if (datatypeClass == CLASS_ENUM) { 871 872 return tid; 873 } 874 875 /** 876 * Allocates an one-dimensional array of byte, short, int, long, float, double, or String to store data in memory. 877 * 878 * For example, 879 * 880 * <pre> 881 * int tid = H5.H5Tcopy(HDF5Constants.H5T_NATIVE_INT32); 882 * int[] data = (int[]) allocateArray(tid, 100); 883 * </pre> 884 * 885 * returns a 32-bit integer array of size 100. 886 * 887 * @param tid 888 * the datatype id. 889 * @param size 890 * the total number of data points of the array. 891 * @return the array object if successful; otherwise, return null. 892 */ 893 public static Object allocateArray(int tid, int size) throws OutOfMemoryError { 894 Object data = null; 895 boolean isVL = false; 896 boolean is_variable_str = false; 897 boolean is_reg_ref = false; 898 log.trace("allocateArray: size={}", size); 899 900 if (size < 0) { 901 return null; 902 } 903 904 // Scalar members have dimensionality zero, i.e. size =0 905 // what can we do about it, set the size to 1 906 if (size == 0) { 907 size = 1; 908 } 909 910 // data type information 911 int tclass = -1, tsize = -1; 912 913 try { 914 tclass = H5.H5Tget_class(tid); 915 tsize = H5.H5Tget_size(tid); 916 log.trace("allocateArray tclass={} : tsize={}", tclass, tsize); 917 } 918 catch (Exception ex) { 919 log.debug("H5Tget_xxxx data type information:", ex); 920 } 921 922 try { 923 is_variable_str = H5.H5Tis_variable_str(tid); 924 } 925 catch (Exception ex) { 926 log.debug("H5Tis_variable_str data type information:", ex); 927 } 928 isVL = (tclass == HDF5Constants.H5T_VLEN); 929 930 try { 931 is_reg_ref = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_DSETREG); 932 } 933 catch (Exception ex) { 934 log.debug("H5Tequal data type information:", ex); 935 } 936 937 if (is_variable_str || isVL || is_reg_ref) { 938 log.trace("allocateArray is_variable_str={} || isVL={} || is_reg_ref={}", is_variable_str, isVL, is_reg_ref); 939 data = new String[size]; 940 for (int i = 0; i < size; i++) { 941 ((String[]) data)[i] = ""; 942 } 943 } 944 else if (tclass == HDF5Constants.H5T_INTEGER) { 945 log.trace("allocateArray class.H5T_INTEGER={}", tclass); 946 if (tsize == 1) { 947 data = new byte[size]; 948 } 949 else if (tsize == 2) { 950 data = new short[size]; 951 } 952 else if (tsize == 4) { 953 data = new int[size]; 954 } 955 else if (tsize == 8) { 956 data = new long[size]; 957 } 958 } 959 else if (tclass == HDF5Constants.H5T_ENUM) { 960 log.trace("allocateArray class.H5T_ENUM={}", tclass); 961 int superTid = -1; 962 try { 963 superTid = H5.H5Tget_super(tid); 964 data = allocateArray(superTid, size); 965 } 966 catch (Exception ex) { 967 log.debug("H5T_ENUM class enum data type information:", ex); 968 } 969 finally { 970 try { 971 H5.H5Tclose(superTid); 972 } 973 catch (Exception ex) { 974 log.debug("H5T_ENUM class finally close:", ex); 975 } 976 } 977 } 978 else if (tclass == HDF5Constants.H5T_FLOAT) { 979 log.trace("allocateArray class.H5T_FLOAT={}", tclass); 980 if (tsize == 4) { 981 data = new float[size]; 982 } 983 else if (tsize == 8) { 984 data = new double[size]; 985 } 986 } 987 else if ((tclass == HDF5Constants.H5T_STRING) || (tclass == HDF5Constants.H5T_REFERENCE)) { 988 log.trace("allocateArray class.H5T_STRING || H5T_REFERENCE={}", tclass); 989 data = new byte[size * tsize]; 990 } 991 else if (tclass == HDF5Constants.H5T_ARRAY) { 992 // use the base datatype to define the array 993 int superTid = -1; 994 try { 995 int mn = H5.H5Tget_array_ndims(tid); 996 long[] marray = new long[mn]; 997 H5.H5Tget_array_dims(tid, marray); 998 int asize = 1; 999 for (int j = 0; j < mn; j++) { 1000 asize *= marray[j]; 1001 } 1002 log.trace("allocateArray class.H5T_ARRAY={} : members={} : asize={}", tclass, mn, asize); 1003 1004 superTid = H5.H5Tget_super(tid); 1005 data = allocateArray(superTid, size * asize); 1006 } 1007 catch (Exception ex) { 1008 log.debug("H5T_ARRAY class: ", ex); 1009 } 1010 finally { 1011 try { 1012 H5.H5Tclose(superTid); 1013 } 1014 catch (Exception ex) { 1015 log.debug("H5T_ARRAY class finally close:", ex); 1016 } 1017 } 1018 } 1019 else if ((tclass == HDF5Constants.H5T_OPAQUE) || (tclass == HDF5Constants.H5T_BITFIELD)) { 1020 log.trace("allocateArray class.H5T_OPAQUE || H5T_BITFIELD={}", tclass); 1021 data = new byte[size * tsize]; 1022 } 1023 else { 1024 log.debug("allocateArray class.????={}", tclass); 1025 data = null; 1026 } 1027 1028 return data; 1029 } 1030 1031 /** 1032 * Returns the size (in bytes) of a given datatype identifier. 1033 * <p> 1034 * It basically just calls H5Tget_size(tid). 1035 * 1036 * @param tid 1037 * The datatype identifier. 1038 * @return The size of the datatype in bytes. 1039 * 1040 * @see hdf.hdf5lib.H5#H5Tget_size(int) 1041 */ 1042 public static final int getDatatypeSize(int tid) { 1043 // data type information 1044 int tsize = -1; 1045 1046 try { 1047 tsize = H5.H5Tget_size(tid); 1048 } 1049 catch (Exception ex) { 1050 tsize = -1; 1051 } 1052 1053 return tsize; 1054 } 1055 1056 /* 1057 * (non-Javadoc) 1058 * 1059 * @see hdf.object.Datatype#getDatatypeDescription() 1060 */ 1061 @Override 1062 public String getDatatypeDescription() { 1063 if (description == null) { 1064 int tid = toNative(); 1065 if (tid >= 0) { 1066 description = getDatatypeDescription(tid); 1067 close(tid); 1068 } 1069 else { 1070 description = "Unknown"; 1071 } 1072 } 1073 1074 return description; 1075 } 1076 1077 /** 1078 * Returns a short description of a given datatype ID. 1079 * 1080 * @param tid 1081 * the HDF5 datatype identifier 1082 * @return a string describing the data type. 1083 */ 1084 public static final String getDatatypeDescription(int tid) { 1085 String description = "Unknown"; 1086 1087 // data type information 1088 int tclass = -1, tsize = -1, tsign = -1; 1089 1090 try { 1091 tclass = H5.H5Tget_class(tid); 1092 tsize = H5.H5Tget_size(tid); 1093 } 1094 catch (Exception ex) { 1095 log.debug("getDatatypeDescription Unknown:", ex); 1096 } 1097 1098 if (tclass == HDF5Constants.H5T_INTEGER) { 1099 try { 1100 tsign = H5.H5Tget_sign(tid); 1101 } 1102 catch (Exception ex) { 1103 log.debug("getDatatypeDescription H5Tget_sign failure:", ex); 1104 } 1105 if (tsize == 1) { 1106 try { 1107 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1108 description = "8-bit unsigned integer"; 1109 } 1110 else { 1111 description = "8-bit integer"; 1112 } 1113 } 1114 catch (Exception ex) { 1115 description = "Unknown"; 1116 } 1117 } 1118 else if (tsize == 2) { 1119 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1120 description = "16-bit unsigned integer"; 1121 } 1122 else { 1123 description = "16-bit integer"; 1124 } 1125 } 1126 else if (tsize == 4) { 1127 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1128 description = "32-bit unsigned integer"; 1129 } 1130 else { 1131 description = "32-bit integer"; 1132 } 1133 } 1134 else if (tsize == 8) { 1135 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1136 description = "64-bit unsigned integer"; 1137 } 1138 else { 1139 description = "64-bit integer"; 1140 } 1141 } 1142 } 1143 else if (tclass == HDF5Constants.H5T_FLOAT) { 1144 if (tsize == 4) { 1145 description = "32-bit floating-point"; 1146 } 1147 else if (tsize == 8) { 1148 description = "64-bit floating-point"; 1149 } 1150 } 1151 else if (tclass == HDF5Constants.H5T_STRING) { 1152 try { 1153 if (H5.H5Tis_variable_str(tid)) { 1154 description = "String, length = variable"; 1155 } 1156 else { 1157 description = "String, length = " + H5.H5Tget_size(tid); 1158 } 1159 } 1160 catch (Exception ex) { 1161 description = "String"; 1162 } 1163 } 1164 else if (tclass == HDF5Constants.H5T_REFERENCE) { 1165 boolean is_reg_ref = false; 1166 try { 1167 is_reg_ref = H5.H5Tequal(tid, HDF5Constants.H5T_STD_REF_DSETREG); 1168 } 1169 catch (Exception ex) { 1170 log.debug("H5T_STD_REF_DSETREG:", ex); 1171 } 1172 1173 if (is_reg_ref) { 1174 description = "Dataset region reference"; 1175 } 1176 else { 1177 description = "Object reference"; 1178 } 1179 } 1180 else if (tclass == HDF5Constants.H5T_BITFIELD) { 1181 description = "Bitfield"; 1182 } 1183 else if (tclass == HDF5Constants.H5T_ENUM) { 1184 byte[] evalue = new byte[tsize]; 1185 String enames = " ( "; 1186 try { 1187 int n = H5.H5Tget_nmembers(tid); 1188 for (int i = 0; i < n; i++) { 1189 H5.H5Tget_member_value(tid, i, evalue); 1190 enames += H5.H5Tget_member_name(tid, i); 1191 enames += "="; 1192 if (tsize == 1) { 1193 description = "8-bit enum"; 1194 enames += (HDFNativeData.byteToByte(evalue[0]))[0]; 1195 } 1196 else if (tsize == 2) { 1197 description = "16-bit enum"; 1198 enames += (HDFNativeData.byteToShort(evalue))[0]; 1199 } 1200 else if (tsize == 4) { 1201 description = "32-bit enum"; 1202 enames += (HDFNativeData.byteToInt(evalue))[0]; 1203 } 1204 else if (tsize == 8) { 1205 description = "64-bit enum"; 1206 enames += (HDFNativeData.byteToLong(evalue))[0]; 1207 } 1208 if(i < n-1) 1209 enames += " "; 1210 } 1211 enames += ")"; 1212 description += enames; 1213 } 1214 catch (Exception ex) { 1215 log.debug("H5T_ENUM:", ex); 1216 } 1217 1218 } 1219 else if (tclass == HDF5Constants.H5T_ARRAY) { 1220 description = "Array of "; 1221 // use the base datatype to define the array 1222 int tmptid = -1; 1223 try { 1224 tmptid = H5.H5Tget_super(tid); 1225 description += getDatatypeDescription(tmptid); 1226 int ndims = H5.H5Tget_array_ndims(tid); 1227 long adims[] = new long[ndims]; 1228 try { 1229 H5.H5Tget_array_dims(tid, adims); 1230 } 1231 catch (Exception ex) { 1232 log.debug("H5T_ARRAY dims:", ex); 1233 } 1234 1235 description += " (" + adims[0]; 1236 for (int j = 1; j < ndims; j++) 1237 description += "x" + adims[j]; 1238 description += ")"; 1239 } 1240 catch (Exception ex) { 1241 log.debug("H5T_ARRAY:", ex); 1242 } 1243 finally { 1244 try { 1245 H5.H5Tclose(tmptid); 1246 } 1247 catch (Exception ex) { 1248 log.debug("finally close:", ex); 1249 } 1250 } 1251 } 1252 else if (tclass == HDF5Constants.H5T_COMPOUND) { 1253 description = "Compound "; 1254 try { 1255 description += "{"; 1256 int n = H5.H5Tget_nmembers(tid); 1257 int mtid = -1; 1258 1259 for (int i = 0; i < n; i++) { 1260 mtid = H5.H5Tget_member_type(tid, i); 1261 description += getDatatypeDescription(mtid) + ", "; 1262 try { 1263 H5.H5Tclose(mtid); 1264 } 1265 catch (Exception ex2) { 1266 log.debug("H5T_COMPOUND member close:", ex2); 1267 } 1268 mtid = -1; 1269 } 1270 description += "}"; 1271 } 1272 catch (Exception ex) { 1273 log.debug("H5T_COMPOUND:", ex); 1274 } 1275 } 1276 else if (tclass == HDF5Constants.H5T_VLEN) { 1277 int tmptid = -1; 1278 try { 1279 tmptid = H5.H5Tget_super(tid); 1280 description = "Variable-length of " + getDatatypeDescription(tmptid); 1281 } 1282 catch (Exception ex) { 1283 description = "Variable-length"; 1284 } 1285 finally { 1286 try { 1287 H5.H5Tclose(tmptid); 1288 } 1289 catch (Exception ex) { 1290 log.debug("finally close:", ex); 1291 } 1292 } 1293 } 1294 else if (tclass == HDF5Constants.H5T_OPAQUE) { 1295 description = "Opaque"; 1296 } 1297 else { 1298 description = "Unknown"; 1299 } 1300 1301 return description; 1302 } 1303 1304 /* 1305 * (non-Javadoc) 1306 * 1307 * @see hdf.object.Datatype#isUnsigned() 1308 */ 1309 @Override 1310 public boolean isUnsigned() { 1311 boolean unsigned = false; 1312 int tid = toNative(); 1313 1314 unsigned = isUnsigned(tid); 1315 try { 1316 H5.H5Tclose(tid); 1317 } 1318 catch (final Exception ex) { 1319 } 1320 1321 return unsigned; 1322 } 1323 1324 /** 1325 * Checks if a datatype specified by the identifier is an unsigned integer. 1326 * <p> 1327 * 1328 * @param datatype 1329 * the datatype ID to be checked. 1330 * 1331 * @return true is the datatype is an unsigned integer; otherwise returns false. 1332 */ 1333 public static final boolean isUnsigned(int datatype) { 1334 boolean unsigned = false; 1335 1336 if (datatype >= 0) { 1337 try { 1338 int tclass = H5.H5Tget_class(datatype); 1339 if (tclass != HDF5Constants.H5T_FLOAT && tclass != HDF5Constants.H5T_STRING 1340 && tclass != HDF5Constants.H5T_REFERENCE && tclass != HDF5Constants.H5T_BITFIELD 1341 && tclass != HDF5Constants.H5T_OPAQUE) { 1342 int tsign = H5.H5Tget_sign(datatype); 1343 if (tsign == HDF5Constants.H5T_SGN_NONE) { 1344 unsigned = true; 1345 } 1346 else { 1347 log.trace("isUnsigned() not unsigned"); 1348 } 1349 } 1350 else { 1351 log.trace("isUnsigned() tclass not integer type"); 1352 } 1353 } 1354 catch (Exception ex) { 1355 log.debug("{} Datatype {} failure", getDatatypeDescription(datatype), datatype, ex); 1356 unsigned = false; 1357 } 1358 } 1359 else { 1360 log.trace("isUnsigned() not a valid datatype"); 1361 } 1362 1363 return unsigned; 1364 } 1365 1366 /** 1367 * Opens access to a named datatype. 1368 * <p> 1369 * It calls H5.H5Topen(loc, name). 1370 * 1371 * @return the datatype identifier if successful; otherwise returns negative value. 1372 * 1373 * @see hdf.hdf5lib.H5#H5Topen(int, String) 1374 */ 1375 @Override 1376 public int open() { 1377 int tid = -1; 1378 1379 try { 1380 tid = H5.H5Topen(getFID(), getPath() + getName(), HDF5Constants.H5P_DEFAULT); 1381 } 1382 catch (HDF5Exception ex) { 1383 tid = -1; 1384 } 1385 1386 return tid; 1387 } 1388 1389 /** 1390 * Closes a datatype identifier. 1391 * <p> 1392 * It calls H5.H5close(tid). 1393 * 1394 * @param tid 1395 * the datatype ID to close 1396 */ 1397 @Override 1398 public void close(int tid) { 1399 try { 1400 H5.H5Tclose(tid); 1401 } 1402 catch (HDF5Exception ex) { 1403 log.debug("close H5Datatype:", ex); 1404 } 1405 } 1406 1407 /* 1408 * (non-Javadoc) 1409 * 1410 * @see hdf.object.Datatype#getMetadata() 1411 */ 1412 @Override 1413 public List<Attribute> getMetadata() throws HDF5Exception { 1414 return this.getMetadata(fileFormat.getIndexType(null), fileFormat.getIndexOrder(null)); 1415 } 1416 1417 /* 1418 * (non-Javadoc) 1419 * 1420 * @see hdf.object.DataFormat#getMetadata(int...) 1421 */ 1422 public List<Attribute> getMetadata(int... attrPropList) throws HDF5Exception { 1423 // load attributes first 1424 if (attributeList == null) { 1425 int tid = open(); 1426 int indxType = fileFormat.getIndexType(null); 1427 int order = fileFormat.getIndexOrder(null); 1428 1429 if (attrPropList.length > 0) { 1430 indxType = attrPropList[0]; 1431 if (attrPropList.length > 1) { 1432 order = attrPropList[1]; 1433 } 1434 } 1435 1436 try { 1437 attributeList = H5File.getAttribute(tid, indxType, order); 1438 } 1439 catch (Exception ex) { 1440 log.debug("attributeList:", ex); 1441 } 1442 finally { 1443 close(tid); 1444 } 1445 } // if (attributeList == null) 1446 1447 try { 1448 this.linkTargetObjName = H5File.getLinkTargetName(this); 1449 } 1450 catch (Exception ex) { 1451 log.debug("linkTargetObjName:", ex); 1452 } 1453 1454 return attributeList; 1455 } 1456 1457 /* 1458 * (non-Javadoc) 1459 * 1460 * @see hdf.object.Datatype#writeMetadata(java.lang.Object) 1461 */ 1462 @Override 1463 public void writeMetadata(Object info) throws Exception { 1464 // only attribute metadata is supported. 1465 if (!(info instanceof Attribute)) { 1466 return; 1467 } 1468 log.trace("writeMetadata start"); 1469 1470 boolean attrExisted = false; 1471 Attribute attr = (Attribute) info; 1472 String name = attr.getName(); 1473 1474 if (attributeList == null) { 1475 this.getMetadata(); 1476 } 1477 1478 if (attributeList != null) 1479 attrExisted = attributeList.contains(attr); 1480 1481 getFileFormat().writeAttribute(this, attr, attrExisted); 1482 1483 // add the new attribute into attribute list 1484 if (!attrExisted) { 1485 attributeList.add(attr); 1486 nAttributes = attributeList.size(); 1487 } 1488 log.trace("writeMetadata finish"); 1489 } 1490 1491 /* 1492 * (non-Javadoc) 1493 * 1494 * @see hdf.object.Datatype#removeMetadata(java.lang.Object) 1495 */ 1496 @Override 1497 public void removeMetadata(Object info) throws HDF5Exception { 1498 // only attribute metadata is supported. 1499 if (!(info instanceof Attribute)) { 1500 return; 1501 } 1502 1503 Attribute attr = (Attribute) info; 1504 int tid = open(); 1505 try { 1506 H5.H5Adelete(tid, attr.getName()); 1507 List<Attribute> attrList = getMetadata(); 1508 attrList.remove(attr); 1509 nAttributes = attributeList.size(); 1510 } 1511 finally { 1512 close(tid); 1513 } 1514 } 1515 1516 public void setName(String newName) throws Exception { 1517 H5File.renameObject(this, newName); 1518 super.setName(newName); 1519 } 1520}