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