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