40 using std::ostringstream;
41 using std::istringstream;
44 #include <Structure.h>
45 #include <Constructor.h>
54 #include <BESInternalError.h>
56 #include <DapFunctionUtils.h>
58 #include "FoDapJsonTransform.h"
59 #include "fojson_utils.h"
61 #define FoDapJsonTransform_debug_key "fojson"
63 const int int_64_precision = 15;
70 unsigned int FoDapJsonTransform::json_simple_type_array_worker(ostream *strm, T *values,
unsigned int indx,
71 vector<unsigned int> *shape,
unsigned int currentDim)
75 unsigned int currentDimSize = (*shape)[currentDim];
77 for (
unsigned int i = 0; i < currentDimSize; i++) {
78 if (currentDim < shape->size() - 1) {
81 indx = json_simple_type_array_worker<T>(strm, values, indx, shape, currentDim + 1);
82 if (i + 1 != currentDimSize) *strm <<
", ";
86 if (
typeid(T) ==
typeid(std::string)) {
88 string val =
reinterpret_cast<string*
>(values)[indx++];
89 *strm <<
"\"" << fojson::escape_for_json(val) <<
"\"";
92 *strm << values[indx++];
106 void FoDapJsonTransform::json_simple_type_array(ostream *strm, libdap::Array *a,
string indent,
bool sendData)
108 *strm << indent <<
"{" << endl;\
109 string childindent = indent + _indent_increment;
111 writeLeafMetadata(strm, a, childindent);
113 int numDim = a->dimensions(
true);
114 vector<unsigned int> shape(numDim);
115 long length = fojson::computeConstrainedShape(a, &shape);
117 *strm << childindent <<
"\"shape\": [";
119 for (std::vector<unsigned int>::size_type i = 0; i < shape.size(); i++) {
120 if (i > 0) *strm <<
",";
126 *strm <<
"," << endl;
129 *strm << childindent <<
"\"data\": ";
130 unsigned int indx = 0;
131 vector<T> src(length);
139 if (
typeid(T) ==
typeid(libdap::dods_float64)) {
140 streamsize prec = strm->precision(int_64_precision);
142 indx = json_simple_type_array_worker(strm, &src[0], 0, &shape, 0);
143 strm->precision(prec);
146 strm->precision(prec);
151 indx = json_simple_type_array_worker(strm, &src[0], 0, &shape, 0);
154 assert(length == indx);
157 *strm << endl << indent <<
"}";
169 void FoDapJsonTransform::json_string_array(std::ostream *strm, libdap::Array *a,
string indent,
bool sendData)
171 *strm << indent <<
"{" << endl;\
172 string childindent = indent + _indent_increment;
174 writeLeafMetadata(strm, a, childindent);
176 int numDim = a->dimensions(
true);
177 vector<unsigned int> shape(numDim);
178 long length = fojson::computeConstrainedShape(a, &shape);
180 *strm << childindent <<
"\"shape\": [";
182 for (std::vector<unsigned int>::size_type i = 0; i < shape.size(); i++) {
183 if (i > 0) *strm <<
",";
189 *strm <<
"," << endl;
192 *strm << childindent <<
"\"data\": ";
196 vector<std::string> sourceValues;
197 a->value(sourceValues);
198 indx = json_simple_type_array_worker(strm, (std::string *) (&sourceValues[0]), 0, &shape, 0);
201 BESDEBUG(FoDapJsonTransform_debug_key,
202 "json_string_array() - indx NOT equal to content length! indx: " << indx <<
" length: " << length << endl);
206 *strm << endl << indent <<
"}";
212 void FoDapJsonTransform::writeDatasetMetadata(ostream *strm, libdap::DDS *dds,
string indent)
216 *strm << indent <<
"\"name\": \"" << dds->get_dataset_name() <<
"\"," << endl;
219 transform(strm, dds->get_attr_table(), indent);
220 *strm <<
"," << endl;
228 void FoDapJsonTransform::writeNodeMetadata(ostream *strm, libdap::BaseType *bt,
string indent)
232 *strm << indent <<
"\"name\": \"" << bt->name() <<
"\"," << endl;
235 transform(strm, bt->get_attr_table(), indent);
236 *strm <<
"," << endl;
244 void FoDapJsonTransform::writeLeafMetadata(ostream *strm, libdap::BaseType *bt,
string indent)
248 *strm << indent <<
"\"name\": \"" << bt->name() <<
"\"," << endl;
251 if (bt->type() == libdap::dods_array_c) {
252 libdap::Array *a = (libdap::Array *) bt;
253 *strm << indent <<
"\"type\": \"" << a->var()->type_name() <<
"\"," << endl;
256 *strm << indent <<
"\"type\": \"" << bt->type_name() <<
"\"," << endl;
260 transform(strm, bt->get_attr_table(), indent);
261 *strm <<
"," << endl;
283 if (!_dds)
throw BESInternalError(
"File out JSON, null DDS passed to constructor", __FILE__, __LINE__);
297 strm << BESIndent::LMarg <<
"FoDapJsonTransform::dump - (" << (
void *)
this <<
")" << endl;
302 BESIndent::UnIndent();
319 void FoDapJsonTransform::transform(ostream &ostrm,
bool sendData)
321 transform(&ostrm, _dds,
"", sendData);
328 void FoDapJsonTransform::transform(ostream *strm, libdap::Constructor *cnstrctr,
string indent,
bool sendData)
330 vector<libdap::BaseType *> leaves;
331 vector<libdap::BaseType *> nodes;
334 libdap::DDS::Vars_iter vi = cnstrctr->var_begin();
335 libdap::DDS::Vars_iter ve = cnstrctr->var_end();
336 for (; vi != ve; vi++) {
337 if ((*vi)->send_p()) {
338 libdap::BaseType *v = *vi;
341 if (type == libdap::dods_array_c) {
342 type = v->var()->type();
344 if (v->is_constructor_type() || (v->is_vector_type() && v->var()->is_constructor_type())) {
354 *strm << indent <<
"{" << endl;
355 string child_indent = indent + _indent_increment;
358 writeNodeMetadata(strm, cnstrctr, child_indent);
360 transform_node_worker(strm, leaves, nodes, child_indent, sendData);
362 *strm << indent <<
"}" << endl;
370 void FoDapJsonTransform::transform_node_worker(ostream *strm, vector<libdap::BaseType *> leaves,
371 vector<libdap::BaseType *> nodes,
string indent,
bool sendData)
374 *strm << indent <<
"\"leaves\": [";
375 if (leaves.size() > 0) *strm << endl;
376 for (std::vector<libdap::BaseType *>::size_type l = 0; l < leaves.size(); l++) {
377 libdap::BaseType *v = leaves[l];
378 BESDEBUG(FoDapJsonTransform_debug_key,
"Processing LEAF: " << v->name() << endl);
383 transform(strm, v, indent + _indent_increment, sendData);
385 if (leaves.size() > 0) *strm << endl << indent;
386 *strm <<
"]," << endl;
389 *strm << indent <<
"\"nodes\": [";
390 if (nodes.size() > 0) *strm << endl;
391 for (std::vector<libdap::BaseType *>::size_type n = 0; n < nodes.size(); n++) {
392 libdap::BaseType *v = nodes[n];
393 transform(strm, v, indent + _indent_increment, sendData);
395 if (nodes.size() > 0) *strm << endl << indent;
397 *strm <<
"]" << endl;
404 void FoDapJsonTransform::transform(ostream *strm, libdap::DDS *dds,
string indent,
bool sendData)
409 vector<libdap::BaseType *> leaves;
410 vector<libdap::BaseType *> nodes;
412 libdap::DDS::Vars_iter vi = dds->var_begin();
413 libdap::DDS::Vars_iter ve = dds->var_end();
414 for (; vi != ve; vi++) {
415 if ((*vi)->send_p()) {
416 libdap::BaseType *v = *vi;
418 if (type == libdap::dods_array_c) {
419 type = v->var()->type();
421 if (v->is_constructor_type() || (v->is_vector_type() && v->var()->is_constructor_type())) {
431 *strm << indent <<
"{" << endl;
432 string child_indent = indent + _indent_increment;
435 writeDatasetMetadata(strm, dds, child_indent);
437 transform_node_worker(strm, leaves, nodes, child_indent, sendData);
439 *strm << indent <<
"}" << endl;
446 void FoDapJsonTransform::transform(ostream *strm, libdap::BaseType *bt,
string indent,
bool sendData)
448 switch (bt->type()) {
450 case libdap::dods_byte_c:
451 case libdap::dods_int16_c:
452 case libdap::dods_uint16_c:
453 case libdap::dods_int32_c:
454 case libdap::dods_uint32_c:
455 case libdap::dods_float32_c:
456 case libdap::dods_float64_c:
457 case libdap::dods_str_c:
458 case libdap::dods_url_c:
459 transformAtomic(strm, bt, indent, sendData);
462 case libdap::dods_structure_c:
463 transform(strm, (libdap::Structure *) bt, indent, sendData);
466 case libdap::dods_grid_c:
467 transform(strm, (libdap::Grid *) bt, indent, sendData);
470 case libdap::dods_sequence_c:
471 transform(strm, (libdap::Sequence *) bt, indent, sendData);
474 case libdap::dods_array_c:
475 transform(strm, (libdap::Array *) bt, indent, sendData);
478 case libdap::dods_int8_c:
479 case libdap::dods_uint8_c:
480 case libdap::dods_int64_c:
481 case libdap::dods_uint64_c:
483 case libdap::dods_enum_c:
484 case libdap::dods_group_c: {
485 string s = (string)
"File out JSON, " +
"DAP4 types not yet supported.";
491 string s = (string)
"File out JSON, " +
"Unrecognized type.";
503 void FoDapJsonTransform::transformAtomic(ostream *strm, libdap::BaseType *b,
string indent,
bool sendData)
506 *strm << indent <<
"{" << endl;
508 string childindent = indent + _indent_increment;
510 writeLeafMetadata(strm, b, childindent);
512 *strm << childindent <<
"\"shape\": [1]," << endl;
516 *strm << childindent <<
"\"data\": [";
518 if (b->type() == libdap::dods_str_c || b->type() == libdap::dods_url_c) {
519 libdap::Str *strVar = (libdap::Str *) b;
520 std::string tmpString = strVar->value();
521 *strm <<
"\"" << fojson::escape_for_json(tmpString) <<
"\"";
524 b->print_val(*strm,
"",
false);
536 void FoDapJsonTransform::transform(ostream *strm, libdap::Array *a,
string indent,
bool sendData)
539 BESDEBUG(FoDapJsonTransform_debug_key,
540 "FoJsonTransform::transform() - Processing Array. " <<
" a->type(): " << a->type() <<
" a->var()->type(): " << a->var()->type() << endl);
542 switch (a->var()->type()) {
544 case libdap::dods_byte_c:
545 json_simple_type_array<libdap::dods_byte>(strm, a, indent, sendData);
548 case libdap::dods_int16_c:
549 json_simple_type_array<libdap::dods_int16>(strm, a, indent, sendData);
552 case libdap::dods_uint16_c:
553 json_simple_type_array<libdap::dods_uint16>(strm, a, indent, sendData);
556 case libdap::dods_int32_c:
557 json_simple_type_array<libdap::dods_int32>(strm, a, indent, sendData);
560 case libdap::dods_uint32_c:
561 json_simple_type_array<libdap::dods_uint32>(strm, a, indent, sendData);
564 case libdap::dods_float32_c:
565 json_simple_type_array<libdap::dods_float32>(strm, a, indent, sendData);
568 case libdap::dods_float64_c:
569 json_simple_type_array<libdap::dods_float64>(strm, a, indent, sendData);
572 case libdap::dods_str_c: {
573 json_string_array(strm, a, indent, sendData);
577 case libdap::dods_url_c: {
578 json_string_array(strm, a, indent, sendData);
582 case libdap::dods_structure_c: {
583 throw BESInternalError(
"File out JSON, Arrays of Structure objects not a supported return type.", __FILE__, __LINE__);
586 case libdap::dods_grid_c: {
587 throw BESInternalError(
"File out JSON, Arrays of Grid objects not a supported return type.", __FILE__, __LINE__);
591 case libdap::dods_sequence_c: {
592 throw BESInternalError(
"File out JSON, Arrays of Sequence objects not a supported return type.", __FILE__, __LINE__);
596 case libdap::dods_array_c: {
597 throw BESInternalError(
"File out JSON, Arrays of Array objects not a supported return type.", __FILE__, __LINE__);
600 case libdap::dods_int8_c:
601 case libdap::dods_uint8_c:
602 case libdap::dods_int64_c:
603 case libdap::dods_uint64_c:
605 case libdap::dods_enum_c:
606 case libdap::dods_group_c: {
607 throw BESInternalError(
"File out JSON, DAP4 types not yet supported.", __FILE__, __LINE__);
612 throw BESInternalError(
"File out JSON, Unrecognized type.", __FILE__, __LINE__);
624 void FoDapJsonTransform::transform(ostream *strm, libdap::AttrTable &attr_table,
string indent)
627 string child_indent = indent + _indent_increment;
630 *strm << indent <<
"\"attributes\": [";
636 if (attr_table.get_size() != 0) {
638 libdap::AttrTable::Attr_iter begin = attr_table.attr_begin();
639 libdap::AttrTable::Attr_iter end = attr_table.attr_end();
641 for (libdap::AttrTable::Attr_iter at_iter = begin; at_iter != end; at_iter++) {
643 switch (attr_table.get_attr_type(at_iter)) {
644 case libdap::Attr_container: {
645 libdap::AttrTable *atbl = attr_table.get_attr_table(at_iter);
648 if (at_iter != begin) *strm <<
"," << endl;
651 *strm << child_indent <<
"{" << endl;
654 if (atbl->get_name().length() > 0)
655 *strm << child_indent + _indent_increment <<
"\"name\": \"" << atbl->get_name() <<
"\"," << endl;
658 transform(strm, *atbl, child_indent + _indent_increment);
659 *strm << endl << child_indent <<
"}";
666 if (at_iter != begin) *strm <<
"," << endl;
669 *strm << child_indent <<
"{\"name\": \"" << attr_table.get_name(at_iter) <<
"\", ";
672 *strm <<
"\"value\": [";
673 vector<std::string> *values = attr_table.get_attr_vector(at_iter);
675 for (std::vector<std::string>::size_type i = 0; i < values->size(); i++) {
678 if (i > 0) *strm <<
",";
681 if (attr_table.get_attr_type(at_iter) == libdap::Attr_string
682 || attr_table.get_attr_type(at_iter) == libdap::Attr_url) {
685 *strm << fojson::escape_for_json((*values)[i]);
690 *strm << (*values)[i];
702 *strm << endl << indent;