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.h4;
016
017import hdf.object.Attribute;
018import hdf.object.Datatype;
019import hdf.object.FileFormat;
020import hdf.object.HObject;
021
022/**
023 * An attribute is a (name, value) pair of metadata attached to a primary data object such as a
024 * dataset, group or named datatype.
025 * <p>
026 * Like a dataset, an attribute has a name, datatype and dataspace.
027 *
028 * <p>
029 * For more details on attributes, <a href=
030 * "https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html">HDF5
031 * User's Guide</a>
032 * <p>
033 *
034 * The following code is an example of an attribute with 1D integer array of two elements.
035 *
036 * <pre>
037 * // Example of creating a new attribute
038 * // The name of the new attribute
039 * String name = "Data range";
040 * // Creating an unsigned 1-byte integer datatype
041 * Datatype type = new Datatype(Datatype.CLASS_INTEGER, // class
042 *                              1,                      // size in bytes
043 *                              Datatype.ORDER_LE,      // byte order
044 *                              Datatype.SIGN_NONE);    // unsigned
045 * // 1-D array of size two
046 * long[] dims = {2};
047 * // The value of the attribute
048 * int[] value = {0, 255};
049 * // Create a new attribute
050 * Attribute dataRange = new Attribute(name, type, dims);
051 * // Set the attribute value
052 * dataRange.setValue(value);
053 * // See FileFormat.writeAttribute() for how to attach an attribute to an object,
054 * &#64;see hdf.object.FileFormat#writeAttribute(HObject, Attribute, boolean)
055 * </pre>
056 *
057 *
058 * For an atomic datatype, the value of an Attribute will be a 1D array of integers, floats and
059 * strings. For a compound datatype, it will be a 1D array of strings with field members separated
060 * by a comma. For example, "{0, 10.5}, {255, 20.0}, {512, 30.0}" is a compound attribute of {int,
061 * float} of three data points.
062 *
063 * @see hdf.object.Datatype
064 *
065 * @version 2.0 4/2/2018
066 * @author Peter X. Cao, Jordan T. Henderson
067 */
068public class H4Attribute extends Attribute {
069
070    private static final long serialVersionUID = 2072473407027648309L;
071
072    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H4Attribute.class);
073
074    /**
075     * Create an attribute with specified name, data type and dimension sizes.
076     *
077     * For scalar attribute, the dimension size can be either an array of size one
078     * or null, and the rank can be either 1 or zero. Attribute is a general class
079     * and is independent of file format, e.g., the implementation of attribute
080     * applies to both HDF4 and HDF5.
081     * <p>
082     * The following example creates a string attribute with the name "CLASS" and
083     * value "IMAGE".
084     *
085     * <pre>
086     * long[] attrDims = { 1 };
087     * String attrName = &quot;CLASS&quot;;
088     * String[] classValue = { &quot;IMAGE&quot; };
089     * Datatype attrType = null;
090     * try {
091     *     attrType = new H5Datatype(Datatype.CLASS_STRING, classValue[0].length() + 1, Datatype.NATIVE, Datatype.NATIVE);
092     * }
093     * catch (Exception ex) {}
094     * Attribute attr = new Attribute(attrName, attrType, attrDims);
095     * attr.setValue(classValue);
096     * </pre>
097     *
098     * @param parentObj
099     *            the HObject to which this Attribute is attached.
100     * @param attrName
101     *            the name of the attribute.
102     * @param attrType
103     *            the datatype of the attribute.
104     * @param attrDims
105     *            the dimension sizes of the attribute, null for scalar attribute
106     *
107     * @see hdf.object.Datatype
108     */
109    public H4Attribute(HObject parentObj, String attrName, Datatype attrType, long[] attrDims) {
110        this(parentObj, attrName, attrType, attrDims, null);
111    }
112
113    /**
114     * Create an attribute with specific name and value.
115     *
116     * For scalar attribute, the dimension size can be either an array of size one
117     * or null, and the rank can be either 1 or zero. Attribute is a general class
118     * and is independent of file format, e.g., the implementation of attribute
119     * applies to both HDF4 and HDF5.
120     * <p>
121     * The following example creates a string attribute with the name "CLASS" and
122     * value "IMAGE".
123     *
124     * <pre>
125     * long[] attrDims = { 1 };
126     * String attrName = &quot;CLASS&quot;;
127     * String[] classValue = { &quot;IMAGE&quot; };
128     * Datatype attrType = null;
129     * try {
130     *     attrType = new H5Datatype(Datatype.CLASS_STRING, classValue[0].length() + 1, Datatype.NATIVE, Datatype.NATIVE);
131     * }
132     * catch (Exception ex) {}
133     * Attribute attr = new Attribute(attrName, attrType, attrDims, classValue);
134     * </pre>
135     *
136     * @param parentObj
137     *            the HObject to which this Attribute is attached.
138     * @param attrName
139     *            the name of the attribute.
140     * @param attrType
141     *            the datatype of the attribute.
142     * @param attrDims
143     *            the dimension sizes of the attribute, null for scalar attribute
144     * @param attrValue
145     *            the value of the attribute, null if no value
146     *
147     * @see hdf.object.Datatype
148     */
149    @SuppressWarnings({ "rawtypes", "unchecked", "deprecation" })
150    public H4Attribute(HObject parentObj, String attrName, Datatype attrType, long[] attrDims, Object attrValue) {
151        super(parentObj, attrName, attrType, null);
152    }
153
154    /*
155     * (non-Javadoc)
156     *
157     * @see hdf.object.HObject#open()
158     */
159    @Override
160    public long open() {
161        long aid = super.open();
162        long pObjID = -1;
163
164        try {
165            pObjID = parentObject.open();
166            if (pObjID >= 0) {
167                if (this.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4))) {
168                    log.trace("open(): FILE_TYPE_HDF4");
169                    /*
170                     * TODO: Get type of HDF4 object this is attached to and retrieve attribute info.
171                     */
172                }
173            }
174
175            log.trace("open(): aid={}", aid);
176        }
177        catch (Exception ex) {
178            log.debug("open(): Failed to open attribute {}: ", getName(), ex);
179            aid = -1;
180        }
181        finally {
182            parentObject.close(pObjID);
183        }
184
185        return aid;
186    }
187
188    /*
189     * (non-Javadoc)
190     *
191     * @see hdf.object.HObject#close(int)
192     */
193    @Override
194    public void close(long aid) {
195        if (aid >= 0) {
196            if (this.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4))) {
197                log.trace("close(): FILE_TYPE_HDF4");
198                /*
199                 * TODO: Get type of HDF4 object this is attached to and close attribute.
200                 */
201            }
202        }
203    }
204
205    @Override
206    public void init() {
207        super.init();
208        if (inited) {
209            return;
210        }
211
212        if (this.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4))) {
213            log.trace("init(): FILE_TYPE_HDF4");
214            /*
215             * TODO: If HDF4 attribute object needs to init dependent objects.
216             */
217            inited = true;
218        }
219
220        resetSelection();
221    }
222}