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.size();
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();
194 BES_STOPWATCH_START_DHI(MODULE, prolog +
"Timing", &dhi);
196 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_data() - BEGIN." << endl);
199 ContextCleanup cleanup;
204 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_data() - reading data into DataDDS" << endl);
208 checkConstraintForW10nCompatibility(dhi.
data[POST_CONSTRAINT]);
209 w10n::checkConstrainedDDSForW10nDataCompatibility(loaded_dds);
211 ostream &o_strm = dhi.get_output_stream();
212 if (!o_strm)
throw BESInternalError(
"Output stream is not set, can not return as JSON", __FILE__, __LINE__);
216 string varName = getProjectedVariableName(dhi.
data[POST_CONSTRAINT]);
225 BESDEBUG(W10N_DEBUG_KEY,
226 "W10nJsonTransmitter::send_data() - Sending w10n data response for variable " << varName << endl);
228 ft.sendW10nDataForVariable(varName);
231 throw BESDapError(
"Failed to read data! Msg: " + e.get_error_message(),
false, e.get_error_code(),
238 throw BESInternalError(
"Failed to read data: Unknown exception caught", __FILE__, __LINE__);
243 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_data() - END. Done transmitting JSON" << endl);
264 BES_STOPWATCH_START_DHI(MODULE, prolog +
"Timing", &dhi);
266 ContextCleanup cleanup;
272 if (!dds)
throw BESInternalError(
"No DDS has been created for transmit", __FILE__, __LINE__);
274 ConstraintEvaluator &eval = bdds->
get_ce();
276 ostream &o_strm = dhi.get_output_stream();
277 if (!o_strm)
throw BESInternalError(
"Output stream is not set, can not return as JSON", __FILE__, __LINE__);
280 string ce = www2id(dhi.
data[POST_CONSTRAINT],
"%",
"%20%26");
282 checkConstraintForW10nCompatibility(ce);
285 eval.parse_constraint(ce, *dds);
288 throw BESDapError(
"Failed to parse the constraint expression: " + e.get_error_message(),
false,
289 e.get_error_code(), __FILE__, __LINE__);
292 throw BESInternalError(
"Failed to parse the constraint expression: Unknown exception caught", __FILE__,
298 string varName = getProjectedVariableName(ce);
300 if (varName.size() == 0) {
301 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_metadata() - Sending w10n meta response for DDS" << endl);
302 ft.sendW10nMetaForDDS();
305 BESDEBUG(W10N_DEBUG_KEY,
306 "W10nJsonTransmitter::send_metadata() - Sending w10n meta response for variable " << varName << endl);
307 ft.sendW10nMetaForVariable(varName,
true);
310 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_metadata() - done transmitting JSON" << endl);
316void W10nJsonTransmitter::cleanupW10nContexts()
318 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::cleanupW10nContexts() - Removing contexts" << endl);
320 BESContextManager::TheManager()->unset_context(W10N_META_OBJECT_KEY);
322 BESContextManager::TheManager()->unset_context(W10N_CALLBACK_KEY);
324 BESContextManager::TheManager()->unset_context(W10N_FLATTEN_KEY);
326 BESContextManager::TheManager()->unset_context(W10N_TRAVERSE_KEY);
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.
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.
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()
Access to the singleton.
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.