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.nc2;
016
017import java.util.List;
018
019import org.slf4j.Logger;
020import org.slf4j.LoggerFactory;
021
022import hdf.object.Datatype;
023
024import ucar.ma2.DataType;
025
026/**
027 * Datatype encapsulates information of a datatype. Information includes the
028 * class, size, endian of a datatype.
029 *
030 * @version 1.1 9/4/2007
031 * @author Peter X. Cao
032 */
033public class NC2Datatype extends Datatype
034{
035    private static final long serialVersionUID = 5399364372073889764L;
036
037    private static final Logger log = LoggerFactory.getLogger(NC2Datatype.class);
038
039    /** the native datatype */
040    private DataType nativeType = null;
041
042    /**
043     * Create an Datatype with specified class, size, byte order and sign. The
044     * following list a few example of how to create a Datatype.
045     * <ol>
046     * <li>to create unsigned native integer<br>
047     * NC2Datatype type = new NC2Datatype(Datatype.CLASS_INTEGER, Datatype.NATIVE, Datatype.NATIVE, Datatype.SIGN_NONE);</li>
048     * <li>to create 16-bit signed integer with big endian<br>
049     * NC2Datatype type = new NC2Datatype(Datatype.CLASS_INTEGER, 2, Datatype.ORDER_BE, Datatype.NATIVE);</li>
050     * <li>to create native float<br>
051     * NC2Datatype type = new NC2Datatype(Datatype.CLASS_FLOAT, Datatype.NATIVE, Datatype.NATIVE, Datatype.NATIVE);</li>
052     * <li>to create 64-bit double<br>
053     * NC2Datatype type = new NC2Datatype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, Datatype.NATIVE);</li>
054     * </ol>
055     *
056     * @param tclass
057     *            the class of the datatype, e.g. CLASS_INTEGER, CLASS_FLOAT and etc.
058     * @param tsize
059     *            the size of the datatype in bytes, e.g. for a 32-bit integer, the size is 4.
060     *            Valid values are NATIVE or a positive value.
061     * @param torder
062     *            the byte order of the datatype. Valid values are ORDER_LE, ORDER_BE, ORDER_VAX,
063     *            ORDER_NONE and NATIVE.
064     * @param tsign
065     *            the sign of the datatype. Valid values are SIGN_NONE, SIGN_2 and NATIVE.
066     *
067     * @throws Exception
068     *            if there is an error
069     */
070    public NC2Datatype(int tclass, int tsize, int torder, int tsign) throws Exception {
071        super(tclass, tsize, torder, tsign);
072        datatypeDescription = getDescription();
073    }
074
075    /**
076     * Constructs a NC2Datatype with a given NetCDF3 native datatype object.
077     *
078     * @param theType
079     *            the netcdf native datatype.
080     *
081     * @throws Exception
082     *            if there is an error
083     */
084    public NC2Datatype(DataType theType) throws Exception {
085        super(null, -1);
086        log.trace("NC2Datatype: start nc2 type = {}", theType);
087        nativeType = theType;
088        fromNative(0);
089        datatypeDescription = getDescription();
090    }
091
092    /*
093     * (non-Javadoc)
094     *
095     * @see hdf.object.Datatype#fromNative(long)
096     */
097    /**
098     * Translate NetCDF3 datatype object into NC2Datatype.
099     *
100     * @param tid the native ID
101     *            UNUSED.
102     */
103    @Override
104    public void fromNative(long tid) {
105        if (nativeType == null)
106            return;
107
108        datatypeOrder = NATIVE;
109        if (nativeType.equals(DataType.CHAR)) {
110            datatypeClass = CLASS_CHAR;
111            datatypeSize = 1;
112        }
113        else if (nativeType.equals(DataType.BYTE)) {
114            datatypeClass = CLASS_INTEGER;
115            datatypeSize = 1;
116        }
117        else if (nativeType.equals(DataType.SHORT)) {
118            datatypeClass = CLASS_INTEGER;
119            datatypeSize = 2;
120        }
121        else if (nativeType.equals(DataType.INT)) {
122            datatypeClass = CLASS_INTEGER;
123            datatypeSize = 4;
124        }
125        else if (nativeType.equals(DataType.LONG)) {
126            datatypeClass = CLASS_INTEGER;
127            datatypeSize = 8;
128        }
129        else if (nativeType.equals(DataType.FLOAT)) {
130            datatypeClass = CLASS_FLOAT;
131            datatypeSize = 4;
132        }
133        else if (nativeType.equals(DataType.DOUBLE)) {
134            datatypeClass = CLASS_FLOAT;
135            datatypeSize = 8;
136        }
137        else if (nativeType.equals(DataType.STRING)) {
138            datatypeClass = CLASS_STRING;
139            datatypeSize = 80; // default length. need to figure out the actual length
140        }
141        else if (nativeType.equals(DataType.OPAQUE)) {
142            datatypeClass = CLASS_OPAQUE;
143            datatypeSize = 1;
144        }
145
146        log.trace("Datatype class={} size={}", datatypeClass, datatypeSize);
147    }
148
149    /**
150     * Allocate an one-dimensional array of byte, short, int, long, float,
151     * double, or String to store data retrieved from an NetCDF3 file based on
152     * the given NetCDF3 datatype and dimension sizes.
153     *
154     * @param dtype
155     *            the NetCDF3 datatype object.
156     * @param datasize
157     *            the size of the data array
158     *
159     * @return an array of 'datasize' numbers of datatype.
160     *
161     * @throws OutOfMemoryError
162     *             if the array cannot be allocated
163     */
164    public static final Object allocateArray(DataType dtype, int datasize) throws OutOfMemoryError {
165        if ((datasize <= 0) || (dtype == null)) {
166            log.debug("datasize <= 0");
167            return null;
168        }
169
170        Object data = null;
171
172        if (dtype.equals(DataType.BYTE))
173            data = new byte[datasize];
174        else if (dtype.equals(DataType.SHORT))
175            data = new short[datasize];
176        else if (dtype.equals(DataType.INT))
177            data = new int[datasize];
178        else if (dtype.equals(DataType.LONG))
179            data = new long[datasize];
180        else if (dtype.equals(DataType.FLOAT))
181            data = new float[datasize];
182        else if (dtype.equals(DataType.DOUBLE))
183            data = new double[datasize];
184        else if (dtype.equals(DataType.STRING))
185            data = new String[datasize];
186
187        return data;
188    }
189
190    /*
191     * (non-Javadoc)
192     *
193     * @see hdf.object.Datatype#getDatatypeDescription()
194     */
195    @Override
196    public String getDescription() {
197        if (datatypeDescription != null)
198            return datatypeDescription;
199
200        String description = null;
201
202        if (nativeType == null)
203            description = "Unknown data type.";
204
205        description = nativeType.toString();
206
207        return description;
208    }
209
210    /*
211     * (non-Javadoc)
212     *
213     * @see hdf.object.Datatype#isUnsigned()
214     */
215    @Override
216    public boolean isUnsigned() {
217        if (nativeType.isNumeric())
218            return false;
219        else
220            return false;
221    }
222
223    @Override
224    public boolean isText() {
225        return (nativeType == DataType.CHAR);
226    }
227
228    /*
229     * (non-Javadoc)
230     * @see hdf.object.Datatype#createNative()
231     */
232    @Override
233    public long createNative() {
234        if (datatypeClass == CLASS_INTEGER) {
235            if (datatypeSize == 1)
236                nativeType = DataType.BYTE;
237            else if (datatypeSize == 2)
238                nativeType = DataType.SHORT;
239            else if (datatypeSize == 4)
240                nativeType = DataType.INT;
241            else if (datatypeSize == 8)
242                nativeType = DataType.LONG;
243        }
244        else if (datatypeClass == CLASS_FLOAT) {
245            if (datatypeSize == 4)
246                nativeType = DataType.FLOAT;
247            else if (datatypeSize == 8)
248                nativeType = DataType.DOUBLE;
249        }
250        else if (datatypeClass == CLASS_STRING) {
251            nativeType = DataType.STRING;
252        }
253        else {
254            log.debug("createNative(): unknown datatype class {}", datatypeClass);
255        }
256
257        return -1;
258    }
259
260    /*
261     * (non-Javadoc)
262     *
263     * @see hdf.object.Datatype#close(int)
264     */
265    @Override
266    public void close(long id) {
267        // No implementation
268    }
269
270    // Implementing MetaDataContainer
271    /**
272     * Retrieves the object's metadata, such as attributes, from the file.
273     *
274     * Metadata, such as attributes, is stored in a List.
275     *
276     * @param attrPropList
277     *             the list of properties to get
278     *
279     * @return the list of metadata objects.
280     *
281     * @throws Exception
282     *             if the metadata can not be retrieved
283     */
284    @SuppressWarnings("rawtypes")
285    public List getMetadata(int... attrPropList) throws Exception {
286        throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported");
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    @Override
295    public boolean hasAttribute() {
296        return false;
297    }
298}