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