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 COPYING file, which can be found * 009 * at the root of the source code distribution tree, * 010 * or in https://www.hdfgroup.org/licenses. * 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.ArrayList; 019import java.util.Arrays; 020import java.util.Collection; 021import java.util.HashMap; 022import java.util.Iterator; 023import java.util.List; 024import java.util.Map; 025import java.util.Vector; 026import java.util.regex.Pattern; 027 028import hdf.object.Datatype; 029import hdf.object.FileFormat; 030 031import hdf.hdf5lib.H5; 032import hdf.hdf5lib.HDF5Constants; 033import hdf.hdf5lib.structs.H5O_info_t; 034 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038/** 039 * This class defines HDF5 reference characteristics and APIs for a data type of H5T_STD_REF. 040 * 041 * This class provides convenient functions to access H5T_STD_REF type information. 042 */ 043public class H5ReferenceType extends H5Datatype { 044 private static final long serialVersionUID = -3360885430038261178L; 045 046 private static final Logger log = LoggerFactory.getLogger(H5ReferenceType.class); 047 048 /** 049 * The memory buffer that holds the raw data array of the reference. 050 */ 051 protected transient ArrayList<H5ReferenceData> refdata; 052 053 /** Flag to indicate if data values are loaded into memory. */ 054 protected boolean isDataLoaded = false; 055 056 /** Flag to indicate if this dataset has been initialized */ 057 protected boolean inited = false; 058 059 /** The current array size of the reference. */ 060 protected long refsize; 061 062 /** 063 * The data buffer that contains the raw data directly reading from file 064 * (before any data conversion). 065 */ 066 protected transient Object originalRefBuf = null; 067 068 /** 069 * Constructs an named HDF5 data type reference for a given file, dataset name and group path. 070 * 071 * The datatype object represents an existing named datatype in file. For example, 072 * 073 * <pre> 074 * new H5ReferenceType(file, "dset1", "/g0") 075 * </pre> 076 * 077 * constructs a datatype object that corresponds to the dataset,"dset1", at group "/g0". 078 * 079 * @param theFile 080 * the file that contains the datatype. 081 * @param theName 082 * the name of the dataset such as "dset1". 083 * @param thePath 084 * the group path to the dataset such as "/g0/". 085 */ 086 public H5ReferenceType(FileFormat theFile, String theName, String thePath) 087 { 088 this(theFile, theName, thePath, null); 089 } 090 091 /** 092 * @deprecated Not for public use in the future. <br> 093 * Using {@link #H5ReferenceType(FileFormat, String, String)} 094 * 095 * @param theFile 096 * the file that contains the datatype. 097 * @param theName 098 * the name of the dataset such as "dset1". 099 * @param thePath 100 * the group path to the dataset such as "/g0/". 101 * @param oid 102 * the oid of the dataset. 103 */ 104 @Deprecated 105 public H5ReferenceType(FileFormat theFile, String theName, String thePath, long[] oid) 106 { 107 super(theFile, theName, thePath, oid); 108 109 log.trace("constructor theName {}", theName); 110 refdata = null; 111 } 112 113 /** 114 * Constructs a H5ReferenceType with specified class, size, byte order and sign. 115 * 116 * @param tclass 117 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 118 * @param tsize 119 * the size must be multiples H5T_STD_REF. 120 * @param torder 121 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX, 122 * ORDER_NONE and NATIVE. 123 * @param tsign 124 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 125 * 126 * @throws Exception 127 * if there is an error 128 */ 129 public H5ReferenceType(int tclass, int tsize, int torder, int tsign) throws Exception 130 { 131 this(tclass, tsize, torder, tsign, null); 132 } 133 134 /** 135 * Constructs a H5ReferenceType with specified class, size, byte order and sign. 136 * 137 * @param tclass 138 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 139 * @param tsize 140 * the size must be multiples H5T_STD_REF. 141 * @param torder 142 * the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX, 143 * ORDER_NONE and NATIVE. 144 * @param tsign 145 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE. 146 * @param tbase 147 * the base datatype of the new datatype 148 * 149 * @throws Exception 150 * if there is an error 151 */ 152 public H5ReferenceType(int tclass, int tsize, int torder, int tsign, Datatype tbase) throws Exception 153 { 154 this(tclass, tsize, torder, tsign, tbase, null); 155 } 156 157 /** 158 * Constructs a H5ReferenceType with specified class, size, byte order and sign. 159 * 160 * @param tclass 161 * the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc. 162 * @param tsize 163 * the size must be multiples H5T_STD_REF. 164 * @param torder 165 * the byte order of the datatype. Valid values are ORDER_LE, 166 * ORDER_BE, ORDER_VAX, ORDER_NONE and NATIVE. 167 * @param tsign 168 * the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and 169 * NATIVE. 170 * @param tbase 171 * the base datatype of the new datatype 172 * @param pbase 173 * the parent datatype of the new datatype 174 * 175 * @throws Exception 176 * if there is an error 177 */ 178 public H5ReferenceType(int tclass, int tsize, int torder, int tsign, Datatype tbase, Datatype pbase) 179 throws Exception 180 { 181 super(tclass, tsize, torder, tsign, tbase, pbase); 182 183 log.trace("constructor tsize {}", tsize); 184 refdata = null; 185 } 186 187 /** 188 * Constructs a H5ReferenceType with a given native datatype identifier. 189 * 190 * @see #fromNative(long nativeID) 191 * 192 * @param theFile 193 * the file that contains the datatype. 194 * @param theSize 195 * the size must be multiples H5T_STD_REF. 196 * @param nativeID 197 * the native datatype identifier. 198 * 199 * @throws Exception 200 * if there is an error 201 */ 202 public H5ReferenceType(FileFormat theFile, long theSize, long nativeID) throws Exception 203 { 204 this(theFile, theSize, nativeID, null); 205 } 206 207 /** 208 * Constructs a H5ReferenceType with a given native datatype identifier. 209 * 210 * @see #fromNative(long nativeID) 211 * 212 * @param theFile 213 * the file that contains the datatype. 214 * @param theSize 215 * the size is the number of H5ReferenceData data structs. 216 * @param nativeID 217 * the native datatype identifier. 218 * @param pbase 219 * the parent datatype of the new datatype 220 * 221 * @throws Exception 222 * if there is an error 223 */ 224 public H5ReferenceType(FileFormat theFile, long theSize, long nativeID, Datatype pbase) throws Exception 225 { 226 super(theFile, nativeID, pbase); 227 228 log.trace("constructor theSize {}", theSize); 229 refsize = theSize; 230 refdata = new ArrayList<>((int)theSize); 231 } 232 233 /** 234 * Clears memory held by the reference, such as the data buffer. 235 */ 236 @SuppressWarnings("rawtypes") 237 public void clear() 238 { 239 if (refdata != null) { 240 if (refdata instanceof List) 241 ((List)refdata).clear(); 242 originalRefBuf = null; 243 } 244 isDataLoaded = false; 245 } 246 247 /** 248 * Writes the memory buffer of this reference to file. 249 * 250 * @throws Exception if buffer can not be written 251 */ 252 public final void write() throws Exception 253 { 254 log.trace("H5ReferenceType: write enter"); 255 if (refdata != null) { 256 log.trace("H5ReferenceType: write data"); 257 // write(refdata); 258 } 259 } 260 261 /** 262 * The status of initialization for this object 263 * 264 * @return true if the data has been initialized 265 */ 266 public final boolean isInited() { return inited; } 267 268 /** 269 * setData() loads the reference raw data into the buffer. This 270 * buffer will be accessed to get the reference strings and data. 271 * Once the references are destroyed, the refdata can only be used 272 * to retrieve existing data. 273 * 274 * @param theData 275 * the data to write. 276 */ 277 public void setData(List theData) 278 { 279 log.trace("setData(List): refsize={} theData={}", refsize, theData); 280 for (int i = 0; i < (int)refsize; i++) { 281 H5ReferenceData rf = (H5ReferenceData)theData.get(i); 282 refdata.add(rf); 283 } 284 isDataLoaded = true; 285 init(); 286 } 287 288 /** 289 * setData() loads the reference raw data into the buffer. This 290 * buffer will be accessed to get the reference strings and data. 291 * Once the references are destroyed, the refdata can only be used 292 * to retrieve existing data. 293 * 294 * @param theData 295 * the data to write. 296 */ 297 public void setData(Object theData) 298 { 299 log.trace("setData(): refsize={} theData={}", refsize, theData); 300 originalRefBuf = theData; 301 for (int i = 0; i < (int)refsize; i++) { 302 byte[] refarr = new byte[(int)datatypeSize]; 303 byte[] rElements = null; 304 if (theData instanceof ArrayList) { 305 rElements = (byte[])((ArrayList)theData).get(i); 306 System.arraycopy(rElements, 0, refarr, 0, (int)datatypeSize); 307 } 308 else { 309 rElements = (byte[])theData; 310 int refIndex = (int)datatypeSize * i; 311 System.arraycopy(rElements, refIndex, refarr, 0, (int)datatypeSize); 312 } 313 log.trace("setData(): refarr={}", refarr); 314 H5ReferenceData rf = new H5ReferenceData(refarr, datatypeSize); 315 refdata.add(rf); 316 } 317 isDataLoaded = true; 318 init(); 319 } 320 321 /** 322 * Returns the data buffer of the reference in memory. 323 * 324 * If data is already loaded into memory, returns the data; otherwise, calls 325 * read() to read data from file into a memory buffer and returns the memory 326 * buffer. 327 * 328 * By default, the whole reference is read into memory. 329 * 330 * @return the memory buffer of the reference. 331 * 332 * @throws Exception if object can not be read 333 * @throws OutOfMemoryError if memory is exhausted 334 */ 335 public Object getData() throws Exception, OutOfMemoryError 336 { 337 log.trace("getData(): isDataLoaded={}", isDataLoaded); 338 if (!isDataLoaded) { 339 // refdata = read(); // load the data 340 log.trace("getData(): size={} refdata={}", refdata.size(), refdata); 341 if (refdata != null) { 342 refsize = refdata.size(); 343 originalRefBuf = refdata; 344 isDataLoaded = true; 345 } 346 } 347 348 return refdata; 349 } 350 351 /** 352 * Clears the current data buffer in memory and forces the next read() to load 353 * the data from file. 354 * 355 * The function read() loads data from file into memory only if the data is 356 * not read. If data is already in memory, read() just returns the memory 357 * buffer. Sometimes we want to force read() to re-read data from file. For 358 * example, when the selection is changed, we need to re-read the data. 359 * 360 * @see #getData() 361 */ 362 public void clearData() { isDataLoaded = false; } 363 364 /** 365 * Returns the array size of the reference. 366 * 367 * @return the array size of the reference. 368 */ 369 public final long getRefSize() 370 { 371 if (!inited) 372 init(); 373 374 return refsize; 375 } 376 377 /** 378 * Sets the array size of the reference. 379 * 380 * @param current_size 381 * the array size of the current reference. 382 */ 383 public final void setRefSize(long current_size) { refsize = current_size; } 384 // public byte[] getOriginalrData() { 385 // if (isDataLoaded) 386 // return originalRefBuf; 387 // } 388 389 /** 390 * Retrieves reference information from file into memory. 391 */ 392 public void init() 393 { 394 if (inited) { 395 log.trace("init(): H5ReferenceType already inited"); 396 return; 397 } 398 399 log.trace("init(): refsize={}", refsize); 400 for (int i = 0; i < (int)refsize; i++) { 401 H5ReferenceData rf = refdata.get(i); 402 log.trace("init(): rf.ref_array={}", rf.ref_array); 403 byte[] refarr = new byte[(int)datatypeSize]; 404 System.arraycopy(rf.ref_array, 0, refarr, 0, (int)datatypeSize); 405 406 if (zeroArrayCheck(refarr)) { 407 log.trace("init(): refarr is zero"); 408 rf.file_fullpath = "NULL"; 409 rf.file_name = "NULL"; 410 rf.obj_name = "NULL"; 411 rf.attr_name = "NULL"; 412 rf.region_type = "NULL"; 413 rf.region_desc = "NULL"; 414 } 415 else { 416 log.trace("init(): refarr={}", refarr); 417 try { 418 rf.file_fullpath = "NULL"; 419 rf.file_name = "NULL"; 420 rf.obj_name = "NULL"; 421 rf.attr_name = "NULL"; 422 if (isStdRef()) { 423 try { 424 rf.file_fullpath = H5.H5Rget_file_name(refarr); 425 log.trace("Reference Full File Path {}", rf.file_fullpath); 426 String[] split = rf.file_fullpath.split(Pattern.quote("/")); 427 rf.file_name = split[split.length - 1]; 428 log.trace("Reference File Name {}", rf.file_name); 429 rf.obj_name = H5.H5Rget_obj_name(refarr, HDF5Constants.H5P_DEFAULT); 430 log.trace("Reference Object Name {}", rf.obj_name); 431 432 if (H5.H5Rget_type(refarr) == HDF5Constants.H5R_ATTR) 433 rf.attr_name = H5.H5Rget_attr_name(refarr); 434 else 435 rf.attr_name = "NULL"; 436 log.trace("Reference Attribute Name {}", rf.attr_name); 437 } 438 catch (Exception ex) { 439 log.debug("Reference H5Rget_*_name", ex); 440 } 441 } 442 else if (isRegRef()) { 443 try { 444 rf.obj_name = 445 H5.H5Rget_name_string(getFID(), HDF5Constants.H5R_DATASET_REGION, refarr); 446 } 447 catch (Exception ex) { 448 log.debug("Reference H5Rget_*_name", ex); 449 } 450 } 451 else { 452 try { 453 rf.obj_name = H5.H5Rget_name_string(getFID(), HDF5Constants.H5R_OBJECT, refarr); 454 } 455 catch (Exception ex) { 456 log.debug("Reference H5Rget_*_name", ex); 457 } 458 } 459 initReferenceRegion(i, refarr, false); 460 } 461 catch (Exception ex) { 462 log.debug("Reference Init", ex); 463 } 464 } 465 } 466 if (isStdRef()) { 467 for (int i = 0; i < (int)refsize; i++) { 468 H5ReferenceData rf = refdata.get(i); 469 log.trace("init(): H5Rdestroy {}", rf.ref_array); 470 byte[] refarr = new byte[(int)datatypeSize]; 471 System.arraycopy(rf.ref_array, 0, refarr, 0, (int)datatypeSize); 472 H5.H5Rdestroy(refarr); 473 } 474 } 475 log.trace("init(): finished"); 476 inited = true; 477 } 478 479 private void initReferenceRegion(int refndx, byte[] refarr, boolean showData) 480 { 481 H5ReferenceData rf = refdata.get(refndx); 482 rf.ref_type = HDF5Constants.H5R_BADTYPE; 483 rf.obj_type = HDF5Constants.H5O_TYPE_UNKNOWN; 484 rf.region_type = "NULL"; 485 rf.region_desc = "NULL"; 486 log.trace("initReferenceRegion start not null"); 487 if (isStdRef()) { 488 try { 489 rf.ref_type = (int)H5.H5Rget_type(refarr); 490 log.debug("initReferenceRegion ref_type={}", rf.ref_type); 491 try { 492 rf.obj_type = H5.H5Rget_obj_type3(refarr, HDF5Constants.H5P_DEFAULT); 493 log.debug("initReferenceRegion obj_type={}", rf.obj_type); 494 } 495 catch (Exception ex2) { 496 log.debug("initReferenceRegion H5Rget_obj_type3", ex2); 497 } 498 } 499 catch (Exception ex1) { 500 log.debug("initReferenceRegion H5Rget_type", ex1); 501 } 502 503 if (rf.ref_type > HDF5Constants.H5R_BADTYPE) { 504 if (rf.ref_type == HDF5Constants.H5R_OBJECT1) { 505 log.trace("initReferenceRegion H5R_OBJECT1"); 506 if (rf.obj_type == HDF5Constants.H5O_TYPE_DATASET) { 507 initRegionDataset(refndx, refarr); 508 } // obj_type == HDF5Constants.H5O_TYPE_DATASET 509 else { 510 /* Object references -- show the type and OID of the referenced object. */ 511 rf.region_type = "H5O_TYPE_OBJ_REF"; 512 H5O_info_t objInfo; 513 long new_obj_id = HDF5Constants.H5I_INVALID_HID; 514 try { 515 new_obj_id = H5.H5Rdereference(getFID(), HDF5Constants.H5P_DEFAULT, 516 HDF5Constants.H5R_OBJECT, refarr); 517 objInfo = H5.H5Oget_info(new_obj_id); 518 if (objInfo.type == HDF5Constants.H5O_TYPE_GROUP) 519 rf.region_desc = "GROUP"; 520 else if (objInfo.type == HDF5Constants.H5O_TYPE_DATASET) 521 rf.region_desc = "DATASET"; 522 else if (objInfo.type == HDF5Constants.H5O_TYPE_NAMED_DATATYPE) 523 rf.region_desc = "DATATYPE"; 524 else 525 rf.region_desc = "UNKNOWN " + objInfo.type; 526 } 527 catch (Exception ex2) { 528 log.debug("typeObjectRef ", ex2); 529 } 530 finally { 531 H5.H5Dclose(new_obj_id); 532 } 533 } 534 } 535 else if (rf.ref_type == HDF5Constants.H5R_DATASET_REGION1) { 536 log.trace("initReferenceRegion H5R_DATASET_REGION1"); 537 initRegionDataset(refndx, refarr); 538 } 539 else if (rf.ref_type == HDF5Constants.H5R_OBJECT2) { 540 log.trace("initReferenceRegion H5R_OBJECT2"); 541 rf.region_type = "H5O_TYPE_OBJ_REF"; 542 } 543 else if (rf.ref_type == HDF5Constants.H5R_DATASET_REGION2) { 544 log.trace("initReferenceRegion H5R_DATASET_REGION2"); 545 initRegionDataset(refndx, refarr); 546 } 547 else if (rf.ref_type == HDF5Constants.H5R_ATTR) { 548 log.trace("initReferenceRegion H5R_ATTR"); 549 rf.region_type = "H5R_ATTR"; 550 initRegionAttribute(refndx, refarr); 551 } 552 else { 553 log.trace("initReferenceRegion OTHER"); 554 rf.region_type = "UNKNOWN"; 555 } 556 } 557 } 558 else { 559 if (isRegRef()) { 560 rf.ref_type = HDF5Constants.H5R_DATASET_REGION1; 561 rf.obj_type = HDF5Constants.H5O_TYPE_DATASET; 562 int region_type = typeObjectRef(getFID(), HDF5Constants.H5R_DATASET_REGION, refarr); 563 if (HDF5Constants.H5S_SEL_POINTS == region_type) 564 rf.region_type = "REGION_TYPE POINT"; 565 else if (HDF5Constants.H5S_SEL_HYPERSLABS == region_type) 566 rf.region_type = "REGION_TYPE BLOCK"; 567 else 568 rf.region_type = "REGION_TYPE UNKNOWN"; 569 rf.region_desc = descRegionDataset(getFID(), refarr); 570 } 571 else { 572 rf.ref_type = HDF5Constants.H5R_OBJECT1; 573 rf.obj_type = typeObjectRef(getFID(), HDF5Constants.H5R_OBJECT, refarr); 574 rf.region_type = "H5O_TYPE_OBJ_REF"; 575 } 576 } 577 log.trace("initReferenceRegion finish"); 578 } 579 580 private void initRegionAttribute(int refndx, byte[] refarr) 581 { 582 H5ReferenceData rf = refdata.get(refndx); 583 long new_obj_id = HDF5Constants.H5I_INVALID_HID; 584 try { 585 log.trace("initRegionAttribute refarr2={}:", refarr); 586 new_obj_id = H5.H5Ropen_attr(refarr, HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 587 long new_obj_sid = HDF5Constants.H5I_INVALID_HID; 588 try { 589 new_obj_sid = H5.H5Aget_space(new_obj_id); 590 long reg_ndims = H5.H5Sget_simple_extent_ndims(new_obj_sid); 591 // rf.region_desc = dump_region_attrs(regStr, new_obj_id); 592 } 593 catch (Exception ex3) { 594 log.debug("initRegionAttribute Space Open", ex3); 595 } 596 finally { 597 H5.H5Sclose(new_obj_sid); 598 } 599 log.trace("initRegionAttribute finish"); 600 } 601 catch (Exception ex2) { 602 log.debug("initRegionAttribute ", ex2); 603 } 604 finally { 605 H5.H5Aclose(new_obj_id); 606 } 607 } 608 609 private void initRegionDataset(int refndx, byte[] refarr) 610 { 611 H5ReferenceData rf = refdata.get(refndx); 612 long new_obj_id = HDF5Constants.H5I_INVALID_HID; 613 try { 614 log.trace("initRegionDataset refarr2={}:", refarr); 615 new_obj_id = H5.H5Ropen_object(refarr, HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 616 long new_obj_sid = HDF5Constants.H5I_INVALID_HID; 617 try { 618 log.trace("initRegionDataset refarr3={}:", refarr); 619 new_obj_sid = H5.H5Ropen_region(refarr, HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT); 620 try { 621 int region_type = H5.H5Sget_select_type(new_obj_sid); 622 log.debug("Reference Region Type {}", region_type); 623 long reg_ndims = H5.H5Sget_simple_extent_ndims(new_obj_sid); 624 StringBuilder sb = new StringBuilder(); 625 if (HDF5Constants.H5S_SEL_POINTS == region_type) { 626 rf.region_type = "REGION_TYPE POINT"; 627 long reg_npoints = H5.H5Sget_select_elem_npoints(new_obj_sid); 628 long getcoord[] = new long[(int)(reg_ndims * reg_npoints)]; 629 try { 630 H5.H5Sget_select_elem_pointlist(new_obj_sid, 0, reg_npoints, getcoord); 631 } 632 catch (Exception ex5) { 633 log.debug("initRegionDataset H5.H5Sget_select_elem_pointlist: ", ex5); 634 } 635 sb.append("{ "); 636 for (int i = 0; i < (int)reg_npoints; i++) { 637 if (i > 0) 638 sb.append(" "); 639 sb.append("("); 640 for (int j = 0; j < (int)reg_ndims; j++) { 641 if (j > 0) 642 sb.append(","); 643 sb.append(getcoord[i * (int)reg_ndims + j]); 644 } 645 sb.append(")"); 646 } 647 sb.append(" }"); 648 rf.region_desc = sb.toString(); 649 } 650 else if (HDF5Constants.H5S_SEL_HYPERSLABS == region_type) { 651 rf.region_type = "REGION_TYPE BLOCK"; 652 long reg_nblocks = H5.H5Sget_select_hyper_nblocks(new_obj_sid); 653 long getblocks[] = new long[(int)(reg_ndims * reg_nblocks) * 2]; 654 try { 655 H5.H5Sget_select_hyper_blocklist(new_obj_sid, 0, reg_nblocks, getblocks); 656 } 657 catch (Exception ex5) { 658 log.debug("initRegionDataset H5.H5Sget_select_hyper_blocklist: ", ex5); 659 } 660 sb.append("{ "); 661 for (int i = 0; i < (int)reg_nblocks; i++) { 662 if (i > 0) 663 sb.append(" "); 664 sb.append("("); 665 for (int j = 0; j < (int)reg_ndims; j++) { 666 if (j > 0) 667 sb.append(","); 668 sb.append(getblocks[i * 2 * (int)reg_ndims + j]); 669 } 670 sb.append(")-("); 671 for (int j = 0; j < (int)reg_ndims; j++) { 672 if (j > 0) 673 sb.append(","); 674 sb.append(getblocks[i * 2 * (int)reg_ndims + (int)reg_ndims + j]); 675 } 676 sb.append(")"); 677 } 678 sb.append(" }"); 679 rf.region_desc = sb.toString(); 680 } 681 else 682 rf.region_type = "REGION_TYPE UNKNOWN"; 683 } 684 catch (Exception ex4) { 685 log.debug("initRegionDataset Region Type", ex4); 686 } 687 } 688 catch (Exception ex3) { 689 log.debug("initRegionDataset Space Open", ex3); 690 } 691 finally { 692 H5.H5Sclose(new_obj_sid); 693 } 694 log.trace("initRegionDataset finish"); 695 } 696 catch (Exception ex2) { 697 log.debug("initRegionDataset ", ex2); 698 } 699 finally { 700 H5.H5Dclose(new_obj_id); 701 } 702 } 703 704 /** 705 * Checks if a reference datatype is all zero. 706 * 707 * @param refarr 708 * the reference datatype data to be checked. 709 * 710 * @return true is the reference datatype data is all zero; otherwise returns false. 711 */ 712 public static final boolean zeroArrayCheck(final byte[] refarr) 713 { 714 for (byte b : refarr) { 715 if (b != 0) 716 return false; 717 } 718 return true; 719 } 720 721 /** 722 * Get the reference datatype reference name. 723 * 724 * @param refarr 725 * the reference datatype data to be queried. 726 * 727 * @return the reference datatype name string, null otherwise. 728 */ 729 public final String getObjectReferenceName(byte[] refarr) 730 { 731 if (!inited) 732 init(); 733 734 // find the index that matches refarr and ref_array 735 H5ReferenceData rf = null; 736 for (int i = 0; i < (int)refsize; i++) { 737 byte[] theref = refdata.get(i).ref_array; 738 if (Arrays.equals(theref, refarr)) { 739 rf = refdata.get(i); 740 break; 741 } 742 } 743 if (rf == null) 744 return null; 745 746 StringBuilder sb = new StringBuilder(); 747 if (!rf.obj_name.equals("NULL")) { 748 sb.append(rf.obj_name); 749 } 750 if (!rf.attr_name.equals("NULL")) { 751 if (sb.length() > 0) 752 sb.append("/"); 753 sb.append(rf.attr_name); 754 } 755 if (!rf.region_desc.equals("NULL")) { 756 if (sb.length() > 0) 757 sb.append(" "); 758 sb.append(rf.region_desc); 759 } 760 log.debug("Reference Object Name {}", sb); 761 return sb.toString(); 762 } 763 764 /** 765 * Get the reference datatype reference name. 766 * 767 * @param refarr 768 * the reference datatype data to be queried. 769 * 770 * @return the reference datatype name string, null otherwise. 771 */ 772 public final String getFullReferenceName(byte[] refarr) 773 { 774 if (!inited) 775 init(); 776 777 // find the index that matches refarr and ref_array 778 H5ReferenceData rf = null; 779 for (int i = 0; i < (int)refsize; i++) { 780 byte[] theref = refdata.get(i).ref_array; 781 if (Arrays.equals(theref, refarr)) { 782 rf = refdata.get(i); 783 break; 784 } 785 } 786 if (rf == null) 787 return null; 788 789 StringBuilder sb = new StringBuilder(); 790 if (!rf.file_name.equals("NULL")) 791 sb.append(rf.file_name); 792 if (!rf.obj_name.equals("NULL")) { 793 if (sb.length() > 0) 794 sb.append("/"); 795 sb.append(rf.obj_name); 796 } 797 if (!rf.attr_name.equals("NULL")) { 798 if (sb.length() > 0) 799 sb.append("/"); 800 sb.append(rf.attr_name); 801 } 802 if (!rf.region_desc.equals("NULL")) { 803 if (sb.length() > 0) 804 sb.append(" "); 805 sb.append(rf.region_desc); 806 } 807 log.debug("Full Reference Name {}", sb); 808 return sb.toString(); 809 } 810 811 /** 812 * Get the reference datatype dataset region reference as string. 813 * 814 * @param refarr 815 * the reference datatype data to be queried. 816 * 817 * @return the reference datatype name string, null otherwise. 818 */ 819 public final String getRegionDataset(byte[] refarr) 820 { 821 if (!inited) 822 init(); 823 824 // find the index that matches refarr and ref_array 825 H5ReferenceData rf = null; 826 for (int i = 0; i < (int)refsize; i++) { 827 byte[] theref = refdata.get(i).ref_array; 828 if (Arrays.equals(theref, refarr)) { 829 rf = refdata.get(i); 830 break; 831 } 832 } 833 if (rf == null) 834 return null; 835 836 StringBuilder sb = new StringBuilder(); 837 sb.append(rf.region_type); 838 if (!rf.region_desc.equals("NULL")) { 839 if (sb.length() > 0) 840 sb.append(" "); 841 sb.append(rf.region_desc); 842 } 843 log.debug("getRegionDataset Value {}", sb); 844 return sb.toString(); 845 } 846 847 /** 848 * Get the reference datatype data. 849 * 850 * @param refarr 851 * the reference datatype data to be queried. 852 * 853 * @return the reference datatype data. 854 */ 855 public final H5ReferenceData getReferenceData(byte[] refarr) 856 { 857 if (!inited) 858 init(); 859 860 // find the index that matches refarr and ref_array 861 H5ReferenceData rf = null; 862 for (int i = 0; i < (int)refsize; i++) { 863 byte[] theref = refdata.get(i).ref_array; 864 if (Arrays.equals(theref, refarr)) { 865 rf = refdata.get(i); 866 break; 867 } 868 } 869 return rf; 870 } 871 872 /** 873 * Get the reference datatype region reference as string. 874 * 875 * @param refarr 876 * the reference datatype data to be queried. 877 * @param showData 878 * show the reference region dims 879 * 880 * @return the reference datatype name string, null otherwise. 881 */ 882 public final String getReferenceRegion(byte[] refarr, boolean showData) 883 { 884 if (!inited) 885 init(); 886 887 log.trace("getReferenceRegion refarr {}", refarr); 888 // find the index that matches refarr and ref_array 889 H5ReferenceData rf = null; 890 for (int i = 0; i < (int)refsize; i++) { 891 byte[] theref = refdata.get(i).ref_array; 892 log.trace("getReferenceRegion theref {}", theref); 893 if (Arrays.equals(theref, refarr)) { 894 rf = refdata.get(i); 895 log.trace("getReferenceRegion rf {}", rf); 896 break; 897 } 898 } 899 if (rf == null) 900 return null; 901 902 StringBuilder objsb = new StringBuilder(); 903 if (!rf.file_name.equals("NULL")) 904 objsb.append(rf.file_name); 905 if (!rf.obj_name.equals("NULL")) { 906 objsb.append(rf.obj_name); 907 } 908 if (!rf.attr_name.equals("NULL")) { 909 if (objsb.length() > 0) 910 objsb.append("/"); 911 objsb.append(rf.attr_name); 912 } 913 log.debug("getReferenceRegion Region Name {}", objsb); 914 915 StringBuilder regsb = new StringBuilder(); 916 if (!rf.region_type.equals("NULL")) 917 regsb.append(rf.region_type); 918 if (!rf.region_desc.equals("NULL")) { 919 if (regsb.length() > 0) 920 regsb.append(" "); 921 regsb.append(rf.region_desc); 922 } 923 log.debug("getReferenceRegion Region Type {}", regsb); 924 StringBuilder sb = new StringBuilder(objsb); 925 if (regsb.length() > 0) { 926 sb.append(" "); 927 sb.append(regsb); 928 } 929 if (sb.length() > 0) 930 return sb.toString(); 931 else 932 return "NULL"; 933 } 934 935 /** 936 * Returns a string representation of the data value. For 937 * example, "0, 255". 938 * 939 * For a compound datatype, it will be a 1D array of strings with field 940 * members separated by the delimiter. For example, 941 * "{0, 10.5}, {255, 20.0}, {512, 30.0}" is a compound attribute of {int, 942 * float} of three data points. 943 * 944 * @param delimiter 945 * The delimiter used to separate individual data points. It 946 * can be a comma, semicolon, tab or space. For example, 947 * toString(",") will separate data by commas. 948 * 949 * @return the string representation of the data values. 950 */ 951 public String toString(String delimiter) { return toString(delimiter, -1); } 952 953 /** 954 * Returns a string representation of the data value. 955 * 956 * @param delimiter 957 * The delimiter used to separate individual data points. It 958 * can be a comma, semicolon, tab or space. For example, 959 * toString(",") will separate data by commas. 960 * @param maxItems 961 * The maximum number of Array values to return 962 * 963 * @return the string representation of the data values. 964 */ 965 public String toString(String delimiter, int maxItems) 966 { 967 Object theData = originalRefBuf; 968 if (theData == null) { 969 log.debug("toString: value is null"); 970 return null; 971 } 972 973 if (theData instanceof List<?>) { 974 log.trace("toString: value is list"); 975 return null; 976 } 977 978 Class<? extends Object> valClass = theData.getClass(); 979 980 if (!valClass.isArray()) { 981 log.trace("toString: finish - not array"); 982 String strValue = theData.toString(); 983 if (maxItems > 0 && strValue.length() > maxItems) 984 // truncate the extra characters 985 strValue = strValue.substring(0, maxItems); 986 return strValue; 987 } 988 989 // value is an array 990 StringBuilder sb = new StringBuilder(); 991 log.trace("toString: refsize={} isStdRef={} Array.getLength={}", refsize, isStdRef(), 992 Array.getLength(theData)); 993 if (isStdRef()) { 994 String cname = valClass.getName(); 995 char dname = cname.charAt(cname.lastIndexOf('[') + 1); 996 log.trace("toString: isStdRef with cname={} dname={}", cname, dname); 997 for (int i = 0; i < (int)refsize; i++) { 998 int refIndex = HDF5Constants.H5R_REF_BUF_SIZE * i; 999 byte[] refarr = new byte[(int)HDF5Constants.H5R_REF_BUF_SIZE]; 1000 System.arraycopy(theData, refIndex, refarr, 0, (int)HDF5Constants.H5R_REF_BUF_SIZE); 1001 log.trace("toString: refarr[{}]={}", i, refarr); 1002 String refarr_str = getReferenceRegion(refarr, false); 1003 StringBuilder ref_str = null; 1004 if (refarr_str != null) { 1005 ref_str = new StringBuilder(refarr_str); 1006 if ((maxItems > 0) && (ref_str.length() > maxItems)) { 1007 ref_str.setLength(maxItems); 1008 } 1009 log.trace("toString: ref_str[{}]={}", i, ref_str); 1010 } 1011 else 1012 ref_str = new StringBuilder("NULL"); 1013 if (i > 0) 1014 sb.append(", "); 1015 sb.append(ref_str); 1016 } 1017 return sb.toString(); 1018 } 1019 return toString(delimiter, maxItems); 1020 } 1021 1022 /** 1023 * The individual reference data for a given object. 1024 */ 1025 public static class H5ReferenceData { 1026 private static final Logger log = LoggerFactory.getLogger(H5ReferenceData.class); 1027 1028 /** The reference array raw data */ 1029 public byte[] ref_array = null; 1030 1031 /** The the full file path referenced */ 1032 public String file_fullpath; 1033 1034 /** The file name referenced */ 1035 public String file_name; 1036 1037 /** The object name referenced */ 1038 public String obj_name; 1039 1040 /** The attribute name referenced */ 1041 public String attr_name; 1042 1043 /** The type of region referenced */ 1044 public String region_type; 1045 1046 /** The point/block description of region referenced */ 1047 public String region_desc; 1048 1049 /** The default type of region referenced */ 1050 public int ref_type = HDF5Constants.H5R_BADTYPE; 1051 1052 /** The default type of object referenced */ 1053 public int obj_type = HDF5Constants.H5O_TYPE_UNKNOWN; 1054 1055 /** The type size of object referenced */ 1056 public long typeSize; 1057 1058 /** 1059 * Copy the individual reference array for further processing 1060 * 1061 * @param theArray the reference datatype data to be copied. 1062 * @param theTypeSize the size of the type for the array 1063 */ 1064 H5ReferenceData(byte[] theArray, long theTypeSize) 1065 { 1066 typeSize = theTypeSize; 1067 ref_array = new byte[(int)theTypeSize]; 1068 System.arraycopy(theArray, 0, ref_array, 0, (int)theTypeSize); 1069 } 1070 } 1071}