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 org.slf4j.Logger;
021import org.slf4j.LoggerFactory;
022
023import hdf.object.Attribute;
024import hdf.object.FileFormat;
025import hdf.object.HObject;
026import hdf.object.MetaDataContainer;
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
042    private static final Logger log = LoggerFactory.getLogger(H5Group.class);
043
044    /** The HObject to which this MetaDataContainer is attached */
045    protected HObject         parentObject;
046
047    /**
048     * The list of attributes of this data object. Members of the list are
049     * instance of Attribute.
050     */
051    @SuppressWarnings("rawtypes")
052    protected List            attributeList;
053
054    /** the number of attributes */
055    private int               nAttributes      = -1;
056
057    /**
058     * Constructs an HDF5 group with specific name, path, and parent.
059     *
060     * @param theFile
061     *            the file which containing the group.
062     * @param name
063     *            the name of this group, e.g. "grp01".
064     * @param path
065     *            the full path of this group, e.g. "/groups/".
066     * @param parent
067     *            the parent of this group.
068     */
069    public H5MetaDataContainer(FileFormat theFile, String name, String path, HObject parent) {
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        super(theFile, name, path, oid);
090
091        this.parentObject = parent;
092    }
093
094    /**
095     * Removes all of the elements from metadata list.
096     * The list should be empty after this call returns.
097     */
098    @SuppressWarnings("rawtypes")
099    @Override
100    public void clear() {
101        if (attributeList != null)
102            ((Vector) attributeList).setSize(0);
103    }
104
105    /**
106     * Retrieves the object's attributeList.
107     *
108     * @return the list.
109     */
110    public List getAttributeList() {
111        return attributeList;
112    }
113
114    /**
115     * Retrieves the object's number of attributes.
116     *
117     * @return the list size.
118     */
119    public int getObjectAttributeSize() {
120        return nAttributes;
121    }
122
123    /**
124     * Updates the object's number of attributes.
125     *
126     * @param objectAttributes
127     *            the number of attributes for an object.
128     */
129    public void setObjectAttributeSize(int objectAttributes) {
130        nAttributes = objectAttributes;
131    }
132
133    /**
134     * Retrieves the object's metadata, such as attributes, from the file.
135     *
136     * Metadata, such as attributes, is stored in a List.
137     *
138     * @return the list of metadata objects.
139     *
140     * @throws Exception
141     *             if the metadata can not be retrieved
142     */
143    public List getMetadata() throws Exception {
144        int gmIndexType = 0;
145        int gmIndexOrder = 0;
146
147        try {
148            gmIndexType = fileFormat.getIndexType(null);
149        }
150        catch (Exception ex) {
151            log.debug("getMetadata(): getIndexType failed: ", ex);
152        }
153        try {
154            gmIndexOrder = fileFormat.getIndexOrder(null);
155        }
156        catch (Exception ex) {
157            log.debug("getMetadata(): getIndexOrder failed: ", ex);
158        }
159        return this.getMetadata(gmIndexType, gmIndexOrder);
160    }
161
162    /**
163     * Retrieves the object's metadata, such as attributes, from the file.
164     *
165     * Metadata, such as attributes, is stored in a List.
166     *
167     * @param attrPropList
168     *             the list of properties to get
169     *
170     * @return the list of metadata objects.
171     *
172     * @throws Exception
173     *             if the metadata can not be retrieved
174     */
175    @SuppressWarnings("rawtypes")
176    public List getMetadata(int... attrPropList) throws Exception {
177        try {
178            this.linkTargetObjName = H5File.getLinkTargetName(this.parentObject);
179        }
180        catch (Exception ex) {
181            log.debug("getMetadata(): getLinkTargetName failed: ", ex);
182        }
183
184        if (attributeList != null) {
185            log.trace("getMetadata(): attributeList != null");
186            return attributeList;
187        }
188
189        int indxType = fileFormat.getIndexType(null);
190        int order = fileFormat.getIndexOrder(null);
191
192        if (attrPropList.length > 0) {
193            indxType = attrPropList[0];
194            if (attrPropList.length > 1)
195                order = attrPropList[1];
196        }
197        try {
198            attributeList = H5File.getAttribute(this.parentObject, indxType, order);
199        }
200        catch (Exception ex) {
201            log.debug("getMetadata(): H5File.getAttribute failure: ", ex);
202        }
203
204        return attributeList;
205    }
206
207    /**
208     * Writes a specific piece of metadata (such as an attribute) into the file.
209     *
210     * If an HDF5 attribute exists in the file, this method updates its
211     * value. If the attribute does not exist in the file, it creates the
212     * attribute in the file and attaches it to the object. It will fail to
213     * write a new attribute to the object where an attribute with the same name
214     * already exists. To update the value of an existing attribute in the file,
215     * one needs to get the instance of the attribute by getMetadata(), change
216     * its values, then use writeMetadata() to write the value.
217     *
218     * @param metadata
219     *            the metadata to write.
220     *
221     * @throws Exception
222     *             if the metadata can not be written
223     */
224    public void writeMetadata(Object metadata) throws Exception {
225        // only attribute metadata is supported.
226        if (!(metadata instanceof Attribute)) {
227            log.debug("writeMetadata(): Object not an Attribute");
228            return;
229        }
230
231        boolean attrExisted = false;
232        Attribute attr = (Attribute) metadata;
233        log.trace("writeMetadata(): {}", attr.getAttributeName());
234
235        if (attributeList == null)
236            attributeList = ((MetaDataContainer)parentObject).getMetadata();
237
238        if (attributeList != null)
239            attrExisted = attributeList.contains(attr);
240
241        getFileFormat().writeAttribute(this.parentObject, attr, attrExisted);
242        // add the new attribute into attribute list
243        if (!attrExisted) {
244            attributeList.add(attr);
245            nAttributes = attributeList.size();
246        }
247    }
248
249    /**
250     * Deletes an existing piece of metadata from this object.
251     *
252     * @param metadata
253     *            the metadata to delete.
254     *
255     * @throws Exception
256     *             if the metadata can not be removed
257     */
258    public void removeMetadata(Object metadata) throws Exception {
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        // only attribute metadata is supported.
281        if (!(metadata instanceof Attribute)) {
282            log.debug("updateMetadata(): Object not an Attribute");
283            return;
284        }
285
286        nAttributes = -1;
287    }
288
289    /**
290     * Check if the object has any attributes attached.
291     *
292     * @return true if it has any attributes, false otherwise.
293     */
294    public boolean hasAttribute() {
295        return (nAttributes > 0);
296    }
297
298    /*
299     * (non-Javadoc)
300     *
301     * @see hdf.object.HObject#open(int)
302     */
303    @Override
304    public long open() {
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}