bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
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 "FONcArrayStructure.h"
53#include "FONcArrayStructureField.h"
54#include "FONcGrid.h"
55#include "FONcArray.h"
56#include "FONcSequence.h"
57
58#include <BESInternalError.h>
59#include <BESDebug.h>
60#include <libdap/D4Dimensions.h>
61
66string FONcUtils::name_prefix = "";
67
71{
72 FONcArray::Dimensions.clear();
73 FONcGrid::Maps.clear();
74 FONcDim::DimNameNum = 0;
75 FONcDim::StructDimNameNum = 0;
76}
77
87string FONcUtils::id2netcdf(string in)
88{
89 // string of allowed characters in netcdf naming convention
90 string allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+_.@";
91 // string of allowed first characters in netcdf naming
92 // convention
93 string first = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
94
95 string::size_type i = 0;
96
97 while ((i = in.find_first_not_of(allowed, i)) != string::npos) {
98 in.replace(i, 1, "_");
99 i++;
100 }
101
102 if (first.find(in[0]) == string::npos) {
103 in = FONcUtils::name_prefix + in;
104 }
105
106 return in;
107}
108
115nc_type FONcUtils::get_nc_type(BaseType *element,bool IsNC4_ENHANCED)
116{
117 nc_type x_type = NC_NAT; // the constant ncdf uses to define simple type
118
119 string var_type = element->type_name();
120 BESDEBUG("fonc", "FONcUtils() - var_type "<< var_type <<endl);
121 BESDEBUG("fonc", "FONcUtils() - var_name "<< element->name() <<endl);
122 if (var_type == "Byte" || var_type == "UInt8") { // check this for dods type
123 if(IsNC4_ENHANCED)
124 x_type = NC_UBYTE;
125 else
126 x_type = NC_SHORT;
127 }
128 else if(var_type =="Int8")
129 x_type = NC_BYTE;
130 else if (var_type == "String")
131 x_type = NC_CHAR;
132 else if (var_type == "Int16")
133 x_type = NC_SHORT;
134 else if (var_type == "UInt16"){
135 if(IsNC4_ENHANCED)
136 x_type = NC_USHORT;
137 else
138 x_type = NC_INT;
139 }
140 else if (var_type == "Int32")
141 x_type = NC_INT;
142 else if (var_type == "UInt32"){
143 if(IsNC4_ENHANCED)
144 x_type = NC_UINT;
145 // classic model: don't support unsigned 32-bit int
146 }
147 else if (var_type == "Int64") {
148 if(IsNC4_ENHANCED)
149 x_type = NC_INT64;
150 // classic model: don't support 64-bit int
151 }
152 else if (var_type == "UInt64"){
153 if(IsNC4_ENHANCED)
154 x_type = NC_UINT64;
155 // classic model: don't support 64-bit int
156 }
157 else if (var_type == "Float32")
158 x_type = NC_FLOAT;
159 else if (var_type == "Float64")
160 x_type = NC_DOUBLE;
161
162 BESDEBUG("fonc", "FONcUtils() - var_type returned"<< x_type <<endl);
163 return x_type;
164}
165
182string FONcUtils::gen_name(const vector<string> &embed, const string &name, string &original)
183{
184 string new_name;
185 vector<string>::const_iterator i = embed.begin();
186 vector<string>::const_iterator e = embed.end();
187 bool first = true;
188 for (; i != e; i++) {
189 if (first)
190 new_name = (*i);
191 else
192 new_name += FONC_EMBEDDED_SEPARATOR + (*i);
193 first = false;
194 }
195 if (first)
196 new_name = name;
197 else
198 new_name += FONC_EMBEDDED_SEPARATOR + name;
199
200 original = new_name;
201
202 return FONcUtils::id2netcdf(new_name);
203}
204
218FONcUtils::convert(BaseType *v, const string &ncdf_version, const bool is_classic_model) {
219 map<string,int>fdimname_to_id;
220 vector<int>rds_nums;
221 return convert(v, ncdf_version, is_classic_model,fdimname_to_id,rds_nums);
222}
223
257FONcUtils::convert(BaseType *v,
258 const string &ncdf_version,
259 const bool is_classic_model,
260 map<string,int>&fdimname_to_id,
261 vector<int>&rds_nums)
262{
263 FONcBaseType *b = nullptr;
264
265 // We need to handle netCDF-4 enhanced differently. More datatypes are supported.
266 bool is_netcdf4_enhanced = false;
267 if(ncdf_version == FONC_RETURN_AS_NETCDF4 && is_classic_model == false)
268 is_netcdf4_enhanced = true;
269
270 bool unsigned_promote = true;
271
272 if (v->type()==dods_array_c && v->var()->type()==dods_structure_c)
273 b = new FONcArrayStructure(v);
274 else {
275 switch (v->type()) {
276 case dods_str_c:
277 case dods_url_c:
278 b = new FONcStr(v);
279 break;
280 case dods_uint8_c:
281 case dods_byte_c: {
282 if (true == is_netcdf4_enhanced)
283 b = new FONcUByte(v);
284 else
285 b = new FONcShort(v, unsigned_promote);
286 break;
287 }
288 case dods_int8_c: {
289 b = new FONcInt8(v);
290 break;
291 }
292
293 case dods_uint16_c: {
294 if (true == is_netcdf4_enhanced)
295 b = new FONcUShort(v);
296 else
297 b = new FONcInt(v, unsigned_promote);
298 break;
299 }
300 case dods_int16_c:
301 b = new FONcShort(v);
302 break;
303 case dods_uint32_c: {
304 if (true == is_netcdf4_enhanced)
305 b = new FONcUInt(v);
306 else {
307 string err = (string) "file out netcdf, " + "classic model-doesn't support unsigned int.";
308 err += " Please use netCDF-4 enhanced model instead.";
309 throw BESInternalError(err, __FILE__, __LINE__);
310 }
311 break;
312 }
313 case dods_int32_c:
314 b = new FONcInt(v);
315 break;
316 case dods_uint64_c: {
317 if (true == is_netcdf4_enhanced)
318 b = new FONcUInt64(v);
319 else {
320 string err = (string) "file out netcdf, " + "classic model-doesn't support unsigned 64-bit int.";
321 err += " Please use netCDF-4 enhanced model instead.";
322 throw BESInternalError(err, __FILE__, __LINE__);
323 }
324 break;
325 }
326 case dods_int64_c: {
327 if (true == is_netcdf4_enhanced)
328 b = new FONcInt64(v);
329 else {
330 string err = (string) "file out netcdf, " + "classic model-doesn't support unsigned 64-bit int.";
331 err += " Please use netCDF-4 enhanced model instead.";
332 throw BESInternalError(err, __FILE__, __LINE__);
333 }
334 break;
335 }
336 case dods_float32_c:
337 b = new FONcFloat(v);
338 break;
339 case dods_float64_c:
340 b = new FONcDouble(v);
341 break;
342 case dods_grid_c:
343 b = new FONcGrid(v);
344 break;
345 case dods_array_c:
346
347 // This "if block" is only true for the netCDF-4 enhanced/DAP4 case.
348 // fdimname_to_id is obtained in FONcTransform:transform_dap4_group_internal().
349 if (fdimname_to_id.size() > 0) {
350 vector<int> dim_ids;
351 vector<bool> use_d4_dim_ids;
352 Array *t_a = dynamic_cast<Array *>(v);
353 Array::Dim_iter di = t_a->dim_begin();
354 Array::Dim_iter de = t_a->dim_end();
355 // Here we want to check if this array has DAP4 dimension.
356 // If yes, we want to check if this DAP4 dimension is defined in the DAP4 group.
357 // A DAP4 dimension fully_qualified name is used as a key.
358 // Note: we also need to use a flag to mark if this dimension
359 // is defined by groups this var belongs to.
360 // DAP4 doesn't require a variable's dimension to have a dimension name.
361 // When dim_id is 0, a dimension name will be created for this dimension.
362 for (; di != de; di++) {
363
364 D4Dimension *d4_dim = t_a->dimension_D4dim(di);
365 if (d4_dim) {
366 BESDEBUG("fonc",
367 "FONcArray() - constructor is dap4: dimension name is " << d4_dim->name() << endl);
368 if (fdimname_to_id.find(d4_dim->fully_qualified_name()) != fdimname_to_id.end()) {
369 int dim_id = fdimname_to_id[d4_dim->fully_qualified_name()];
370 dim_ids.push_back(dim_id);
371 use_d4_dim_ids.push_back(true);
372 } else {
373 dim_ids.push_back(0);
374 use_d4_dim_ids.push_back(false);
375 }
376 } else {
377 dim_ids.push_back(0);
378 use_d4_dim_ids.push_back(false);
379 }
380
381 }
382 b = new FONcArray(v, dim_ids, use_d4_dim_ids, rds_nums);
383
384 } else {
385 b = new FONcArray(v);
386 }
387 break;
388 case dods_structure_c:
389 b = new FONcStructure(v);
390 break;
391 case dods_sequence_c:
392 b = new FONcSequence(v);
393 break;
394 default:
395 string err = (string) "file out netcdf, unable to " + "write unknown variable type";
396 throw BESInternalError(err, __FILE__, __LINE__);
397
398 }
399 }
400 // The following code may be combined with other related code. TODO: later.
401 b->setVersion(ncdf_version);
402 if(ncdf_version == FONC_RETURN_AS_NETCDF4) {
403 if(is_classic_model)
404 b->setNC4DataModel(FONC_NC4_CLASSIC_MODEL);
405 else
406 b->setNC4DataModel(FONC_NC4_ENHANCED);
407 }
408 return b;
409}
410
429void FONcUtils::handle_error(int stax, const string &err, const string &file, int line)
430{
431 assert(stax != NC_NOERR); // This should not be called for NOERR
432
433 throw BESInternalError(err + string(": ") + nc_strerror(stax), file, line);
434}
435
exception thrown if internal error encountered
A DAP BaseType with file out netcdf information included.
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.
static vector< FONcMap * > Maps
global list of maps that could be shared amongst the different grids
Definition FONcGrid.h:80
static void handle_error(int stax, const string &err, const string &file, int line)
handle any netcdf errors
Definition FONcUtils.cc:429
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:70
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:115
static string id2netcdf(string in)
convert the provided string to a netcdf allowed identifier.
Definition FONcUtils.cc:87
static string gen_name(const vector< string > &embed, const string &name, string &original)
generate a new name for the embedded variable
Definition FONcUtils.cc:182
STL class.
STL iterator class.
STL class.