bes  Updated for version 3.20.8
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 <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  if (var_type == "Byte") { // check this for dods type
118  if(IsNC4_ENHANCED)
119  x_type = NC_UBYTE;
120  else
121  x_type = NC_SHORT;
122  }
123  else if(var_type =="Int8") {
124  if(IsNC4_ENHANCED)
125  x_type = NC_BYTE;
126  }
127  else if(var_type =="UInt8") {
128  if(IsNC4_ENHANCED)
129  x_type = NC_UBYTE;
130  }
131  else if (var_type == "String")
132  x_type = NC_CHAR;
133  else if (var_type == "Int16")
134  x_type = NC_SHORT;
135  // The attribute of UInt16 maps to NC_INT, so we need to map UInt16
136  // to NC_INT for the variable so that end_def won't complain about
137  // the inconsistent datatype between fillvalue and the variable. KY 2012-10-25
138  //else if( var_type == "UInt16" )
139  // x_type = NC_SHORT ;
140  else if (var_type == "UInt16"){
141  if(IsNC4_ENHANCED)
142  x_type = NC_USHORT;
143  else
144  x_type = NC_INT;
145  }
146  else if (var_type == "Int32")
147  x_type = NC_INT;
148  else if (var_type == "UInt32"){
149  if(IsNC4_ENHANCED)
150  x_type = NC_UINT;
151  else
152  x_type = NC_INT;
153  }
154  else if (var_type == "Int64")
155  if(IsNC4_ENHANCED)
156  x_type = NC_INT64;
157  else
158  x_type = NC_INT;
159  else if (var_type == "UInt64"){
160  if(IsNC4_ENHANCED)
161  x_type = NC_UINT64;
162  else
163  x_type = NC_INT;
164  }
165  else if (var_type == "Float32")
166  x_type = NC_FLOAT;
167  else if (var_type == "Float64")
168  x_type = NC_DOUBLE;
169 
170  return x_type;
171 }
172 
189 string FONcUtils::gen_name(const vector<string> &embed, const string &name, string &original)
190 {
191  string new_name;
192  vector<string>::const_iterator i = embed.begin();
193  vector<string>::const_iterator e = embed.end();
194  bool first = true;
195  for (; i != e; i++) {
196  if (first)
197  new_name = (*i);
198  else
199  new_name += FONC_EMBEDDED_SEPARATOR + (*i);
200  first = false;
201  }
202  if (first)
203  new_name = name;
204  else
205  new_name += FONC_EMBEDDED_SEPARATOR + name;
206 
207  original = new_name;
208 
209  return FONcUtils::id2netcdf(new_name);
210 }
211 
224 FONcBaseType *
225 FONcUtils::convert(BaseType *v,const string &ncdf_version, const bool is_classic_model) {
226  map<string,int>fdimname_to_id;
227  vector<int>rds_nums;
228  return convert(v,ncdf_version, is_classic_model,fdimname_to_id,rds_nums);
229 }
230 
243 FONcBaseType *
244 FONcUtils::convert(BaseType *v,const string &ncdf_version, const bool is_classic_model, map<string,int>&fdimname_to_id,vector<int>&rbs_nums)
245 {
246  FONcBaseType *b = 0;
247 
248  // We need to handle netCDF-4 enhanced differently. More datatypes are supported.
249  bool is_netcdf4_enhanced = false;
250  if(ncdf_version == RETURNAS_NETCDF4 && is_classic_model == false)
251  is_netcdf4_enhanced = true;
252 
253  switch (v->type()) {
254  case dods_str_c:
255  case dods_url_c:
256  b = new FONcStr(v);
257  break;
258  case dods_uint8_c:
259  case dods_byte_c: {
260  if(true == is_netcdf4_enhanced)
261  b = new FONcUByte(v);
262  else
263  b = new FONcByte(v);
264  break;
265  }
266  case dods_int8_c: {
267  if(true == is_netcdf4_enhanced)
268  b = new FONcInt8(v);
269  else
270  b = new FONcByte(v);
271  break;
272  }
273 
274  case dods_uint16_c: {
275  if(true == is_netcdf4_enhanced)
276  b = new FONcUShort(v);
277  else
278  b = new FONcShort(v);
279  break;
280  }
281  case dods_int16_c:
282  b = new FONcShort(v);
283  break;
284  case dods_uint32_c: {
285  if(true == is_netcdf4_enhanced)
286  b = new FONcUInt(v);
287  else
288  b = new FONcInt(v);
289  break;
290  }
291  case dods_int32_c:
292  b = new FONcInt(v);
293  break;
294  case dods_uint64_c: {
295  if(true == is_netcdf4_enhanced)
296  b = new FONcUInt64(v);
297  else
298  b = new FONcInt(v);
299  break;
300  }
301  case dods_int64_c: {
302  if(true == is_netcdf4_enhanced)
303  b = new FONcInt64(v);
304  else
305  b = new FONcInt(v);
306  break;
307  }
308  case dods_float32_c:
309  b = new FONcFloat(v);
310  break;
311  case dods_float64_c:
312  b = new FONcDouble(v);
313  break;
314  case dods_grid_c:
315  b = new FONcGrid(v);
316  break;
317  case dods_array_c:
318 
319  // This if block will only be true with netCDF-4 enhanced.
320  if(fdimname_to_id.size()>0) {
321  vector<int> dim_ids;
322  vector<bool> use_d4_dim_ids;
323  Array *t_a = dynamic_cast<Array *>(v);
324  Array::Dim_iter di = t_a->dim_begin();
325  Array::Dim_iter de = t_a->dim_end();
326  // Here we want to check if a dimension fully_qualified name is the same as the dim. name in the dimname to dim id map.
327  // The dimname to dim id is obtained from the DAP4 dimensions of the group the var belongs to. KY 2020/06/17
328  // Then we find all the netCDF-4 dimension IDs that are associated with the dimensions of this array.
329  // Note: we need to use a flag to mark if this dimension is defined by groups this var belongs to.
330  // DAP4 doesn't require a dimension of a variable has dimension names.
331  for (; di != de; di++) {
332  D4Dimension * d4_dim = t_a->dimension_D4dim(di);
333  if(d4_dim) {
334  BESDEBUG("fonc", "FONcArray() - constructor is dap4: dimension name is "<< d4_dim->name() <<endl);
335  if(fdimname_to_id.find(d4_dim->fully_qualified_name())!= fdimname_to_id.end()) {
336  int dim_id = fdimname_to_id[d4_dim->fully_qualified_name()];
337  //int dim_id = (fdimname_to_id.find(d4_dim->fully_qualified_name()))->second();
338  dim_ids.push_back(dim_id);
339  use_d4_dim_ids.push_back(true);
340  }
341  else {
342  dim_ids.push_back(0);
343  use_d4_dim_ids.push_back(false);
344  }
345  }
346  else {
347  dim_ids.push_back(0);
348  use_d4_dim_ids.push_back(false);
349  }
350 
351  }
352  b = new FONcArray(v,dim_ids,use_d4_dim_ids,rbs_nums);
353 
354  }
355  else {
356  b = new FONcArray(v);
357  }
358  break;
359  case dods_structure_c:
360  b = new FONcStructure(v);
361  break;
362  case dods_sequence_c:
363  b = new FONcSequence(v);
364  break;
365  default:
366  string err = (string) "file out netcdf, unable to " + "write unknown variable type";
367  throw BESInternalError(err, __FILE__, __LINE__);
368 
369  }
370  // The following code may be combined with other related code. TODO: later.
371  b->setVersion(ncdf_version);
372  if(ncdf_version == RETURNAS_NETCDF4) {
373  if(is_classic_model)
374  b->setNC4DataModel("NC4_CLASSIC_MODEL");
375  else
376  b->setNC4DataModel("NC4_ENHANCED");
377  }
378  return b;
379 }
380 
399 void FONcUtils::handle_error(int stax, const string &err, const string &file, int line)
400 {
401  assert(stax != NC_NOERR); // This should not be called for NOERR
402 
403  throw BESInternalError(err + string(": ") + nc_strerror(stax), file, line);
404 }
405 
exception thrown if internal error encountered
A DAP Array with file out netcdf information included.
Definition: FONcArray.h:55
A DAP BaseType with file out netcdf information included.
Definition: FONcBaseType.h:61
virtual void setVersion(std::string version)
Identifies variable with use of NetCDF4 features.
Definition: FONcBaseType.cc:89
virtual void setNC4DataModel(std::string nc4_datamodel)
Identifies the netCDF4 data model (CLASSIC or ENHANCED)
Definition: FONcBaseType.cc:98
A class representing the DAP Byte class for file out netcdf.
Definition: FONcByte.h:49
A DAP Float64 with file out netcdf information included.
Definition: FONcDouble.h:48
A DAP Float32 with file out netcdf information included.
Definition: FONcFloat.h:48
A DAP Grid with file out netcdf information included.
Definition: FONcGrid.h:57
static vector< FONcMap * > Maps
global list of maps that could be shared amongst the different grids
Definition: FONcGrid.h:74
A DAP Int64 with file out netcdf information included.
Definition: FONcInt64.h:43
A class representing the DAP4 int8 class for file out netcdf.
Definition: FONcInt8.h:45
A DAP Int32 and UInt32 with file out netcdf information included.
Definition: FONcInt.h:48
A DAP Sequence with file out netcdf information included.
Definition: FONcSequence.h:48
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:49
A class representing the DAP Byte class for file out netcdf.
Definition: FONcUByte.h:45
A DAP UInt32 with file out netcdf information included.
Definition: FONcUInt64.h:43
A DAP UInt32 with file out netcdf information included.
Definition: FONcUInt.h:43
A DAP UInt16 with file out netcdf information included.
Definition: FONcUShort.h:43
static void handle_error(int stax, const string &err, const string &file, int line)
handle any netcdf errors
Definition: FONcUtils.cc:399
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:58
static void reset()
Resets the FONc transformation for a new input and out file.
Definition: FONcUtils.cc:68
static string id2netcdf(string in)
convert the provided string to a netcdf allowed identifier.
Definition: FONcUtils.cc:84
static nc_type get_nc_type(BaseType *element, bool isNC4_ENHANCED)
translate the OPeNDAP data type to a netcdf data type
Definition: FONcUtils.cc:112
static FONcBaseType * convert(BaseType *v, const string &version, const bool classic_model)
Creates a FONc object for the given DAP object.
Definition: FONcUtils.cc:225
static string gen_name(const vector< string > &embed, const string &name, string &original)
generate a new name for the embedded variable
Definition: FONcUtils.cc:189