41 #include <Structure.h>
42 #include <Constructor.h>
50 #include <BESInternalError.h>
52 #include "FoInstanceJsonTransform.h"
53 #include "fojson_utils.h"
57 #define ATTRIBUTE_SEPARATOR "."
58 #define JSON_ORIGINAL_NAME "json_original_name"
60 #define FoInstanceJsonTransform_debug_key "fojson"
61 const int int_64_precision = 15;
67 unsigned int FoInstanceJsonTransform::json_simple_type_array_worker(std::ostream *strm,
68 const std::vector<T> &values,
unsigned int indx,
const std::vector<unsigned int> &shape,
unsigned int currentDim)
72 unsigned int currentDimSize = shape.at(currentDim);
74 for (
unsigned int i = 0; i < currentDimSize; i++) {
75 if (currentDim < shape.size() - 1) {
76 BESDEBUG(FoInstanceJsonTransform_debug_key,
77 "json_simple_type_array_worker() - Recursing! indx: " << indx <<
" currentDim: " << currentDim <<
" currentDimSize: " << currentDimSize << endl);
79 indx = json_simple_type_array_worker<T>(strm, values, indx, shape, currentDim + 1);
80 if (i + 1 != currentDimSize) *strm <<
", ";
84 *strm << values[indx++];
101 template<
typename T>
void FoInstanceJsonTransform::json_simple_type_array(std::ostream *strm, libdap::Array *a,
102 std::string indent,
bool sendData)
104 std::string name = a->name();
105 *strm << indent <<
"\"" << fojson::escape_for_json(name) +
"\": ";
108 std::vector<unsigned int> shape(a->dimensions(
true));
109 long length = fojson::computeConstrainedShape(a, &shape);
111 vector<T> src(length);
114 unsigned int indx = 0;
116 if (
typeid(T) ==
typeid(libdap::dods_float64)) {
117 streamsize prec = strm->precision(int_64_precision);
119 indx = json_simple_type_array_worker(strm, src, 0, shape, 0);
120 strm->precision(prec);
123 strm->precision(prec);
128 indx = json_simple_type_array_worker(strm, src, 0, shape, 0);
132 assert(length == indx);
135 BESDEBUG(FoInstanceJsonTransform_debug_key,
136 "json_simple_type_array() - indx NOT equal to content length! indx: " << indx <<
" length: " << length << endl);
140 *strm <<
"{" << endl;
142 transform(strm, a->get_attr_table(), indent + _indent_increment);
143 *strm << endl << indent <<
"}";
156 void FoInstanceJsonTransform::json_string_array(std::ostream *strm, libdap::Array *a, std::string indent,
bool sendData)
158 std::string name = a->name();
159 *strm << indent <<
"\"" << fojson::escape_for_json(name) +
"\": ";
162 std::vector<unsigned int> shape(a->dimensions(
true));
163 long length = fojson::computeConstrainedShape(a, &shape);
166 std::vector<std::string> sourceValues;
167 a->value(sourceValues);
169 unsigned int indx = json_simple_type_array_worker(strm, sourceValues, 0, shape, 0);
173 BESDEBUG(FoInstanceJsonTransform_debug_key,
174 "json_string_array() - indx NOT equal to content length! indx: " << indx <<
" length: " << length << endl);
177 *strm <<
"{" << endl;
179 transform(strm, a->get_attr_table(), indent + _indent_increment);
180 *strm << endl << indent <<
"}";
200 const string &localfile) :
201 _dds(dds), _localfile(localfile), _indent_increment(
" "), _ostrm(0)
205 if (!_dds)
throw BESInternalError(
"File out JSON, null DDS passed to constructor", __FILE__, __LINE__);
206 if (_localfile.empty())
207 throw BESInternalError(
"File out JSON, empty local file name passed to constructor", __FILE__, __LINE__);
223 if (!_dds)
throw BESInternalError(
"File out JSON, null DDS passed to constructor", __FILE__, __LINE__);
237 strm << BESIndent::LMarg <<
"FoInstanceJsonTransform::dump - (" << (
void *)
this <<
")" << endl;
242 BESIndent::UnIndent();
257 void FoInstanceJsonTransform::transform(ostream &ostrm,
bool sendData)
259 transform(&ostrm, _dds,
"", sendData);
272 void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::DDS *dds,
string indent,
bool sendData)
274 bool sentSomething =
false;
277 *strm <<
"{" << endl;
280 std::string name = dds->get_dataset_name();
281 *strm << indent + _indent_increment <<
"\"name\": \"" << fojson::escape_for_json(name) <<
"\"," << endl;
287 transform(strm, dds->get_attr_table(), indent);
288 if (dds->get_attr_table().get_size() > 0) *strm <<
",";
293 if (dds->num_var() > 0) {
295 libdap::DDS::Vars_iter vi = dds->var_begin();
296 libdap::DDS::Vars_iter ve = dds->var_end();
297 for (; vi != ve; vi++) {
298 if ((*vi)->send_p()) {
300 libdap::BaseType *v = *vi;
301 BESDEBUG(FoInstanceJsonTransform_debug_key,
"Processing top level variable: " << v->name() << endl);
307 transform(strm, v, indent + _indent_increment, sendData);
309 sentSomething =
true;
315 *strm << endl <<
"}" << endl;
327 void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::BaseType *bt,
string indent,
bool sendData)
329 switch (bt->type()) {
331 case libdap::dods_byte_c:
332 case libdap::dods_int16_c:
333 case libdap::dods_uint16_c:
334 case libdap::dods_int32_c:
335 case libdap::dods_uint32_c:
336 case libdap::dods_float32_c:
337 case libdap::dods_float64_c:
338 case libdap::dods_str_c:
339 case libdap::dods_url_c:
340 transformAtomic(strm, bt, indent, sendData);
343 case libdap::dods_structure_c:
344 transform(strm, (libdap::Structure *) bt, indent, sendData);
347 case libdap::dods_grid_c:
348 transform(strm, (libdap::Grid *) bt, indent, sendData);
351 case libdap::dods_sequence_c:
352 transform(strm, (libdap::Sequence *) bt, indent, sendData);
355 case libdap::dods_array_c:
356 transform(strm, (libdap::Array *) bt, indent, sendData);
359 case libdap::dods_int8_c:
360 case libdap::dods_uint8_c:
361 case libdap::dods_int64_c:
362 case libdap::dods_uint64_c:
365 case libdap::dods_enum_c:
366 case libdap::dods_group_c: {
367 string s = (string)
"File out JSON, " +
"DAP4 types not yet supported.";
373 string s = (string)
"File out JSON, " +
"Unrecognized type.";
392 void FoInstanceJsonTransform::transformAtomic(std::ostream *strm, libdap::BaseType *b,
string indent,
bool sendData)
394 std::string name = b->name();
395 *strm << indent <<
"\"" << fojson::escape_for_json(name) <<
"\": ";
399 if (b->type() == libdap::dods_str_c || b->type() == libdap::dods_url_c) {
400 libdap::Str *strVar = (libdap::Str *) b;
401 std::string tmpString = strVar->value();
402 *strm <<
"\"" << fojson::escape_for_json(tmpString) <<
"\"";
405 b->print_val(*strm,
"",
false);
410 transform(strm, b->get_attr_table(), indent);
423 void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::Structure *b,
string indent,
bool sendData)
427 std::string name = b->name();
428 *strm << indent <<
"\"" << fojson::escape_for_json(name) <<
"\": {" << endl;
431 if (b->width(
true) > 0) {
433 libdap::Structure::Vars_iter vi = b->var_begin();
434 libdap::Structure::Vars_iter ve = b->var_end();
435 for (; vi != ve; vi++) {
438 if ((*vi)->send_p()) {
439 libdap::BaseType *v = *vi;
440 BESDEBUG(FoInstanceJsonTransform_debug_key,
441 "FoInstanceJsonTransform::transform() - Processing structure variable: " << v->name() << endl);
442 transform(strm, v, indent + _indent_increment, sendData);
443 if ((vi + 1) != ve) {
450 *strm << indent <<
"}";
462 void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::Grid *g,
string indent,
bool sendData)
466 std::string name = g->name();
467 *strm << indent <<
"\"" << fojson::escape_for_json(name) <<
"\": {" << endl;
469 BESDEBUG(FoInstanceJsonTransform_debug_key,
470 "FoInstanceJsonTransform::transform() - Processing Grid data Array: " << g->get_array()->name() << endl);
473 transform(strm, g->get_array(), indent + _indent_increment, sendData);
474 *strm <<
"," << endl;
477 for (libdap::Grid::Map_iter mapi = g->map_begin(); mapi < g->map_end(); mapi++) {
478 BESDEBUG(FoInstanceJsonTransform_debug_key,
479 "FoInstanceJsonTransform::transform() - Processing Grid Map Array: " << (*mapi)->name() << endl);
480 if (mapi != g->map_begin()) {
481 *strm <<
"," << endl;
483 transform(strm, *mapi, indent + _indent_increment, sendData);
486 *strm << endl << indent <<
"}";
499 void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::Sequence *s,
string indent,
bool sendData)
503 std::string name = s->name();
504 *strm << indent <<
"\"" << fojson::escape_for_json(name) <<
"\": {" << endl;
506 string child_indent = indent + _indent_increment;
510 *strm << indent <<
"\"table\": {" << endl;
512 string child_indent = indent + _indent_increment;
514 *strm << child_indent <<
"\"name\": \"" << s->name() <<
"\"," << endl;
518 *strm << child_indent <<
"\"columnNames\": [";
519 for (libdap::Constructor::Vars_iter v = s->var_begin(); v < s->var_end(); v++) {
520 if (v != s->var_begin()) *strm <<
",";
521 std::string name = (*v)->name();
522 *strm <<
"\"" << fojson::escape_for_json(name) <<
"\"";
524 *strm <<
"]," << endl;
526 *strm << child_indent <<
"\"columnTypes\": [";
527 for (libdap::Constructor::Vars_iter v = s->var_begin(); v < s->var_end(); v++) {
528 if (v != s->var_begin()) *strm <<
",";
529 *strm <<
"\"" << (*v)->type_name() <<
"\"";
531 *strm <<
"]," << endl;
534 *strm << child_indent <<
"\"rows\": [";
536 if (!first) *strm <<
", ";
537 *strm << endl << child_indent <<
"[";
538 for (libdap::Constructor::Vars_iter v = s->var_begin(); v < s->var_end(); v++) {
539 if (v != s->var_begin()) *strm << child_indent <<
",";
540 transform(strm, (*v), child_indent + _indent_increment, sendData);
542 *strm << child_indent <<
"]";
545 *strm << endl << child_indent <<
"]" << endl;
548 *strm << indent <<
"}" << endl;
560 void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::Array *a,
string indent,
bool sendData)
563 BESDEBUG(FoInstanceJsonTransform_debug_key,
564 "FoInstanceJsonTransform::transform() - Processing Array. " <<
" a->type(): " << a->type() <<
" a->var()->type(): " << a->var()->type() << endl);
566 switch (a->var()->type()) {
568 case libdap::dods_byte_c:
569 json_simple_type_array<libdap::dods_byte>(strm, a, indent, sendData);
572 case libdap::dods_int16_c:
573 json_simple_type_array<libdap::dods_int16>(strm, a, indent, sendData);
576 case libdap::dods_uint16_c:
577 json_simple_type_array<libdap::dods_uint16>(strm, a, indent, sendData);
580 case libdap::dods_int32_c:
581 json_simple_type_array<libdap::dods_int32>(strm, a, indent, sendData);
584 case libdap::dods_uint32_c:
585 json_simple_type_array<libdap::dods_uint32>(strm, a, indent, sendData);
588 case libdap::dods_float32_c:
589 json_simple_type_array<libdap::dods_float32>(strm, a, indent, sendData);
592 case libdap::dods_float64_c:
593 json_simple_type_array<libdap::dods_float64>(strm, a, indent, sendData);
596 case libdap::dods_str_c: {
597 json_string_array(strm, a, indent, sendData);
601 string s = (string)
"File out JSON, " +
"Arrays of Strings are not yet a supported return type.";
608 case libdap::dods_url_c: {
609 json_string_array(strm, a, indent, sendData);
613 string s = (string)
"File out JSON, " +
"Arrays of URLs are not yet a supported return type.";
620 case libdap::dods_structure_c: {
621 string s = (string)
"File out JSON, " +
"Arrays of Structure objects not a supported return type.";
625 case libdap::dods_grid_c: {
626 string s = (string)
"File out JSON, " +
"Arrays of Grid objects not a supported return type.";
631 case libdap::dods_sequence_c: {
632 string s = (string)
"File out JSON, " +
"Arrays of Sequence objects not a supported return type.";
637 case libdap::dods_array_c: {
638 string s = (string)
"File out JSON, " +
"Arrays of Array objects not a supported return type.";
642 case libdap::dods_int8_c:
643 case libdap::dods_uint8_c:
644 case libdap::dods_int64_c:
645 case libdap::dods_uint64_c:
647 case libdap::dods_enum_c:
648 case libdap::dods_group_c: {
649 string s = (string)
"File out JSON, " +
"DAP4 types not yet supported.";
655 string s = (string)
"File out JSON, " +
"Unrecognized type.";
676 void FoInstanceJsonTransform::transform(std::ostream *strm, libdap::AttrTable &attr_table,
string indent)
683 string child_indent = indent + _indent_increment;
686 if (attr_table.get_size() != 0) {
688 libdap::AttrTable::Attr_iter begin = attr_table.attr_begin();
689 libdap::AttrTable::Attr_iter end = attr_table.attr_end();
692 for (libdap::AttrTable::Attr_iter at_iter = begin; at_iter != end; at_iter++) {
694 switch (attr_table.get_attr_type(at_iter)) {
696 case libdap::Attr_container:
698 libdap::AttrTable *atbl = attr_table.get_attr_table(at_iter);
700 if (at_iter != begin) *strm <<
"," << endl;
703 std::string name = atbl->get_name();
704 *strm << child_indent <<
"\"" << fojson::escape_for_json(name) <<
"\": {" << endl;
707 transform(strm, *atbl, child_indent + _indent_increment);
710 *strm << endl << child_indent <<
"}";
717 if (at_iter != begin) *strm <<
"," << endl;
720 std::string name = attr_table.get_name(at_iter);
721 *strm << child_indent <<
"\"" << fojson::escape_for_json(name) <<
"\": ";
726 std::vector<std::string> *values = attr_table.get_attr_vector(at_iter);
727 for (std::vector<std::string>::size_type i = 0; i < values->size(); i++) {
728 if (i > 0) *strm <<
",";
729 if (attr_table.get_attr_type(at_iter) == libdap::Attr_string
730 || attr_table.get_attr_type(at_iter) == libdap::Attr_url) {
733 string value = (*values)[i];
734 *strm << fojson::escape_for_json(value);
738 *strm << (*values)[i];