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