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 http://hdfgroup.org/products/hdf-java/doc/Copyright.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="http://hdfgroup.org/HDF5/doc/UG/">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 * 050 */ 051 private static final long serialVersionUID = -951164512330444150L; 052 053 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H5Group.class); 054 055 /** 056 * The list of attributes of this data object. Members of the list are 057 * instance of Attribute. 058 */ 059 protected List attributeList; 060 061 private int nAttributes = -1; 062 063 private H5O_info_t obj_info; 064 065 /** 066 * Constructs an HDF5 group with specific name, path, and parent. 067 * 068 * @param theFile 069 * the file which containing the group. 070 * @param name 071 * the name of this group, e.g. "grp01". 072 * @param path 073 * the full path of this group, e.g. "/groups/". 074 * @param parent 075 * the parent of this group. 076 */ 077 public H5Group(FileFormat theFile, String name, String path, Group parent) { 078 this(theFile, name, path, parent, null); 079 } 080 081 /** 082 * @deprecated Not for public use in the future.<br> 083 * Using {@link #H5Group(FileFormat, String, String, Group)} 084 * 085 * @param theFile 086 * the file which containing the group. 087 * @param name 088 * the name of this group, e.g. "grp01". 089 * @param path 090 * the full path of this group, e.g. "/groups/". 091 * @param parent 092 * the parent of this group. 093 * @param oid 094 * the oid of this group. 095 */ 096 @Deprecated 097 public H5Group(FileFormat theFile, String name, String path, Group parent, long[] oid) { 098 super(theFile, name, path, parent, oid); 099 nMembersInFile = -1; 100 obj_info = new H5O_info_t(-1L, -1L, 0, 0, -1L, 0L, 0L, 0L, 0L, null, null, null); 101 102 if ((oid == null) && (theFile != null)) { 103 // retrieve the object ID 104 try { 105 byte[] ref_buf = H5.H5Rcreate(theFile.getFID(), this.getFullName(), HDF5Constants.H5R_OBJECT, -1); 106 this.oid = new long[1]; 107 this.oid[0] = HDFNativeData.byteToLong(ref_buf, 0); 108 } 109 catch (Exception ex) { 110 this.oid = new long[1]; 111 this.oid[0] = 0; 112 } 113 } 114 } 115 116 /* 117 * (non-Javadoc) 118 * 119 * @see hdf.object.DataFormat#hasAttribute() 120 */ 121 public boolean hasAttribute() { 122 obj_info.num_attrs = nAttributes; 123 124 if (obj_info.num_attrs < 0) { 125 int 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 return (obj_info.num_attrs > 0); 139 } 140 141 /* 142 * (non-Javadoc) 143 * 144 * @see hdf.object.Group#getNumberOfMembersInFile() 145 */ 146 @Override 147 public int getNumberOfMembersInFile() { 148 if (nMembersInFile < 0) { 149 int gid = open(); 150 if (gid > 0) { 151 try { 152 H5G_info_t group_info = null; 153 group_info = H5.H5Gget_info(gid); 154 nMembersInFile = (int) group_info.nlinks; 155 } 156 catch (Exception ex) { 157 nMembersInFile = 0; 158 } 159 close(gid); 160 } 161 } 162 return nMembersInFile; 163 } 164 165 /* 166 * (non-Javadoc) 167 * 168 * @see hdf.object.Group#clear() 169 */ 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 public List getMetadata() throws HDF5Exception { 185 return this.getMetadata(fileFormat.getIndexType(null), fileFormat.getIndexOrder(null)); 186 } 187 188 /* 189 * (non-Javadoc) 190 * 191 * @see hdf.object.DataFormat#getMetadata(int...) 192 */ 193 public List getMetadata(int... attrPropList) throws HDF5Exception { 194 if (attributeList == null) { 195 int gid = open(); 196 if(gid >= 0) { 197 int indxType = fileFormat.getIndexType(null); 198 int order = fileFormat.getIndexOrder(null); 199 200 if (attrPropList.length > 0) { 201 indxType = attrPropList[0]; 202 if (attrPropList.length > 1) { 203 order = attrPropList[1]; 204 } 205 } 206 try { 207 attributeList = H5File.getAttribute(gid, indxType, order); 208 } 209 finally { 210 close(gid); 211 } 212 } 213 else { 214 log.debug("failed to open group"); 215 } 216 } 217 218 try { 219 this.linkTargetObjName = H5File.getLinkTargetName(this); 220 } 221 catch (Exception ex) { 222 log.debug("getLinkTargetName:", ex); 223 } 224 225 return attributeList; 226 } 227 228 /* 229 * (non-Javadoc) 230 * 231 * @see hdf.object.DataFormat#writeMetadata(java.lang.Object) 232 */ 233 public void writeMetadata(Object info) throws Exception { 234 // only attribute metadata is supported. 235 if (!(info instanceof Attribute)) { 236 return; 237 } 238 239 boolean attrExisted = false; 240 Attribute attr = (Attribute) info; 241 log.trace("writeMetadata: {}", attr.getName()); 242 243 if (attributeList == null) { 244 this.getMetadata(); 245 } 246 247 if (attributeList != null) attrExisted = attributeList.contains(attr); 248 249 getFileFormat().writeAttribute(this, attr, attrExisted); 250 // add the new attribute into attribute list 251 if (!attrExisted) { 252 attributeList.add(attr); 253 nAttributes = attributeList.size(); 254 } 255 } 256 257 /* 258 * (non-Javadoc) 259 * 260 * @see hdf.object.DataFormat#removeMetadata(java.lang.Object) 261 */ 262 public void removeMetadata(Object info) throws HDF5Exception { 263 // only attribute metadata is supported. 264 if (!(info instanceof Attribute)) { 265 return; 266 } 267 268 Attribute attr = (Attribute) info; 269 log.trace("removeMetadata: {}", attr.getName()); 270 int gid = open(); 271 if(gid >= 0) { 272 try { 273 H5.H5Adelete(gid, attr.getName()); 274 List attrList = getMetadata(); 275 attrList.remove(attr); 276 nAttributes = attributeList.size(); 277 } 278 finally { 279 close(gid); 280 } 281 } 282 else { 283 log.debug("failed to open group"); 284 } 285 } 286 287 /* 288 * (non-Javadoc) 289 * 290 * @see hdf.object.DataFormat#updateMetadata(java.lang.Object) 291 */ 292 public void updateMetadata(Object info) throws HDF5Exception { 293 // only attribute metadata is supported. 294 if (!(info instanceof Attribute)) { 295 return; 296 } 297 log.trace("updateMetadata"); 298 299 nAttributes = -1; 300 } 301 302 /* 303 * (non-Javadoc) 304 * 305 * @see hdf.object.HObject#open() 306 */ 307 @Override 308 public int open() { 309 int gid = -1; 310 311 try { 312 if (isRoot()) { 313 gid = H5.H5Gopen(getFID(), separator, HDF5Constants.H5P_DEFAULT); 314 } 315 else { 316 gid = H5.H5Gopen(getFID(), getPath() + getName(), HDF5Constants.H5P_DEFAULT); 317 } 318 319 } 320 catch (HDF5Exception ex) { 321 gid = -1; 322 } 323 324 return gid; 325 } 326 327 /* 328 * (non-Javadoc) 329 * 330 * @see hdf.object.HObject#close(int) 331 */ 332 @Override 333 public void close(int gid) { 334 try { 335 H5.H5Gclose(gid); 336 } 337 catch (HDF5Exception ex) { 338 log.debug("H5Gclose:", ex); 339 } 340 } 341 342 /** 343 * Creates a new group with a name in a group and with the group creation 344 * properties specified in gplist. 345 * <p> 346 * The gplist contains a sequence of group creation property list 347 * identifiers, lcpl, gcpl, gapl. It allows the user to create a group with 348 * group creation properties. It will close the group creation properties 349 * specified in gplist. 350 * 351 * @see hdf.hdf5lib.H5#H5Gcreate(int, String, int, int, int) for the 352 * order of property list identifiers. 353 * 354 * @param name 355 * The name of a new group. 356 * @param pgroup 357 * The parent group object. 358 * @param gplist 359 * The group creation properties, in which the order of the 360 * properties conforms the HDF5 library API, H5Gcreate(), i.e. 361 * lcpl, gcpl and gapl, where 362 * <ul> 363 * <li>lcpl : Property list for link creation <li>gcpl : Property 364 * list for group creation <li>gapl : Property list for group 365 * access 366 * </ul> 367 * 368 * @return The new group if successful; otherwise returns null. 369 * 370 * @throws Exception if there is a failure. 371 */ 372 public static H5Group create(String name, Group pgroup, int... gplist) throws Exception { 373 H5Group group = null; 374 String fullPath = null; 375 int lcpl = HDF5Constants.H5P_DEFAULT; 376 int gcpl = HDF5Constants.H5P_DEFAULT; 377 int gapl = HDF5Constants.H5P_DEFAULT; 378 379 if (gplist.length > 0) { 380 lcpl = gplist[0]; 381 if (gplist.length > 1) { 382 gcpl = gplist[1]; 383 if (gplist.length > 2) gapl = gplist[2]; 384 } 385 } 386 387 if ((name == null) || (pgroup == null)) { 388 System.err.println("(name == null) || (pgroup == null)"); 389 return null; 390 } 391 392 H5File file = (H5File) pgroup.getFileFormat(); 393 394 if (file == null) { 395 System.err.println("Could not get file that contains object"); 396 return null; 397 } 398 399 String path = HObject.separator; 400 if (!pgroup.isRoot()) { 401 path = pgroup.getPath() + pgroup.getName() + HObject.separator; 402 if (name.endsWith("/")) { 403 name = name.substring(0, name.length() - 1); 404 } 405 int idx = name.lastIndexOf("/"); 406 if (idx >= 0) { 407 name = name.substring(idx + 1); 408 } 409 } 410 411 fullPath = path + name; 412 413 // create a new group and add it to the parent node 414 int gid = H5.H5Gcreate(file.open(), fullPath, lcpl, gcpl, gapl); 415 try { 416 H5.H5Gclose(gid); 417 } 418 catch (Exception ex) { 419 log.debug("H5Gcreate {} H5Gclose:", fullPath, ex); 420 } 421 422 byte[] ref_buf = H5.H5Rcreate(file.open(), fullPath, HDF5Constants.H5R_OBJECT, -1); 423 long l = HDFNativeData.byteToLong(ref_buf, 0); 424 long[] oid = { l }; 425 426 group = new H5Group(file, name, path, pgroup, oid); 427 428 if (group != null) { 429 pgroup.addToMemberList(group); 430 } 431 432 if (gcpl > 0) { 433 try { 434 H5.H5Pclose(gcpl); 435 } 436 catch (final Exception ex) { 437 log.debug("create prop H5Pclose:", ex); 438 } 439 } 440 441 return group; 442 } 443 444 /* 445 * (non-Javadoc) 446 * 447 * @see hdf.object.HObject#setName(java.lang.String) 448 */ 449 @Override 450 public void setName(String newName) throws Exception { 451 H5File.renameObject(this, newName); 452 super.setName(newName); 453 } 454 455 /* 456 * (non-Javadoc) 457 * 458 * @see hdf.object.HObject#setPath(java.lang.String) 459 */ 460 @Override 461 public void setPath(String newPath) throws Exception { 462 super.setPath(newPath); 463 464 List members = this.getMemberList(); 465 if (members == null) { 466 return; 467 } 468 469 int n = members.size(); 470 HObject obj = null; 471 for (int i = 0; i < n; i++) { 472 obj = (HObject) members.get(i); 473 obj.setPath(getPath() + getName() + HObject.separator); 474 } 475 } 476}