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 *
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     *
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     *
242     * @param name the name of the group to create.
243     * @param pgroup the parent group of the new group.
244     *
245     * @return the new group if successful. Otherwise returns null.
246     *
247     * @throws Exception if the group can not be created
248     */
249    public static H4Group create(String name, Group pgroup)
250        throws Exception
251    {
252        H4Group group = null;
253        if ((pgroup == null) ||
254            (name == null)) {
255            return null;
256        }
257
258        H4File file = (H4File)pgroup.getFileFormat();
259
260        if (file == null) {
261            return null;
262        }
263
264        String path = HObject.separator;
265        if (!pgroup.isRoot()) {
266            path = pgroup.getPath()+pgroup.getName()+HObject.separator;
267        }
268        int fileid = file.open();
269        if (fileid < 0) {
270            return null;
271        }
272
273        int gid = HDFLibrary.Vattach(fileid, -1, "w");
274        if (gid < 0) {
275            return null;
276        }
277
278        HDFLibrary.Vsetname(gid, name);
279        int ref = HDFLibrary.VQueryref(gid);
280        int tag = HDFLibrary.VQuerytag(gid);
281
282        if (!pgroup.isRoot()) {
283            // add the dataset to the parent group
284            int pid = pgroup.open();
285            if (pid < 0) {
286                throw (new HDFException("Unable to open the parent group."));
287            }
288
289            HDFLibrary.Vinsert(pid, gid);
290
291            pgroup.close(pid);
292        }
293
294        try {
295            HDFLibrary.Vdetach(gid);
296        }
297        catch (Exception ex) {
298            log.debug("create.Vdetach:", ex);
299        }
300
301        long[] oid = {tag, ref};
302        group = new H4Group(file, name, path, pgroup, oid);
303
304        if (group != null) {
305            pgroup.addToMemberList(group);
306        }
307
308        return group;
309    }
310
311    //Implementing DataFormat
312    public List getMetadata(int... attrPropList) throws Exception {
313        throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported");
314    }
315
316}