bes  Updated for version 3.20.10
FONcUtils.cc
1 // FONcUtils.cc
2 
3 // This file is part of BES Netcdf File Out Module
4 
5 // Copyright (c) 2004,2005 University Corporation for Atmospheric Research
6 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 // You can contact University Corporation for Atmospheric Research at
23 // 3080 Center Green Drive, Boulder, CO 80301
24 
25 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
26 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
27 //
28 // Authors:
29 // pwest Patrick West <pwest@ucar.edu>
30 // jgarcia Jose Garcia <jgarcia@ucar.edu>
31 // kyang Kent Yang <myang6@hdfgroup.org> (for netCDF-4 enhancement)
32 
33 #include "config.h"
34 
35 #include <cassert>
36 
37 #include "FONcUtils.h"
38 #include "FONcDim.h"
39 #include "FONcByte.h"
40 #include "FONcInt8.h"
41 #include "FONcUByte.h"
42 #include "FONcStr.h"
43 #include "FONcShort.h"
44 #include "FONcUShort.h"
45 #include "FONcInt.h"
46 #include "FONcUInt.h"
47 #include "FONcInt64.h"
48 #include "FONcUInt64.h"
49 #include "FONcFloat.h"
50 #include "FONcDouble.h"
51 #include "FONcStructure.h"
52 #include "FONcGrid.h"
53 #include "FONcArray.h"
54 #include "FONcSequence.h"
55 
56 #include <BESInternalError.h>
57 #include <BESDebug.h>
58 #include <libdap/D4Dimensions.h>
59 
64 string FONcUtils::name_prefix = "";
65 
69 {
70  FONcArray::Dimensions.clear();
71  FONcGrid::Maps.clear();
72  FONcDim::DimNameNum = 0;
73 }
74 
84 string FONcUtils::id2netcdf(string in)
85 {
86  // string of allowed characters in netcdf naming convention
87  string allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+_.@";
88  // string of allowed first characters in netcdf naming
89  // convention
90  string first = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
91 
92  string::size_type i = 0;
93 
94  while ((i = in.find_first_not_of(allowed, i)) != string::npos) {
95  in.replace(i, 1, "_");
96  i++;
97  }
98 
99  if (first.find(in[0]) == string::npos) {
100  in = FONcUtils::name_prefix + in;
101  }
102 
103  return in;
104 }
105 
112 nc_type FONcUtils::get_nc_type(BaseType *element,bool IsNC4_ENHANCED)
113 {
114  nc_type x_type = NC_NAT; // the constant ncdf uses to define simple type
115 
116  string var_type = element->type_name();
117  BESDEBUG("fonc", "FONcUtils() - var_type "<< var_type <<endl);
118  BESDEBUG("fonc", "FONcUtils() - var_name "<< element->name() <<endl);
119  if (var_type == "Byte" || var_type == "UInt8") { // check this for dods type
120  if(IsNC4_ENHANCED)
121  x_type = NC_UBYTE;
122  else
123  x_type = NC_SHORT;
124  }
125  else if(var_type =="Int8")
126  x_type = NC_BYTE;
127  else if (var_type == "String")
128  x_type = NC_CHAR;
129  else if (var_type == "Int16")
130  x_type = NC_SHORT;
131  else if (var_type == "UInt16"){
132  if(IsNC4_ENHANCED)
133  x_type = NC_USHORT;
134  else
135  x_type = NC_INT;
136  }
137  else if (var_type == "Int32")
138  x_type = NC_INT;
139  else if (var_type == "UInt32"){
140  if(IsNC4_ENHANCED)
141  x_type = NC_UINT;
142  // classic model: don't support unsigned 32-bit int
143  }
144  else if (var_type == "Int64") {
145  if(IsNC4_ENHANCED)
146  x_type = NC_INT64;
147  // classic model: don't support 64-bit int
148  }
149  else if (var_type == "UInt64"){
150  if(IsNC4_ENHANCED)
151  x_type = NC_UINT64;
152  // classic model: don't support 64-bit int
153  }
154  else if (var_type == "Float32")
155  x_type = NC_FLOAT;
156  else if (var_type == "Float64")
157  x_type = NC_DOUBLE;
158 
159  BESDEBUG("fonc", "FONcUtils() - var_type returned"<< x_type <<endl);
160  return x_type;
161 }
162 
179 string FONcUtils::gen_name(const vector<string> &embed, const string &name, string &original)
180 {
181  string new_name;
182  vector<string>::const_iterator i = embed.begin();
183  vector<string>::const_iterator e = embed.end();
184  bool first = true;
185  for (; i != e; i++) {
186  if (first)
187  new_name = (*i);
188  else
189  new_name += FONC_EMBEDDED_SEPARATOR + (*i);
190  first = false;
191  }
192  if (first)
193  new_name = name;
194  else
195  new_name += FONC_EMBEDDED_SEPARATOR + name;
196 
197  original = new_name;
198 
199  return FONcUtils::id2netcdf(new_name);
200 }
201 
214 FONcBaseType *
215 FONcUtils::convert(BaseType *v, const string &ncdf_version, const bool is_classic_model) {
216  map<string,int>fdimname_to_id;
217  vector<int>rds_nums;
218  return convert(v, ncdf_version, is_classic_model,fdimname_to_id,rds_nums);
219 }
220 
253 FONcBaseType *
254 FONcUtils::convert(BaseType *v,
255  const string &ncdf_version,
256  const bool is_classic_model,
257  map<string,int>&fdimname_to_id,
258  vector<int>&rds_nums)
259 {
260  FONcBaseType *b = nullptr;
261 
262  // We need to handle netCDF-4 enhanced differently. More datatypes are supported.
263  bool is_netcdf4_enhanced = false;
264  if(ncdf_version == RETURN_AS_NETCDF4 && is_classic_model == false)
265  is_netcdf4_enhanced = true;
266 
267  bool unsigned_promote = true;
268 
269  switch (v->type()) {
270  case dods_str_c:
271  case dods_url_c:
272  b = new FONcStr(v);
273  break;
274  case dods_uint8_c:
275  case dods_byte_c: {
276  if(true == is_netcdf4_enhanced)
277  b = new FONcUByte(v);
278  else
279  b = new FONcShort(v,unsigned_promote);
280  break;
281  }
282  case dods_int8_c: {
283  b = new FONcInt8(v);
284  break;
285  }
286 
287  case dods_uint16_c: {
288  if(true == is_netcdf4_enhanced)
289  b = new FONcUShort(v);
290  else
291  b = new FONcInt(v,unsigned_promote);
292  break;
293  }
294  case dods_int16_c:
295  b = new FONcShort(v);
296  break;
297  case dods_uint32_c: {
298  if(true == is_netcdf4_enhanced)
299  b = new FONcUInt(v);
300  else {
301  string err = (string) "file out netcdf, " + "classic model-doesn't support unsigned int.";
302  err += " Please use netCDF-4 enhanced model instead.";
303  throw BESInternalError(err, __FILE__, __LINE__);
304  }
305  break;
306  }
307  case dods_int32_c:
308  b = new FONcInt(v);
309  break;
310  case dods_uint64_c: {
311  if(true == is_netcdf4_enhanced)
312  b = new FONcUInt64(v);
313  else {
314  string err = (string) "file out netcdf, " + "classic model-doesn't support unsigned 64-bit int.";
315  err += " Please use netCDF-4 enhanced model instead.";
316  throw BESInternalError(err, __FILE__, __LINE__);
317  }
318  break;
319  }
320  case dods_int64_c: {
321  if(true == is_netcdf4_enhanced)
322  b = new FONcInt64(v);
323  else {
324  string err = (string) "file out netcdf, " + "classic model-doesn't support unsigned 64-bit int.";
325  err += " Please use netCDF-4 enhanced model instead.";
326  throw BESInternalError(err, __FILE__, __LINE__);
327  }
328  break;
329  }
330  case dods_float32_c:
331  b = new FONcFloat(v);
332  break;
333  case dods_float64_c:
334  b = new FONcDouble(v);
335  break;
336  case dods_grid_c:
337  b = new FONcGrid(v);
338  break;
339  case dods_array_c:
340 
341  // This "if block" is only true for the netCDF-4 enhanced/DAP4 case.
342  // fdimname_to_id is obtained in FONcTransform:transform_dap4_group_internal().
343  if(fdimname_to_id.size()>0) {
344  vector<int> dim_ids;
345  vector<bool> use_d4_dim_ids;
346  Array *t_a = dynamic_cast<Array *>(v);
347  Array::Dim_iter di = t_a->dim_begin();
348  Array::Dim_iter de = t_a->dim_end();
349  // Here we want to check if this array has DAP4 dimension.
350  // If yes, we want to check if this DAP4 dimension is defined in the DAP4 group.
351  // A DAP4 dimension fully_qualified name is used as a key.
352  // Note: we also need to use a flag to mark if this dimension
353  // is defined by groups this var belongs to.
354  // DAP4 doesn't require a variable's dimension to have a dimension name.
355  // When dim_id is 0, a dimension name will be created for this dimension.
356  for (; di != de; di++) {
357 
358  D4Dimension * d4_dim = t_a->dimension_D4dim(di);
359  if(d4_dim) {
360  BESDEBUG("fonc", "FONcArray() - constructor is dap4: dimension name is "<< d4_dim->name() <<endl);
361  if(fdimname_to_id.find(d4_dim->fully_qualified_name())!= fdimname_to_id.end()) {
362  int dim_id = fdimname_to_id[d4_dim->fully_qualified_name()];
363  dim_ids.push_back(dim_id);
364  use_d4_dim_ids.push_back(true);
365  }
366  else {
367  dim_ids.push_back(0);
368  use_d4_dim_ids.push_back(false);
369  }
370  }
371  else {
372  dim_ids.push_back(0);
373  use_d4_dim_ids.push_back(false);
374  }
375 
376  }
377  b = new FONcArray(v,dim_ids,use_d4_dim_ids,rds_nums);
378 
379  }
380  else {
381  b = new FONcArray(v);
382  }
383  break;
384  case dods_structure_c:
385  b = new FONcStructure(v);
386  break;
387  case dods_sequence_c:
388  b = new FONcSequence(v);
389  break;
390  default:
391  string err = (string) "file out netcdf, unable to " + "write unknown variable type";
392  throw BESInternalError(err, __FILE__, __LINE__);
393 
394  }
395  // The following code may be combined with other related code. TODO: later.
396  b->setVersion(ncdf_version);
397  if(ncdf_version == RETURN_AS_NETCDF4) {
398  if(is_classic_model)
399  b->setNC4DataModel("NC4_CLASSIC_MODEL");
400  else
401  b->setNC4DataModel("NC4_ENHANCED");
402  }
403  return b;
404 }
405 
424 void FONcUtils::handle_error(int stax, const string &err, const string &file, int line)
425 {
426  assert(stax != NC_NOERR); // This should not be called for NOERR
427 
428  throw BESInternalError(err + string(": ") + nc_strerror(stax), file, line);
429 }
430 
exception thrown if internal error encountered
A DAP Array with file out netcdf information included.
Definition: FONcArray.h:57
A DAP BaseType with file out netcdf information included.
Definition: FONcBaseType.h:64
virtual void setNC4DataModel(const string &nc4_datamodel)
Identifies the netCDF4 data model (CLASSIC or ENHANCED)
virtual void setVersion(const std::string &version)
Identifies variable with use of NetCDF4 features.
A DAP Float64 with file out netcdf information included.
Definition: FONcDouble.h:52
A DAP Float32 with file out netcdf information included.
Definition: FONcFloat.h:51
A DAP Grid with file out netcdf information included.
Definition: FONcGrid.h:61
static vector< FONcMap * > Maps
global list of maps that could be shared amongst the different grids
Definition: FONcGrid.h:80
A DAP Int64 with file out netcdf information included.
Definition: FONcInt64.h:45
A class representing the DAP4 int8 class for file out netcdf.
Definition: FONcInt8.h:47
A DAP Int32 and UInt32 with file out netcdf information included.
Definition: FONcInt.h:50
A DAP Sequence with file out netcdf information included.
Definition: FONcSequence.h:51
A DAP Int16 and UInt16 with file out netcdf information included.
Definition: FONcShort.h:48
A class representing the DAP Str class for file out netcdf.
Definition: FONcStr.h:50
A DAP Structure with file out netcdf information included.
Definition: FONcStructure.h:52
A class representing the DAP Byte class for file out netcdf.
Definition: FONcUByte.h:48
A DAP UInt32 with file out netcdf information included.
Definition: FONcUInt64.h:45
A DAP UInt32 with file out netcdf information included.
Definition: FONcUInt.h:45
A DAP UInt16 with file out netcdf information included.
Definition: FONcUShort.h:45
static void handle_error(int stax, const string &err, const string &file, int line)
handle any netcdf errors
Definition: FONcUtils.cc:424
static string name_prefix
If a variable name, dimension name, or attribute name begins with a character that is not supported b...
Definition: FONcUtils.h:60
static void reset()
Resets the FONc transformation for a new input and out file.
Definition: FONcUtils.cc:68
static nc_type get_nc_type(libdap::BaseType *element, bool isNC4_ENHANCED)
translate the OPeNDAP data type to a netcdf data type
Definition: FONcUtils.cc:112
static string id2netcdf(string in)
convert the provided string to a netcdf allowed identifier.
Definition: FONcUtils.cc:84
static string gen_name(const vector< string > &embed, const string &name, string &original)
generate a new name for the embedded variable
Definition: FONcUtils.cc:179