bes Updated for version 3.20.13
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
64string FONcUtils::name_prefix = "";
65
69{
70 FONcArray::Dimensions.clear();
71 FONcGrid::Maps.clear();
72 FONcDim::DimNameNum = 0;
73}
74
84string 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
112nc_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
179string 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
215FONcUtils::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
254FONcUtils::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 == FONC_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 == FONC_RETURN_AS_NETCDF4) {
398 if(is_classic_model)
399 b->setNC4DataModel(FONC_NC4_CLASSIC_MODEL);
400 else
401 b->setNC4DataModel(FONC_NC4_ENHANCED);
402 }
403 return b;
404}
405
424void 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:60
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