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