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