bes  Updated for version 3.20.6
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 
BESDataHandlerInterface::container
BESContainer * container
pointer to current container in this interface
Definition: BESDataHandlerInterface.h:75
FONcBaseType::define
virtual void define(int ncid)
Define the variable in the netcdf file.
Definition: FONcBaseType.cc:53
FONcBaseType::dump
virtual void dump(std::ostream &strm) const =0
dump the contents of this object to the specified ostream
FONcTransform::~FONcTransform
virtual ~FONcTransform()
Destructor.
Definition: FONcTransform.cc:101
FONcUtils::handle_error
static void handle_error(int stax, const string &err, const string &file, int line)
handle any netcdf errors
Definition: FONcUtils.cc:245
FONcTransform::dump
virtual void dump(ostream &strm) const
dumps information about this transformation object for debugging purposes
Definition: FONcTransform.cc:233
BESContainer::get_container_type
std::string get_container_type() const
retrieve the type of data this container holds, such as cedar or netcdf.
Definition: BESContainer.h:232
FONcTransform::transform
virtual void transform()
Transforms each of the variables of the DataDDS to the NetCDF file.
Definition: FONcTransform.cc:127
FONcUtils::reset
static void reset()
Resets the FONc transformation for a new input and out file.
Definition: FONcUtils.cc:59
FONcTransform::FONcTransform
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...
Definition: FONcTransform.cc:67
FONcAttributes::add_attributes
static void add_attributes(int ncid, int varid, AttrTable &attrs, const string &var_name, const string &prepend_attr)
helper function for add_attributes
Definition: FONcAttributes.cc:129
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
FONcUtils::convert
static FONcBaseType * convert(BaseType *v)
Creates a FONc object for the given DAP object.
Definition: FONcUtils.cc:182
FONcBaseType
A DAP BaseType with file out netcdf information included.
Definition: FONcBaseType.h:58
BESDataHandlerInterface::first_container
void first_container()
set the container pointer to the first container in the containers list
Definition: BESDataHandlerInterface.h:135
BESDataHandlerInterface
Structure storing information used by the BES to handle the request.
Definition: BESDataHandlerInterface.h:56
BESError
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
FONcUtils::name_prefix
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:56
FONcBaseType::setVersion
virtual void setVersion(std::string version)
Identifies variable with use of NetCDF4 features.
Definition: FONcBaseType.cc:88