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.h5; 016 017import java.util.List; 018import java.util.Vector; 019 020import hdf.hdf5lib.H5; 021import hdf.hdf5lib.HDF5Constants; 022import hdf.hdf5lib.HDFNativeData; 023import hdf.hdf5lib.exceptions.HDF5Exception; 024import hdf.hdf5lib.structs.H5G_info_t; 025import hdf.hdf5lib.structs.H5O_info_t; 026import hdf.object.Attribute; 027import hdf.object.FileFormat; 028import hdf.object.Group; 029import hdf.object.HObject; 030 031/** 032 * An H5Group object represents an existing HDF5 group in file. 033 * <p> 034 * In HDF5, every object has at least one name. An HDF5 group is used to store a 035 * set of the names together in one place, i.e. a group. The general structure 036 * of a group is similar to that of the UNIX file system in that the group may 037 * contain references to other groups or data objects just as the UNIX directory 038 * may contain sub-directories or files. 039 * <p> 040 * For more information on HDF5 Groups, 041 * 042 * <a href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5 User's Guide</a> 043 * 044 * @version 1.1 9/4/2007 045 * @author Peter X. Cao 046 */ 047public class H5Group extends Group { 048 049 private static final long serialVersionUID = -951164512330444150L; 050 051 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H5Group.class); 052 053 /** 054 * The list of attributes of this data object. Members of the list are 055 * instance of Attribute. 056 */ 057 @SuppressWarnings("rawtypes") 058 protected List attributeList; 059 060 private int nAttributes = -1; 061 062 private H5O_info_t obj_info; 063 064 /** 065 * Constructs an HDF5 group with specific name, path, and parent. 066 * 067 * @param theFile 068 * the file which containing the group. 069 * @param name 070 * the name of this group, e.g. "grp01". 071 * @param path 072 * the full path of this group, e.g. "/groups/". 073 * @param parent 074 * the parent of this group. 075 */ 076 public H5Group(FileFormat theFile, String name, String path, Group parent) { 077 this(theFile, name, path, parent, null); 078 } 079 080 /** 081 * @deprecated Not for public use in the future.<br> 082 * Using {@link #H5Group(FileFormat, String, String, Group)} 083 * 084 * @param theFile 085 * the file which containing the group. 086 * @param name 087 * the name of this group, e.g. "grp01". 088 * @param path 089 * the full path of this group, e.g. "/groups/". 090 * @param parent 091 * the parent of this group. 092 * @param oid 093 * the oid of this group. 094 */ 095 @Deprecated 096 public H5Group(FileFormat theFile, String name, String path, Group parent, long[] oid) { 097 super(theFile, name, path, parent, oid); 098 nMembersInFile = -1; 099 obj_info = new H5O_info_t(-1L, -1L, 0, 0, -1L, 0L, 0L, 0L, 0L, null, null, null); 100 101 if ((oid == null) && (theFile != null)) { 102 // retrieve the object ID 103 try { 104 byte[] ref_buf = H5.H5Rcreate(theFile.getFID(), this.getFullName(), HDF5Constants.H5R_OBJECT, -1); 105 this.oid = new long[1]; 106 this.oid[0] = HDFNativeData.byteToLong(ref_buf, 0); 107 } 108 catch (Exception ex) { 109 this.oid = new long[1]; 110 this.oid[0] = 0; 111 } 112 } 113 } 114 115 /* 116 * (non-Javadoc) 117 * 118 * @see hdf.object.DataFormat#hasAttribute() 119 */ 120 @Override 121 public boolean hasAttribute() { 122 obj_info.num_attrs = nAttributes; 123 124 if (obj_info.num_attrs < 0) { 125 long gid = open(); 126 if (gid > 0) { 127 try { 128 obj_info = H5.H5Oget_info(gid); 129 130 } 131 catch (Exception ex) { 132 obj_info.num_attrs = 0; 133 } 134 close(gid); 135 } 136 } 137 138 log.trace("hasAttribute(): nAttributes={}", obj_info.num_attrs); 139 140 return (obj_info.num_attrs > 0); 141 } 142 143 /* 144 * (non-Javadoc) 145 * 146 * @see hdf.object.Group#getNumberOfMembersInFile() 147 */ 148 @Override 149 public int getNumberOfMembersInFile() { 150 if (nMembersInFile < 0) { 151 long gid = open(); 152 if (gid > 0) { 153 try { 154 H5G_info_t group_info = null; 155 group_info = H5.H5Gget_info(gid); 156 nMembersInFile = (int) group_info.nlinks; 157 } 158 catch (Exception ex) { 159 nMembersInFile = 0; 160 } 161 close(gid); 162 } 163 } 164 return nMembersInFile; 165 } 166 167 /* 168 * (non-Javadoc) 169 * 170 * @see hdf.object.Group#clear() 171 */ 172 @SuppressWarnings("rawtypes") 173 @Override 174 public void clear() { 175 super.clear(); 176 177 if (attributeList != null) { 178 ((Vector) attributeList).setSize(0); 179 } 180 } 181 182 /* 183 * (non-Javadoc) 184 * 185 * @see hdf.object.DataFormat#getMetadata() 186 */ 187 @Override 188 @SuppressWarnings("rawtypes") 189 public List getMetadata() throws HDF5Exception { 190 return this.getMetadata(fileFormat.getIndexType(null), fileFormat.getIndexOrder(null)); 191 } 192 193 /* 194 * (non-Javadoc) 195 * 196 * @see hdf.object.DataFormat#getMetadata(int...) 197 */ 198 @SuppressWarnings("rawtypes") 199 public List getMetadata(int... attrPropList) throws HDF5Exception { 200 log.trace("getMetadata(): start"); 201 if (attributeList == null) { 202 log.trace("getMetadata(): get attributeList"); 203 204 int indxType = fileFormat.getIndexType(null); 205 int order = fileFormat.getIndexOrder(null); 206 207 if (attrPropList.length > 0) { 208 indxType = attrPropList[0]; 209 if (attrPropList.length > 1) { 210 order = attrPropList[1]; 211 } 212 } 213 try { 214 attributeList = H5File.getAttribute(this, indxType, order); 215 } 216 catch (Exception ex) { 217 log.debug("getMetadata(): H5File.getAttribute failure: ", ex); 218 } 219 } 220 221 try { 222 if (!this.isRoot()) this.linkTargetObjName = H5File.getLinkTargetName(this); 223 } 224 catch (Exception ex) { 225 log.debug("getMetadata(): getLinkTargetName failure: ", ex); 226 } 227 228 log.trace("getMetadata(): finish"); 229 return attributeList; 230 } 231 232 /* 233 * (non-Javadoc) 234 * 235 * @see hdf.object.DataFormat#writeMetadata(java.lang.Object) 236 */ 237 @Override 238 @SuppressWarnings("unchecked") 239 public void writeMetadata(Object info) throws Exception { 240 log.trace("writeMetadata(): start"); 241 // only attribute metadata is supported. 242 if (!(info instanceof Attribute)) { 243 log.debug("writeMetadata(): Object not an Attribute"); 244 log.trace("writeMetadata(): finish"); 245 return; 246 } 247 248 boolean attrExisted = false; 249 Attribute attr = (Attribute) info; 250 log.trace("writeMetadata(): {}", attr.getName()); 251 252 if (attributeList == null) { 253 this.getMetadata(); 254 } 255 256 if (attributeList != null) attrExisted = attributeList.contains(attr); 257 258 getFileFormat().writeAttribute(this, attr, attrExisted); 259 // add the new attribute into attribute list 260 if (!attrExisted) { 261 attributeList.add(attr); 262 nAttributes = attributeList.size(); 263 } 264 log.trace("writeMetadata(): finish"); 265 } 266 267 /* 268 * (non-Javadoc) 269 * 270 * @see hdf.object.DataFormat#removeMetadata(java.lang.Object) 271 */ 272 @Override 273 @SuppressWarnings("rawtypes") 274 public void removeMetadata(Object info) throws HDF5Exception { 275 log.trace("removeMetadata(): start"); 276 // only attribute metadata is supported. 277 if (!(info instanceof Attribute)) { 278 log.debug("removeMetadata(): Object not an Attribute"); 279 log.trace("removeMetadata(): finish"); 280 return; 281 } 282 283 Attribute attr = (Attribute) info; 284 log.trace("removeMetadata(): {}", attr.getName()); 285 long gid = open(); 286 if(gid >= 0) { 287 try { 288 H5.H5Adelete(gid, attr.getName()); 289 List attrList = getMetadata(); 290 attrList.remove(attr); 291 nAttributes = attributeList.size(); 292 } 293 finally { 294 close(gid); 295 } 296 } 297 else { 298 log.debug("removeMetadata(): failed to open group"); 299 } 300 301 log.trace("removeMetadata(): finish"); 302 } 303 304 /* 305 * (non-Javadoc) 306 * 307 * @see hdf.object.DataFormat#updateMetadata(java.lang.Object) 308 */ 309 @Override 310 public void updateMetadata(Object info) throws HDF5Exception { 311 log.trace("updateMetadata(): start"); 312 // only attribute metadata is supported. 313 if (!(info instanceof Attribute)) { 314 log.debug("updateMetadata(): Object not an Attribute"); 315 log.trace("updateMetadata(): finish"); 316 return; 317 } 318 319 nAttributes = -1; 320 log.trace("updateMetadata(): finish"); 321 } 322 323 /* 324 * (non-Javadoc) 325 * 326 * @see hdf.object.HObject#open() 327 */ 328 @Override 329 public long open() { 330 log.trace("open(): start"); 331 long gid = -1; 332 333 try { 334 if (isRoot()) { 335 gid = H5.H5Gopen(getFID(), separator, HDF5Constants.H5P_DEFAULT); 336 } 337 else { 338 gid = H5.H5Gopen(getFID(), getPath() + getName(), HDF5Constants.H5P_DEFAULT); 339 } 340 341 } 342 catch (HDF5Exception ex) { 343 gid = -1; 344 } 345 346 log.trace("open(): finish"); 347 return gid; 348 } 349 350 /* 351 * (non-Javadoc) 352 * 353 * @see hdf.object.HObject#close(int) 354 */ 355 @Override 356 public void close(long gid) { 357 try { 358 H5.H5Gclose(gid); 359 } 360 catch (HDF5Exception ex) { 361 log.debug("close(): H5Gclose(gid {}): ", gid, ex); 362 } 363 } 364 365 /** 366 * Creates a new group with a name in a group and with the group creation 367 * properties specified in gplist. 368 * <p> 369 * The gplist contains a sequence of group creation property list 370 * identifiers, lcpl, gcpl, gapl. It allows the user to create a group with 371 * group creation properties. It will close the group creation properties 372 * specified in gplist. 373 * 374 * @see hdf.hdf5lib.H5#H5Gcreate(long, String, long, long, long) for the 375 * order of property list identifiers. 376 * 377 * @param name 378 * The name of a new group. 379 * @param pgroup 380 * The parent group object. 381 * @param gplist 382 * The group creation properties, in which the order of the 383 * properties conforms the HDF5 library API, H5Gcreate(), i.e. 384 * lcpl, gcpl and gapl, where 385 * <ul> 386 * <li>lcpl : Property list for link creation <li>gcpl : Property 387 * list for group creation <li>gapl : Property list for group 388 * access 389 * </ul> 390 * 391 * @return The new group if successful; otherwise returns null. 392 * 393 * @throws Exception if there is a failure. 394 */ 395 public static H5Group create(String name, Group pgroup, long... gplist) throws Exception { 396 log.trace("create(): start"); 397 H5Group group = null; 398 String fullPath = null; 399 long lcpl = HDF5Constants.H5P_DEFAULT; 400 long gcpl = HDF5Constants.H5P_DEFAULT; 401 long gapl = HDF5Constants.H5P_DEFAULT; 402 403 if (gplist.length > 0) { 404 lcpl = gplist[0]; 405 if (gplist.length > 1) { 406 gcpl = gplist[1]; 407 if (gplist.length > 2) gapl = gplist[2]; 408 } 409 } 410 411 if ((name == null) || (pgroup == null)) { 412 log.debug("create(): one or more parameters are null"); 413 log.trace("create(): finish"); 414 System.err.println("(name == null) || (pgroup == null)"); 415 return null; 416 } 417 418 H5File file = (H5File) pgroup.getFileFormat(); 419 420 if (file == null) { 421 log.debug("create(): Parent Group FileFormat is null"); 422 log.trace("create(): finish"); 423 System.err.println("Could not get file that contains object"); 424 return null; 425 } 426 427 String path = HObject.separator; 428 if (!pgroup.isRoot()) { 429 path = pgroup.getPath() + pgroup.getName() + HObject.separator; 430 if (name.endsWith("/")) { 431 name = name.substring(0, name.length() - 1); 432 } 433 int idx = name.lastIndexOf("/"); 434 if (idx >= 0) { 435 name = name.substring(idx + 1); 436 } 437 } 438 439 fullPath = path + name; 440 441 // create a new group and add it to the parent node 442 long gid = H5.H5Gcreate(file.open(), fullPath, lcpl, gcpl, gapl); 443 try { 444 H5.H5Gclose(gid); 445 } 446 catch (Exception ex) { 447 log.debug("create(): H5Gcreate {} H5Gclose(gid {}) failure: ", fullPath, gid, ex); 448 } 449 450 byte[] ref_buf = H5.H5Rcreate(file.open(), fullPath, HDF5Constants.H5R_OBJECT, -1); 451 long l = HDFNativeData.byteToLong(ref_buf, 0); 452 long[] oid = { l }; 453 454 group = new H5Group(file, name, path, pgroup, oid); 455 456 if (group != null) { 457 pgroup.addToMemberList(group); 458 } 459 460 if (gcpl > 0) { 461 try { 462 H5.H5Pclose(gcpl); 463 } 464 catch (final Exception ex) { 465 log.debug("create(): create prop H5Pclose(gcpl {}) failure: ", gcpl, ex); 466 } 467 } 468 469 log.trace("create(): finish"); 470 return group; 471 } 472 473 /* 474 * (non-Javadoc) 475 * 476 * @see hdf.object.HObject#setName(java.lang.String) 477 */ 478 @Override 479 public void setName(String newName) throws Exception { 480 H5File.renameObject(this, newName); 481 super.setName(newName); 482 } 483 484 /* 485 * (non-Javadoc) 486 * 487 * @see hdf.object.HObject#setPath(java.lang.String) 488 */ 489 @SuppressWarnings("rawtypes") 490 @Override 491 public void setPath(String newPath) throws Exception { 492 super.setPath(newPath); 493 494 List members = this.getMemberList(); 495 if (members == null) { 496 return; 497 } 498 499 int n = members.size(); 500 HObject obj = null; 501 for (int i = 0; i < n; i++) { 502 obj = (HObject) members.get(i); 503 obj.setPath(getPath() + getName() + HObject.separator); 504 } 505 } 506}