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.util.List; 018import java.util.Vector; 019 020import hdf.hdflib.HDFConstants; 021import hdf.hdflib.HDFException; 022import hdf.hdflib.HDFLibrary; 023 024import hdf.object.Attribute; 025import hdf.object.Dataset; 026import hdf.object.FileFormat; 027import hdf.object.Group; 028import hdf.object.HObject; 029 030import hdf.object.h4.H4ScalarAttribute; 031 032/** 033 * An H4Group is a vgroup in HDF4, inheriting from Group. 034 * A vgroup is a structure designed to associate related data objects. The 035 * general structure of a vgroup is similar to that of the UNIX file system in 036 * that the vgroup may contain references to other vgroups or HDF data objects 037 * just as the UNIX directory may contain subdirectories or files. 038 * 039 * @version 1.1 9/4/2007 040 * @author Peter X. Cao 041 */ 042public class H4Group extends Group 043{ 044 private static final long serialVersionUID = 3785240955078867900L; 045 046 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H4Group.class); 047 048 /** 049 * The list of attributes of this data object. Members of the list are 050 * instance of H4ScalarAttribute. 051 */ 052 @SuppressWarnings("rawtypes") 053 private List attributeList; 054 055 /** the number of attributes */ 056 private int nAttributes = -1; 057 058 /** The default object ID for HDF4 objects */ 059 private static final long[] DEFAULT_OID = {0, 0}; 060 061 /** 062 * Creates a group object with specific name, path, and parent. 063 * 064 * @param theFile the HDF file. 065 * @param name the name of this group. 066 * @param path the full path of this group. 067 * @param parent the parent of this group. 068 */ 069 public H4Group(FileFormat theFile, String name, String path, Group parent) 070 { 071 this(theFile, name, path, parent, null); 072 } 073 074 /** 075 * Creates a group object with specific name, path, parent and oid. 076 * 077 * @param theFile the HDF file. 078 * @param name the name of this group. 079 * @param path the full path of this group. 080 * @param parent the parent of this group. 081 * @param oid the unique identifier of this data object. 082 */ 083 @SuppressWarnings("deprecation") 084 public H4Group(FileFormat theFile, String name, String path, Group parent, long[] oid) { 085 super (theFile, name, path, parent, ((oid == null) ? DEFAULT_OID : oid)); 086 } 087 088 /* 089 * (non-Javadoc) 090 * @see hdf.object.DataFormat#hasAttribute() 091 */ 092 @Override 093 public boolean hasAttribute() { 094 if (nAttributes < 0) { 095 long vgid = open(); 096 097 if (vgid > 0) { 098 try { 099 nAttributes = HDFLibrary.Vnattrs(vgid); 100 nMembersInFile = HDFLibrary.Vntagrefs(vgid); 101 } 102 catch (Exception ex) { 103 log.debug("hasAttribute(): failure: ", ex); 104 nAttributes = 0; 105 } 106 107 log.trace("hasAttribute(): nAttributes={}", nAttributes); 108 109 close(vgid); 110 } 111 } 112 113 return (nAttributes > 0); 114 } 115 116 // Implementing DataFormat 117 /** 118 * Retrieves the object's metadata, such as attributes, from the file. 119 * 120 * Metadata, such as attributes, is stored in a List. 121 * 122 * @return the list of metadata objects. 123 * 124 * @throws HDFException 125 * if the metadata can not be retrieved 126 */ 127 @Override 128 @SuppressWarnings({"rawtypes", "unchecked"}) 129 public List getMetadata() throws HDFException { 130 if (attributeList != null) { 131 log.trace("getMetadata(): attributeList != null"); 132 return attributeList; 133 } 134 else { 135 attributeList = new Vector(); 136 } 137 138 // Library methods cannot be called on HDF4 dummy root group since it has a ref of 0 139 if (oid[1] > 0) { 140 long vgid = open(); 141 log.trace("getMetadata(): open: id={}", vgid); 142 if (vgid < 0) { 143 log.debug("getMetadata(): Invalid VG ID"); 144 return attributeList; 145 } 146 147 int n = -1; 148 149 try { 150 n = HDFLibrary.Vnattrs(vgid); 151 log.trace("getMetadata(): Vnattrs: n={}", n); 152 153 boolean b = false; 154 String[] attrName = new String[1]; 155 int[] attrInfo = new int[5]; 156 for (int i=0; i<n; i++) { 157 attrName[0] = ""; 158 try { 159 b = HDFLibrary.Vattrinfo(vgid, i, attrName, attrInfo); 160 // mask off the litend bit 161 attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND); 162 } 163 catch (HDFException ex) { 164 log.trace("getMetadata(): attribute[{}] Vattrinfo failure: ", i, ex); 165 b = false; 166 } 167 168 if (!b) 169 continue; 170 171 long[] attrDims = {attrInfo[1]}; 172 H4ScalarAttribute attr = new H4ScalarAttribute(this, attrName[0], new H4Datatype(attrInfo[0]), attrDims); 173 attributeList.add(attr); 174 175 Object buf = null; 176 try { 177 buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]); 178 } 179 catch (OutOfMemoryError e) { 180 log.debug("getMetadata(): out of memory: ", e); 181 } 182 183 try { 184 HDFLibrary.Vgetattr(vgid, i, buf); 185 } 186 catch (HDFException ex) { 187 log.trace("getMetadata(): attribute[{}] Vgetattr failure: ", i, ex); 188 buf = null; 189 } 190 191 if (buf != null) { 192 if ((attrInfo[0] == HDFConstants.DFNT_CHAR) || (attrInfo[0] == HDFConstants.DFNT_UCHAR8)) 193 buf = Dataset.byteToString((byte[])buf, attrInfo[1]); 194 195 attr.setAttributeData(buf); 196 } 197 } 198 } 199 catch (Exception ex) { 200 log.trace("getMetadata(): failure: ", ex); 201 } 202 finally { 203 close(vgid); 204 } 205 } 206 207 return attributeList; 208 } 209 210 // To do: implementing DataFormat 211 /** 212 * Writes a specific piece of metadata (such as an attribute) into the file. 213 * 214 * If an HDF(4&5) attribute exists in the file, this method updates its 215 * value. If the attribute does not exist in the file, it creates the 216 * attribute in the file and attaches it to the object. It will fail to 217 * write a new attribute to the object where an attribute with the same name 218 * already exists. To update the value of an existing attribute in the file, 219 * one needs to get the instance of the attribute by getMetadata(), change 220 * its values, then use writeMetadata() to write the value. 221 * 222 * @param info 223 * the metadata to write. 224 * 225 * @throws Exception 226 * if the metadata can not be written 227 */ 228 @Override 229 @SuppressWarnings({"rawtypes", "unchecked"}) 230 public void writeMetadata(Object info) throws Exception { 231 // only attribute metadata is supported. 232 if (!(info instanceof Attribute)) { 233 log.debug("writeMetadata(): Object not an H4ScalarAttribute"); 234 return; 235 } 236 237 try { 238 getFileFormat().writeAttribute(this, (H4ScalarAttribute)info, true); 239 240 if (attributeList == null) 241 attributeList = new Vector(); 242 243 attributeList.add(info); 244 nAttributes = attributeList.size(); 245 } 246 catch (Exception ex) { 247 log.debug("writeMetadata(): failure: ", ex); 248 } 249 } 250 251 252 /** 253 * Deletes an existing piece of metadata from this object. 254 * 255 * @param info 256 * the metadata to delete. 257 * 258 * @throws HDFException 259 * if the metadata can not be removed 260 */ 261 @Override 262 public void removeMetadata(Object info) throws HDFException { 263 log.trace("removeMetadata(): disabled"); 264 } 265 266 /** 267 * Updates an existing piece of metadata attached to this object. 268 * 269 * @param info 270 * the metadata to update. 271 * 272 * @throws Exception 273 * if the metadata can not be updated 274 */ 275 @Override 276 public void updateMetadata(Object info) throws Exception { 277 log.trace("updateMetadata(): disabled"); 278 } 279 280 // Implementing HObject 281 @Override 282 public long open() { 283 log.trace("open(): start: for file={} with ref={}", getFID(), oid[1]); 284 285 if (oid[1] <= 0) { 286 log.debug("open(): oid[1] <= 0"); 287 return -1; // Library methods cannot be called on HDF4 dummy group with ref 0 288 } 289 290 long vgid = -1; 291 292 if (!getFileFormat().isReadOnly()) { 293 // try to open with write permission 294 try { 295 vgid = HDFLibrary.Vattach(getFID(), (int)oid[1], "w"); 296 log.trace("open(): Vattach write id={}", vgid); 297 } 298 catch (HDFException ex) { 299 log.debug("open(): Vattach failure: ", ex); 300 vgid = -1; 301 } 302 } 303 304 // try to open with read-only permission 305 if (getFileFormat().isReadOnly() || vgid < 0) { 306 try { 307 vgid = HDFLibrary.Vattach(getFID(), (int)oid[1], "r"); 308 log.trace("open(): Vattach readonly id={}", vgid); 309 } 310 catch (HDFException ex) { 311 log.debug("open(): Vattach failure: ", ex); 312 vgid = -1; 313 } 314 } 315 316 return vgid; 317 } 318 319 /** close group access. */ 320 @Override 321 public void close(long vgid) { 322 log.trace("close(): id={}", vgid); 323 324 if (vgid >= 0) { 325 try { 326 HDFLibrary.Vdetach(vgid); 327 } 328 catch (Exception ex) { 329 log.debug("close(): Vdetach failure: ", ex); 330 } 331 } 332 } 333 334 /** 335 * Creates a new group. 336 * 337 * @param name the name of the group to create. 338 * @param pgroup the parent group of the new group. 339 * 340 * @return the new group if successful. Otherwise returns null. 341 * 342 * @throws Exception if the group can not be created 343 */ 344 public static H4Group create(String name, Group pgroup) throws Exception { 345 log.trace("create(): start: name={} parentGroup={}", name, pgroup); 346 347 H4Group group = null; 348 if ((pgroup == null) || 349 (name == null)) { 350 log.debug("create(): one or more parameters are null"); 351 return null; 352 } 353 354 H4File file = (H4File)pgroup.getFileFormat(); 355 356 if (file == null) { 357 log.debug("create(): Parent group FileFormat is null"); 358 return null; 359 } 360 361 String path = HObject.SEPARATOR; 362 if (!pgroup.isRoot()) 363 path = pgroup.getPath()+pgroup.getName()+HObject.SEPARATOR; 364 long fileid = file.open(); 365 if (fileid < 0) { 366 log.debug("create(): Invalid File ID"); 367 return null; 368 } 369 370 long gid = HDFLibrary.Vattach(fileid, -1, "w"); 371 if (gid < 0) { 372 log.debug("create(): Invalid Group ID"); 373 return null; 374 } 375 376 HDFLibrary.Vsetname(gid, name); 377 int ref = HDFLibrary.VQueryref(gid); 378 int tag = HDFLibrary.VQuerytag(gid); 379 380 if (!pgroup.isRoot()) { 381 // add the dataset to the parent group 382 long pid = pgroup.open(); 383 if (pid < 0) { 384 log.debug("create(): Invalid Parent Group ID"); 385 throw (new HDFException("Unable to open the parent group.")); 386 } 387 388 HDFLibrary.Vinsert(pid, gid); 389 390 pgroup.close(pid); 391 } 392 393 try { 394 HDFLibrary.Vdetach(gid); 395 } 396 catch (Exception ex) { 397 log.debug("create(): Vdetach failure: ", ex); 398 } 399 400 long[] oid = {tag, ref}; 401 group = new H4Group(file, name, path, pgroup, oid); 402 403 if (group != null) 404 pgroup.addToMemberList(group); 405 406 return group; 407 } 408 409 //Implementing DataFormat 410 /** 411 * Retrieves the object's metadata, such as attributes, from the file. 412 * 413 * Metadata, such as attributes, is stored in a List. 414 * 415 * @param attrPropList 416 * the list of properties to get 417 * 418 * @return the list of metadata objects. 419 * 420 * @throws Exception 421 * if the metadata can not be retrieved 422 */ 423 @SuppressWarnings("rawtypes") 424 public List getMetadata(int... attrPropList) throws Exception { 425 throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported"); 426 } 427}