40using std::ostringstream;
41using std::istringstream;
44#define prolog string("FoDapJsonTransform::").append(__func__).append("() - ")
46#include <libdap/DDS.h>
47#include <libdap/Structure.h>
48#include <libdap/Constructor.h>
49#include <libdap/Array.h>
50#include <libdap/Grid.h>
51#include <libdap/Sequence.h>
52#include <libdap/Float64.h>
53#include <libdap/Str.h>
54#include <libdap/Url.h>
57#include <BESInternalError.h>
60#include "RequestServiceTimer.h"
62#include <DapFunctionUtils.h>
64#include "FoDapJsonTransform.h"
65#include "fojson_utils.h"
67#define FoDapJsonTransform_debug_key "fojson"
69const int int_64_precision = 15;
76unsigned int FoDapJsonTransform::json_simple_type_array_worker(
ostream *strm, T *values,
unsigned int indx,
81 unsigned int currentDimSize = (*shape)[currentDim];
83 for (
unsigned int i = 0; i < currentDimSize; i++) {
84 if (currentDim < shape->size() - 1) {
87 indx = json_simple_type_array_worker<T>(strm, values, indx, shape, currentDim + 1);
88 if (i + 1 != currentDimSize) *strm <<
", ";
92 if (
typeid(T) ==
typeid(std::string)) {
94 string val =
reinterpret_cast<string*
>(values)[indx++];
95 *strm <<
"\"" << fojson::escape_for_json(val) <<
"\"";
98 *strm << values[indx++];
112void FoDapJsonTransform::json_simple_type_array(
ostream *strm, libdap::Array *a,
string indent,
bool sendData)
114 *strm << indent <<
"{" << endl;\
115 string childindent = indent + _indent_increment;
117 writeLeafMetadata(strm, a, childindent);
119 int numDim = a->dimensions(
true);
121 long length = fojson::computeConstrainedShape(a, &shape);
123 *strm << childindent <<
"\"shape\": [";
125 for (std::vector<unsigned int>::size_type i = 0; i < shape.size(); i++) {
126 if (i > 0) *strm <<
",";
132 *strm <<
"," << endl;
135 *strm << childindent <<
"\"data\": ";
136 unsigned int indx = 0;
138 a->value(src.data());
145 if (
typeid(T) ==
typeid(libdap::dods_float64)) {
146 streamsize prec = strm->precision(int_64_precision);
148 indx = json_simple_type_array_worker(strm, src.data(), 0, &shape, 0);
149 strm->precision(prec);
152 strm->precision(prec);
157 indx = json_simple_type_array_worker(strm, src.data(), 0, &shape, 0);
160 assert(length == indx);
163 *strm << endl << indent <<
"}";
175void FoDapJsonTransform::json_string_array(std::ostream *strm, libdap::Array *a,
string indent,
bool sendData)
177 *strm << indent <<
"{" << endl;\
178 string childindent = indent + _indent_increment;
180 writeLeafMetadata(strm, a, childindent);
182 int numDim = a->dimensions(
true);
184 long length = fojson::computeConstrainedShape(a, &shape);
186 *strm << childindent <<
"\"shape\": [";
188 for (std::vector<unsigned int>::size_type i = 0; i < shape.size(); i++) {
189 if (i > 0) *strm <<
",";
195 *strm <<
"," << endl;
198 *strm << childindent <<
"\"data\": ";
202 vector<std::string> sourceValues;
203 a->value(sourceValues);
204 indx = json_simple_type_array_worker(strm, (std::string *) (sourceValues.data()), 0, &shape, 0);
207 BESDEBUG(FoDapJsonTransform_debug_key,
208 "json_string_array() - indx NOT equal to content length! indx: " << indx <<
" length: " << length << endl);
212 *strm << endl << indent <<
"}";
218void FoDapJsonTransform::writeDatasetMetadata(
ostream *strm, libdap::DDS *dds,
string indent)
222 *strm << indent <<
"\"name\": \"" << dds->get_dataset_name() <<
"\"," << endl;
225 transform(strm, dds->get_attr_table(), indent);
226 *strm <<
"," << endl;
234void FoDapJsonTransform::writeNodeMetadata(
ostream *strm, libdap::BaseType *bt,
string indent)
238 *strm << indent <<
"\"name\": \"" << bt->name() <<
"\"," << endl;
241 transform(strm, bt->get_attr_table(), indent);
242 *strm <<
"," << endl;
250void FoDapJsonTransform::writeLeafMetadata(
ostream *strm, libdap::BaseType *bt,
string indent)
254 *strm << indent <<
"\"name\": \"" << bt->name() <<
"\"," << endl;
257 if (bt->type() == libdap::dods_array_c) {
258 libdap::Array *a = (libdap::Array *) bt;
259 *strm << indent <<
"\"type\": \"" << a->var()->type_name() <<
"\"," << endl;
262 *strm << indent <<
"\"type\": \"" << bt->type_name() <<
"\"," << endl;
266 transform(strm, bt->get_attr_table(), indent);
267 *strm <<
"," << endl;
289 if (!_dds)
throw BESInternalError(
"File out JSON, null DDS passed to constructor", __FILE__, __LINE__);
303 strm << BESIndent::LMarg <<
"FoDapJsonTransform::dump - (" << (
void *)
this <<
")" << endl;
308 BESIndent::UnIndent();
325void FoDapJsonTransform::transform(
ostream &ostrm,
bool sendData)
327 transform(&ostrm, _dds,
"", sendData);
334void FoDapJsonTransform::transform(
ostream *strm, libdap::Constructor *cnstrctr,
string indent,
bool sendData)
336 vector<libdap::BaseType *> leaves;
337 vector<libdap::BaseType *> nodes;
340 libdap::DDS::Vars_iter vi = cnstrctr->var_begin();
341 libdap::DDS::Vars_iter ve = cnstrctr->var_end();
342 for (; vi != ve; vi++) {
343 if ((*vi)->send_p()) {
344 libdap::BaseType *v = *vi;
346 libdap::Type type = v->type();
347 if (type == libdap::dods_array_c) {
348 type = v->var()->type();
350 if (v->is_constructor_type() || (v->is_vector_type() && v->var()->is_constructor_type())) {
367 *strm << indent <<
"{" << endl;
368 string child_indent = indent + _indent_increment;
371 writeNodeMetadata(strm, cnstrctr, child_indent);
373 transform_node_worker(strm, leaves, nodes, child_indent, sendData);
375 *strm << indent <<
"}" << endl;
387 *strm << indent <<
"\"leaves\": [";
388 if (leaves.size() > 0) *strm << endl;
389 for (std::vector<libdap::BaseType *>::size_type l = 0; l < leaves.size(); l++) {
390 libdap::BaseType *v = leaves[l];
391 BESDEBUG(FoDapJsonTransform_debug_key,
"Processing LEAF: " << v->name() << endl);
399 transform(strm, v, indent + _indent_increment, sendData);
401 if (leaves.size() > 0) *strm << endl << indent;
402 *strm <<
"]," << endl;
405 *strm << indent <<
"\"nodes\": [";
406 if (nodes.size() > 0) *strm << endl;
407 for (std::vector<libdap::BaseType *>::size_type n = 0; n < nodes.size(); n++) {
408 libdap::BaseType *v = nodes[n];
412 transform(strm, v, indent + _indent_increment, sendData);
414 if (nodes.size() > 0) *strm << endl << indent;
416 *strm <<
"]" << endl;
423void FoDapJsonTransform::transform(
ostream *strm, libdap::DDS *dds,
string indent,
bool sendData)
428 vector<libdap::BaseType *> leaves;
429 vector<libdap::BaseType *> nodes;
431 libdap::DDS::Vars_iter vi = dds->var_begin();
432 libdap::DDS::Vars_iter ve = dds->var_end();
433 for (; vi != ve; vi++) {
434 if ((*vi)->send_p()) {
435 libdap::BaseType *v = *vi;
436 libdap::Type type = v->type();
437 if (type == libdap::dods_array_c) {
438 type = v->var()->type();
440 if (v->is_constructor_type() || (v->is_vector_type() && v->var()->is_constructor_type())) {
450 *strm << indent <<
"{" << endl;
451 string child_indent = indent + _indent_increment;
454 writeDatasetMetadata(strm, dds, child_indent);
456 transform_node_worker(strm, leaves, nodes, child_indent, sendData);
458 *strm << indent <<
"}" << endl;
465void FoDapJsonTransform::transform(
ostream *strm, libdap::BaseType *bt,
string indent,
bool sendData)
467 switch (bt->type()) {
469 case libdap::dods_byte_c:
470 case libdap::dods_int16_c:
471 case libdap::dods_uint16_c:
472 case libdap::dods_int32_c:
473 case libdap::dods_uint32_c:
474 case libdap::dods_float32_c:
475 case libdap::dods_float64_c:
476 case libdap::dods_str_c:
477 case libdap::dods_url_c:
478 transformAtomic(strm, bt, indent, sendData);
481 case libdap::dods_structure_c:
482 transform(strm, (libdap::Structure *) bt, indent, sendData);
485 case libdap::dods_grid_c:
486 transform(strm, (libdap::Grid *) bt, indent, sendData);
489 case libdap::dods_sequence_c:
490 transform(strm, (libdap::Sequence *) bt, indent, sendData);
493 case libdap::dods_array_c:
494 transform(strm, (libdap::Array *) bt, indent, sendData);
497 case libdap::dods_int8_c:
498 case libdap::dods_uint8_c:
499 case libdap::dods_int64_c:
500 case libdap::dods_uint64_c:
502 case libdap::dods_enum_c:
503 case libdap::dods_group_c: {
504 string s = (string)
"File out JSON, " +
"DAP4 types not yet supported.";
505 throw BESInternalError(s, __FILE__, __LINE__);
510 string s = (string)
"File out JSON, " +
"Unrecognized type.";
511 throw BESInternalError(s, __FILE__, __LINE__);
522void FoDapJsonTransform::transformAtomic(
ostream *strm, libdap::BaseType *b,
string indent,
bool sendData)
525 *strm << indent <<
"{" << endl;
527 string childindent = indent + _indent_increment;
529 writeLeafMetadata(strm, b, childindent);
531 *strm << childindent <<
"\"shape\": [1]," << endl;
535 *strm << childindent <<
"\"data\": [";
537 if (b->type() == libdap::dods_str_c || b->type() == libdap::dods_url_c) {
538 libdap::Str *strVar = (libdap::Str *) b;
539 std::string tmpString = strVar->value();
540 *strm <<
"\"" << fojson::escape_for_json(tmpString) <<
"\"";
543 b->print_val(*strm,
"",
false);
555void FoDapJsonTransform::transform(
ostream *strm, libdap::Array *a,
string indent,
bool sendData)
558 BESDEBUG(FoDapJsonTransform_debug_key,
559 "FoJsonTransform::transform() - Processing Array. " <<
" a->type(): " << a->type() <<
" a->var()->type(): " << a->var()->type() << endl);
561 switch (a->var()->type()) {
563 case libdap::dods_byte_c:
564 json_simple_type_array<libdap::dods_byte>(strm, a, indent, sendData);
567 case libdap::dods_int16_c:
568 json_simple_type_array<libdap::dods_int16>(strm, a, indent, sendData);
571 case libdap::dods_uint16_c:
572 json_simple_type_array<libdap::dods_uint16>(strm, a, indent, sendData);
575 case libdap::dods_int32_c:
576 json_simple_type_array<libdap::dods_int32>(strm, a, indent, sendData);
579 case libdap::dods_uint32_c:
580 json_simple_type_array<libdap::dods_uint32>(strm, a, indent, sendData);
583 case libdap::dods_float32_c:
584 json_simple_type_array<libdap::dods_float32>(strm, a, indent, sendData);
587 case libdap::dods_float64_c:
588 json_simple_type_array<libdap::dods_float64>(strm, a, indent, sendData);
591 case libdap::dods_str_c: {
592 json_string_array(strm, a, indent, sendData);
596 case libdap::dods_url_c: {
597 json_string_array(strm, a, indent, sendData);
601 case libdap::dods_structure_c: {
602 throw BESInternalError(
"File out JSON, Arrays of Structure objects not a supported return type.", __FILE__, __LINE__);
605 case libdap::dods_grid_c: {
606 throw BESInternalError(
"File out JSON, Arrays of Grid objects not a supported return type.", __FILE__, __LINE__);
610 case libdap::dods_sequence_c: {
611 throw BESInternalError(
"File out JSON, Arrays of Sequence objects not a supported return type.", __FILE__, __LINE__);
615 case libdap::dods_array_c: {
616 throw BESInternalError(
"File out JSON, Arrays of Array objects not a supported return type.", __FILE__, __LINE__);
619 case libdap::dods_int8_c:
620 case libdap::dods_uint8_c:
621 case libdap::dods_int64_c:
622 case libdap::dods_uint64_c:
624 case libdap::dods_enum_c:
625 case libdap::dods_group_c: {
626 throw BESInternalError(
"File out JSON, DAP4 types not yet supported.", __FILE__, __LINE__);
631 throw BESInternalError(
"File out JSON, Unrecognized type.", __FILE__, __LINE__);
643void FoDapJsonTransform::transform(
ostream *strm, libdap::AttrTable &attr_table,
string indent)
646 string child_indent = indent + _indent_increment;
649 *strm << indent <<
"\"attributes\": [";
655 if (attr_table.get_size() != 0) {
657 libdap::AttrTable::Attr_iter begin = attr_table.attr_begin();
658 libdap::AttrTable::Attr_iter end = attr_table.attr_end();
660 for (libdap::AttrTable::Attr_iter at_iter = begin; at_iter != end; at_iter++) {
662 switch (attr_table.get_attr_type(at_iter)) {
663 case libdap::Attr_container: {
664 libdap::AttrTable *atbl = attr_table.get_attr_table(at_iter);
667 if (at_iter != begin) *strm <<
"," << endl;
670 *strm << child_indent <<
"{" << endl;
673 if (atbl->get_name().size() > 0)
674 *strm << child_indent + _indent_increment <<
"\"name\": \"" << atbl->get_name() <<
"\"," << endl;
677 transform(strm, *atbl, child_indent + _indent_increment);
678 *strm << endl << child_indent <<
"}";
685 if (at_iter != begin) *strm <<
"," << endl;
688 *strm << child_indent <<
"{\"name\": \"" << attr_table.get_name(at_iter) <<
"\", ";
691 *strm <<
"\"value\": [";
692 vector<std::string> *values = attr_table.get_attr_vector(at_iter);
694 for (std::vector<std::string>::size_type i = 0; i < values->size(); i++) {
697 if (i > 0) *strm <<
",";
700 if (attr_table.get_attr_type(at_iter) == libdap::Attr_string
701 || attr_table.get_attr_type(at_iter) == libdap::Attr_url) {
704 *strm << fojson::escape_for_json((*values)[i]);
709 *strm << (*values)[i];
721 *strm << endl << indent;
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...