bes  Updated for version 3.20.10
CSVRequestHandler.cc
1 // CSVRequestHandler.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Stephan Zednik <zednik@ucar.edu> and Patrick West <pwest@ucar.edu>
8 // and Jose Garcia <jgarcia@ucar.edu>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact University Corporation for Atmospheric Research at
25 // 3080 Center Green Drive, Boulder, CO 80301
26 
27 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
28 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
29 //
30 // Authors:
31 // zednik Stephan Zednik <zednik@ucar.edu>
32 // pwest Patrick West <pwest@ucar.edu>
33 // jgarcia Jose Garcia <jgarcia@ucar.edu>
34 
35 #include "config.h"
36 
37 #include <libdap/DDS.h>
38 #include <libdap/DAS.h>
39 #include <libdap/DataDDS.h>
40 #include <libdap/BaseTypeFactory.h>
41 #include <libdap/Ancillary.h>
42 
43 #include <libdap/DMR.h>
44 #include <libdap/D4BaseTypeFactory.h>
45 #include <libdap/mime_util.h>
46 #include <libdap/InternalErr.h>
47 
48 #include <BESDASResponse.h>
49 #include <BESDDSResponse.h>
50 #include <BESDataDDSResponse.h>
51 #include <BESDMRResponse.h>
52 
53 #include <BESInfo.h>
54 #include <BESContainer.h>
55 #include <BESVersionInfo.h>
56 #include <BESDataNames.h>
57 #include <BESDapNames.h>
58 #include <BESResponseHandler.h>
59 #include <BESResponseNames.h>
60 #include <BESVersionInfo.h>
61 #include <BESTextInfo.h>
62 #include <BESConstraintFuncs.h>
63 #include <BESDapError.h>
64 #include <BESDebug.h>
65 
66 #include "CSVDDS.h"
67 #include "CSVDAS.h"
68 #include "CSVRequestHandler.h"
69 
70 // using namespace libdap;
71 #define prolog std::string("CSVRequestHandler::").append(__func__).append("() - ")
72 #define MODULE "csv"
73 
74 CSVRequestHandler::CSVRequestHandler(string name) :
75  BESRequestHandler(name)
76 {
77  add_method(DAS_RESPONSE, CSVRequestHandler::csv_build_das);
78  add_method(DDS_RESPONSE, CSVRequestHandler::csv_build_dds);
79  add_method(DATA_RESPONSE, CSVRequestHandler::csv_build_data);
80 
81  // We can use the same DMR object for both the metadata and data
82  // responses. jhrg 8/13/14
83  add_method(DMR_RESPONSE, CSVRequestHandler::csv_build_dmr);
84  add_method(DAP4DATA_RESPONSE, CSVRequestHandler::csv_build_dmr);
85 
86  add_method(VERS_RESPONSE, CSVRequestHandler::csv_build_vers);
87  add_method(HELP_RESPONSE, CSVRequestHandler::csv_build_help);
88 }
89 
90 CSVRequestHandler::~CSVRequestHandler()
91 {
92 }
93 
94 bool CSVRequestHandler::csv_build_das(BESDataHandlerInterface &dhi)
95 {
96  string error;
97  bool ret = true;
98  BESResponseObject *response = dhi.response_handler->get_response_object();
99  BESDASResponse *bdas = dynamic_cast<BESDASResponse *>(response);
100  DAS *das = 0;
101  if (bdas)
102  das = bdas->get_das();
103  else
104  throw BESInternalError("cast error", __FILE__, __LINE__);
105 
106  try {
107  string accessed = dhi.container->access();
108  csv_read_attributes(*das, accessed);
109  Ancillary::read_ancillary_das(*das, accessed);
110  return ret;
111  }
112  catch (libdap::InternalErr &e) {
113  throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
114  }
115  catch (libdap::Error &e) {
116  throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
117  }
118  catch (BESError &e) {
119  throw e;
120  }
121  catch (...) {
122  throw BESDapError(prolog + "Caught unknown error building the DAS response", false, unknown_error, __FILE__, __LINE__);
123  }
124 }
125 
126 bool CSVRequestHandler::csv_build_dds(BESDataHandlerInterface &dhi)
127 {
128  bool ret = true;
129  BESResponseObject *response = dhi.response_handler->get_response_object();
130  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(response);
131  DDS *dds = 0;
132  if (bdds)
133  dds = bdds->get_dds();
134  else
135  throw BESInternalError("cast error", __FILE__, __LINE__);
136 
137  BaseTypeFactory factory;
138  dds->set_factory(&factory);
139 
140  try {
141  string accessed = dhi.container->access();
142  dds->filename(accessed);
143  csv_read_descriptors(*dds, accessed);
144  Ancillary::read_ancillary_dds(*dds, accessed);
145 
146  DAS das;
147  csv_read_attributes(das, accessed);
148  Ancillary::read_ancillary_das(das, accessed);
149  dds->transfer_attributes(&das);
150 
151  bdds->set_constraint(dhi);
152  return ret;
153  }
154  catch (libdap::InternalErr &e) {
155  throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
156  }
157  catch (libdap::Error &e) {
158  throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
159  }
160  catch (BESError &e) {
161  throw e;
162  }
163  catch (...) {
164  throw BESDapError(prolog + "Caught unknown error building the DDS response", false, unknown_error, __FILE__, __LINE__);
165  }
166 }
167 
168 bool CSVRequestHandler::csv_build_data(BESDataHandlerInterface &dhi)
169 {
170  bool ret = true;
171  BESResponseObject *response = dhi.response_handler->get_response_object();
172  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(response);
173  DDS *dds = 0;
174  if (bdds)
175  dds = bdds->get_dds();
176  else
177  throw BESInternalError("cast error", __FILE__, __LINE__);
178 
179  BaseTypeFactory factory;
180  dds->set_factory(&factory);
181 
182  try {
183  string accessed = dhi.container->access();
184  dds->filename(accessed);
185  csv_read_descriptors(*dds, accessed);
186  Ancillary::read_ancillary_dds(*dds, accessed);
187  bdds->set_constraint(dhi);
188 
189  // We don't need to build the DAS here. Set the including attribute flag to false. KY 10/30/19
190  BESDEBUG(MODULE, prolog << "Data ACCESS build_data(): set the including attribute flag to false: "<<accessed << endl);
191  bdds->set_ia_flag(false);
192  return ret;
193  }
194  catch (libdap::InternalErr &e) {
195  throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
196  }
197  catch (libdap::Error &e) {
198  throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
199  }
200  catch (BESError &e) {
201  throw e;
202  }
203  catch (...) {
204  throw BESDapError(prolog + "Caught unknown error building the DataDDS response", false, unknown_error, __FILE__, __LINE__);
205  }
206 
207 
208 }
209 
219 {
220  // Because this code does not yet know how to build a DMR directly, use
221  // the DMR ctor that builds a DMR using a 'full DDS' (a DDS with attributes).
222  // First step, build the 'full DDS'
223  string data_path = dhi.container->access();
224 
225  BaseTypeFactory factory;
226  DDS dds(&factory, name_path(data_path), "3.2");
227  dds.filename(data_path);
228 
229  try {
230  csv_read_descriptors(dds, data_path);
231  // ancillary DDS objects never took off - this does nothing. jhrg 8/12/14
232  // Ancillary::read_ancillary_dds(*dds, data_path);
233 
234  DAS das;
235  csv_read_attributes(das, data_path);
236  Ancillary::read_ancillary_das(das, data_path);
237  dds.transfer_attributes(&das);
238  }
239  catch (libdap::InternalErr &e) {
240  throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
241  }
242  catch (libdap::Error &e) {
243  throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
244  }
245  catch (BESError &e) {
246  throw e;
247  }
248  catch (...) {
249  throw BESDapError(prolog + "Caught unknown error building the DMR response", false, unknown_error, __FILE__, __LINE__);
250  }
251 
252  // Second step, make a DMR using the DDS
253 
254  // Extract the DMR Response object - this holds the DMR used by the
255  // other parts of the framework.
256  BESResponseObject *response = dhi.response_handler->get_response_object();
257  BESDMRResponse &bdmr = dynamic_cast<BESDMRResponse &>(*response);
258 
259  // Extract the DMR Response object - this holds the DMR used by the
260  // other parts of the framework.
261  DMR *dmr = bdmr.get_dmr();
262  D4BaseTypeFactory MyD4TypeFactory;
263  dmr->set_factory(&MyD4TypeFactory);
264 
265  dmr->build_using_dds(dds);
266 
267  // Instead of fiddling with the internal storage of the DHI object,
268  // (by setting dhi.data[DAP4_CONSTRAINT], etc., directly) use these
269  // methods to set the constraints. But, why? Maybe setting data[]
270  // directly is better? jhrg 8/14/14
271  bdmr.set_dap4_constraint(dhi);
272  bdmr.set_dap4_function(dhi);
273 
274  // What about async and store_result? See BESDapTransmit::send_dap4_data()
275 
276  return true;
277 }
278 
279 bool CSVRequestHandler::csv_build_vers(BESDataHandlerInterface &dhi)
280 {
281  bool ret = true;
282 
283  BESResponseObject *response = dhi.response_handler->get_response_object();
284  BESVersionInfo *info = dynamic_cast<BESVersionInfo *>(response);
285  if (!info) throw BESInternalError("cast error", __FILE__, __LINE__);
286 
287  info->add_module(MODULE_NAME, MODULE_VERSION);
288  return ret;
289 }
290 
291 bool CSVRequestHandler::csv_build_help(BESDataHandlerInterface &dhi)
292 {
293  bool ret = true;
294  BESInfo *info = dynamic_cast<BESInfo *>(dhi.response_handler->get_response_object());
295  if (!info) throw BESInternalError("cast error", __FILE__, __LINE__);
296 
297  map<string, string> attrs;
298  attrs["name"] = PACKAGE_NAME;
299  attrs["version"] = PACKAGE_VERSION;
300  string handles = (string) DAS_RESPONSE + "," + DDS_RESPONSE + "," + DATA_RESPONSE + "," + HELP_RESPONSE + ","
301  + VERS_RESPONSE;
302  attrs["handles"] = handles;
303  info->begin_tag("module", &attrs);
304  info->end_tag("module");
305 
306  return ret;
307 }
308 
309 void CSVRequestHandler::dump(ostream &strm) const
310 {
311  strm << BESIndent::LMarg << "CSVRequestHandler::dump - (" << (void *) this << ")" << endl;
312  BESIndent::Indent();
314  BESIndent::UnIndent();
315 }
316 
317 
318 void CSVRequestHandler::add_attributes(BESDataHandlerInterface &dhi) {
319 
320  BESResponseObject *response = dhi.response_handler->get_response_object();
321  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(response);
322  if (!bdds)
323  throw BESInternalError("cast error", __FILE__, __LINE__);
324  DDS *dds = bdds->get_dds();
325  string dataset_name = dhi.container->access();
326  DAS das;
327  csv_read_attributes(das, dataset_name);
328  Ancillary::read_ancillary_das(das, dataset_name);
329  dds->transfer_attributes(&das);
330  BESDEBUG(MODULE, prolog << "Data ACCESS in add_attributes(): set the including attribute flag to true: "<<dataset_name << endl);
331  bdds->set_ia_flag(true);
332  return;
333 }
334 
virtual std::string access()=0
returns the true name of this container
Represents an OPeNDAP DAS DAP2 data object within the BES.
Holds a DDS object within the BES.
libdap::DDS * get_dds()
Represents an OPeNDAP DMR DAP4 data object within the BES.
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:59
virtual void set_dap4_function(BESDataHandlerInterface &dhi)
set the constraint depending on the context
virtual void set_dap4_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
virtual void set_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
Structure storing information used by the BES to handle the request.
BESContainer * container
pointer to current container in this interface
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
informational response object
Definition: BESInfo.h:63
exception thrown if internal error encountered
Represents a specific data type request handler.
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual BESResponseObject * get_response_object()
return the current response object
Abstract base class representing a specific set of information in response to a request to the BES.
virtual void dump(std::ostream &strm) const
dumps information about this object
static bool csv_build_dmr(BESDataHandlerInterface &dhi)