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