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; 018import java.util.Vector; 019 020import hdf.object.Dataset; 021import hdf.object.Datatype; 022import hdf.object.FileFormat; 023import hdf.object.Group; 024import hdf.object.HObject; 025import hdf.object.MetaDataContainer; 026import hdf.object.ScalarDS; 027 028import ucar.ma2.DataType; 029import ucar.nc2.Variable; 030 031/** 032 * NC2Dataset describes an multi-dimension array of HDF5 scalar or atomic data 033 * types, such as byte, int, short, long, float, double and string, and 034 * operations performed on the scalar dataset 035 * 036 * The library predefines a modest number of datatypes. For details, read <a 037 * href="https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/HDF5_Users_Guide/Datatypes/HDF5_Datatypes.htm">HDF5 Datatypes</a> 038 * 039 * @version 1.1 9/4/2007 040 * @author Peter X. Cao 041 */ 042public class NC2Dataset extends ScalarDS implements MetaDataContainer { 043 private static final long serialVersionUID = -6031051694304457461L; 044 045 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NC2Dataset.class); 046 047 /** tag for netCDF datasets. 048 * HDF4 library supports netCDF version 2.3.2. It only supports SDS APIs. 049 */ 050 // magic number for netCDF: "C(67) D(68) F(70) '\001'" 051 public static final int DFTAG_NDG_NETCDF = 67687001; 052 053 /** 054 * The list of attributes of this data object. Members of the list are 055 * instance of Attribute. 056 */ 057 @SuppressWarnings("rawtypes") 058 private List attributeList; 059 060 /** the native dataset */ 061 private Variable nativeDataset; 062 063 /** 064 * Constructs an NC2Dataset object with specific netcdf variable. 065 * 066 * @param fileFormat 067 * the netcdf file. 068 * @param ncDataset 069 * the netcdf variable. 070 * @param oid 071 * the unique identifier of this data object. 072 */ 073 public NC2Dataset(FileFormat fileFormat, Variable ncDataset, long[] oid) { 074 super(fileFormat, ncDataset.getName(), HObject.SEPARATOR, oid); 075 unsignedConverted = false; 076 nativeDataset = ncDataset; 077 } 078 079 /** 080 * Check if the object has any attributes attached. 081 * 082 * @return true if it has any attributes, false otherwise. 083 */ 084 @Override 085 public boolean hasAttribute() { 086 return false; 087 } 088 089 // Implementing Dataset 090 @Override 091 public Dataset copy(Group pgroup, String dstName, long[] dims, Object buff) throws Exception { 092 // not supported 093 throw new UnsupportedOperationException("Unsupported operation for NetCDF."); 094 } 095 096 // implementing Dataset 097 @Override 098 public byte[] readBytes() throws Exception { 099 // not supported 100 throw new UnsupportedOperationException("Unsupported operation for NetCDF."); 101 } 102 103 // Implementing DataFormat 104 /** 105 * Reads the data from file. 106 * 107 * read() reads the data from file to a memory buffer and returns the memory 108 * buffer. The dataset object does not hold the memory buffer. To store the 109 * memory buffer in the dataset object, one must call getData(). 110 * 111 * By default, the whole dataset is read into memory. Users can also select 112 * a subset to read. Subsetting is done in an implicit way. 113 * 114 * @return the data read from file. 115 * 116 * @see #getData() 117 * 118 * @throws Exception 119 * if object can not be read 120 * @throws OutOfMemoryError 121 * if memory is exhausted 122 */ 123 @Override 124 public Object read() throws Exception { 125 Object theData = null; 126 127 if (nativeDataset == null) 128 return null; 129 130 int[] origin = new int[rank]; 131 int[] shape = new int[rank]; 132 133 for (int i = 0; i < rank; i++) { 134 origin[i] = (int) startDims[i]; 135 shape[i] = (int) selectedDims[i]; 136 log.trace("read(): origin-shape [{}]={}-{}", i, origin[i], shape[i]); 137 } 138 139 ucar.ma2.Array ncArray = null; 140 141 try { 142 ncArray = nativeDataset.read(origin, shape); 143 } 144 catch (Exception ex) { 145 ncArray = nativeDataset.read(); 146 } 147 Object oneD = ncArray.copyTo1DJavaArray(); 148 149 if (oneD == null) 150 return null; 151 152 if (oneD.getClass().getName().startsWith("[C")) { 153 char[] charA = (char[]) oneD; 154 int nCols = (int) getWidth(); 155 int nRows = (int) getHeight(); 156 157 String[] strA = new String[nRows]; 158 String allStr = new String(charA); 159 160 int indx0 = 0; 161 for (int i = 0; i < nRows; i++) { 162 indx0 = i * nCols; 163 strA[i] = allStr.substring(indx0, indx0 + nCols); 164 } 165 theData = strA; 166 } 167 else { 168 theData = oneD; 169 } 170 171 return theData; 172 } 173 174 // Implementing DataFormat 175 /** 176 * Writes a memory buffer to the object in the file. 177 * 178 * @param buf 179 * the data to write 180 * 181 * @throws Exception 182 * if data can not be written 183 */ 184 @Override 185 public void write(Object buf) throws Exception { 186 // not supported 187 throw new UnsupportedOperationException("Unsupported operation for NetCDF."); 188 } 189 190 // Implementing DataFormat 191 /** 192 * Retrieves the object's metadata, such as attributes, from the file. 193 * 194 * Metadata, such as attributes, is stored in a List. 195 * 196 * @return the list of metadata objects. 197 * 198 * @throws Exception 199 * if the metadata can not be retrieved 200 */ 201 @Override 202 public List getMetadata() throws Exception { 203 if (attributeList != null) 204 return attributeList; 205 206 if (nativeDataset == null) 207 return (attributeList = null); 208 209 List ncAttrList = nativeDataset.getAttributes(); 210 if (ncAttrList == null) 211 return (attributeList = null); 212 213 int n = ncAttrList.size(); 214 attributeList = new Vector(n); 215 ucar.nc2.Attribute ncAttr = null; 216 for (int i = 0; i < n; i++) { 217 ncAttr = (ucar.nc2.Attribute) ncAttrList.get(i); 218 log.trace("getMetadata(): Attribute[{}]:{}", i, ncAttr.toString()); 219 attributeList.add(NC2File.convertAttribute(this, ncAttr)); 220 } 221 222 return attributeList; 223 } 224 225 // implementing DataFormat 226 /** 227 * Writes a specific piece of metadata (such as an attribute) into the file. 228 * 229 * If an HDF(4&5) attribute exists in the file, this method updates its 230 * value. If the attribute does not exist in the file, it creates the 231 * attribute in the file and attaches it to the object. It will fail to 232 * write a new attribute to the object where an attribute with the same name 233 * already exists. To update the value of an existing attribute in the file, 234 * one needs to get the instance of the attribute by getMetadata(), change 235 * its values, then use writeMetadata() to write the value. 236 * 237 * @param info 238 * the metadata to write. 239 * 240 * @throws Exception 241 * if the metadata can not be written 242 */ 243 @Override 244 public void writeMetadata(Object info) throws Exception { 245 // not supported 246 throw new UnsupportedOperationException("Unsupported operation for NetCDF."); 247 } 248 249 // implementing DataFormat 250 /** 251 * Deletes an existing piece of metadata from this object. 252 * 253 * @param info 254 * the metadata to delete. 255 * 256 * @throws Exception 257 * if the metadata can not be removed 258 */ 259 @Override 260 public void removeMetadata(Object info) throws Exception { 261 // not supported 262 throw new UnsupportedOperationException("Unsupported operation for NetCDF."); 263 } 264 265 /** 266 * Updates an existing piece of metadata attached to this object. 267 * 268 * @param info 269 * the metadata to update. 270 * 271 * @throws Exception 272 * if the metadata can not be updated 273 */ 274 @Override 275 public void updateMetadata(Object info) throws Exception { 276 // not supported 277 throw new UnsupportedOperationException("Unsupported operation for NetCDF."); 278 } 279 280 // Implementing HObject 281 @Override 282 public long open() { 283 return -1; 284 } 285 286 // Implementing HObject 287 @Override 288 public void close(long did) { 289 } 290 291 /** 292 * Retrieve and initialize dimensions and member information. 293 */ 294 @Override 295 public void init() { 296 if (nativeDataset == null) 297 return; 298 299 if (inited) 300 return; // already called. Initialize only once 301 302 isText = nativeDataset.getDataType().equals(DataType.STRING); 303 boolean isChar = nativeDataset.getDataType().equals(DataType.CHAR); 304 305 rank = nativeDataset.getRank(); 306 log.trace("init(): rank:{}", rank); 307 308 if (rank == 0) { 309 // a scalar data point 310 isScalar = true; 311 rank = 1; 312 dims = new long[] { 1 }; 313 } 314 else { 315 isScalar = false; 316 dims = new long[rank]; 317 for (int i = 0; i < rank; i++) 318 dims[i] = (nativeDataset.getDimension(i).getLength()); 319 } 320 321 startDims = new long[rank]; 322 selectedDims = new long[rank]; 323 for (int i = 0; i < rank; i++) { 324 startDims[i] = 0; 325 selectedDims[i] = 1; 326 } 327 328 if (rank == 1) { 329 selectedIndex[0] = 0; 330 selectedDims[0] = dims[0]; 331 } 332 else if (rank == 2) { 333 selectedIndex[0] = 0; 334 selectedIndex[1] = 1; 335 selectedDims[0] = dims[0]; 336 selectedDims[1] = dims[1]; 337 } 338 else if (rank > 2) { 339 selectedIndex[0] = 0; 340 selectedIndex[1] = 1; 341 selectedIndex[2] = 2; 342 selectedDims[0] = dims[0]; 343 selectedDims[1] = dims[1]; 344 } 345 346 if ((rank > 1) && isText) 347 selectedDims[1] = 1; 348 349 inited = true; 350 } 351 352 /** 353 * Creates a new dataset. 354 * 355 * @param name 356 * the name of the dataset to create. 357 * @param pgroup 358 * the parent group of the new dataset. 359 * @param type 360 * the datatype of the dataset. 361 * @param dims 362 * the dimension size of the dataset. 363 * @param maxdims 364 * the max dimension size of the dataset. 365 * @param chunks 366 * the chunk size of the dataset. 367 * @param gzip 368 * the level of the gzip compression. 369 * @param data 370 * the array of data values. 371 * 372 * @return the new dataset if successful. Otherwise returns null. 373 * 374 * @throws Exception 375 * if there is an error 376 */ 377 public static NC2Dataset create(String name, Group pgroup, Datatype type, 378 long[] dims, long[] maxdims, long[] chunks, int gzip, Object data) throws Exception { 379 // not supported 380 throw new UnsupportedOperationException("Unsupported operation for NetCDF."); 381 } 382 383 // implementing ScalarDS 384 /** 385 * Returns the datatype of the data object. 386 * 387 * @return the datatype of the data object. 388 */ 389 @Override 390 public Datatype getDatatype() { 391 if (datatype == null) { 392 try { 393 datatype = new NC2Datatype(nativeDataset.getDataType()); 394 } 395 catch (Exception ex) { 396 datatype = null; 397 } 398 } 399 400 return datatype; 401 } 402 403 /** 404 * Sets the name of the data object. 405 * 406 * @param newName 407 * the new name of the object. 408 */ 409 @Override 410 public void setName(String newName) throws Exception { 411 // not supported 412 throw new UnsupportedOperationException("Unsupported operation for NetCDF."); 413 } 414 415 //Implementing DataFormat 416 /** 417 * Retrieves the object's metadata, such as attributes, from the file. 418 * 419 * Metadata, such as attributes, is stored in a List. 420 * 421 * @param attrPropList 422 * the list of properties to get 423 * 424 * @return the list of metadata objects. 425 * 426 * @throws Exception 427 * if the metadata can not be retrieved 428 */ 429 public List getMetadata(int... attrPropList) throws Exception { 430 throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported"); 431 } 432}