44#include <libdap/DataDDS.h>
45#include <libdap/BaseType.h>
46#include <libdap/escaping.h>
47#include <libdap/ConstraintEvaluator.h>
50#include <BESInternalError.h>
51#include <BESDapError.h>
52#include <BESDapError.h>
53#include <TheBESKeys.h>
54#include <BESContextManager.h>
55#include <BESDataDDSResponse.h>
56#include <BESDDSResponse.h>
57#include <BESDapError.h>
58#include <BESDapNames.h>
59#include <BESDataNames.h>
61#include <BESStopWatch.h>
62#include <BESSyntaxUserError.h>
63#include <BESDapResponseBuilder.h>
64#include <RequestServiceTimer.h>
66#include "W10nJsonTransmitter.h"
68#include "W10nJsonTransform.h"
70#include "w10n_utils.h"
75#define prolog string("W10nJsonTransmitter::").append(__func__).append("() - ")
77#define W10N_JSON_TEMP_DIR "/tmp"
79string W10nJsonTransmitter::temp_dir;
98 if (W10nJsonTransmitter::temp_dir.empty()) {
101 string key =
"W10nJson.Tempdir";
103 if (!found || W10nJsonTransmitter::temp_dir.empty()) {
104 W10nJsonTransmitter::temp_dir = W10N_JSON_TEMP_DIR;
106 string::size_type len = W10nJsonTransmitter::temp_dir.length();
107 if (W10nJsonTransmitter::temp_dir[len - 1] ==
'/') {
108 W10nJsonTransmitter::temp_dir = W10nJsonTransmitter::temp_dir.substr(0, len - 1);
117void W10nJsonTransmitter::checkConstraintForW10nCompatibility(
const string &ce)
119 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::checkConstraintForW10nCompatibility() - BEGIN. ce: "<< ce << endl);
121 string projectionClause = getProjectionClause(ce);
122 int firstComma = projectionClause.find(
",");
124 if (firstComma != -1) {
125 string msg =
"The w10n protocol only allows one variable to be selected at a time. ";
126 msg +=
"The constraint expression '" + ce +
"' requests more than one.";
127 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::checkConstraintForW10nCompatibility() - ERROR! "<< msg << endl);
131 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::checkConstraintForW10nCompatibility() - END: " << endl);
137string W10nJsonTransmitter::getProjectionClause(
const string &constraintExpression)
139 string projectionClause = constraintExpression;
140 BESDEBUG(W10N_DEBUG_KEY,
141 "W10nJsonTransmitter::getProjectionClause() - constraintExpression: "<< constraintExpression << endl);
143 int firstAmpersand = constraintExpression.find(
"&");
144 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::getProjectionClause() - firstAmpersand: "<< firstAmpersand << endl);
145 if (firstAmpersand >= 0) projectionClause = constraintExpression.substr(0, firstAmpersand);
147 BESDEBUG(W10N_DEBUG_KEY,
148 "W10nJsonTransmitter::getProjectionClause() - CE projection clause: "<< projectionClause << endl);
150 return projectionClause;
156string W10nJsonTransmitter::getProjectedVariableName(
const string &constraintExpression)
158 string varName = getProjectionClause(constraintExpression);
160 int firstSquareBracket = varName.find(
"[");
161 if (firstSquareBracket != -1) {
162 varName = varName.substr(0, firstSquareBracket);
168struct ContextCleanup {
171 BESDEBUG(W10N_DEBUG_KEY,
"Cleanup w10n contexts" << endl);
172 W10nJsonTransmitter::cleanupW10nContexts();
199 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_data() - BEGIN." << endl);
202 ContextCleanup cleanup;
207 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_data() - reading data into DataDDS" << endl);
211 checkConstraintForW10nCompatibility(dhi.
data[POST_CONSTRAINT]);
212 w10n::checkConstrainedDDSForW10nDataCompatibility(loaded_dds);
214 ostream &o_strm = dhi.get_output_stream();
215 if (!o_strm)
throw BESInternalError(
"Output stream is not set, can not return as JSON", __FILE__, __LINE__);
219 string varName = getProjectedVariableName(dhi.
data[POST_CONSTRAINT]);
228 BESDEBUG(W10N_DEBUG_KEY,
229 "W10nJsonTransmitter::send_data() - Sending w10n data response for variable " << varName << endl);
231 ft.sendW10nDataForVariable(varName);
234 throw BESDapError(
"Failed to read data! Msg: " + e.get_error_message(),
false, e.get_error_code(),
241 throw BESInternalError(
"Failed to read data: Unknown exception caught", __FILE__, __LINE__);
246 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_data() - END. Done transmitting JSON" << endl);
272 ContextCleanup cleanup;
278 if (!dds)
throw BESInternalError(
"No DDS has been created for transmit", __FILE__, __LINE__);
280 ConstraintEvaluator &eval = bdds->
get_ce();
282 ostream &o_strm = dhi.get_output_stream();
283 if (!o_strm)
throw BESInternalError(
"Output stream is not set, can not return as JSON", __FILE__, __LINE__);
286 string ce = www2id(dhi.
data[POST_CONSTRAINT],
"%",
"%20%26");
288 checkConstraintForW10nCompatibility(ce);
291 eval.parse_constraint(ce, *dds);
294 throw BESDapError(
"Failed to parse the constraint expression: " + e.get_error_message(),
false,
295 e.get_error_code(), __FILE__, __LINE__);
298 throw BESInternalError(
"Failed to parse the constraint expression: Unknown exception caught", __FILE__,
304 string varName = getProjectedVariableName(ce);
306 if (varName.length() == 0) {
307 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_metadata() - Sending w10n meta response for DDS" << endl);
308 ft.sendW10nMetaForDDS();
311 BESDEBUG(W10N_DEBUG_KEY,
312 "W10nJsonTransmitter::send_metadata() - Sending w10n meta response for variable " << varName << endl);
313 ft.sendW10nMetaForVariable(varName,
true);
316 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_metadata() - done transmitting JSON" << endl);
322void W10nJsonTransmitter::cleanupW10nContexts()
324 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::cleanupW10nContexts() - Removing contexts" << endl);
326 BESContextManager::TheManager()->
unset_context(W10N_META_OBJECT_KEY);
328 BESContextManager::TheManager()->
unset_context(W10N_CALLBACK_KEY);
330 BESContextManager::TheManager()->
unset_context(W10N_FLATTEN_KEY);
332 BESContextManager::TheManager()->
unset_context(W10N_TRAVERSE_KEY);
virtual void unset_context(const std::string &name)
set context in the BES
Holds a DDS object within the BES.
libdap::ConstraintEvaluator & get_ce()
error object created from libdap error objects and can handle those errors
virtual libdap::DDS * intern_dap2_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
Structure storing information used by the BES to handle the request.
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
static bool IsSet(const std::string &flagName)
see if the debug context flagName is set to true
Base exception class for the BES with basic string message.
exception thrown if internal error encountered
Abstract base class representing a specific set of information in response to a request to the BES.
virtual bool start(std::string name)
error thrown if there is a user syntax error in the request or any other user error
static void conditional_timeout_cancel()
Checks if the timeout alarm should be canceled based on the value of the BES key BES....
static RequestServiceTimer * TheTimer()
Return a pointer to a singleton timer instance. If an instance does not exist it will create and init...
void throw_if_timeout_expired(const std::string &message, const std::string &file, const int line)
Checks the RequestServiceTimer to determine if the time spent servicing the request at this point has...
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
static void send_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP data objects as a JSON file.
static void send_metadata(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP data objects as a JSON file.
W10nJsonTransmitter()
Construct the W10nJsonTransmitter.