40#include <libdap/DDS.h>
41#include <libdap/Structure.h>
42#include <libdap/Constructor.h>
43#include <libdap/Array.h>
44#include <libdap/Grid.h>
45#include <libdap/Sequence.h>
46#include <libdap/Str.h>
47#include <libdap/Url.h>
51#include <BESInternalError.h>
52#include "RequestServiceTimer.h"
54#include "FoInstanceJsonTransform.h"
55#include "fojson_utils.h"
60#define prolog string("FoInstanceJsonTransform::").append(__func__).append("() - ")
62#define ATTRIBUTE_SEPARATOR "."
63#define JSON_ORIGINAL_NAME "json_original_name"
65#define FoInstanceJsonTransform_debug_key "fojson"
66const int int_64_precision = 15;
72unsigned int FoInstanceJsonTransform::json_simple_type_array_worker(std::ostream *strm,
73 const std::vector<T> &values,
unsigned int indx,
const std::vector<unsigned int> &shape,
unsigned int currentDim)
77 unsigned int currentDimSize = shape.at(currentDim);
79 for (
unsigned int i = 0; i < currentDimSize; i++) {
80 if (currentDim < shape.size() - 1) {
81 BESDEBUG(FoInstanceJsonTransform_debug_key,
82 "json_simple_type_array_worker() - Recursing! indx: " << indx <<
" currentDim: " << currentDim <<
" currentDimSize: " << currentDimSize << endl);
84 indx = json_simple_type_array_worker<T>(strm, values, indx, shape, currentDim + 1);
85 if (i + 1 != currentDimSize) *strm <<
", ";
89 *strm << values[indx++];
106template<
typename T>
void FoInstanceJsonTransform::json_simple_type_array(std::ostream *strm, libdap::Array *a,
107 std::string indent,
bool sendData)
109 std::string name = a->name();
110 *strm << indent <<
"\"" << fojson::escape_for_json(name) +
"\": ";
113 std::vector<unsigned int> shape(a->dimensions(
true));
114 long length = fojson::computeConstrainedShape(a, &shape);
116 vector<T> src(length);
117 a->value(src.data());
119 unsigned int indx = 0;
121 if (
typeid(T) ==
typeid(libdap::dods_float64)) {
122 streamsize prec = strm->precision(int_64_precision);
124 indx = json_simple_type_array_worker(strm, src, 0, shape, 0);
125 strm->precision(prec);
128 strm->precision(prec);
133 indx = json_simple_type_array_worker(strm, src, 0, shape, 0);
137 assert(length == indx);
140 BESDEBUG(FoInstanceJsonTransform_debug_key,
141 "json_simple_type_array() - indx NOT equal to content length! indx: " << indx <<
" length: " << length << endl);
145 *strm <<
"{" << endl;
147 transform(strm, a->get_attr_table(), indent + _indent_increment);
148 *strm << endl << indent <<
"}";
161void FoInstanceJsonTransform::json_string_array(std::ostream *strm, libdap::Array *a, std::string indent,
bool sendData)
163 std::string name = a->name();
164 *strm << indent <<
"\"" << fojson::escape_for_json(name) +
"\": ";
167 std::vector<unsigned int> shape(a->dimensions(
true));
168 long length = fojson::computeConstrainedShape(a, &shape);
171 std::vector<std::string> sourceValues;
172 a->value(sourceValues);
174 unsigned int indx = json_simple_type_array_worker(strm, sourceValues, 0, shape, 0);
178 BESDEBUG(FoInstanceJsonTransform_debug_key,
179 "json_string_array() - indx NOT equal to content length! indx: " << indx <<
" length: " << length << endl);
182 *strm <<
"{" << endl;
184 transform(strm, a->get_attr_table(), indent + _indent_increment);
185 *strm << endl << indent <<
"}";
205 const string &localfile) :
206 _dds(dds), _localfile(localfile), _indent_increment(
" "), _ostrm(0)
210 if (!_dds)
throw BESInternalError(
"File out JSON, null DDS passed to constructor", __FILE__, __LINE__);
211 if (_localfile.empty())
212 throw BESInternalError(
"File out JSON, empty local file name passed to constructor", __FILE__, __LINE__);
228 if (!_dds)
throw BESInternalError(
"File out JSON, null DDS passed to constructor", __FILE__, __LINE__);
242 strm << BESIndent::LMarg <<
"FoInstanceJsonTransform::dump - (" << (
void *)
this <<
")" << endl;
247 BESIndent::UnIndent();
262void FoInstanceJsonTransform::transform(ostream &ostrm,
bool sendData)
264 transform(&ostrm, _dds,
"", sendData);
277void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::DDS *dds,
string indent,
bool sendData)
279 bool sentSomething =
false;
289 *strm <<
"{" << endl;
292 std::string name = dds->get_dataset_name();
293 *strm << indent + _indent_increment <<
"\"name\": \"" << fojson::escape_for_json(name) <<
"\"," << endl;
299 transform(strm, dds->get_attr_table(), indent);
300 if (dds->get_attr_table().get_size() > 0) *strm <<
",";
305 if (dds->num_var() > 0) {
307 libdap::DDS::Vars_iter vi = dds->var_begin();
308 libdap::DDS::Vars_iter ve = dds->var_end();
309 for (; vi != ve; vi++) {
310 if ((*vi)->send_p()) {
312 libdap::BaseType *v = *vi;
313 BESDEBUG(FoInstanceJsonTransform_debug_key,
"Processing top level variable: " << v->name() << endl);
321 transform(strm, v, indent + _indent_increment, sendData);
323 sentSomething =
true;
329 *strm << endl <<
"}" << endl;
341void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::BaseType *bt,
string indent,
bool sendData)
343 switch (bt->type()) {
345 case libdap::dods_byte_c:
346 case libdap::dods_int16_c:
347 case libdap::dods_uint16_c:
348 case libdap::dods_int32_c:
349 case libdap::dods_uint32_c:
350 case libdap::dods_float32_c:
351 case libdap::dods_float64_c:
352 case libdap::dods_str_c:
353 case libdap::dods_url_c:
354 transformAtomic(strm, bt, indent, sendData);
357 case libdap::dods_structure_c:
358 transform(strm, (libdap::Structure *) bt, indent, sendData);
361 case libdap::dods_grid_c:
362 transform(strm, (libdap::Grid *) bt, indent, sendData);
365 case libdap::dods_sequence_c:
366 transform(strm, (libdap::Sequence *) bt, indent, sendData);
369 case libdap::dods_array_c:
370 transform(strm, (libdap::Array *) bt, indent, sendData);
373 case libdap::dods_int8_c:
374 case libdap::dods_uint8_c:
375 case libdap::dods_int64_c:
376 case libdap::dods_uint64_c:
379 case libdap::dods_enum_c:
380 case libdap::dods_group_c: {
381 string s = (string)
"File out JSON, " +
"DAP4 types not yet supported.";
382 throw BESInternalError(s, __FILE__, __LINE__);
387 string s = (string)
"File out JSON, " +
"Unrecognized type.";
388 throw BESInternalError(s, __FILE__, __LINE__);
406void FoInstanceJsonTransform::transformAtomic(std::ostream *strm, libdap::BaseType *b,
string indent,
bool sendData)
408 std::string name = b->name();
409 *strm << indent <<
"\"" << fojson::escape_for_json(name) <<
"\": ";
413 if (b->type() == libdap::dods_str_c || b->type() == libdap::dods_url_c) {
414 libdap::Str *strVar = (libdap::Str *) b;
415 std::string tmpString = strVar->value();
416 *strm <<
"\"" << fojson::escape_for_json(tmpString) <<
"\"";
419 b->print_val(*strm,
"",
false);
424 transform(strm, b->get_attr_table(), indent);
437void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::Structure *b,
string indent,
bool sendData)
441 std::string name = b->name();
442 *strm << indent <<
"\"" << fojson::escape_for_json(name) <<
"\": {" << endl;
445 if (b->width(
true) > 0) {
447 libdap::Structure::Vars_iter vi = b->var_begin();
448 libdap::Structure::Vars_iter ve = b->var_end();
449 for (; vi != ve; vi++) {
452 if ((*vi)->send_p()) {
453 libdap::BaseType *v = *vi;
454 BESDEBUG(FoInstanceJsonTransform_debug_key,
455 "FoInstanceJsonTransform::transform() - Processing structure variable: " << v->name() << endl);
456 transform(strm, v, indent + _indent_increment, sendData);
457 if ((vi + 1) != ve) {
464 *strm << indent <<
"}";
476void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::Grid *g,
string indent,
bool sendData)
480 std::string name = g->name();
481 *strm << indent <<
"\"" << fojson::escape_for_json(name) <<
"\": {" << endl;
483 BESDEBUG(FoInstanceJsonTransform_debug_key,
484 "FoInstanceJsonTransform::transform() - Processing Grid data Array: " << g->get_array()->name() << endl);
487 transform(strm, g->get_array(), indent + _indent_increment, sendData);
488 *strm <<
"," << endl;
491 for (libdap::Grid::Map_iter mapi = g->map_begin(); mapi < g->map_end(); mapi++) {
492 BESDEBUG(FoInstanceJsonTransform_debug_key,
493 "FoInstanceJsonTransform::transform() - Processing Grid Map Array: " << (*mapi)->name() << endl);
494 if (mapi != g->map_begin()) {
495 *strm <<
"," << endl;
497 transform(strm, *mapi, indent + _indent_increment, sendData);
500 *strm << endl << indent <<
"}";
513void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::Sequence *s,
string indent,
bool sendData)
517 std::string name = s->name();
518 *strm << indent <<
"\"" << fojson::escape_for_json(name) <<
"\": {" << endl;
520 string child_indent = indent + _indent_increment;
524 *strm << indent <<
"\"table\": {" << endl;
526 string child_indent = indent + _indent_increment;
528 *strm << child_indent <<
"\"name\": \"" << s->name() <<
"\"," << endl;
532 *strm << child_indent <<
"\"columnNames\": [";
533 for (libdap::Constructor::Vars_iter v = s->var_begin(); v < s->var_end(); v++) {
534 if (v != s->var_begin()) *strm <<
",";
535 std::string name = (*v)->name();
536 *strm <<
"\"" << fojson::escape_for_json(name) <<
"\"";
538 *strm <<
"]," << endl;
540 *strm << child_indent <<
"\"columnTypes\": [";
541 for (libdap::Constructor::Vars_iter v = s->var_begin(); v < s->var_end(); v++) {
542 if (v != s->var_begin()) *strm <<
",";
543 *strm <<
"\"" << (*v)->type_name() <<
"\"";
545 *strm <<
"]," << endl;
548 *strm << child_indent <<
"\"rows\": [";
550 if (!first) *strm <<
", ";
551 *strm << endl << child_indent <<
"[";
552 for (libdap::Constructor::Vars_iter v = s->var_begin(); v < s->var_end(); v++) {
553 if (v != s->var_begin()) *strm << child_indent <<
",";
554 transform(strm, (*v), child_indent + _indent_increment, sendData);
556 *strm << child_indent <<
"]";
559 *strm << endl << child_indent <<
"]" << endl;
562 *strm << indent <<
"}" << endl;
574void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::Array *a,
string indent,
bool sendData)
577 BESDEBUG(FoInstanceJsonTransform_debug_key,
578 "FoInstanceJsonTransform::transform() - Processing Array. " <<
" a->type(): " << a->type() <<
" a->var()->type(): " << a->var()->type() << endl);
580 switch (a->var()->type()) {
582 case libdap::dods_byte_c:
583 json_simple_type_array<libdap::dods_byte>(strm, a, indent, sendData);
586 case libdap::dods_int16_c:
587 json_simple_type_array<libdap::dods_int16>(strm, a, indent, sendData);
590 case libdap::dods_uint16_c:
591 json_simple_type_array<libdap::dods_uint16>(strm, a, indent, sendData);
594 case libdap::dods_int32_c:
595 json_simple_type_array<libdap::dods_int32>(strm, a, indent, sendData);
598 case libdap::dods_uint32_c:
599 json_simple_type_array<libdap::dods_uint32>(strm, a, indent, sendData);
602 case libdap::dods_float32_c:
603 json_simple_type_array<libdap::dods_float32>(strm, a, indent, sendData);
606 case libdap::dods_float64_c:
607 json_simple_type_array<libdap::dods_float64>(strm, a, indent, sendData);
610 case libdap::dods_str_c: {
611 json_string_array(strm, a, indent, sendData);
615 string s = (string)
"File out JSON, " +
"Arrays of Strings are not yet a supported return type.";
616 throw BESInternalError(s, __FILE__, __LINE__);
622 case libdap::dods_url_c: {
623 json_string_array(strm, a, indent, sendData);
627 string s = (string)
"File out JSON, " +
"Arrays of URLs are not yet a supported return type.";
628 throw BESInternalError(s, __FILE__, __LINE__);
634 case libdap::dods_structure_c: {
635 string s = (string)
"File out JSON, " +
"Arrays of Structure objects not a supported return type.";
636 throw BESInternalError(s, __FILE__, __LINE__);
639 case libdap::dods_grid_c: {
640 string s = (string)
"File out JSON, " +
"Arrays of Grid objects not a supported return type.";
641 throw BESInternalError(s, __FILE__, __LINE__);
645 case libdap::dods_sequence_c: {
646 string s = (string)
"File out JSON, " +
"Arrays of Sequence objects not a supported return type.";
647 throw BESInternalError(s, __FILE__, __LINE__);
651 case libdap::dods_array_c: {
652 string s = (string)
"File out JSON, " +
"Arrays of Array objects not a supported return type.";
653 throw BESInternalError(s, __FILE__, __LINE__);
656 case libdap::dods_int8_c:
657 case libdap::dods_uint8_c:
658 case libdap::dods_int64_c:
659 case libdap::dods_uint64_c:
661 case libdap::dods_enum_c:
662 case libdap::dods_group_c: {
663 string s = (string)
"File out JSON, " +
"DAP4 types not yet supported.";
664 throw BESInternalError(s, __FILE__, __LINE__);
669 string s = (string)
"File out JSON, " +
"Unrecognized type.";
670 throw BESInternalError(s, __FILE__, __LINE__);
690void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::AttrTable &attr_table,
string indent)
697 string child_indent = indent + _indent_increment;
700 if (attr_table.get_size() != 0) {
702 libdap::AttrTable::Attr_iter begin = attr_table.attr_begin();
703 libdap::AttrTable::Attr_iter end = attr_table.attr_end();
706 for (libdap::AttrTable::Attr_iter at_iter = begin; at_iter != end; at_iter++) {
708 switch (attr_table.get_attr_type(at_iter)) {
710 case libdap::Attr_container:
712 libdap::AttrTable *atbl = attr_table.get_attr_table(at_iter);
714 if (at_iter != begin) *strm <<
"," << endl;
717 std::string name = atbl->get_name();
718 *strm << child_indent <<
"\"" << fojson::escape_for_json(name) <<
"\": {" << endl;
721 transform(strm, *atbl, child_indent + _indent_increment);
724 *strm << endl << child_indent <<
"}";
731 if (at_iter != begin) *strm <<
"," << endl;
734 std::string name = attr_table.get_name(at_iter);
735 *strm << child_indent <<
"\"" << fojson::escape_for_json(name) <<
"\": ";
740 std::vector<std::string> *values = attr_table.get_attr_vector(at_iter);
741 for (std::vector<std::string>::size_type i = 0; i < values->size(); i++) {
742 if (i > 0) *strm <<
",";
743 if (attr_table.get_attr_type(at_iter) == libdap::Attr_string
744 || attr_table.get_attr_type(at_iter) == libdap::Attr_url) {
747 string value = (*values)[i];
748 *strm << fojson::escape_for_json(value);
752 *strm << (*values)[i];
Structure storing information used by the BES to handle the request.
exception thrown if internal error encountered
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...