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.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 * <p>
036 * @version 1.1 9/4/2007
037 * @author Peter X. Cao
038 */
039public class H4Group extends Group
040{
041    /**
042     * 
043     */
044    private static final long serialVersionUID = 3785240955078867900L;
045
046    private final static 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 Attribute.
051     */
052    private List attributeList;
053    
054    private int nAttributes = -1;
055
056    /** The default object ID for HDF4 objects */
057    private final static long[] DEFAULT_OID = {0, 0};
058
059    public H4Group(FileFormat theFile, String name, String path, Group parent)
060    {
061        this(theFile, name, path, parent, null);
062    }
063
064    /**
065     * Creates a group object with specific name, path, and parent.
066     * <p>
067     * @param theFile the HDF file.
068     * @param name the name of this group.
069     * @param path the full path of this group.
070     * @param parent the parent of this group.
071     * @param oid the unique identifier of this data object.
072     */
073    public H4Group(
074        FileFormat theFile,
075        String name,
076        String path,
077        Group parent,
078        long[] oid)
079    {
080        super (theFile, name, path, parent, ((oid == null) ? DEFAULT_OID : oid));
081    }
082
083    /*
084     * (non-Javadoc)
085     * @see hdf.object.DataFormat#hasAttribute()
086     */
087    public boolean hasAttribute () 
088    { 
089        if (nAttributes < 0) {
090            int vgid = open();
091            try {  
092                nAttributes =HDFLibrary.Vnattrs(vgid);
093                nMembersInFile = HDFLibrary.Vntagrefs(vgid);
094            } 
095            catch (Exception ex) {
096                nAttributes = 0;
097            }
098            close(vgid);
099        }
100        
101        return (nAttributes > 0);
102    }
103    
104    // Implementing DataFormat
105    public List getMetadata() throws HDFException
106    {
107        if (attributeList != null) {
108            return attributeList;
109        } 
110        else {
111            attributeList = new Vector();
112        }
113
114        int vgid = open();
115        if (vgid <= 0) {
116            return attributeList;
117        }
118
119        int n = -1;
120
121        try {
122            n = HDFLibrary.Vnattrs(vgid);
123            
124            boolean b = false;
125            String[] attrName = new String[1];
126            int[] attrInfo = new int[5];
127            for (int i=0; i<n; i++) {
128                attrName[0] = "";
129                try {
130                    b = HDFLibrary.Vattrinfo(vgid, i, attrName, attrInfo);
131                    // mask off the litend bit
132                    attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND);
133                } 
134                catch (HDFException ex) {
135                    b = false;
136                }
137
138                if (!b) {
139                    continue;
140                }
141
142                long[] attrDims = {attrInfo[1]};
143                Attribute attr = new Attribute(attrName[0], new H4Datatype(attrInfo[0]), attrDims);;
144                attributeList.add(attr);
145
146                Object buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]);
147                
148                try {
149                    HDFLibrary.Vgetattr(vgid, i, buf);
150                } 
151                catch (HDFException ex) {
152                        ex.printStackTrace();
153                    buf = null;
154                }
155
156                if (buf != null) {
157                    if ((attrInfo[0] == HDFConstants.DFNT_CHAR) ||
158                        (attrInfo[0] ==  HDFConstants.DFNT_UCHAR8)) {
159                        buf = Dataset.byteToString((byte[])buf, attrInfo[1]);
160                    }
161
162                    attr.setValue(buf);
163                }
164            }
165        } 
166        finally {
167            close(vgid);
168        }
169
170        return attributeList;
171    }
172
173    // To do: implementing DataFormat
174    public void writeMetadata(Object info) throws Exception
175    {
176        // only attribute metadata is supported.
177        if (!(info instanceof Attribute)) {
178            return;
179        }
180
181        getFileFormat().writeAttribute(this, (Attribute)info, true);
182
183        if (attributeList == null) {
184            attributeList = new Vector();
185        }
186
187        attributeList.add(info);
188        nAttributes = attributeList.size();
189    }
190
191
192   // To do: implementing DataFormat
193    public void removeMetadata(Object info) throws HDFException {;}
194
195    // implementing DataFormat
196    public void updateMetadata(Object info) throws Exception {
197        log.trace("updateMetadata(): disabled");
198    }
199
200   // Implementing HObject
201    @Override
202    public int open()
203    {
204        int vgid = -1;
205
206        // try to open with write permission
207        try {
208            vgid = HDFLibrary.Vattach(getFID(), (int)oid[1], "w");
209        } 
210        catch (HDFException ex) {
211            vgid = -1;
212        }
213
214        // try to open with read-only permission
215        if (vgid < 0) {
216            try {
217                vgid = HDFLibrary.Vattach(getFID(), (int)oid[1], "r");
218            } 
219            catch (HDFException ex) {
220                vgid = -1;
221            }
222        }
223
224        return vgid;
225    }
226
227    /** close group access. */
228    @Override
229    public void close(int vgid)
230    {
231        try { 
232                HDFLibrary.Vdetach(vgid); 
233        }
234        catch (Exception ex) {
235                log.debug("close.Vdetach:", ex);
236        }
237    }
238
239    /**
240     * Creates a new group.
241     * @param name the name of the group to create.
242     * @param pgroup the parent group of the new group.
243     * @return the new group if successful. Otherwise returns null.
244     */
245    public static H4Group create(String name, Group pgroup)
246        throws Exception
247    {
248        H4Group group = null;
249        if ((pgroup == null) ||
250            (name == null)) {
251            return null;
252        }
253
254        H4File file = (H4File)pgroup.getFileFormat();
255
256        if (file == null) {
257            return null;
258        }
259
260        String path = HObject.separator;
261        if (!pgroup.isRoot()) {
262            path = pgroup.getPath()+pgroup.getName()+HObject.separator;
263        }
264        int fileid = file.open();
265        if (fileid < 0) {
266            return null;
267        }
268
269        int gid = HDFLibrary.Vattach(fileid, -1, "w");
270        if (gid < 0) {
271            return null;
272        }
273
274        HDFLibrary.Vsetname(gid, name);
275        int ref = HDFLibrary.VQueryref(gid);
276        int tag = HDFLibrary.VQuerytag(gid);
277
278        if (!pgroup.isRoot()) {
279            // add the dataset to the parent group
280            int pid = pgroup.open();
281            if (pid < 0) {
282                throw (new HDFException("Unable to open the parent group."));
283            }
284
285            HDFLibrary.Vinsert(pid, gid);
286
287            pgroup.close(pid);
288        }
289
290        try { 
291                HDFLibrary.Vdetach(gid); 
292        }
293        catch (Exception ex) {
294                log.debug("create.Vdetach:", ex);
295        }
296
297        long[] oid = {tag, ref};
298        group = new H4Group(file, name, path, pgroup, oid);
299
300        if (group != null) {
301            pgroup.addToMemberList(group);
302        }
303
304        return group;
305    }
306
307    //Implementing DataFormat
308    public List getMetadata(int... attrPropList) throws Exception {
309        throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported");
310    }
311
312}