001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see https://support.hdfgroup.org/products/licenses.html * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object.h4; 016 017import java.io.File; 018import java.lang.reflect.Array; 019import java.util.ArrayList; 020import java.util.Iterator; 021import java.util.LinkedList; 022import java.util.List; 023import java.util.Queue; 024import java.util.Vector; 025 026import hdf.hdflib.HDFConstants; 027import hdf.hdflib.HDFException; 028import hdf.hdflib.HDFLibrary; 029 030import hdf.object.Attribute; 031import hdf.object.Dataset; 032import hdf.object.Datatype; 033import hdf.object.FileFormat; 034import hdf.object.Group; 035import hdf.object.HObject; 036 037import hdf.object.h4.H4ScalarAttribute; 038 039/** 040 * This class provides file level APIs. File access APIs include retrieving the 041 * file hierarchy, opening and closing file, and writing file content to disk. 042 * 043 * @version 2.4 9/4/2007 044 * @author Peter X. Cao 045 */ 046public class H4File extends FileFormat { 047 private static final long serialVersionUID = 8985533001471224030L; 048 049 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H4File.class); 050 051 /** 052 * the file access flag. 053 */ 054 private int flag; 055 056 /** 057 * The root object of this file. 058 */ 059 private HObject rootObject; 060 061 /** 062 * The list of unique (tag, ref) pairs. It is used to avoid duplicate 063 * objects in memory. 064 */ 065 @SuppressWarnings("rawtypes") 066 private List objList; 067 068 /** 069 * The GR interface identifier. The identifier is returned by GRstart(fid), 070 * which initializes the GR interface for the file specified by the 071 * parameter. GRstart(fid) is an expensive call. It should be called only 072 * once. Calling GRstart(fid) in a loop should be avoided. 073 */ 074 private long grid; 075 076 /** if this is a netcdf file */ 077 private boolean isNetCDF = false; 078 079 /** 080 * The SDS interface identifier. The identifier is returned by 081 * SDstart(fname, flag), which initializes the SD interface for the file 082 * specified by the parameter. SDstart(fname, flag) is an expensive call. It 083 * should be called only once. Calling SDstart(fname, flag) in a loop should 084 * be avoided. 085 */ 086 private long sdid; 087 088 /** 089 * secret flag: show CDF0.0, etc., to help debug 090 */ 091 private boolean showAll = false; 092 093 /** 094 * Creates an H4File with read write access. 095 */ 096 public H4File() { 097 this("", WRITE); 098 } 099 100 /** 101 * Creates an H4File with read write access. 102 * 103 * @param pathname 104 * The file path string. 105 */ 106 public H4File(String pathname) { 107 this(pathname, WRITE); 108 } 109 110 /** 111 * Creates an H4File instance with specified file name and access. 112 * 113 * The access parameter values and corresponding behaviors: 114 * <ul> 115 * <li>READ: Read-only access; open() will fail if file doesn't exist. 116 * <li>WRITE: Read/Write access; if file doesn't exist, open() will create 117 * it; open() will fail if read/write access not allowed. 118 * <li>CREATE: Read/Write access; create a new file or truncate an existing 119 * one; open() will fail if file can't be created or if file exists but 120 * can't be opened read/write. 121 * </ul> 122 * 123 * This constructor does not open the file for access, nor does it confirm 124 * that the file can later be opened read/write or created. 125 * 126 * The flag returned by {@link #isReadOnly()} is set to true if the access 127 * parameter value is READ, even though the file isn't yet open. 128 * 129 * @param fileName 130 * A valid file name, with a relative or absolute path. 131 * @param access 132 * The file access flag, which determines behavior when file is 133 * opened. Acceptable values are <code> READ, WRITE, </code> and 134 * <code>CREATE</code>. 135 * 136 * @throws NullPointerException 137 * If the <code>fileName</code> argument is <code>null</code>. 138 */ 139 @SuppressWarnings("rawtypes") 140 public H4File(String fileName, int access) { 141 super(fileName); 142 143 isReadOnly = (access == READ); 144 objList = new Vector(); 145 146 this.fid = -1; 147 148 if ((access & FILE_CREATE_OPEN) == FILE_CREATE_OPEN) { 149 File f = new File(fileName); 150 if (f.exists()) 151 access = WRITE; 152 else 153 access = CREATE; 154 } 155 156 if (access == READ) 157 flag = HDFConstants.DFACC_READ; 158 else if (access == WRITE) 159 flag = HDFConstants.DFACC_WRITE; 160 else if (access == CREATE) 161 flag = HDFConstants.DFACC_CREATE; 162 else 163 flag = access; 164 165 if (log != null) log.trace("File: {} isReadOnly={} accessType={}", fileName, isReadOnly, flag); 166 167 String shwAll = System.getProperty("h4showall"); 168 if (shwAll != null) { 169 showAll = true; 170 if (log != null) log.debug("show all is on"); 171 } 172 else { 173 if (log != null) log.debug("show all is off"); 174 } 175 } 176 177 /** 178 * Checks if the given file format is an HDF4 file. 179 * 180 * @param fileformat 181 * the fileformat to be checked. 182 * 183 * @return true if the given file is an HDF4 file; otherwise returns false. 184 */ 185 @Override 186 public boolean isThisType(FileFormat fileformat) { 187 return (fileformat instanceof H4File); 188 } 189 190 /** 191 * Checks if the given file is an HDF4 file or netCDF. HDF4 library supports 192 * netCDF version 2.3.2. It only supports SDS APIs. 193 * 194 * @param filename 195 * the file to be checked. 196 * 197 * @return true if the given file is an HDF4 file; otherwise returns false. 198 */ 199 @Override 200 public boolean isThisType(String filename) { 201 boolean isH4 = false; 202 203 try { 204 isH4 = HDFLibrary.Hishdf(filename); 205 } 206 catch (HDFException ex) { 207 isH4 = false; 208 } 209 210 if (!isH4) 211 isH4 = isNetCDF(filename); 212 213 log.trace("isThisType(): isH4={}", isH4); 214 return isH4; 215 } 216 217 /** 218 * Creates an HDF4 file with the specified name and returns a new H4File 219 * instance associated with the file. 220 * 221 * @throws HDFException 222 * If the file cannot be created or if createFlag has unexpected value. 223 * 224 * @see hdf.object.FileFormat#createFile(java.lang.String, int) 225 * @see #H4File(String, int) 226 */ 227 @Override 228 public FileFormat createFile(String filename, int createFlag) throws Exception { 229 // Flag if we need to create or truncate the file. 230 Boolean doCreateFile = true; 231 232 // Won't create or truncate if CREATE_OPEN specified and file exists 233 if (createFlag == FILE_CREATE_OPEN) { 234 File f = new File(filename); 235 if (f.exists()) { 236 doCreateFile = false; 237 } 238 } 239 240 log.trace("createFile(): doCreateFile={}", doCreateFile); 241 242 if (doCreateFile) { 243 long fileid = HDFLibrary.Hopen(filename, HDFConstants.DFACC_CREATE); 244 try { 245 HDFLibrary.Hclose(fileid); 246 } 247 catch (HDFException ex) { 248 log.debug("Hclose failure: ", ex); 249 } 250 } 251 252 return new H4File(filename, WRITE); 253 } 254 255 /** 256 * Creates an H4File instance with specified file name and access. 257 * 258 * @see hdf.object.FileFormat#createInstance(java.lang.String, int) 259 * @see #H4File(String, int) 260 */ 261 @Override 262 public FileFormat createInstance(String filename, int access) throws Exception { 263 return new H4File(filename, access); 264 } 265 266 // Implementing FileFormat 267 @Override 268 public long open() throws Exception { 269 if (fid >= 0) { 270 log.trace("open(): File {} already open", fid); 271 return fid; // file is opened already 272 } 273 274 // check for valid file access permission 275 if (flag < 0) { // invalid access id 276 throw new HDFException("Invalid access identifer -- " + flag); 277 } 278 else if (flag == HDFConstants.DFACC_READ) { 279 if (!exists()) { 280 log.debug("File {} does not exist", fullFileName); 281 throw new HDFException("File does not exist -- " + fullFileName); 282 } 283 else if (exists() && !canRead()) { 284 log.debug("Cannot read file {}", fullFileName); 285 throw new HDFException("Cannot read file -- " + fullFileName); 286 } 287 } 288 else if ((flag == HDFConstants.DFACC_WRITE) || (flag == HDFConstants.DFACC_CREATE)) { 289 if (exists() && !canWrite()) { 290 log.debug("Cannot write file {}, try opening as read-only", fullFileName); 291 throw new HDFException("Cannot write file, try opening as read-only -- " + fullFileName); 292 } 293 } 294 295 // Only check for NetCDF if the file exists, else isNetCDF() throws an exception 296 if (exists()) 297 isNetCDF = isNetCDF(fullFileName); 298 if (isNetCDF) 299 isReadOnly = true; // read only for netCDF 300 log.trace("open(): isNetCDF={}", isNetCDF); 301 302 // only support SDS APIs for netCDF 303 if (isNetCDF) { 304 fid = 0; 305 } 306 else { 307 log.trace("HDFLibrary - open({},{})", fullFileName, flag); 308 fid = HDFLibrary.Hopen(fullFileName, flag); 309 HDFLibrary.Vstart(fid); 310 grid = HDFLibrary.GRstart(fid); 311 log.trace("open(): fid:{} grid:{}", fid, grid); 312 } 313 314 try { 315 sdid = HDFLibrary.SDstart(fullFileName, flag & ~HDFConstants.DFACC_CREATE); 316 317 if (sdid < 0) 318 log.debug("open(): SDstart failed!"); 319 } 320 catch (HDFException ex) { 321 log.debug("open(): SDstart failure: ", ex); 322 } 323 324 log.trace("open(): sdid:{}", sdid); 325 326 // load the file hierarchy 327 loadIntoMemory(); 328 329 return fid; 330 } 331 332 // Implementing FileFormat 333 @Override 334 public void close() throws HDFException { 335 // clean unused objects 336 if (rootObject != null) { 337 HObject theObj = null; 338 Iterator<HObject> it = getMembersBreadthFirst(rootObject).iterator(); 339 while (it.hasNext()) { 340 theObj = it.next(); 341 342 if (theObj instanceof Dataset) 343 ((Dataset) theObj).clearData(); 344 else if (theObj instanceof Group) 345 ((Group) theObj).clear(); 346 } 347 } 348 349 try { 350 HDFLibrary.GRend(grid); 351 } 352 catch (HDFException ex) { 353 log.debug("close(): GRend failure: ", ex); 354 } 355 try { 356 HDFLibrary.SDend(sdid); 357 } 358 catch (HDFException ex) { 359 log.debug("close(): SDend failure: ", ex); 360 } 361 try { 362 HDFLibrary.Vend(fid); 363 } 364 catch (HDFException ex) { 365 log.debug("close(): Vend failure: ", ex); 366 } 367 368 HDFLibrary.Hclose(fid); 369 370 fid = -1; 371 objList = null; 372 } 373 374 // Implementing FileFormat 375 @Override 376 public HObject getRootObject() { 377 return rootObject; 378 } 379 380 @Override 381 public Group createGroup(String name, Group pgroup) throws Exception { 382 return H4Group.create(name, pgroup); 383 } 384 385 @Override 386 public Datatype createDatatype(int tclass, int tsize, int torder, int tsign) throws Exception { 387 return new H4Datatype(tclass, tsize, torder, tsign); 388 } 389 390 @Override 391 public Datatype createDatatype(int tclass, int tsize, int torder, int tsign, Datatype tbase) throws Exception { 392 return new H4Datatype(tclass, tsize, torder, tsign); 393 } 394 395 @Override 396 public Datatype createNamedDatatype(Datatype tnative, String name) throws Exception { 397 throw new UnsupportedOperationException("HDF4 does not support named datatype."); 398 } 399 400 @Override 401 public Dataset createScalarDS(String name, Group pgroup, Datatype type, 402 long[] dims, long[] maxdims, long[] chunks, 403 int gzip, Object fillValue, Object data) throws Exception { 404 return H4SDS.create(name, pgroup, type, dims, maxdims, chunks, gzip, fillValue, data); 405 } 406 407 @Override 408 public Dataset createImage(String name, Group pgroup, Datatype type, 409 long[] dims, long[] maxdims, long[] chunks, 410 int gzip, int ncomp, int interlace, Object data) throws Exception { 411 return H4GRImage.create(name, pgroup, type, dims, maxdims, chunks, gzip, ncomp, interlace, data); 412 } 413 414 /** 415 * Delete an object from the file. 416 * 417 * @param obj 418 * the data object to delete. 419 * 420 * @throws Exception if the object can not be deleted 421 */ 422 @Override 423 public void delete(HObject obj) throws Exception { 424 throw new UnsupportedOperationException("Cannot delete HDF4 object."); 425 } 426 427 /** 428 * Copy an object to a group. 429 * 430 * @param srcObj 431 * the object to copy. 432 * @param dstGroup 433 * the destination group. 434 * 435 * @return the destination group, if the copy was successful, or 436 * null otherwise. 437 * 438 * @throws Exception if the object can not be copied 439 */ 440 @Override 441 public HObject copy(HObject srcObj, Group dstGroup, String dstName) throws Exception { 442 log.trace("copy(): start: srcObj={} dstGroup={} dstName={}", srcObj, dstGroup, dstName); 443 444 if ((srcObj == null) || (dstGroup == null)) { 445 log.debug("copy(): source or destination is null"); 446 return null; 447 } 448 449 if (dstName == null) { 450 dstName = srcObj.getName(); 451 log.trace("copy(): dstName is null, using dstName={}", dstName); 452 } 453 454 HObject newObj = null; 455 if (srcObj instanceof H4SDS) { 456 log.trace("copy(): srcObj instanceof H4SDS"); 457 newObj = ((H4SDS) srcObj).copy(dstGroup, dstName, null, null); 458 } 459 else if (srcObj instanceof H4GRImage) { 460 log.trace("copy(): srcObj instanceof H4GRImage"); 461 newObj = ((H4GRImage) srcObj).copy(dstGroup, dstName, null, null); 462 } 463 else if (srcObj instanceof H4Vdata) { 464 log.trace("copy(): srcObj instanceof H4Vdata"); 465 newObj = ((H4Vdata) srcObj).copy(dstGroup, dstName, null, null); 466 } 467 else if (srcObj instanceof H4Group) { 468 log.trace("copy(): srcObj instanceof H4Group"); 469 newObj = copyGroup((H4Group) srcObj, (H4Group) dstGroup); 470 } 471 472 return newObj; 473 } 474 475 /** 476 * Creates a new attribute and attaches it to the object if the 477 * attribute does not exist. Otherwise, just update the value of 478 * the attribute. 479 * 480 * @param obj 481 * the object which the attribute is to be attached to. 482 * @param attr 483 * the attribute to attach. 484 * @param isSDglobalAttr 485 * The indicator if the given attribute exists. 486 * 487 * @throws HDFException if the attribute can not be written 488 */ 489 @Override 490 public void writeAttribute(HObject obj, Attribute attr, boolean isSDglobalAttr) throws HDFException { 491 log.trace("writeAttribute(): start: obj={} attribute={} isSDglobalAttr={}", obj, attr, isSDglobalAttr); 492 493 String attrName = attr.getAttributeName(); 494 long attrType = attr.getAttributeDatatype().createNative(); 495 long[] dims = attr.getAttributeDims(); 496 int count = 1; 497 if (dims != null) { 498 for (int i = 0; i < dims.length; i++) 499 count *= (int) dims[i]; 500 } 501 502 log.trace("writeAttribute(): count={}", count); 503 504 Object attrValue; 505 try { 506 attrValue = attr.getAttributeData(); 507 } 508 catch (Exception ex) { 509 attrValue = null; 510 log.trace("writeAttribute(): getData() failure:", ex); 511 } 512 513 if (Array.get(attrValue, 0) instanceof String) { 514 String strValue = (String) Array.get(attrValue, 0); 515 516 if (strValue.length() > count) { 517 // truncate the extra characters 518 strValue = strValue.substring(0, count); 519 Array.set(attrValue, 0, strValue); 520 } 521 else { 522 // pad space to the unused space 523 for (int i = strValue.length(); i < count; i++) { 524 strValue += " "; 525 } 526 } 527 528 byte[] bval = strValue.getBytes(); 529 // add null to the end to get rid of the junks 530 bval[(strValue.length() - 1)] = 0; 531 attrValue = bval; 532 } 533 534 if ((obj instanceof H4Group) && ((H4Group) obj).isRoot()) { 535 if (isSDglobalAttr) 536 HDFLibrary.SDsetattr(sdid, attrName, attrType, count, attrValue); 537 else 538 HDFLibrary.GRsetattr(grid, attrName, attrType, count, attrValue); 539 log.trace("writeAttribute(): wrote attribute to root H4Group"); 540 return; 541 } 542 543 long id = obj.open(); 544 545 if (id >= 0) { 546 if (obj instanceof H4Group) { 547 HDFLibrary.Vsetattr(id, attrName, attrType, count, attrValue); 548 log.trace("writeAttribute(): wrote attribute to H4Group"); 549 } 550 else if (obj instanceof H4SDS) { 551 HDFLibrary.SDsetattr(id, attrName, attrType, count, attrValue); 552 log.trace("writeAttribute(): wrote attribute to H4SDS"); 553 } 554 else if (obj instanceof H4GRImage) { 555 HDFLibrary.GRsetattr(id, attrName, attrType, count, attrValue); 556 log.trace("writeAttribute(): wrote attribute to H4GRImage"); 557 } 558 else if (obj instanceof H4Vdata) { 559 HDFLibrary.VSsetattr(id, -1, attrName, attrType, count, attrValue); 560 log.trace("writeAttribute(): wrote attribute to H4Vdata"); 561 } 562 563 obj.close(id); 564 } 565 } 566 567 private HObject copyGroup(H4Group srcGroup, H4Group pgroup) throws Exception { 568 log.trace("copyGroup(): start: srcGroup={} parentGroup={}", srcGroup, pgroup); 569 570 H4Group group = null; 571 long srcgid = -1; 572 long dstgid = -1; 573 String gname = null; 574 String path = null; 575 576 dstgid = HDFLibrary.Vattach(fid, -1, "w"); 577 if (dstgid < 0) { 578 log.trace("copyGroup(): Invalid dst Group Id"); 579 return null; 580 } 581 582 gname = srcGroup.getName(); 583 srcgid = srcGroup.open(); 584 585 HDFLibrary.Vsetname(dstgid, gname); 586 int ref = HDFLibrary.VQueryref(dstgid); 587 int tag = HDFLibrary.VQuerytag(dstgid); 588 589 if (pgroup.isRoot()) { 590 path = HObject.SEPARATOR; 591 } 592 else { 593 // add the dataset to the parent group 594 path = pgroup.getPath() + pgroup.getName() + HObject.SEPARATOR; 595 long pid = pgroup.open(); 596 HDFLibrary.Vinsert(pid, dstgid); 597 pgroup.close(pid); 598 } 599 600 // copy attributes 601 int numberOfAttributes = 0; 602 try { 603 numberOfAttributes = HDFLibrary.Vnattrs(srcgid); 604 } 605 catch (Exception ex) { 606 log.debug("copyGroup(): Vnattrs failure: ", ex); 607 numberOfAttributes = 0; 608 } 609 610 String[] attrName = new String[1]; 611 byte[] attrBuff = null; 612 int[] attrInfo = new int[3]; // data_type, count, size 613 for (int i = 0; i < numberOfAttributes; i++) { 614 try { 615 attrName[0] = ""; 616 HDFLibrary.Vattrinfo(srcgid, i, attrName, attrInfo); 617 attrBuff = new byte[attrInfo[2]]; 618 HDFLibrary.Vgetattr(srcgid, i, attrBuff); 619 HDFLibrary.Vsetattr(dstgid, attrName[0], attrInfo[0], 620 attrInfo[2], attrBuff); 621 } 622 catch (Exception ex) { 623 log.trace("copyGroup(): failure: ", ex); 624 } 625 } 626 627 long[] oid = { tag, ref }; 628 group = new H4Group(this, gname, path, pgroup, oid); 629 630 pgroup.addToMemberList(group); 631 632 // copy members of the source group to the new group 633 List<HObject> members = srcGroup.getMemberList(); 634 if ((members != null) && !members.isEmpty()) { 635 Iterator<HObject> iterator = members.iterator(); 636 while (iterator.hasNext()) { 637 HObject mObj = iterator.next(); 638 try { 639 copy(mObj, group, mObj.getName()); 640 } 641 catch (Exception ex) { 642 log.debug("copy(): failure: ", ex); 643 } 644 } 645 } 646 647 srcGroup.close(srcgid); 648 649 if (dstgid >= 0) { 650 try { 651 HDFLibrary.Vdetach(dstgid); 652 } 653 catch (Exception ex) { 654 log.debug("copyGroup(): Vdetach failure: ", ex); 655 } 656 } 657 658 return group; 659 } 660 661 /** 662 * Retrieves the file structure from disk and returns the root object. 663 * 664 * First gets the top level objects or objects that do not belong to any 665 * groups. If a top level object is a group, call the depth_first() to 666 * retrieve the sub-tree of that group, recursively. 667 */ 668 private void loadIntoMemory() { 669 if (fid < 0) { 670 log.debug("loadIntoMemory(): Invalid File Id"); 671 return; 672 } 673 674 int n = 0; 675 int ref = -1; 676 int[] argv = null; 677 678 // get top level VGroup 679 int[] tmpN = new int[1]; 680 int[] refs = null; 681 682 try { 683 // first call to get the number of lone Vgroups 684 log.trace("loadIntoMemory(): first call to Vlone: get number of lone Vgroups"); 685 n = HDFLibrary.Vlone(fid, tmpN, 0); 686 log.trace("loadIntoMemory(): number of lone Vgroups={}", n); 687 refs = new int[n]; 688 689 // second call to get the references of all lone Vgroups 690 log.trace("loadIntoMemory(): second call to Vlone: get references of lone Vgroups"); 691 n = HDFLibrary.Vlone(fid, refs, n); 692 } 693 catch (HDFException ex) { 694 log.trace("loadIntoMemory(): get Vlone failure: ", ex); 695 n = 0; 696 } 697 698 /* 699 * TODO: Root group's name should be changed to 'this.getName()' and all 700 * previous accesses of this field should now use getPath() instead of getName() 701 * to get the root group. The root group actually does have a path of "/". The 702 * depth_first method will have to be changed to setup other object paths 703 * appropriately, as it currently assumes the root path to be null. 704 */ 705 long[] oid = { 0, 0 }; 706 // root object does not have a parent path or a parent object 707 rootObject = new H4Group(this, "/", null, null, oid); 708 709 int i0 = Math.max(0, getStartMembers()); 710 int i1 = getMaxMembers(); 711 if (i1 >= n) { 712 i1 = n; 713 i0 = 0; // load all members 714 } 715 i1 += i0; 716 i1 = Math.min(i1, n); 717 718 // Iterate through the file to see members of the group 719 log.trace("loadIntoMemory(): start={} to last={}", i0, i1); 720 for (int i = i0; i < i1; i++) { 721 ref = refs[i]; 722 log.trace("loadIntoMemory(): Iterate[{}] members of the group ref={}",i,ref); 723 H4Group g = getVGroup(HDFConstants.DFTAG_VG, ref, HObject.SEPARATOR, (H4Group) rootObject, false); 724 725 if (g != null) { 726 ((H4Group) rootObject).addToMemberList(g); 727 728 // recursively get the sub-tree 729 depth_first(g); 730 } 731 } 732 733 // get the top level GR images 734 argv = new int[2]; 735 boolean b = false; 736 try { 737 b = HDFLibrary.GRfileinfo(grid, argv); 738 } 739 catch (HDFException ex) { 740 log.debug("loadIntoMemory(): GRfileinfo failure: ",ex); 741 b = false; 742 } 743 744 if (b) { 745 n = argv[0]; 746 747 for (int i = 0; i < n; i++) { 748 // no duplicate object at top level 749 H4GRImage gr = getGRImage(HDFConstants.DFTAG_RIG, i, HObject.SEPARATOR, false); 750 if (gr != null) { 751 ((H4Group) rootObject).addToMemberList(gr); 752 } 753 } // (int i=0; i<n; i++) 754 } // ( grid!=HDFConstants.FAIL && HDFLibrary.GRfileinfo(grid,argv) ) 755 756 // get top level SDS 757 try { 758 b = HDFLibrary.SDfileinfo(sdid, argv); 759 } 760 catch (HDFException ex) { 761 log.debug("loadIntoMemory(): SDfileinfo failure: ",ex); 762 b = false; 763 } 764 765 if (b) { 766 n = argv[0]; 767 for (int i = 0; i < n; i++) { 768 // no duplicate object at top level 769 H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, i, HObject.SEPARATOR, false); 770 if (sds != null) 771 ((H4Group) rootObject).addToMemberList(sds); 772 } 773 } // (HDFLibrary.SDfileinfo(sdid, argv)) 774 775 // get top level VData 776 try { 777 n = HDFLibrary.VSlone(fid, tmpN, 0); 778 log.trace("loadIntoMemory(): number of lone Vdatas={}", n); 779 refs = new int[n]; 780 n = HDFLibrary.VSlone(fid, refs, n); 781 } 782 catch (HDFException ex) { 783 log.debug("loadIntoMemory(): VSlone failure: ",ex); 784 n = 0; 785 } 786 787 for (int i = 0; i < n; i++) { 788 ref = refs[i]; 789 log.trace("loadIntoMemory(): references of Vdata[{}]={}", i, ref); 790 791 // no duplicate object at top level 792 H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref, HObject.SEPARATOR, false); 793 794 if (vdata != null) 795 ((H4Group) rootObject).addToMemberList(vdata); 796 } 797 798 if (rootObject != null) { 799 // retrieve file annotation, GR and SDS global attributes 800 @SuppressWarnings("rawtypes") 801 List attributeList = null; 802 try { 803 attributeList = ((H4Group) rootObject).getMetadata(); 804 } 805 catch (HDFException ex) { 806 log.debug("loadIntoMemory(): getMetadata failure: ", ex); 807 } 808 809 try { 810 getFileAnnotation(fid, attributeList); 811 } 812 catch (HDFException ex) { 813 log.debug("loadIntoMemory(): getFileAnnotation failure: ", ex); 814 } 815 try { 816 getGRglobalAttribute(grid, attributeList); 817 } 818 catch (HDFException ex) { 819 log.debug("loadIntoMemory(): getGRglobalAttribute failure: ", ex); 820 } 821 try { 822 getSDSglobalAttribute(sdid, attributeList); 823 } 824 catch (HDFException ex) { 825 log.debug("loadIntoMemory(): getSDglobalAttribute failure: ", ex); 826 } 827 } 828 829 } 830 831 /** 832 * Retrieves the tree structure of the file by depth-first order. The 833 * current implementation only retrieves groups and datasets. It does not 834 * include named datatypes and soft links. 835 * 836 * @param parentObject 837 * the parent object. 838 */ 839 private void depth_first(HObject parentObj) { 840 log.trace("depth_first(pobj = {})", parentObj); 841 842 if (parentObj == null) { 843 log.debug("depth_first(): Parent object is null"); 844 return; 845 } 846 847 int nelems = 0; 848 int ref = -1; 849 int tag = -1; 850 int index = -1; 851 int[] tags = null; 852 int[] refs = null; 853 854 H4Group parentGroup = (H4Group) parentObj; 855 856 String fullPath = parentGroup.getPath() + parentGroup.getName() + HObject.SEPARATOR; 857 long gid = parentGroup.open(); 858 if (gid == HDFConstants.FAIL) { 859 log.debug("depth_first(): Invalid Parent group ID"); 860 return; 861 } 862 863 try { 864 nelems = HDFLibrary.Vntagrefs(gid); 865 tags = new int[nelems]; 866 refs = new int[nelems]; 867 nelems = HDFLibrary.Vgettagrefs(gid, tags, refs, nelems); 868 } 869 catch (HDFException ex) { 870 log.debug("depth_first(): failure: ", ex); 871 nelems = 0; 872 } 873 finally { 874 parentGroup.close(gid); 875 } 876 877 int i0 = Math.max(0, getStartMembers()); 878 int i1 = getMaxMembers(); 879 if (i1 >= nelems) { 880 i1 = nelems; 881 i0 = 0; // load all members 882 } 883 i1 += i0; 884 i1 = Math.min(i1, nelems); 885 886 // Iterate through the file to see members of the group 887 for (int i = i0; i < i1; i++) { 888 tag = tags[i]; 889 ref = refs[i]; 890 891 switch (tag) { 892 case HDFConstants.DFTAG_RIG: 893 case HDFConstants.DFTAG_RI: 894 case HDFConstants.DFTAG_RI8: 895 try { 896 index = HDFLibrary.GRreftoindex(grid, (short) ref); 897 } 898 catch (HDFException ex) { 899 index = HDFConstants.FAIL; 900 } 901 if (index != HDFConstants.FAIL) { 902 H4GRImage gr = getGRImage(tag, index, fullPath, true); 903 parentGroup.addToMemberList(gr); 904 } 905 break; 906 case HDFConstants.DFTAG_SD: 907 case HDFConstants.DFTAG_SDG: 908 case HDFConstants.DFTAG_NDG: 909 try { 910 index = HDFLibrary.SDreftoindex(sdid, ref); 911 } 912 catch (HDFException ex) { 913 index = HDFConstants.FAIL; 914 } 915 if (index != HDFConstants.FAIL) { 916 H4SDS sds = getSDS(tag, index, fullPath, true); 917 parentGroup.addToMemberList(sds); 918 } 919 break; 920 case HDFConstants.DFTAG_VH: 921 case HDFConstants.DFTAG_VS: 922 H4Vdata vdata = getVdata(tag, ref, fullPath, true); 923 parentGroup.addToMemberList(vdata); 924 break; 925 case HDFConstants.DFTAG_VG: 926 H4Group vgroup = getVGroup(tag, ref, fullPath, parentGroup, true); 927 parentGroup.addToMemberList(vgroup); 928 if ((vgroup != null) && (parentGroup != null)) { 929 // check for loops 930 boolean looped = false; 931 H4Group theGroup = parentGroup; 932 while ((theGroup != null) && !looped) { 933 long[] oid = { tag, ref }; 934 if (theGroup.equalsOID(oid)) { 935 looped = true; 936 } 937 else { 938 theGroup = (H4Group) theGroup.getParent(); 939 } 940 } 941 if (!looped) { 942 depth_first(vgroup); 943 } 944 } 945 break; 946 default: 947 break; 948 } // switch 949 950 } // (int i=0; i<nelms; i++) 951 } // private depth_first() 952 953 /** 954 * Returns a list of all the members of this H4File in a 955 * breadth-first ordering that are rooted at the specified 956 * object. 957 */ 958 private static List<HObject> getMembersBreadthFirst(HObject obj) { 959 List<HObject> allMembers = new ArrayList<>(); 960 Queue<HObject> queue = new LinkedList<>(); 961 HObject currentObject = obj; 962 963 queue.add(currentObject); 964 965 while(!queue.isEmpty()) { 966 currentObject = queue.remove(); 967 allMembers.add(currentObject); 968 969 if(currentObject instanceof Group) 970 queue.addAll(((Group) currentObject).getMemberList()); 971 } 972 973 return allMembers; 974 } 975 976 /** 977 * Retrieve a GR image for the given GR image identifier and index. 978 * 979 * @param tag 980 * the reference tag of the GR image. 981 * @param index 982 * the index of the image. 983 * @param path 984 * the path of the image. 985 * @param copyAllowed 986 * The indicator if multiple copies of an object is allowed. 987 * 988 * @return the new H5GRImage if successful; otherwise returns null. 989 */ 990 @SuppressWarnings("unchecked") 991 private final H4GRImage getGRImage(int tag, int index, String path, boolean copyAllowed) { 992 log.trace("getGRImage(): start: tag={} index={} path={} copyAllowed={}", tag, index, path, copyAllowed); 993 994 long id = -1; 995 int ref = -1; 996 H4GRImage gr = null; 997 String[] objName = { "" }; 998 int[] imgInfo = new int[4]; 999 int[] dimSizes = { 0, 0 }; 1000 1001 try { 1002 id = HDFLibrary.GRselect(grid, index); 1003 ref = HDFLibrary.GRidtoref(id); 1004 log.trace("getGRImage(): GRselect:{} GRidtoref:{}",id,ref); 1005 HDFLibrary.GRgetiminfo(id, objName, imgInfo, dimSizes); 1006 } 1007 catch (HDFException ex) { 1008 log.debug("getGRImage(): failure: ", ex); 1009 id = HDFConstants.FAIL; 1010 } 1011 finally { 1012 if (id >= 0) { 1013 try { 1014 HDFLibrary.GRendaccess(id); 1015 } 1016 catch (HDFException ex) { 1017 log.debug("getGRImage(): GRendaccess failure: ", ex); 1018 } 1019 } 1020 } 1021 1022 if (id != HDFConstants.FAIL) { 1023 long[] oid = { tag, ref }; 1024 1025 if (copyAllowed) { 1026 objList.add(oid); 1027 } 1028 else if (find(oid)) { 1029 log.trace("getGRImage(): Image found in memory with OID:({}, {})", oid[0], oid[1]); 1030 return null; 1031 } 1032 1033 gr = new H4GRImage(this, objName[0], path, oid); 1034 } 1035 1036 return gr; 1037 } 1038 1039 /** 1040 * Retrieve a SDS for the given sds identifier and index. 1041 * 1042 * @param tag 1043 * the reference tag of the group (DFTAG_SD, DFTAG_SDG, DFTAG_NDG). 1044 * @param index 1045 * the index of the SDS. 1046 * @param path 1047 * the path of the SDS. 1048 * @param copyAllowed 1049 * The indicator if multiple copies of an object is allowed. 1050 * 1051 * @return the new H4SDS if successful; otherwise returns null. 1052 */ 1053 @SuppressWarnings("unchecked") 1054 private final H4SDS getSDS(int tag, int index, String path, boolean copyAllowed) { 1055 log.trace("getSDS(): start: tag={} index={} path={} copyAllowed={}", tag, index, path, copyAllowed); 1056 1057 long id = -1; 1058 int ref = -1; 1059 H4SDS sds = null; 1060 String[] objName = { "" }; 1061 int[] tmpInfo = new int[HDFConstants.MAX_VAR_DIMS]; 1062 int[] sdInfo = { 0, 0, 0 }; 1063 1064 boolean isCoordvar = false; 1065 try { 1066 id = HDFLibrary.SDselect(sdid, index); 1067 if (isNetCDF) { 1068 ref = index; // HDFLibrary.SDidtoref(id) fails for netCDF 1069 tag = H4SDS.DFTAG_NDG_NETCDF; 1070 } 1071 else { 1072 ref = HDFLibrary.SDidtoref(id); 1073 } 1074 log.trace("getSDS(): SDselect id={} with ref={} isNetCDF={}", id, ref, isNetCDF); 1075 1076 HDFLibrary.SDgetinfo(id, objName, tmpInfo, sdInfo); 1077 log.trace("getSDS(): SDselect id={} with objName={}: rank={}, numberType={}, nAttributes={}", id, objName, sdInfo[0], sdInfo[1], sdInfo[2]); 1078 1079 try { 1080 isCoordvar = HDFLibrary.SDiscoordvar(id); 1081 } 1082 catch (Exception ex) { 1083 log.debug("getSDS(): SDiscoordvar failure: ", ex); 1084 } 1085 } 1086 catch (HDFException ex) { 1087 log.debug("getSDS(): failure: ", ex); 1088 id = HDFConstants.FAIL; 1089 } 1090 finally { 1091 if (id >= 0) { 1092 try { 1093 HDFLibrary.SDendaccess(id); 1094 } 1095 catch (HDFException ex) { 1096 log.debug("getSDS(): SDendaccess failure: ", ex); 1097 } 1098 } 1099 } 1100 1101 // check if the given SDS has dimension metadata 1102 // Coordinate variables are not displayed. They are created to store 1103 // metadata associated with dimensions. To ensure compatibility with 1104 // netCDF, coordinate variables are implemented as data sets 1105 1106 if (isCoordvar) 1107 objName[0] += " (dimension)"; 1108 1109 if (id != HDFConstants.FAIL) { // && !isCoordvar) 1110 long[] oid = { tag, ref }; 1111 1112 if (copyAllowed) { 1113 objList.add(oid); 1114 } 1115 else if (find(oid)) { 1116 log.trace("getSDS(): SDS found in memory with OID:({}, {})", oid[0], oid[1]); 1117 return null; 1118 } 1119 1120 sds = new H4SDS(this, objName[0], path, oid); 1121 } 1122 1123 return sds; 1124 } 1125 1126 /** 1127 * Retrieve a Vdata for the given Vdata identifier and index. 1128 * 1129 * @param tag 1130 * the reference tag of the Vdata. 1131 * @param ref 1132 * the reference identifier of the Vdata. 1133 * @param path 1134 * the path of the Vdata. 1135 * @param copyAllowed 1136 * The indicator if multiple copies of an object is allowed. 1137 * 1138 * @return the new H4Vdata if successful; otherwise returns null. 1139 */ 1140 @SuppressWarnings("unchecked") 1141 private final H4Vdata getVdata(int tag, int ref, String path, boolean copyAllowed) { 1142 log.trace("getVdata(): start: tag={} ref={} path={} copyAllowed={}", tag, ref, path, copyAllowed); 1143 1144 long id = -1; 1145 H4Vdata vdata = null; 1146 String[] objName = { "" }; 1147 String[] vClass = { "" }; 1148 long[] oid = { tag, ref }; 1149 1150 if (copyAllowed) { 1151 objList.add(oid); 1152 } 1153 else if (find(oid)) { 1154 log.trace("getVdata(): VData found in memory with OID:({}, {})", oid[0], oid[1]); 1155 return null; 1156 } 1157 1158 try { 1159 id = HDFLibrary.VSattach(fid, ref, "r"); 1160 HDFLibrary.VSgetclass(id, vClass); 1161 vClass[0] = vClass[0].trim(); 1162 HDFLibrary.VSgetname(id, objName); 1163 } 1164 catch (HDFException ex) { 1165 log.trace("getVData(): failure: ", ex); 1166 id = HDFConstants.FAIL; 1167 } 1168 finally { 1169 if (id >= 0) { 1170 try { 1171 HDFLibrary.VSdetach(id); 1172 } 1173 catch (HDFException ex) { 1174 log.debug("getVData(): VSdetach failure: ", ex); 1175 } 1176 } 1177 } 1178 1179 if (showAll || 1180 ((id != HDFConstants.FAIL) 1181 && !vClass[0].equalsIgnoreCase(HDFConstants.HDF_ATTRIBUTE) // do not display Vdata named "Attr0.0" // commented out for bug 1737 1182 && !vClass[0].startsWith(HDFConstants.HDF_CHK_TBL) // do not display internal Vdata, "_HDF_CHK_TBL_" 1183 && !vClass[0].startsWith(HDFConstants.HDF_SDSVAR) // do not display attributes 1184 && !vClass[0].startsWith(HDFConstants.HDF_CRDVAR) 1185 && !vClass[0].startsWith(HDFConstants.DIM_VALS) 1186 && !vClass[0].startsWith(HDFConstants.DIM_VALS01) 1187 && !vClass[0].startsWith(HDFConstants.RIGATTRCLASS) 1188 && !vClass[0].startsWith(HDFConstants.RIGATTRNAME) 1189 && !vClass[0].equalsIgnoreCase(HDFConstants.HDF_CDF))) // do not display internal vdata for CDF, "CDF0.0" 1190 { 1191 vdata = new H4Vdata(this, objName[0], path, oid); 1192 } 1193 1194 return vdata; 1195 } 1196 1197 /** 1198 * Retrieve a VGroup for the given VGroup identifier and index. 1199 * 1200 * @param tag 1201 * the reference tag of the VGroup. 1202 * @param ref 1203 * the reference identifier of the VGroup. 1204 * @param path 1205 * the path of the VGroup. 1206 * @param pgroup 1207 * the parent group. 1208 * @param copyAllowed 1209 * The indicator if multiple copies of an object is allowed. 1210 * 1211 * @return the new H4VGroup if successful; otherwise returns null. 1212 */ 1213 @SuppressWarnings("unchecked") 1214 private final H4Group getVGroup(int tag, int ref, String path, H4Group pgroup, boolean copyAllowed) { 1215 log.trace("getVGroup(): start: tag={}, ref={} path={} pgroup={} copyAllowed={}", tag, ref, path, pgroup, copyAllowed); 1216 1217 long id = -1; 1218 H4Group vgroup = null; 1219 String[] objName = { "" }; 1220 String[] vClass = { "" }; 1221 long[] oid = { tag, ref }; 1222 1223 if (ref <= 0) { 1224 log.trace("getVGroup(): Skipping dummy root group with ref={}", ref); 1225 return null; 1226 } 1227 1228 if (copyAllowed) { 1229 objList.add(oid); 1230 } 1231 else if (find(oid)) { 1232 log.trace("getVGroup(): VGroup found in memory with OID:({}, {})", oid[0], oid[1]); 1233 return null; 1234 } 1235 1236 try { 1237 id = HDFLibrary.Vattach(fid, ref, "r"); 1238 log.trace("getVGroup(): Vattach fid={} id={}", fid, id); 1239 HDFLibrary.Vgetclass(id, vClass); 1240 vClass[0] = vClass[0].trim(); 1241 HDFLibrary.Vgetname(id, objName); 1242 } 1243 catch (HDFException ex) { 1244 log.debug("getVGroup(): failure: ",ex); 1245 id = HDFConstants.FAIL; 1246 } 1247 finally { 1248 if (id >= 0) { 1249 try { 1250 HDFLibrary.Vdetach(id); 1251 } 1252 catch (HDFException ex) { 1253 log.debug("getVGroup(): Vdetach failure: ", ex); 1254 } 1255 } 1256 } 1257 1258 // ignore the Vgroups created by the GR interface 1259 if (showAll || ((id != HDFConstants.FAIL) 1260 && !vClass[0].equalsIgnoreCase(HDFConstants.GR_NAME) // do not display Vdata named "Attr0.0" 1261 && !vClass[0].equalsIgnoreCase(HDFConstants.RI_NAME) 1262 && !vClass[0].equalsIgnoreCase(HDFConstants.RIGATTRNAME) 1263 && !vClass[0].equalsIgnoreCase(HDFConstants.RIGATTRCLASS) 1264 && !vClass[0].equalsIgnoreCase(HDFConstants.HDF_CDF))) 1265 { 1266 vgroup = new H4Group(this, objName[0], path, pgroup, oid); 1267 } 1268 1269 return vgroup; 1270 } 1271 1272 /** 1273 * Check if object already exists in memory by matching the (tag, ref) pairs. 1274 */ 1275 @SuppressWarnings("unchecked") 1276 private final boolean find(long[] oid) { 1277 log.trace("find(): start: oid({}, {})", oid[0], oid[1]); 1278 1279 boolean existed = false; 1280 1281 if (objList == null) { 1282 log.debug("find(): objList is null"); 1283 return false; 1284 } 1285 1286 int n = objList.size(); 1287 long[] theOID = null; 1288 1289 for (int i = 0; i < n; i++) { 1290 theOID = (long[]) objList.get(i); 1291 if ((theOID[0] == oid[0]) && (theOID[1] == oid[1])) { 1292 log.trace("find(): matched object in objList"); 1293 existed = true; 1294 break; 1295 } 1296 } 1297 1298 if (!existed) { 1299 objList.add(oid); 1300 } 1301 1302 return existed; 1303 } 1304 1305 /** 1306 * Returns the GR identifier, which is returned from GRstart(fid). 1307 * 1308 * @return the identifier. 1309 */ 1310 long getGRAccessID() { 1311 return grid; 1312 } 1313 1314 /** 1315 * Returns the SDS identifier, which is returned from SDstart(fname, flag). 1316 * 1317 * @return the identifier. 1318 */ 1319 long getSDAccessID() { 1320 return sdid; 1321 } 1322 1323 /** 1324 * Reads HDF file annotation (file labels and descriptions) into memory. 1325 * The file annotation is stored as an attribute of the root group. 1326 * 1327 * @param fid 1328 * the file identifier. 1329 * @param attrList 1330 * the list of attributes. 1331 * 1332 * @return the updated attribute list. 1333 * 1334 * @throws Exception if the annotation can not be read 1335 */ 1336 @SuppressWarnings({"rawtypes", "unchecked"}) 1337 private List getFileAnnotation(long fid, List attrList) throws HDFException { 1338 log.trace("getFileAnnotation(): start: FID={}", fid); 1339 1340 if (fid < 0) { 1341 log.debug("getFileAnnotation(): Invalid FID"); 1342 return attrList; 1343 } 1344 1345 long anid = HDFConstants.FAIL; 1346 try { 1347 anid = HDFLibrary.ANstart(fid); 1348 // fileInfo[0] = n_file_label, fileInfo[1] = n_file_desc, 1349 // fileInfo[2] = n_data_label, fileInfo[3] = n_data_desc 1350 int[] fileInfo = new int[4]; 1351 HDFLibrary.ANfileinfo(anid, fileInfo); 1352 1353 if (fileInfo[0] + fileInfo[1] <= 0) { 1354 try { 1355 HDFLibrary.ANend(anid); 1356 } 1357 catch (HDFException ex) { 1358 log.debug("getFileAnnotation(): ANend failure: ", ex); 1359 } 1360 1361 log.debug("getFileAnnotation(): n_file_labels + n_file_descriptions <= 0"); 1362 return attrList; 1363 } 1364 1365 if (attrList == null) 1366 attrList = new Vector(fileInfo[0] + fileInfo[1], 5); 1367 1368 // load file labels and descriptions 1369 long id = -1; 1370 int[] annTypes = { HDFConstants.AN_FILE_LABEL, 1371 HDFConstants.AN_FILE_DESC }; 1372 for (int j = 0; j < 2; j++) { 1373 String annName = null; 1374 if (j == 0) 1375 annName = "File Label"; 1376 else 1377 annName = "File Description"; 1378 1379 for (int i = 0; i < fileInfo[j]; i++) { 1380 try { 1381 id = HDFLibrary.ANselect(anid, i, annTypes[j]); 1382 } 1383 catch (HDFException ex) { 1384 log.debug("getFileAnnotation(): ANselect failure: ", ex); 1385 id = HDFConstants.FAIL; 1386 } 1387 1388 if (id == HDFConstants.FAIL) { 1389 log.trace("getFileAnnotation(): ANselect({}, {}, {}) failure", anid, i, annTypes[j]); 1390 try { 1391 HDFLibrary.ANendaccess(id); 1392 } 1393 catch (HDFException ex) { 1394 log.debug("getFileAnnotation(): ANendaccess failure: ", ex); 1395 } 1396 continue; 1397 } 1398 1399 int length = 0; 1400 try { 1401 length = HDFLibrary.ANannlen(id) + 1; 1402 } 1403 catch (HDFException ex) { 1404 log.debug("getFileAnnotation(): ANannlen failure: ", ex); 1405 length = 0; 1406 } 1407 1408 if (length > 0) { 1409 boolean b = false; 1410 String[] str = { "" }; 1411 try { 1412 b = HDFLibrary.ANreadann(id, str, length); 1413 } 1414 catch (HDFException ex) { 1415 log.debug("getFileAnnotation(): ANreadann failure: ", ex); 1416 b = false; 1417 } 1418 1419 if (b && (str[0].length() > 0)) { 1420 long[] attrDims = { str.length }; 1421 Datatype attrType = null; 1422 try { 1423 attrType = new H4Datatype(HDFConstants.DFNT_CHAR); 1424 } 1425 catch (Exception ex) { 1426 log.debug("getFileAnnotation(): failed to create datatype for attribute: ", ex); 1427 } 1428 H4ScalarAttribute newAttr = new H4ScalarAttribute(getRootObject(), annName + " #" + i, attrType, attrDims); 1429 attrList.add(newAttr); 1430 newAttr.setData(str); 1431 } 1432 } 1433 1434 try { 1435 HDFLibrary.ANendaccess(id); 1436 } 1437 catch (HDFException ex) { 1438 log.debug("getFileAnnotation(): ANendaccess failure: ", ex); 1439 } 1440 } // (int i=0; i < fileInfo[annTYpe]; i++) 1441 } // (int annType=0; annType<2; annType++) 1442 } 1443 finally { 1444 if (anid >= 0) { 1445 try { 1446 HDFLibrary.ANend(anid); 1447 } 1448 catch (HDFException ex) { 1449 log.debug("getFileAnnotation(): ANend failure: ", ex); 1450 } 1451 } 1452 } 1453 1454 return attrList; 1455 } 1456 1457 /** 1458 * Reads GR global attributes into memory. The attributes are stored as 1459 * attributes of the root group. 1460 * 1461 * @param grid 1462 * the GR identifier. 1463 * @param attrList 1464 * the list of attributes. 1465 * 1466 * @return the updated attribute list. 1467 * 1468 * @throws HDFException if the GR attributes can not be read 1469 */ 1470 @SuppressWarnings({"rawtypes", "unchecked"}) 1471 private List getGRglobalAttribute(long grid, List attrList) throws HDFException { 1472 log.trace("getGRglobalAttribute(): start: GRID={}", grid); 1473 1474 if (grid == HDFConstants.FAIL) { 1475 log.debug("getGRglobalAttribute(): Invalid GRID"); 1476 return attrList; 1477 } 1478 1479 int[] attrInfo = { 0, 0 }; 1480 HDFLibrary.GRfileinfo(grid, attrInfo); 1481 int numberOfAttributes = attrInfo[1]; 1482 1483 if (numberOfAttributes > 0) { 1484 if (attrList == null) 1485 attrList = new Vector(numberOfAttributes, 5); 1486 1487 String[] attrName = new String[1]; 1488 for (int i = 0; i < numberOfAttributes; i++) { 1489 attrName[0] = ""; 1490 boolean b = false; 1491 try { 1492 b = HDFLibrary.GRattrinfo(grid, i, attrName, attrInfo); 1493 // mask off the litend bit 1494 attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND); 1495 } 1496 catch (HDFException ex) { 1497 log.debug("getGRglobalAttribute(): GRattrinfo failure: ", ex); 1498 b = false; 1499 } 1500 1501 if (!b) 1502 continue; 1503 1504 long[] attrDims = { attrInfo[1] }; 1505 1506 Object buf = null; 1507 try { 1508 buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]); 1509 } 1510 catch (OutOfMemoryError e) { 1511 log.debug("getGRglobalAttribute(): out of memory: ", e); 1512 buf = null; 1513 } 1514 1515 try { 1516 HDFLibrary.GRgetattr(grid, i, buf); 1517 } 1518 catch (HDFException ex) { 1519 log.debug("getGRglobalAttribute(): GRgetattr failure: ", ex); 1520 buf = null; 1521 } 1522 1523 if ((buf != null) && ((attrInfo[0] == HDFConstants.DFNT_CHAR) || (attrInfo[0] == HDFConstants.DFNT_UCHAR8))) { 1524 buf = Dataset.byteToString((byte[]) buf, attrInfo[1]); 1525 attrDims[0] = ((String[]) buf).length; 1526 } 1527 1528 Datatype attrType = null; 1529 try { 1530 attrType = new H4Datatype(attrInfo[0]); 1531 } 1532 catch (Exception ex) { 1533 log.debug("getGRglobalAttribute(): failed to create datatype for attribute: ", ex); 1534 } 1535 1536 H4ScalarAttribute attr = new H4ScalarAttribute(getRootObject(), attrName[0], attrType, attrDims, buf); 1537 attrList.add(attr); 1538 } // (int i=0; i<numberOfAttributes; i++) 1539 } // (b && numberOfAttributes>0) 1540 1541 return attrList; 1542 } 1543 1544 /** 1545 * Reads SDS global attributes into memory. The attributes are stored as 1546 * attributes of the root group. 1547 * 1548 * @param sdid 1549 * the SD identifier. 1550 * @param attrList 1551 * the list of attributes. 1552 * 1553 * @return the updated attribute list. 1554 * 1555 * @throws HDFException if the SDS attributes can not be read 1556 */ 1557 @SuppressWarnings({"rawtypes", "unchecked"}) 1558 private List getSDSglobalAttribute(long sdid, List attrList) throws HDFException { 1559 log.trace("getSDSglobalAttribute(): start: SDID:{}", sdid); 1560 1561 if (sdid == HDFConstants.FAIL) { 1562 log.debug("getSDSglobalAttribute(): Invalid SDID"); 1563 return attrList; 1564 } 1565 1566 int[] attrInfo = { 0, 0 }; 1567 HDFLibrary.SDfileinfo(sdid, attrInfo); 1568 1569 int numberOfAttributes = attrInfo[1]; 1570 if (numberOfAttributes > 0) { 1571 if (attrList == null) 1572 attrList = new Vector(numberOfAttributes, 5); 1573 1574 String[] attrName = new String[1]; 1575 for (int i = 0; i < numberOfAttributes; i++) { 1576 attrName[0] = ""; 1577 boolean b = false; 1578 try { 1579 b = HDFLibrary.SDattrinfo(sdid, i, attrName, attrInfo); 1580 // mask off the litend bit 1581 attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND); 1582 } 1583 catch (HDFException ex) { 1584 log.debug("getSDSglobalAttribute(): SDattrinfo failure: ", ex); 1585 b = false; 1586 } 1587 1588 if (!b) 1589 continue; 1590 1591 long[] attrDims = { attrInfo[1] }; 1592 1593 Object buf = null; 1594 try { 1595 buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]); 1596 } 1597 catch (OutOfMemoryError e) { 1598 log.debug("getSDSglobalAttribute(): out of memory: ", e); 1599 buf = null; 1600 } 1601 1602 try { 1603 HDFLibrary.SDreadattr(sdid, i, buf); 1604 } 1605 catch (HDFException ex) { 1606 log.debug("getSDSglobalAttribute(): SDreadattr failure: ", ex); 1607 buf = null; 1608 } 1609 1610 if ((buf != null) && ((attrInfo[0] == HDFConstants.DFNT_CHAR) || (attrInfo[0] == HDFConstants.DFNT_UCHAR8))) { 1611 buf = Dataset.byteToString((byte[]) buf, attrInfo[1]); 1612 attrDims[0] = ((String[]) buf).length; 1613 } 1614 1615 Datatype attrType = null; 1616 try { 1617 attrType = new H4Datatype(attrInfo[0]); 1618 } 1619 catch (Exception ex) { 1620 log.debug("getSDSglobalAttribute(): failed to create datatype for attribute: ", ex); 1621 } 1622 1623 H4ScalarAttribute attr = new H4ScalarAttribute(getRootObject(), attrName[0], attrType, attrDims, buf); 1624 attrList.add(attr); 1625 } // (int i=0; i<numberOfAttributes; i++) 1626 } // (b && numberOfAttributes>0) 1627 1628 return attrList; 1629 } 1630 1631 /** 1632 * Returns the version of the HDF4 library. 1633 */ 1634 @Override 1635 public String getLibversion() { 1636 int[] vers = new int[3]; 1637 String ver = "HDF "; 1638 String[] verStr = { "" }; 1639 1640 try { 1641 HDFLibrary.Hgetlibversion(vers, verStr); 1642 } 1643 catch (HDFException ex) { 1644 log.debug("getLibVersion(): Hgetlibversion failure: ", ex); 1645 } 1646 1647 ver += vers[0] + "." + vers[1] + "." + vers[2]; 1648 log.debug("getLibversion(): libversion is {}", ver); 1649 1650 return ver; 1651 } 1652 1653 /** HDF4 library supports netCDF version 2.3.2. It only supports SDS APIs. */ 1654 private boolean isNetCDF(String filename) { 1655 log.trace("isNetCDF(): start: filename={}", filename); 1656 1657 boolean isnetcdf = false; 1658 1659 try (java.io.RandomAccessFile raf = new java.io.RandomAccessFile(filename, "r")) { 1660 byte[] header = new byte[4]; 1661 raf.read(header); 1662 // netCDF 1663 if (((header[0] == 67) && (header[1] == 68) && (header[2] == 70) && (header[3] == 1))) 1664 isnetcdf = true; 1665 else 1666 isnetcdf = false; 1667 } 1668 catch (Exception ex) { 1669 log.debug("RandomAccessFile {}", filename, ex); 1670 } 1671 1672 return isnetcdf; 1673 } 1674 1675 /** 1676 * Get an individual HObject with a given path. It does not load the whole 1677 * file structure. 1678 * 1679 * @param path the path of the object 1680 * 1681 * @throws Exception if the object cannot be found 1682 */ 1683 @Override 1684 @SuppressWarnings("rawtypes") 1685 public HObject get(String path) throws Exception { 1686 log.trace("get(): start: path={}", path); 1687 1688 if (objList == null) 1689 objList = new Vector(); 1690 1691 if ((path == null) || (path.length() <= 0)) { 1692 log.debug("get(): path is null or invalid path length"); 1693 return null; 1694 } 1695 1696 path = path.replace('\\', '/'); 1697 if (!path.startsWith("/")) 1698 path = "/" + path; 1699 1700 String name = null; 1701 String pPath = null; 1702 boolean isRoot = false; 1703 1704 if (path.equals("/")) { 1705 name = "/"; // the root 1706 isRoot = true; 1707 } 1708 else { 1709 if (path.endsWith("/")) { 1710 path = path.substring(0, path.length() - 2); 1711 } 1712 int idx = path.lastIndexOf('/'); 1713 name = path.substring(idx + 1); 1714 if (idx == 0) 1715 pPath = "/"; 1716 else 1717 pPath = path.substring(0, idx); 1718 } 1719 1720 log.trace("get(): isRoot={}", isRoot); 1721 1722 HObject obj = null; 1723 isReadOnly = false; 1724 1725 if (fid < 0) { 1726 fid = HDFLibrary.Hopen(fullFileName, HDFConstants.DFACC_WRITE); 1727 if (fid < 0) { 1728 isReadOnly = true; 1729 fid = HDFLibrary.Hopen(fullFileName, HDFConstants.DFACC_READ); 1730 } 1731 HDFLibrary.Vstart(fid); 1732 grid = HDFLibrary.GRstart(fid); 1733 sdid = HDFLibrary.SDstart(fullFileName, flag); 1734 } 1735 1736 if (isRoot) 1737 obj = getRootGroup(); 1738 else 1739 obj = getAttachedObject(pPath, name); 1740 1741 return obj; 1742 } 1743 1744 /** Get the root group and all the alone objects */ 1745 private H4Group getRootGroup() { 1746 long[] oid = { 0, 0 }; 1747 int n = 0; 1748 int ref = -1; 1749 int[] argv = null; 1750 1751 H4Group rootGroup = new H4Group(this, "/", null, null, oid); 1752 1753 // get top level VGroup 1754 int[] tmpN = new int[1]; 1755 int[] refs = null; 1756 try { 1757 // first call to get the number of lone Vgroups 1758 log.trace("getRootGroup(): first call to Vlone, get number of lone Vgroups"); 1759 n = HDFLibrary.Vlone(fid, tmpN, 0); 1760 log.trace("getRootGroup(): number of lone Vgroups={}", n); 1761 refs = new int[n]; 1762 // second call to get the references of all lone Vgroups 1763 log.trace("getRootGroup(): second call to Vlone, get references of lone Vgroups"); 1764 n = HDFLibrary.Vlone(fid, refs, n); 1765 } 1766 catch (HDFException ex) { 1767 log.debug("getRootGroup(): Vlone failure: ", ex); 1768 n = 0; 1769 } 1770 1771 // Iterate through the file to see members of the group 1772 for (int i = 0; i < n; i++) { 1773 ref = refs[i]; 1774 H4Group g = getVGroup(HDFConstants.DFTAG_VG, ref, HObject.SEPARATOR, rootGroup, false); 1775 if (g != null) 1776 rootGroup.addToMemberList(g); 1777 } 1778 1779 // get the top level GR images 1780 argv = new int[2]; 1781 boolean b = false; 1782 try { 1783 b = HDFLibrary.GRfileinfo(grid, argv); 1784 } 1785 catch (HDFException ex) { 1786 log.debug("getRootGroup(): GRfileinfo failure: ", ex); 1787 b = false; 1788 } 1789 1790 if (b) { 1791 n = argv[0]; 1792 for (int i = 0; i < n; i++) { 1793 // no duplicate object at top level 1794 H4GRImage gr = getGRImage(HDFConstants.DFTAG_RIG, i, 1795 HObject.SEPARATOR, false); 1796 if (gr != null) 1797 rootGroup.addToMemberList(gr); 1798 } 1799 } // ( HDFLibrary.GRfileinfo(grid, argv) ) 1800 1801 // get top level SDS 1802 try { 1803 b = HDFLibrary.SDfileinfo(sdid, argv); 1804 } 1805 catch (HDFException ex) { 1806 log.debug("getRootGroup(): SDfileinfo failure: ", ex); 1807 b = false; 1808 } 1809 1810 if (b) { 1811 n = argv[0]; 1812 1813 for (int i = 0; i < n; i++) { 1814 // no duplicate object at top level 1815 H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, i, HObject.SEPARATOR, false); 1816 if (sds != null) 1817 rootGroup.addToMemberList(sds); 1818 } 1819 } // (HDFLibrary.SDfileinfo(sdid, argv)) 1820 1821 // get top level VData 1822 try { 1823 log.trace("getRootGroup(): first call to VSlone, get number of lone VDatas"); 1824 n = HDFLibrary.VSlone(fid, tmpN, 0); 1825 log.trace("getRootGroup(): number of lone Vdatas={}", n); 1826 refs = new int[n]; 1827 log.trace("getRootGroup(): second call to VSlone, get references of lone VDatas"); 1828 n = HDFLibrary.VSlone(fid, refs, n); 1829 } 1830 catch (HDFException ex) { 1831 log.debug("getRootGroup(): VSlone failure: ex"); 1832 n = 0; 1833 } 1834 1835 for (int i = 0; i < n; i++) { 1836 ref = refs[i]; 1837 1838 // no duplicate object at top level 1839 H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref, HObject.SEPARATOR, false); 1840 1841 if (vdata != null) 1842 rootGroup.addToMemberList(vdata); 1843 } 1844 1845 if (rootGroup != null) { 1846 // retrieve file annotation, GR and SDS globle attributes 1847 @SuppressWarnings("rawtypes") 1848 List attributeList = null; 1849 try { 1850 attributeList = rootGroup.getMetadata(); 1851 } 1852 catch (HDFException ex) { 1853 log.debug("getRootGroup(): getMetadata() failure: ", ex); 1854 } 1855 1856 if (attributeList != null) { 1857 try { 1858 getFileAnnotation(fid, attributeList); 1859 } 1860 catch (HDFException ex) { 1861 log.debug("getRootGroup(): getFileAnnotation() failure: ", ex); 1862 } 1863 try { 1864 getGRglobalAttribute(grid, attributeList); 1865 } 1866 catch (HDFException ex) { 1867 log.debug("getRootGroup(): getGRglobalAttribute() failure: ", ex); 1868 } 1869 try { 1870 getSDSglobalAttribute(sdid, attributeList); 1871 } 1872 catch (HDFException ex) { 1873 log.debug("getRootGroup(): getSDSglobalAttribute() failure: ", ex); 1874 } 1875 } 1876 } 1877 1878 return rootGroup; 1879 } 1880 1881 /** Get the object attached to a vgroup */ 1882 private HObject getAttachedObject(String path, String name) { 1883 if ((name == null) || (name.length() <= 0)) { 1884 log.debug("getAttachedObject(): name is null or invalid name length"); 1885 return null; 1886 } 1887 1888 // get top level VGroup 1889 String[] objName = { "" }; 1890 // check if it is an image 1891 int idx = -1; 1892 try { 1893 idx = HDFLibrary.GRnametoindex(grid, name); 1894 } 1895 catch (HDFException ex) { 1896 log.debug("getAttachedObject(): GRnametoindex failure: ", ex); 1897 idx = -1; 1898 } 1899 1900 if (idx >= 0) { 1901 H4GRImage img = getGRImage(HDFConstants.DFTAG_RIG, idx, HObject.SEPARATOR, false); 1902 return img; 1903 } 1904 1905 // get top level SDS 1906 try { 1907 idx = HDFLibrary.SDnametoindex(sdid, name); 1908 } 1909 catch (HDFException ex) { 1910 log.debug("getAttachedObject(): SDnametoindex failure: ", ex); 1911 idx = -1; 1912 } 1913 1914 if (idx >= 0) { 1915 H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, idx, HObject.SEPARATOR, false); 1916 return sds; 1917 } 1918 1919 int ref = 0; 1920 try { 1921 ref = HDFLibrary.Vfind(fid, name); 1922 } 1923 catch (HDFException ex) { 1924 log.debug("getAttachedObject(): Vfind failure: ", ex); 1925 ref = -1; 1926 } 1927 1928 if (ref > 0) { 1929 long oid[] = { HDFConstants.DFTAG_VG, ref }; 1930 H4Group g = new H4Group(this, objName[0], path, null, oid); 1931 depth_first(g); 1932 return g; 1933 } 1934 1935 // get top level VData 1936 try { 1937 ref = HDFLibrary.VSfind(fid, name); 1938 } 1939 catch (HDFException ex) { 1940 log.debug("getAttachedObject(): VSfind failure: ", ex); 1941 ref = -1; 1942 } 1943 1944 if (ref > 0) { 1945 H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref, HObject.SEPARATOR, false); 1946 return vdata; 1947 } 1948 1949 log.debug("getAttachedObject(): Object not found"); 1950 return null; 1951 } 1952 1953 @Override 1954 public void setNewLibBounds(String lowStr, String highStr) throws Exception { 1955 // HDF4 does not have this feature 1956 } 1957 1958 @Override 1959 public int getIndexType(String strtype) { 1960 return -1; 1961 } 1962 1963 @Override 1964 public void setIndexType(int indexType) { 1965 // HDF4 does not have this feature 1966 } 1967 1968 @Override 1969 public int getIndexOrder(String strorder) { 1970 return -1; 1971 } 1972 1973 @Override 1974 public void setIndexOrder(int indexOrder) { 1975 // HDF4 does not have this feature 1976 } 1977 1978}