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