27#include "DapRequestHandler.h"
29#include <BESResponseHandler.h>
30#include <BESResponseNames.h>
31#include <BESVersionInfo.h>
32#include <BESTextInfo.h>
33#include <BESDapNames.h>
35#include <BESDataDDSResponse.h>
36#include <BESDDSResponse.h>
37#include <BESDASResponse.h>
38#include <BESDMRResponse.h>
40#include <BESConstraintFuncs.h>
41#include <BESServiceRegistry.h>
43#include <TheBESKeys.h>
45#include <BESDapError.h>
46#include <BESInternalFatalError.h>
49#include <libdap/BaseTypeFactory.h>
50#include <test/TestTypeFactory.h>
51#include <libdap/D4BaseTypeFactory.h>
52#include <test/D4TestTypeFactory.h>
53#include <test/TestCommon.h>
55#include <libdap/DMR.h>
56#include <libdap/D4Group.h>
57#include <libdap/D4Connect.h>
58#include <libdap/D4ParserSax2.h>
60#include <libdap/Ancillary.h>
61#include <libdap/Connect.h>
62#include <libdap/Response.h>
63#include <libdap/InternalErr.h>
64#include <libdap/mime_util.h>
68int test_variable_sleep_interval = 0;
70bool DapRequestHandler::d_use_series_values =
true;
71bool DapRequestHandler::d_use_series_values_set =
false;
73bool DapRequestHandler::d_use_test_types =
true;
74bool DapRequestHandler::d_use_test_types_set =
false;
76const string module =
"dapreader";
78static void read_key_value(
const std::string &key_name,
bool &key_value,
bool &is_key_set)
80 if (is_key_set ==
false) {
81 bool key_found =
false;
89 key_value = (doset ==
"true" || doset ==
"yes");
94static bool extension_match(
const string &data_source,
const string &extension)
96 string::size_type pos = data_source.rfind(extension);
97 return pos != string::npos && pos + extension.size() == data_source.size();
100DapRequestHandler::DapRequestHandler(
const string &name) :
103 add_method(DAS_RESPONSE, dap_build_das);
104 add_method(DDS_RESPONSE, dap_build_dds);
105 add_method(DATA_RESPONSE, dap_build_data);
107 add_method(DMR_RESPONSE, dap_build_dmr);
108 add_method(DAP4DATA_RESPONSE, dap_build_dap4data);
110 add_method(VERS_RESPONSE, dap_build_vers);
111 add_method(HELP_RESPONSE, dap_build_help);
113 read_key_value(
"DR.UseTestTypes", d_use_test_types, d_use_test_types_set);
114 read_key_value(
"DR.UseSeriesValues", d_use_series_values, d_use_series_values_set);
123void DapRequestHandler::load_dds_from_data_file(
const string &accessed, DDS &dds)
125 BESDEBUG(
"dapreader",
"In DapRequestHandler::load_dds_from_data_file; accessed: " << accessed << endl);
127 TestTypeFactory t_factory;
128 BaseTypeFactory b_factory;
129 if (d_use_test_types)
130 dds.set_factory(&t_factory);
134 dds.set_factory(&b_factory);
138 unique_ptr<Connect> url(
new Connect(accessed));
139 Response r(fopen(accessed.c_str(),
"r"), 0);
140 if (!r.get_stream())
throw Error(
string(
"The input source: ") + accessed +
string(
" could not be opened"));
141 url->read_data_no_mime(dds, &r);
143 unique_ptr<DAS> das(
new DAS);
144 Ancillary::read_ancillary_das(*das, accessed);
146 if (das->get_size() > 0) dds.transfer_attributes(das.get());
151 for (
auto i = dds.var_begin(), e = dds.var_end(); i != e; i++) {
152 (*i)->set_read_p(
true);
163void DapRequestHandler::build_dds_from_file(
const string &accessed,
bool explicit_containers, DDS *dds)
165 BESDEBUG(
"dapreader",
"In DapRequestHandler::build_dds_from_file; accessed: " << accessed << endl);
167 if (extension_match(accessed,
".dds") && d_use_test_types) {
168 dds->set_factory(
new TestTypeFactory);
169 dds->parse(accessed);
172 Ancillary::read_ancillary_das(*das, accessed);
174 if (das->get_size() > 0) dds->transfer_attributes(das);
176 else if (extension_match(accessed,
".dods") || extension_match(accessed,
".data")) {
177 if (explicit_containers) {
178 BESDEBUG(
"dapreader",
"In DapRequestHandler::build_dds_from_file; in container code" << endl);
187 load_dds_from_data_file(accessed, local_dds);
190 for (DDS::Vars_iter i = local_dds.var_begin(), e = local_dds.var_end(); i != e; i++) {
194 dds->set_dataset_name(name_path(accessed));
197 BESDEBUG(
"dapreader",
"In DapRequestHandler::build_dds_from_file; in plain code" << endl);
199 load_dds_from_data_file(accessed, *dds);
202 dds->filename(accessed);
205 throw Error(
"The dapreader module can only return DDS/DODS responses for files ending in .dods, .data or .dds");
208 BESDEBUG(
"dapreader2",
"DDS/DDX in DapRequestHandler::build_dds_from_file: ");
212void DapRequestHandler::build_dmr_from_file(
const string& accessed,
bool explicit_containers, DMR* dmr)
214 BESDEBUG(
"dapreader",
"In DapRequestHandler::build_dmr_from_file; accessed: " << accessed << endl);
216 dmr->set_filename(accessed);
217 dmr->set_name(name_path(accessed));
219 D4TestTypeFactory TestFactory;
220 D4BaseTypeFactory BaseFactory;
221 if (d_use_test_types) {
222 dmr->set_factory(&TestFactory);
225 dmr->set_factory(&BaseFactory);
228 if ((extension_match(accessed,
".dmr") || extension_match(accessed,
".xml")) && d_use_test_types) {
230 ifstream in(accessed.c_str(), ios::in);
231 parser.intern(in, dmr);
233 else if (extension_match(accessed,
".dap")) {
234 unique_ptr<D4Connect> url(
new D4Connect(accessed));
235 fstream f(accessed.c_str(), std::ios_base::in);
236 if (!f.is_open() || f.bad() || f.eof())
throw Error((
string) (
"Could not open: ") + accessed);
241 url->read_data_no_mime(*dmr, r);
243 else if (extension_match(accessed,
".dds") || extension_match(accessed,
".dods")
244 || extension_match(accessed,
".data")) {
246 unique_ptr<DDS> dds(
new DDS(0 ));
248 build_dds_from_file(accessed, explicit_containers, dds.get());
250 dmr->build_using_dds(*dds);
253 dmr->set_factory(
nullptr);
254 throw Error(
"The dapreader module can only return DMR/DAP responses for files ending in .dmr, .xml or .dap");
257 dmr->set_factory(
nullptr);
273 BESDEBUG(module,
"Entering dap_build_dmr..." << endl);
277 if (!bdmr)
throw BESInternalError(
"BESDMRResponse cast error", __FILE__, __LINE__);
288 catch (InternalErr & e) {
289 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
292 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
298 BESDEBUG(module,
"Leaving dap_build_dmr..." << endl);
311 BESDEBUG(module,
"Entering dap_build_dap4data..." << endl);
315 if (!bdmr)
throw BESInternalError(
"BESDMRResponse cast error", __FILE__, __LINE__);
318 DMR *dmr = bdmr->get_dmr();
321 if (d_use_series_values) {
322 dmr->root()->set_read_p(
false);
324 TestCommon *tc =
dynamic_cast<TestCommon*
>(dmr->root());
326 tc->set_series_values(
true);
328 throw Error(
"In the reader handler: Could not set UseSeriesValues");
334 catch (BESError &e) {
337 catch (InternalErr & e) {
338 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
341 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
344 throw BESInternalFatalError(
"Unknown exception caught building DAP4 Data response", __FILE__, __LINE__);
347 BESDEBUG(module,
"Leaving dap_build_dap4data..." << endl);
366 DAS *das = bdas->get_das();
369 if (extension_match(accessed,
".das")) {
370 das->parse(accessed);
372 else if (extension_match(accessed,
".dods") || extension_match(accessed,
".data")) {
373 Ancillary::read_ancillary_das(*das, accessed);
377 "The dapreader module can only return DAS responses for files ending in .das or .dods/.data.\nIn the latter case there must be an ancillary das file present.");
385 catch (InternalErr & e) {
386 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
389 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
401 BESDEBUG(module,
"Entering dap_build_dds..." << endl);
415 catch (BESError &e) {
418 catch (InternalErr & e) {
419 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
422 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
425 throw BESInternalFatalError(
"Unknown exception caught building DDS", __FILE__, __LINE__);
428 BESDEBUG(module,
"Exiting dap_build_dds..." << endl);
435 BESDEBUG(module,
"Entering dap_build_data..." << endl);
438 BESDataDDSResponse *bdds =
dynamic_cast<BESDataDDSResponse *
>(response);
439 if (!bdds)
throw BESInternalError(
"DDS cast error", __FILE__, __LINE__);
449 catch (BESError &e) {
452 catch (InternalErr & e) {
453 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
456 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
459 throw BESInternalFatalError(
"Unknown exception caught building a data response", __FILE__, __LINE__);
462 BESDEBUG(module,
"Exiting dap_build_data..." << endl);
471 BESDataDDSResponse *bdds =
dynamic_cast<BESDataDDSResponse *
>(response);
473 throw BESInternalError(
"cast error", __FILE__, __LINE__);
475 DDS *dds = bdds->get_dds();
483 if (!container_name.empty()) das->container_name(container_name);
485 nc_read_dataset_attributes(*das, dataset_name);
486 Ancillary::read_ancillary_das(*das, dataset_name);
488 dds->transfer_attributes(das);
493 BESDEBUG(NC_NAME,
"DAS added to the cache for : " << dataset_name << endl);
494 das_cache->add(das, dataset_name);
501 BESDEBUG(NC_NAME,
"Data ACCESS in add_attributes(): set the including attribute flag to true: "<<dataset_name << endl);
502 bdds->set_ia_flag(
true);
509 BESVersionInfo *info =
dynamic_cast<BESVersionInfo *
>(dhi.response_handler->
get_response_object());
510 if (!info)
throw BESInternalFatalError(
"Expected a BESVersionInfo instance.", __FILE__, __LINE__);
512 info->add_module(DAPREADER_PACKAGE, DAPREADER_VERSION);
519 if (!info)
throw BESInternalFatalError(
"Expected a BESVersionInfo instance.", __FILE__, __LINE__);
523 map<string, string, std::less<>> attrs;
524 attrs[
"name"] = DAPREADER_PACKAGE ;
525 attrs[
"version"] = DAPREADER_VERSION ;
526 list<string> services;
528 if (services.size() > 0) {
530 attrs[
"handles"] = handles;
532 info->begin_tag(
"module", &attrs);
533 info->end_tag(
"module");
540 strm << BESIndent::LMarg <<
"DapRequestHandler::dump - (" << (
void *)
this <<
")" << endl;
543 BESIndent::UnIndent();
std::string get_symbolic_name() const
retrieve the symbolic name for this container
virtual std::string access()=0
returns the true name of this container
Represents an OPeNDAP DAS DAP2 data object within the BES.
virtual void clear_container()
clear the container in the DAP response object
virtual void set_container(const std::string &cn)
set the container in the DAP response object
Holds a DDS object within the BES.
virtual void set_container(const std::string &cn)
set the container in the DAP response object
virtual void clear_container()
clear the container in the DAP response object
Represents an OPeNDAP DMR DAP4 data object within the BES.
error object created from libdap error objects and can handle those errors
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
bool get_explicit_containers() const
Should containers be explicitly represented in the DD* responses?
virtual void set_container(const std::string &cn)
set the container in the DAP response object
virtual void clear_container()
clear the container in the DAP response object
Structure storing information used by the BES to handle the request.
BESContainer * container
pointer to current container in this interface
static bool IsSet(const std::string &flagName)
see if the debug context flagName is set to true
static std::ostream * GetStrm()
return the debug stream
Base exception class for the BES with basic string message.
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
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 services_handled(const std::string &handler, std::list< std::string > &services)
returns the list of servies provided by the handler in question
static std::string lowercase(const std::string &s)
static std::string implode(const std::list< std::string > &values, char delim)
static bool dap_build_das(BESDataHandlerInterface &dhi)
static bool dap_build_dmr(BESDataHandlerInterface &dhi)
virtual void dump(std::ostream &strm) const
dumps information about this object
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
Access to the singleton.