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