bes  Updated for version 3.20.5
FONcTransform.cc
1 // FONcTransform.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 
32 #include "config.h"
33 
34 #include <sstream>
35 
36 using std::ostringstream;
37 using std::istringstream;
38 
39 #include "FONcRequestHandler.h" // for the keys
40 
41 #include "FONcTransform.h"
42 #include "FONcUtils.h"
43 #include "FONcBaseType.h"
44 #include "FONcAttributes.h"
45 
46 #include <DDS.h>
47 #include <Structure.h>
48 #include <Array.h>
49 #include <Grid.h>
50 #include <Sequence.h>
51 #include <BESDebug.h>
52 #include <BESInternalError.h>
53 
54 #include "DapFunctionUtils.h"
55 
67 FONcTransform::FONcTransform(DDS *dds, BESDataHandlerInterface &dhi, const string &localfile, const string &ncVersion) :
68  _ncid(0), _dds(0)
69 {
70  if (!dds) {
71  string s = (string) "File out netcdf, " + "null DDS passed to constructor";
72  throw BESInternalError(s, __FILE__, __LINE__);
73  }
74  if (localfile.empty()) {
75  string s = (string) "File out netcdf, " + "empty local file name passed to constructor";
76  throw BESInternalError(s, __FILE__, __LINE__);
77  }
78  _localfile = localfile;
79  _dds = dds;
80  _returnAs = ncVersion;
81 
82  // if there is a variable, attribute, dimension name that is not
83  // compliant with netcdf naming conventions then we will create
84  // a new name. If the new name does not begin with an alpha
85  // character then we will prefix it with name_prefix. We will
86  // get this prefix from the type of data that we are reading in,
87  // such as nc, h4, h5, ff, jg, etc...
88  dhi.first_container();
89  if (dhi.container) {
91  }
92  else {
93  FONcUtils::name_prefix = "nc_";
94  }
95 }
96 
102 {
103  bool done = false;
104  while (!done) {
105  vector<FONcBaseType *>::iterator i = _fonc_vars.begin();
106  vector<FONcBaseType *>::iterator e = _fonc_vars.end();
107  if (i == e) {
108  done = true;
109  }
110  else {
111  // These are the FONc types, not the actual ones
112  FONcBaseType *b = (*i);
113  delete b;
114  _fonc_vars.erase(i);
115  }
116  }
117 }
118 
128 {
130 
131  // Convert the DDS into an internal format to keep track of
132  // variables, arrays, shared dimensions, grids, common maps,
133  // embedded structures. It only grabs the variables that are to be
134  // sent.
135  DDS::Vars_iter vi = _dds->var_begin();
136  DDS::Vars_iter ve = _dds->var_end();
137  for (; vi != ve; vi++) {
138  if ((*vi)->send_p()) {
139  BaseType *v = *vi;
140 
141  BESDEBUG("fonc", "FONcTransform::transform() - Converting variable '" << v->name() << "'" << endl);
142 
143  // This is a factory class call, and 'fg' is specialized for 'v'
145  fb->setVersion( FONcTransform::_returnAs );
146  _fonc_vars.push_back(fb);
147 
148  vector<string> embed;
149  fb->convert(embed);
150  }
151  }
152 
153  // Open the file for writing
154  int stax;
155  if ( FONcTransform::_returnAs == RETURNAS_NETCDF4 ) {
156  if (FONcRequestHandler::classic_model){
157  BESDEBUG("fonc", "FONcTransform::transform() - Opening NetCDF-4 cache file in classic mode. fileName: " << _localfile << endl);
158  stax = nc_create(_localfile.c_str(), NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &_ncid);
159  }
160  else {
161  BESDEBUG("fonc", "FONcTransform::transform() - Opening NetCDF-4 cache file. fileName: " << _localfile << endl);
162  stax = nc_create(_localfile.c_str(), NC_CLOBBER|NC_NETCDF4, &_ncid);
163  }
164  }
165  else {
166  BESDEBUG("fonc", "FONcTransform::transform() - Opening NetCDF-3 cache file. fileName: " << _localfile << endl);
167  stax = nc_create(_localfile.c_str(), NC_CLOBBER, &_ncid);
168  }
169 
170  if (stax != NC_NOERR) {
171  FONcUtils::handle_error(stax, "File out netcdf, unable to open: " + _localfile, __FILE__, __LINE__);
172  }
173 
174  try {
175  // Here we will be defining the variables of the netcdf and
176  // adding attributes. To do this we must be in define mode.
177  nc_redef(_ncid);
178 
179  // For each converted FONc object, call define on it to define
180  // that object to the netcdf file. This also adds the attributes
181  // for the variables to the netcdf file
182  vector<FONcBaseType *>::iterator i = _fonc_vars.begin();
183  vector<FONcBaseType *>::iterator e = _fonc_vars.end();
184  for (; i != e; i++) {
185  FONcBaseType *fbt = *i;
186  BESDEBUG("fonc", "FONcTransform::transform() - Defining variable: " << fbt->name() << endl);
187  fbt->define(_ncid);
188  }
189 
190  // Add any global attributes to the netcdf file
191  AttrTable &globals = _dds->get_attr_table();
192  BESDEBUG("fonc", "FONcTransform::transform() - Adding Global Attributes" << endl << globals << endl);
193  FONcAttributes::add_attributes(_ncid, NC_GLOBAL, globals, "", "");
194 
195  // We are done defining the variables, dimensions, and
196  // attributes of the netcdf file. End the define mode.
197  int stax = nc_enddef(_ncid);
198 
199  // Check error for nc_enddef. Handling of HDF failures
200  // can be detected here rather than later. KY 2012-10-25
201  if (stax != NC_NOERR) {
202  FONcUtils::handle_error(stax, "File out netcdf, unable to end the define mode: " + _localfile, __FILE__, __LINE__);
203  }
204 
205  // Write everything out
206  i = _fonc_vars.begin();
207  e = _fonc_vars.end();
208  for (; i != e; i++) {
209  FONcBaseType *fbt = *i;
210  BESDEBUG("fonc", "FONcTransform::transform() - Writing data for variable: " << fbt->name() << endl);
211  fbt->write(_ncid);
212  }
213 
214  stax = nc_close(_ncid);
215  if (stax != NC_NOERR)
216  FONcUtils::handle_error(stax, "File out netcdf, unable to close: " + _localfile, __FILE__, __LINE__);
217  }
218  catch (BESError &e) {
219  (void) nc_close(_ncid); // ignore the error at this point
220  throw;
221  }
222 }
223 
233 void FONcTransform::dump(ostream &strm) const
234 {
235  strm << BESIndent::LMarg << "FONcTransform::dump - (" << (void *) this << ")" << endl;
236  BESIndent::Indent();
237  strm << BESIndent::LMarg << "ncid = " << _ncid << endl;
238  strm << BESIndent::LMarg << "temporary file = " << _localfile << endl;
239  BESIndent::Indent();
240  vector<FONcBaseType *>::const_iterator i = _fonc_vars.begin();
241  vector<FONcBaseType *>::const_iterator e = _fonc_vars.end();
242  for (; i != e; i++) {
243  FONcBaseType *fbt = *i;
244  fbt->dump(strm);
245  }
246  BESIndent::UnIndent();
247  BESIndent::UnIndent();
248 }
249 
250 
static void handle_error(int stax, const string &err, const string &file, int line)
handle any netcdf errors
Definition: FONcUtils.cc:245
exception thrown if inernal error encountered
virtual ~FONcTransform()
Destructor.
virtual void define(int ncid)
Define the variable in the netcdf file.
Definition: FONcBaseType.cc:53
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:57
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
FONcTransform(DDS *dds, BESDataHandlerInterface &dhi, const string &localfile, const string &netcdfVersion="netcdf")
Constructor that creates transformation object from the specified DataDDS object to the specified fil...
virtual void dump(ostream &strm) const
dumps information about this transformation object for debugging purposes
virtual void transform()
Transforms each of the variables of the DataDDS to the NetCDF file.
static void reset()
Resets the FONc transformation for a new input and out file.
Definition: FONcUtils.cc:59
A DAP BaseType with file out netcdf information included.
Definition: FONcBaseType.h:58
Structure storing information used by the BES to handle the request.
string get_container_type() const
retrieve the type of data this container holds, such as cedar or netcdf.
Definition: BESContainer.h:235
static void add_attributes(int ncid, int varid, AttrTable &attrs, const string &var_name, const string &prepend_attr)
helper function for add_attributes
void first_container()
set the container pointer to the first container in the containers list
static FONcBaseType * convert(BaseType *v)
Creates a FONc object for the given DAP object.
Definition: FONcUtils.cc:182
virtual void dump(std::ostream &strm) const =0
dump the contents of this object to the specified ostream
BESContainer * container
pointer to current container in this interface