bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
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
74CSVRequestHandler::CSVRequestHandler(string 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
90CSVRequestHandler::~CSVRequestHandler()
91{
92}
93
94bool 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
126bool 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
168bool 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
279bool 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
291bool 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, std::less<>> 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
310{
311 strm << BESIndent::LMarg << "CSVRequestHandler::dump - (" << (void *) this << ")" << endl;
312 BESIndent::Indent();
314 BESIndent::UnIndent();
315}
316
317
318void 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
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:50
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
Base exception class for the BES with basic string message.
Definition BESError.h:66
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)
STL class.