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 COPYING file, which can be found  *
009 * at the root of the source code distribution tree,                         *
010 * or in https://www.hdfgroup.org/licenses.                                  *
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.object.Attribute;
021import hdf.object.FileFormat;
022import hdf.object.HObject;
023import hdf.object.MetaDataContainer;
024
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028/**
029 * An class that provides general I/O operations for object metadata
030 * attached to an object. For example, reading metadata content from the file
031 * into memory or writing metadata content from memory into the file.
032 *
033 * @see hdf.object.HObject
034 *
035 * @version 2.0 4/2/2018
036 * @author Peter X. Cao, Jordan T. Henderson
037 */
038@SuppressWarnings("rawtypes")
039public class H5MetaDataContainer extends HObject implements MetaDataContainer {
040
041    private static final Logger log = LoggerFactory.getLogger(H5Group.class);
042
043    /** The HObject to which this MetaDataContainer is attached */
044    protected HObject parentObject;
045
046    /**
047     * The list of attributes of this data object. Members of the list are
048     * instance of Attribute.
049     */
050    @SuppressWarnings("rawtypes")
051    protected List attributeList;
052
053    /** the number of attributes */
054    private int nAttributes = -1;
055
056    /**
057     * Constructs an HDF5 group with specific name, path, and parent.
058     *
059     * @param theFile
060     *            the file which containing the group.
061     * @param name
062     *            the name of this group, e.g. "grp01".
063     * @param path
064     *            the full path of this group, e.g. "/groups/".
065     * @param parent
066     *            the parent of this group.
067     */
068    public H5MetaDataContainer(FileFormat theFile, String name, String path, HObject parent)
069    {
070        this(theFile, name, path, parent, null);
071    }
072
073    /**
074     * @deprecated Not for public use in the future.<br>
075     *
076     * @param theFile
077     *            the file which containing the group.
078     * @param name
079     *            the name of this group, e.g. "grp01".
080     * @param path
081     *            the full path of this group, e.g. "/groups/".
082     * @param parent
083     *            the parent of this group.
084     * @param oid
085     *            the oid of this group.
086     */
087    @Deprecated
088    public H5MetaDataContainer(FileFormat theFile, String name, String path, HObject parent, long[] oid)
089    {
090        super(theFile, name, path, oid);
091
092        this.parentObject = parent;
093    }
094
095    /**
096     * Removes all of the elements from metadata list.
097     * The list should be empty after this call returns.
098     */
099    @SuppressWarnings("rawtypes")
100    @Override
101    public void clear()
102    {
103        if (attributeList != null)
104            ((Vector)attributeList).setSize(0);
105    }
106
107    /**
108     * Retrieves the object's attributeList.
109     *
110     * @return the list.
111     */
112    public List getAttributeList() { return attributeList; }
113
114    /**
115     * Retrieves the object's number of attributes.
116     *
117     * @return the list size.
118     */
119    public int getObjectAttributeSize() { return nAttributes; }
120
121    /**
122     * Updates the object's number of attributes.
123     *
124     * @param objectAttributes
125     *            the number of attributes for an object.
126     */
127    public void setObjectAttributeSize(int objectAttributes) { nAttributes = objectAttributes; }
128
129    /**
130     * Retrieves the object's metadata, such as attributes, from the file.
131     *
132     * Metadata, such as attributes, is stored in a List.
133     *
134     * @return the list of metadata objects.
135     *
136     * @throws Exception
137     *             if the metadata can not be retrieved
138     */
139    public List getMetadata() throws Exception
140    {
141        int gmIndexType  = 0;
142        int gmIndexOrder = 0;
143
144        try {
145            gmIndexType = fileFormat.getIndexType(null);
146        }
147        catch (Exception ex) {
148            log.debug("getMetadata(): getIndexType failed: ", ex);
149        }
150        try {
151            gmIndexOrder = fileFormat.getIndexOrder(null);
152        }
153        catch (Exception ex) {
154            log.debug("getMetadata(): getIndexOrder failed: ", ex);
155        }
156        return this.getMetadata(gmIndexType, gmIndexOrder);
157    }
158
159    /**
160     * Retrieves the object's metadata, such as attributes, from the file.
161     *
162     * Metadata, such as attributes, is stored in a List.
163     *
164     * @param attrPropList
165     *             the list of properties to get
166     *
167     * @return the list of metadata objects.
168     *
169     * @throws Exception
170     *             if the metadata can not be retrieved
171     */
172    @SuppressWarnings("rawtypes")
173    public List getMetadata(int... attrPropList) throws Exception
174    {
175        try {
176            this.linkTargetObjName = H5File.getLinkTargetName(this.parentObject);
177        }
178        catch (Exception ex) {
179            log.debug("getMetadata(): getLinkTargetName failed: ", ex);
180        }
181
182        if (attributeList != null) {
183            log.trace("getMetadata(): attributeList != null");
184            return attributeList;
185        }
186
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        try {
196            attributeList = H5File.getAttribute(this.parentObject, indxType, order);
197        }
198        catch (Exception ex) {
199            log.debug("getMetadata(): H5File.getAttribute failure: ", ex);
200        }
201
202        return attributeList;
203    }
204
205    /**
206     * Writes a specific piece of metadata (such as an attribute) into the file.
207     *
208     * If an HDF5 attribute exists in the file, this method updates its
209     * value. If the attribute does not exist in the file, it creates the
210     * attribute in the file and attaches it to the object. It will fail to
211     * write a new attribute to the object where an attribute with the same name
212     * already exists. To update the value of an existing attribute in the file,
213     * one needs to get the instance of the attribute by getMetadata(), change
214     * its values, then use writeMetadata() to write the value.
215     *
216     * @param metadata
217     *            the metadata to write.
218     *
219     * @throws Exception
220     *             if the metadata can not be written
221     */
222    public void writeMetadata(Object metadata) throws Exception
223    {
224        // only attribute metadata is supported.
225        if (!(metadata instanceof Attribute)) {
226            log.debug("writeMetadata(): Object not an Attribute");
227            return;
228        }
229
230        boolean attrExisted = false;
231        Attribute attr      = (Attribute)metadata;
232        log.trace("writeMetadata(): {}", attr.getAttributeName());
233
234        if (attributeList == null)
235            attributeList = ((MetaDataContainer)parentObject).getMetadata();
236
237        if (attributeList != null)
238            attrExisted = attributeList.contains(attr);
239
240        getFileFormat().writeAttribute(this.parentObject, attr, attrExisted);
241        // add the new attribute into attribute list
242        if (!attrExisted) {
243            attributeList.add(attr);
244            nAttributes = attributeList.size();
245        }
246    }
247
248    /**
249     * Deletes an existing piece of metadata from this object.
250     *
251     * @param metadata
252     *            the metadata to delete.
253     *
254     * @throws Exception
255     *             if the metadata can not be removed
256     */
257    public void removeMetadata(Object metadata) throws Exception
258    {
259        // only attribute metadata is supported.
260        if (!(metadata instanceof Attribute))
261            throw new IllegalArgumentException("Object not an Attribute");
262
263        Attribute attr = (Attribute)metadata;
264        log.trace("removeMetadata(): {}", attr.getAttributeName());
265        List attrList = getMetadata();
266        attrList.remove(attr);
267        nAttributes = attributeList.size();
268    }
269
270    /**
271     * Updates an existing piece of metadata attached to this object.
272     *
273     * @param metadata
274     *            the metadata to update.
275     *
276     * @throws Exception
277     *             if the metadata can not be updated
278     */
279    public void updateMetadata(Object metadata) throws Exception
280    {
281        // only attribute metadata is supported.
282        if (!(metadata instanceof Attribute)) {
283            log.debug("updateMetadata(): Object not an Attribute");
284            return;
285        }
286
287        nAttributes = -1;
288    }
289
290    /**
291     * Check if the object has any attributes attached.
292     *
293     * @return true if it has any attributes, false otherwise.
294     */
295    public boolean hasAttribute() { return (nAttributes > 0); }
296
297    /*
298     * (non-Javadoc)
299     *
300     * @see hdf.object.HObject#open(int)
301     */
302    @Override
303    public long open()
304    {
305        return -1;
306    }
307
308    /*
309     * (non-Javadoc)
310     *
311     * @see hdf.object.HObject#close(int)
312     */
313    @Override
314    public void close(long tid)
315    {
316    }
317}