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