    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}