38 #include <sys/types.h>
47 #include <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>
65 #include "W10nJsonTransmitter.h"
67 #include "W10nJsonTransform.h"
68 #include "W10NNames.h"
69 #include "w10n_utils.h"
73 #define W10N_JSON_TEMP_DIR "/tmp"
75 string W10nJsonTransmitter::temp_dir;
94 if (W10nJsonTransmitter::temp_dir.empty()) {
97 string key =
"W10nJson.Tempdir";
99 if (!found || W10nJsonTransmitter::temp_dir.empty()) {
100 W10nJsonTransmitter::temp_dir = W10N_JSON_TEMP_DIR;
102 string::size_type len = W10nJsonTransmitter::temp_dir.length();
103 if (W10nJsonTransmitter::temp_dir[len - 1] ==
'/') {
104 W10nJsonTransmitter::temp_dir = W10nJsonTransmitter::temp_dir.substr(0, len - 1);
113 void W10nJsonTransmitter::checkConstraintForW10nCompatibility(
const string &ce)
115 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::checkConstraintForW10nCompatibility() - BEGIN. ce: "<< ce << endl);
117 string projectionClause = getProjectionClause(ce);
118 int firstComma = projectionClause.find(
",");
120 if (firstComma != -1) {
121 string msg =
"The w10n protocol only allows one variable to be selected at a time. ";
122 msg +=
"The constraint expression '" + ce +
"' requests more than one.";
123 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::checkConstraintForW10nCompatibility() - ERROR! "<< msg << endl);
127 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::checkConstraintForW10nCompatibility() - END: " << endl);
133 string W10nJsonTransmitter::getProjectionClause(
const string &constraintExpression)
135 string projectionClause = constraintExpression;
136 BESDEBUG(W10N_DEBUG_KEY,
137 "W10nJsonTransmitter::getProjectionClause() - constraintExpression: "<< constraintExpression << endl);
139 int firstAmpersand = constraintExpression.find(
"&");
140 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::getProjectionClause() - firstAmpersand: "<< firstAmpersand << endl);
141 if (firstAmpersand >= 0) projectionClause = constraintExpression.substr(0, firstAmpersand);
143 BESDEBUG(W10N_DEBUG_KEY,
144 "W10nJsonTransmitter::getProjectionClause() - CE projection clause: "<< projectionClause << endl);
146 return projectionClause;
152 string W10nJsonTransmitter::getProjectedVariableName(
const string &constraintExpression)
154 string varName = getProjectionClause(constraintExpression);
156 int firstSquareBracket = varName.find(
"[");
157 if (firstSquareBracket != -1) {
158 varName = varName.substr(0, firstSquareBracket);
164 struct ContextCleanup {
167 BESDEBUG(W10N_DEBUG_KEY,
"Cleanup w10n contexts" << endl);
168 W10nJsonTransmitter::cleanupW10nContexts();
192 if (BESISDEBUG(TIMING_LOG)) sw.
start(
"W10nJsonTransmitter::send_data", dhi.
data[REQUEST_ID]);
195 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_data() - BEGIN." << endl);
198 ContextCleanup cleanup;
203 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_data() - reading data into DataDDS" << endl);
207 checkConstraintForW10nCompatibility(dhi.
data[POST_CONSTRAINT]);
208 w10n::checkConstrainedDDSForW10nDataCompatibility(loaded_dds);
210 ostream &o_strm = dhi.get_output_stream();
211 if (!o_strm)
throw BESInternalError(
"Output stream is not set, can not return as JSON", __FILE__, __LINE__);
215 string varName = getProjectedVariableName(dhi.
data[POST_CONSTRAINT]);
221 BESDEBUG(W10N_DEBUG_KEY,
222 "W10nJsonTransmitter::send_data() - Sending w10n data response for variable " << varName << endl);
224 ft.sendW10nDataForVariable(varName);
227 throw BESDapError(
"Failed to read data! Msg: " + e.get_error_message(),
false, e.get_error_code(),
234 throw BESInternalError(
"Failed to read data: Unknown exception caught", __FILE__, __LINE__);
239 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_data() - END. Done transmitting JSON" << endl);
262 if (BESISDEBUG(TIMING_LOG)) sw.
start(
"W10nJsonTransmitter::send_metadata", dhi.
data[REQUEST_ID]);
265 ContextCleanup cleanup;
271 if (!dds)
throw BESInternalError(
"No DDS has been created for transmit", __FILE__, __LINE__);
273 ConstraintEvaluator &eval = bdds->
get_ce();
275 ostream &o_strm = dhi.get_output_stream();
276 if (!o_strm)
throw BESInternalError(
"Output stream is not set, can not return as JSON", __FILE__, __LINE__);
279 string ce = www2id(dhi.
data[POST_CONSTRAINT],
"%",
"%20%26");
281 checkConstraintForW10nCompatibility(ce);
284 eval.parse_constraint(ce, *dds);
287 throw BESDapError(
"Failed to parse the constraint expression: " + e.get_error_message(),
false,
288 e.get_error_code(), __FILE__, __LINE__);
291 throw BESInternalError(
"Failed to parse the constraint expression: Unknown exception caught", __FILE__,
297 string varName = getProjectedVariableName(ce);
299 if (varName.length() == 0) {
300 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_metadata() - Sending w10n meta response for DDS" << endl);
301 ft.sendW10nMetaForDDS();
304 BESDEBUG(W10N_DEBUG_KEY,
305 "W10nJsonTransmitter::send_metadata() - Sending w10n meta response for variable " << varName << endl);
306 ft.sendW10nMetaForVariable(varName,
true);
309 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::send_metadata() - done transmitting JSON" << endl);
315 void W10nJsonTransmitter::cleanupW10nContexts()
317 BESDEBUG(W10N_DEBUG_KEY,
"W10nJsonTransmitter::cleanupW10nContexts() - Removing contexts" << endl);
319 BESContextManager::TheManager()->
unset_context(W10N_META_OBJECT_KEY);
321 BESContextManager::TheManager()->
unset_context(W10N_CALLBACK_KEY);
323 BESContextManager::TheManager()->
unset_context(W10N_FLATTEN_KEY);
325 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.
Abstract 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()
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.