bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
W10nJsonTransform.cc
1// -*- mode: c++; c-basic-offset:4 -*-
2//
3// W10nJsonTransform.cc
4//
5// This file is part of BES JSON File Out Module
6//
7// Copyright (c) 2014 OPeNDAP, Inc.
8// Author: Nathan Potter <ndp@opendap.org>
9//
10// This library is free software; you can redistribute it and/or
11// modify it under the terms of the GNU Lesser General Public
12// License as published by the Free Software Foundation; either
13// version 2.1 of the License, or (at your option) any later version.
14//
15// This library is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18// Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public
21// License along with this library; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23//
24// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25// (c) COPYRIGHT URI/MIT 1995-1999
26// Please read the full copyright statement in the file COPYRIGHT_URI.
27//
28
29#include "W10NNames.h"
30#include "W10nJsonTransform.h"
31#include "config.h"
32
33#include <sstream>
34#include <iostream>
35#include <fstream>
36#include <stddef.h>
37#include <string>
38#include <typeinfo>
39
40using std::ostringstream;
41using std::istringstream;
42
43#include <libdap/DDS.h>
44#include <libdap/Type.h>
45#include <libdap/Structure.h>
46#include <libdap/Constructor.h>
47#include <libdap/Array.h>
48#include <libdap/Grid.h>
49#include <libdap/Str.h>
50#include <libdap/Sequence.h>
51#include <libdap/Str.h>
52#include <libdap/Url.h>
53
54#include <BESDebug.h>
55#include <BESInternalError.h>
56#include <BESContextManager.h>
57#include <BESSyntaxUserError.h>
58
59#include <w10n_utils.h>
60
65template<typename T>
66unsigned int W10nJsonTransform::json_simple_type_array_worker(ostream *strm, T *values,
67 unsigned int indx, vector<unsigned int> *shape, unsigned int currentDim, bool flatten)
68{
69 if (currentDim == 0 || !flatten) *strm << "[";
70
71 unsigned int currentDimSize = (*shape)[currentDim];
72
73 for (unsigned int i = 0; i < currentDimSize; i++) {
74 if (currentDim < shape->size() - 1) {
75 indx = json_simple_type_array_worker<T>(strm, values, indx, shape, currentDim + 1, flatten);
76 if (i + 1 != currentDimSize) *strm << ", ";
77 }
78 else {
79 if (i) *strm << ", ";
80 if (typeid(T) == typeid(std::string)) {
81 // Strings need to be escaped to be included in a JSON object.
82 // std::string val = ((std::string *) values)[indx++]; replaced w/below jhrg 9/7/16
83 std::string val = reinterpret_cast<std::string*>(values)[indx++];
84 *strm << "\"" << w10n::escape_for_json(val) << "\"";
85 }
86 else {
87 *strm << values[indx++];
88 }
89 }
90 }
91
92 if (currentDim == 0 || !flatten) *strm << "]";
93
94 return indx;
95}
96
97void W10nJsonTransform::json_array_starter(ostream *strm, libdap::Array *a, std::string indent)
98{
99
100 bool found_w10n_callback = false;
101 std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY, found_w10n_callback);
102 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
103
104 BESDEBUG(W10N_DEBUG_KEY,
105 "W10nJsonTransform::json_simple_type_array() - Processing Array of " << a->var()->type_name() << endl);
106
107 if (found_w10n_callback) {
108 *strm << w10n_callback << "(";
109 }
110
111 *strm << "{" << endl;
112
113 std::string child_indent = indent + _indent_increment;
114
115 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - Writing variable metadata..." << endl);
116
117 writeVariableMetadata(strm, a, child_indent);
118 *strm << "," << endl;
119
120 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - Writing variable data..." << endl);
121
122 // Data
123 *strm << child_indent << "\"data\": ";
124
125}
126void W10nJsonTransform::json_array_ender(ostream *strm, std::string indent)
127{
128
129 bool found_w10n_meta_object = false;
130 std::string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,
131 found_w10n_meta_object);
132 BESDEBUG(W10N_DEBUG_KEY,
133 "W10nJsonTransform::json_simple_type_array_ender() - w10n_meta_object: "<< w10n_meta_object << endl);
134
135 bool found_w10n_callback = false;
136 std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY, found_w10n_callback);
137 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
138
139 std::string child_indent = indent + _indent_increment;
140
141 if (found_w10n_meta_object)
142 *strm << "," << endl << child_indent << w10n_meta_object << endl;
143 else
144 *strm << endl;
145
146 *strm << indent << "}" << endl;
147
148 if (found_w10n_callback) {
149 *strm << ")";
150 }
151
152 *strm << endl;
153
154}
159template<typename T> void W10nJsonTransform::json_simple_type_array_sender(ostream *strm, libdap::Array *a)
160{
161
162 bool found_w10n_flatten = false;
163 std::string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY, found_w10n_flatten);
164 BESDEBUG(W10N_DEBUG_KEY,
165 "W10nJsonTransform::json_simple_type_array_sender() - w10n_flatten: "<< w10n_flatten << endl);
166
167 int numDim = a->dimensions(true);
168 vector<unsigned int> shape(numDim);
169 long length = w10n::computeConstrainedShape(a, &shape);
170
171 vector<T> src(length);
172 a->value(src.data());
173 unsigned int indx = json_simple_type_array_worker(strm, src.data(), 0, &shape, 0, found_w10n_flatten);
174
175 if (length != indx)
176 BESDEBUG(W10N_DEBUG_KEY,
177 "json_simple_type_array_sender() - indx NOT equal to content length! indx: " << indx << " length: " << length << endl);
178
179}
180
185void W10nJsonTransform::json_string_array_sender(ostream *strm, libdap::Array *a)
186{
187
188 bool found_w10n_flatten = false;
189 std::string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY, found_w10n_flatten);
190 BESDEBUG(W10N_DEBUG_KEY,
191 "W10nJsonTransform::json_simple_type_array_sender() - w10n_flatten: "<< w10n_flatten << endl);
192
193 int numDim = a->dimensions(true);
194 vector<unsigned int> shape(numDim);
195 long length = w10n::computeConstrainedShape(a, &shape);
196
197 // The string type utilizes a specialized version of libdap:Array.value()
198 vector<std::string> sourceValues;
199 a->value(sourceValues);
200 unsigned int indx = json_simple_type_array_worker(strm, (std::string *) (sourceValues.data()), 0, &shape, 0,
201 found_w10n_flatten);
202
203 if (length != indx)
204 BESDEBUG(W10N_DEBUG_KEY,
205 "json_simple_type_array_sender() - indx NOT equal to content length! indx: " << indx << " length: " << length << endl);
206
207}
208
213template<typename T> void W10nJsonTransform::json_simple_type_array(ostream *strm, libdap::Array *a, std::string indent)
214{
215 json_array_starter(strm, a, indent);
216 json_simple_type_array_sender<T>(strm, a);
217 json_array_ender(strm, indent);
218}
219
224void W10nJsonTransform::json_string_array(ostream *strm, libdap::Array *a, std::string indent)
225{
226 json_array_starter(strm, a, indent);
227 json_string_array_sender(strm, a);
228 json_array_ender(strm, indent);
229}
230
234void W10nJsonTransform::writeDatasetMetadata(ostream *strm, libdap::DDS *dds, std::string indent)
235{
236 // Name
237 *strm << indent << "\"name\": \"" << dds->get_dataset_name() << "\"," << endl;
238
239 //Attributes
240 writeAttributes(strm, dds->get_attr_table(), indent);
241 *strm << "," << endl;
242}
243
248void W10nJsonTransform::writeVariableMetadata(ostream *strm, libdap::BaseType *bt, std::string indent)
249{
250
251 // Name
252 *strm << indent << "\"name\": \"" << bt->name() << "\"," << endl;
253 libdap::BaseType *var = bt;
254
255 // w10n type
256 if (bt->type() == libdap::dods_array_c) {
257 libdap::Array *a = (libdap::Array *) bt;
258 var = a->var();
259 }
260 if (!var->is_constructor_type()) *strm << indent << "\"type\": \"" << var->type_name() << "\"," << endl;
261
262 //Attributes
263 writeAttributes(strm, bt->get_attr_table(), indent);
264
265}
266
278W10nJsonTransform::W10nJsonTransform(libdap::DDS *dds, BESDataHandlerInterface &, const std::string &localfile) :
279 _dds(dds), _localfile(localfile), _indent_increment(" "), _ostrm(0), _usingTempFile(false)
280{
281 if (!_dds) {
282 std::string msg = "W10nJsonTransform: ERROR! A null DDS reference was passed to the constructor";
283 BESDEBUG(W10N_DEBUG_KEY, msg << endl);
284 throw BESInternalError(msg, __FILE__, __LINE__);
285 }
286
287 if (_localfile.empty()) {
288 std::string msg = "W10nJsonTransform: An empty local file name passed to constructor";
289 BESDEBUG(W10N_DEBUG_KEY, msg << endl);
290 throw BESInternalError(msg, __FILE__, __LINE__);
291 }
292}
293
294W10nJsonTransform::W10nJsonTransform(libdap::DDS *dds, BESDataHandlerInterface &, std::ostream *ostrm) :
295 _dds(dds), _localfile(""), _indent_increment(" "), _ostrm(ostrm), _usingTempFile(false)
296{
297 if (!_dds) {
298 std::string msg = "W10nJsonTransform: ERROR! A null DDS reference was passed to the constructor";
299 BESDEBUG(W10N_DEBUG_KEY, msg << endl);
300 throw BESInternalError(msg, __FILE__, __LINE__);
301 }
302
303 if (!_ostrm) {
304 std::string msg = "W10nJsonTransform: ERROR! A null std::ostream pointer was passed to the constructor";
305 BESDEBUG(W10N_DEBUG_KEY, msg << endl);
306 throw BESInternalError(msg, __FILE__, __LINE__);
307 }
308}
309
317
328{
329 strm << BESIndent::LMarg << "W10nJsonTransform::dump - (" << (void *) this << ")" << endl;
330 BESIndent::Indent();
331 strm << BESIndent::LMarg << "temporary file = " << _localfile << endl;
332 if (_dds != 0) {
333 _dds->print(strm);
334 }
335 BESIndent::UnIndent();
336}
337
342void W10nJsonTransform::writeAttributes(ostream *strm, libdap::AttrTable &attr_table, std::string indent)
343{
344
345 std::string child_indent = indent + _indent_increment;
346
347 // Start the attributes block
348 *strm << indent << "\"attributes\": [";
349
350// if(attr_table.get_name().size()>0)
351// *strm << endl << child_indent << "{\"name\": \"name\", \"value\": \"" << attr_table.get_name() << "\"},";
352
353// Only do more if there are actually attributes in the table
354 if (attr_table.get_size() != 0) {
355 *strm << endl;
356 libdap::AttrTable::Attr_iter begin = attr_table.attr_begin();
357 libdap::AttrTable::Attr_iter end = attr_table.attr_end();
358
359 for (libdap::AttrTable::Attr_iter at_iter = begin; at_iter != end; at_iter++) {
360
361 switch (attr_table.get_attr_type(at_iter)) {
362 case libdap::Attr_container: {
363 libdap::AttrTable *atbl = attr_table.get_attr_table(at_iter);
364
365 // not first thing? better use a comma...
366 if (at_iter != begin) *strm << "," << endl;
367
368 // Attribute Containers need to be opened and then a recursive call gets made
369 *strm << child_indent << "{" << endl;
370
371 // If the table has a name, write it out as a json property.
372 if (atbl->get_name().size() > 0)
373 *strm << child_indent + _indent_increment << "\"name\": \"" << atbl->get_name() << "\"," << endl;
374
375 // Recursive call for child attribute table.
376 writeAttributes(strm, *atbl, child_indent + _indent_increment);
377 *strm << endl << child_indent << "}";
378
379 break;
380
381 }
382 default: {
383 // not first thing? better use a comma...
384 if (at_iter != begin) *strm << "," << endl;
385
386 // Open attribute object, write name
387 *strm << child_indent << "{\"name\": \"" << attr_table.get_name(at_iter) << "\", ";
388
389 // Open value array
390 *strm << "\"value\": [";
391 vector<std::string> *values = attr_table.get_attr_vector(at_iter);
392 // write values
393 for (std::vector<std::string>::size_type i = 0; i < values->size(); i++) {
394
395 // not first thing? better use a comma...
396 if (i > 0) *strm << ",";
397
398 // Escape the double quotes found in String and URL type attribute values.
399 if (attr_table.get_attr_type(at_iter) == libdap::Attr_string
400 || attr_table.get_attr_type(at_iter) == libdap::Attr_url) {
401 *strm << "\"";
402 std::string value = (*values)[i];
403 *strm << w10n::escape_for_json(value);
404 *strm << "\"";
405 }
406 else {
407
408 *strm << (*values)[i];
409 }
410
411 }
412 // close value array
413 *strm << "]}";
414 break;
415 }
416
417 }
418 }
419 *strm << endl << indent;
420
421 }
422
423 // close AttrTable JSON
424
425 *strm << "]";
426
427}
428
429std::ostream *W10nJsonTransform::getOutputStream()
430{
431 // used to ensure the _ostrm is closed only when it's a temp file
432 _usingTempFile = false;
433 std::fstream _tempFile;
434
435 if (!_ostrm) {
436 _tempFile.open(_localfile.c_str(), std::fstream::out);
437 if (!_tempFile) {
438 std::string msg = "Could not open temp file: " + _localfile;
439 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::getOutputStream() - ERROR! "<< msg << endl);
440 throw BESInternalError(msg, __FILE__, __LINE__);
441 }
442 _ostrm = &_tempFile;
443 _usingTempFile = true;
444 }
445
446 return _ostrm;
447}
448
449void W10nJsonTransform::releaseOutputStream()
450{
451 if (_usingTempFile) {
452 ((std::fstream *) _ostrm)->close();
453 _ostrm = 0;
454 }
455}
456
457void W10nJsonTransform::sendW10nMetaForDDS()
458{
459
460 std::ostream *strm = getOutputStream();
461 try {
462 sendW10nMetaForDDS(strm, _dds, "");
463 releaseOutputStream();
464 }
465 catch (...) {
466 releaseOutputStream();
467 throw;
468 }
469
470}
471
472void W10nJsonTransform::sendW10nMetaForDDS(ostream *strm, libdap::DDS *dds, std::string indent)
473{
474
475 bool found_w10n_meta_object = false;
476 std::string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,
477 found_w10n_meta_object);
478 BESDEBUG(W10N_DEBUG_KEY,
479 "W10nJsonTransform::json_simple_type_array() - w10n_meta_object: "<< w10n_meta_object << endl);
480
481 bool found_w10n_callback = false;
482 std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY, found_w10n_callback);
483 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
484
488 vector<libdap::BaseType *> leaves;
489 vector<libdap::BaseType *> nodes;
490
491 libdap::DDS::Vars_iter vi = dds->var_begin();
492 libdap::DDS::Vars_iter ve = dds->var_end();
493 for (; vi != ve; vi++) {
494 libdap::BaseType *v = *vi;
495 if (v->send_p()) {
496 libdap::Type type = v->type();
497 if (type == libdap::dods_array_c) {
498 type = v->var()->type();
499 }
500 if (v->is_constructor_type() || (v->is_vector_type() && v->var()->is_constructor_type())) {
501 nodes.push_back(v);
502 }
503 else {
504 leaves.push_back(v);
505 }
506 }
507 }
508
509 if (found_w10n_callback) {
510 *strm << w10n_callback << "(";
511 }
512
513 // Declare the top level node
514 *strm << "{" << endl;
515 std::string child_indent = indent + _indent_increment;
516
517 // Write the top level node's metadata (name & attributes)
518 writeDatasetMetadata(strm, dds, child_indent);
519
520 // Write down the leaves
521 *strm << child_indent << "\"leaves\": [";
522 if (leaves.size() > 0) *strm << endl;
523 for (std::vector<libdap::BaseType *>::size_type l = 0; l < leaves.size(); l++) {
524 libdap::BaseType *v = leaves[l];
525 BESDEBUG(W10N_DEBUG_KEY, "Processing LEAF: " << v->name() << endl);
526 if (l > 0) {
527 *strm << "," << endl;
528 }
529
530 sendW10nMetaForVariable(strm, v, child_indent + _indent_increment, false);
531 }
532 if (leaves.size() > 0) *strm << endl << child_indent;
533 *strm << "]," << endl;
534
535 // Write down the child nodes
536 *strm << child_indent << "\"nodes\": [";
537 if (nodes.size() > 0) *strm << endl;
538 for (std::vector<libdap::BaseType *>::size_type n = 0; n < nodes.size(); n++) {
539 libdap::BaseType *v = nodes[n];
540 BESDEBUG(W10N_DEBUG_KEY, "Processing NODE: " << v->name() << endl);
541 if (n > 0) {
542 *strm << "," << endl;
543 }
544 sendW10nMetaForVariable(strm, v, child_indent + _indent_increment, false);
545 }
546 if (nodes.size() > 0) *strm << endl << child_indent;
547
548 *strm << "]";
549
550 if (found_w10n_meta_object)
551 *strm << "," << endl << child_indent << w10n_meta_object << endl;
552 else
553 *strm << endl;
554
555 *strm << "}";
556
557 if (found_w10n_callback) {
558 *strm << ")";
559 }
560
561 *strm << endl;
562
563}
564
565void W10nJsonTransform::sendW10nMetaForVariable(ostream *strm, libdap::BaseType *bt, std::string indent, bool isTop)
566{
567
568 bool found_w10n_meta_object = false;
569 std::string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,
570 found_w10n_meta_object);
571 BESDEBUG(W10N_DEBUG_KEY,
572 "W10nJsonTransform::json_simple_type_array() - w10n_meta_object: "<< w10n_meta_object << endl);
573
574 bool found_w10n_callback = false;
575 std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY, found_w10n_callback);
576 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
577
578 bool found_w10n_flatten = false;
579 std::string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY, found_w10n_flatten);
580 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_flatten: "<< w10n_flatten << endl);
581
582 bool found_w10n_traverse = false;
583 std::string w10n_traverse = BESContextManager::TheManager()->get_context(W10N_TRAVERSE_KEY, found_w10n_traverse);
584 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_traverse: "<< w10n_traverse << endl);
585
586 if (isTop && found_w10n_callback) {
587 *strm << w10n_callback << "(";
588 }
589
590 *strm << indent << "{" << endl;\
591 std::string child_indent = indent + _indent_increment;
592
593 writeVariableMetadata(strm, bt, child_indent);
594
595 if (bt->type() == libdap::dods_array_c) {
596 *strm << "," << endl;
597
598 libdap::Array *a = (libdap::Array *) bt;
599 int numDim = a->dimensions(true);
600 vector<unsigned int> shape(numDim);
601 long length = w10n::computeConstrainedShape(a, &shape);
602
603 if (found_w10n_flatten) {
604 *strm << child_indent << "\"shape\": [" << length << "]";
605
606 }
607 else {
608 *strm << child_indent << "\"shape\": [";
609 for (std::vector<unsigned int>::size_type i = 0; i < shape.size(); i++) {
610 if (i > 0) *strm << ",";
611 *strm << shape[i];
612 }
613 *strm << "]";
614 }
615 }
616 else {
617 if (bt->is_constructor_type() && (found_w10n_traverse || isTop)) {
618 *strm << "," << endl;
619
620 libdap::Constructor *ctor = (libdap::Constructor *) bt;
621
622 vector<libdap::BaseType *> leaves;
623 vector<libdap::BaseType *> nodes;
624 libdap::Constructor::Vars_iter vi = ctor->var_begin();
625 libdap::Constructor::Vars_iter ve = ctor->var_end();
626 for (; vi != ve; vi++) {
627 libdap::BaseType *v = *vi;
628 if (v->send_p()) {
629 libdap::Type type = v->type();
630 if (type == libdap::dods_array_c) {
631 type = v->var()->type();
632 }
633 if (v->is_constructor_type() || (v->is_vector_type() && v->var()->is_constructor_type())) {
634 nodes.push_back(v);
635 }
636 else {
637 leaves.push_back(v);
638 }
639 }
640 }
641
642 // Write down the leaves
643 *strm << child_indent << "\"leaves\": [";
644 if (leaves.size() > 0) *strm << endl;
645 for (std::vector<libdap::BaseType *>::size_type l = 0; l < leaves.size(); l++) {
646 libdap::BaseType *v = leaves[l];
647 BESDEBUG(W10N_DEBUG_KEY, "Processing LEAF: " << v->name() << endl);
648 if (l > 0) {
649 *strm << ",";
650 *strm << endl;
651 }
652
653 sendW10nMetaForVariable(strm, v, child_indent + _indent_increment, false);
654 }
655 if (leaves.size() > 0) *strm << endl << child_indent;
656 *strm << "]," << endl;
657
658 // Write down the child nodes
659 *strm << child_indent << "\"nodes\": [";
660 if (nodes.size() > 0) *strm << endl;
661 for (std::vector<libdap::BaseType *>::size_type n = 0; n < nodes.size(); n++) {
662 libdap::BaseType *v = nodes[n];
663 BESDEBUG(W10N_DEBUG_KEY, "Processing NODE: " << v->name() << endl);
664 if (n > 0) {
665 *strm << "," << endl;
666 }
667 sendW10nMetaForVariable(strm, v, child_indent + _indent_increment, false);
668 }
669 if (nodes.size() > 0) *strm << endl << child_indent;
670
671 *strm << "]";
672
673 }
674 else {
675 if (!bt->is_constructor_type()) {
676 // *strm << endl;
677 // *strm << "," << endl;
678 // *strm << child_indent << "\"shape\": [1]";
679 }
680
681 }
682 }
683
684 if (isTop && found_w10n_meta_object) {
685 *strm << "," << endl << child_indent << w10n_meta_object << endl;
686 }
687
688 *strm << endl << indent << "}";
689
690 if (isTop && found_w10n_callback) {
691 *strm << ")";
692 }
693
694}
695
696void W10nJsonTransform::sendW10nMetaForVariable(std::string &vName, bool isTop)
697{
698
699 libdap::BaseType *bt = _dds->var(vName);
700
701 if (!bt) {
702 std::string msg = "The dataset does not contain a variable named '" + vName + "'";
703 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << msg << endl);
704 throw BESSyntaxUserError(msg, __FILE__, __LINE__);
705 }
706
707 std::ostream *strm = getOutputStream();
708 try {
709 sendW10nMetaForVariable(strm, bt, "", isTop);
710 *strm << endl;
711 releaseOutputStream();
712 }
713 catch (...) {
714 releaseOutputStream();
715 throw;
716 }
717
718}
719
720void W10nJsonTransform::sendW10nDataForVariable(std::string &vName)
721{
722
723 libdap::BaseType *bt = _dds->var(vName);
724
725 if (!bt) {
726 std::string msg = "The dataset does not contain a variable named '" + vName + "'";
727 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nDataForVariable() - ERROR! " << msg << endl);
728 throw BESSyntaxUserError(msg, __FILE__, __LINE__);
729 }
730
731 std::ostream *strm = getOutputStream();
732 try {
733 sendW10nDataForVariable(strm, bt, "");
734 releaseOutputStream();
735 }
736 catch (...) {
737 releaseOutputStream();
738 throw;
739 }
740
741}
742
743void W10nJsonTransform::sendW10nDataForVariable(ostream *strm, libdap::BaseType *bt, std::string indent)
744{
745
746 if (bt->is_simple_type()) {
747
748 sendW10nData(strm, bt, indent);
749
750 }
751 else if (bt->type() == libdap::dods_array_c && bt->var()->is_simple_type()) {
752 sendW10nData(strm, (libdap::Array *) bt, indent);
753
754 }
755 else {
756 std::string msg = "The variable '" + bt->name() + "' is not a simple type or an Array of simple types. ";
757 msg += "The w10n protocol does not support the transmission of data for complex types.";
758 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nDataForVariable() - ERROR! " << msg << endl);
759 throw BESSyntaxUserError(msg, __FILE__, __LINE__);
760 }
761
762}
763
768void W10nJsonTransform::sendW10nData(ostream *strm, libdap::BaseType *b, std::string indent)
769{
770
771 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nData() - Sending data for simple type "<< b->name() << endl);
772
773 bool found_w10n_meta_object = false;
774 std::string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,
775 found_w10n_meta_object);
776 BESDEBUG(W10N_DEBUG_KEY,
777 "W10nJsonTransform::json_simple_type_array() - w10n_meta_object: "<< w10n_meta_object << endl);
778
779 bool found_w10n_callback = false;
780 std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY, found_w10n_callback);
781 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
782
783 bool found_w10n_flatten = false;
784 std::string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY, found_w10n_flatten);
785 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_flatten: "<< w10n_flatten << endl);
786
787 std::string child_indent = indent + _indent_increment;
788
789 if (found_w10n_callback) {
790 *strm << w10n_callback << "(";
791 }
792
793 *strm << "{" << endl;
794
795 writeVariableMetadata(strm, b, child_indent);
796 *strm << "," << endl;
797
798 *strm << child_indent << "\"data\": ";
799
800 if (b->type() == libdap::dods_str_c || b->type() == libdap::dods_url_c) {
801 libdap::Str *strVar = (libdap::Str *) b;
802 *strm << "\"" << w10n::escape_for_json(strVar->value()) << "\"";
803 }
804 else {
805 b->print_val(*strm, "", false);
806 }
807
808 if (found_w10n_meta_object)
809 *strm << "," << endl << child_indent << w10n_meta_object << endl;
810 else
811 *strm << endl;
812
813 *strm << "}";
814
815 if (found_w10n_callback) {
816 *strm << ")";
817 }
818 *strm << endl;
819
820 // *strm << "]";
821
822}
823
824void W10nJsonTransform::sendW10nData(ostream *strm, libdap::Array *a, std::string indent)
825{
826
827 BESDEBUG(W10N_DEBUG_KEY,
828 "W10nJsonTransform::transform() - Processing Array. " << " a->type_name(): " << a->type_name() << " a->var()->type_name(): " << a->var()->type_name() << endl);
829
830 switch (a->var()->type()) {
831 // Handle the atomic types - that's easy!
832 case libdap::dods_byte_c:
833 json_simple_type_array<libdap::dods_byte>(strm, a, indent);
834 break;
835
836 case libdap::dods_int16_c:
837 json_simple_type_array<libdap::dods_int16>(strm, a, indent);
838 break;
839
840 case libdap::dods_uint16_c:
841 json_simple_type_array<libdap::dods_uint16>(strm, a, indent);
842 break;
843
844 case libdap::dods_int32_c:
845 json_simple_type_array<libdap::dods_int32>(strm, a, indent);
846 break;
847
848 case libdap::dods_uint32_c:
849 json_simple_type_array<libdap::dods_uint32>(strm, a, indent);
850 break;
851
852 case libdap::dods_float32_c:
853 json_simple_type_array<libdap::dods_float32>(strm, a, indent);
854 break;
855
856 case libdap::dods_float64_c:
857 json_simple_type_array<libdap::dods_float64>(strm, a, indent);
858 break;
859
860 case libdap::dods_str_c: {
861 json_string_array(strm, a, indent);
862 break;
863#if 0
864 string s = (string) "W10nJsonTransform: Arrays of String objects not a supported return type.";
865 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
866 throw BESInternalError(s, __FILE__, __LINE__);
867 break;
868#endif
869 }
870
871 case libdap::dods_url_c: {
872 json_string_array(strm, a, indent);
873 break;
874
875#if 0
876 string s = (string) "W10nJsonTransform: Arrays of URL objects not a supported return type.";
877 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
878 throw BESInternalError(s, __FILE__, __LINE__);
879 break;
880#endif
881 }
882
883 case libdap::dods_structure_c: {
884 std::string s = (std::string) "W10nJsonTransform: Arrays of Structure objects not a supported return type.";
885 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
886 throw BESInternalError(s, __FILE__, __LINE__);
887 break;
888 }
889 case libdap::dods_grid_c: {
890 std::string s = (std::string) "W10nJsonTransform: Arrays of Grid objects not a supported return type.";
891 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
892 throw BESInternalError(s, __FILE__, __LINE__);
893 break;
894 }
895
896 case libdap::dods_sequence_c: {
897 std::string s = (std::string) "W10nJsonTransform: Arrays of Sequence objects not a supported return type.";
898 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
899 throw BESInternalError(s, __FILE__, __LINE__);
900 break;
901 }
902
903 case libdap::dods_array_c: {
904 std::string s = (std::string) "W10nJsonTransform: Arrays of Array objects not a supported return type.";
905 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
906 throw BESInternalError(s, __FILE__, __LINE__);
907 break;
908 }
909 case libdap::dods_int8_c:
910 case libdap::dods_uint8_c:
911 case libdap::dods_int64_c:
912 case libdap::dods_uint64_c:
913 // case libdap::dods_url4_c:
914 case libdap::dods_enum_c:
915 case libdap::dods_group_c: {
916 std::string s = (std::string) "W10nJsonTransform: DAP4 types not yet supported.";
917 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
918 throw BESInternalError(s, __FILE__, __LINE__);
919 break;
920 }
921
922 default: {
923 std::string s = (std::string) "W10nJsonTransform: Unrecognized type.";
924 BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
925 throw BESInternalError(s, __FILE__, __LINE__);
926 break;
927 }
928
929 }
930}
931
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
Structure storing information used by the BES to handle the request.
exception thrown if internal error encountered
virtual ~W10nJsonTransform()
Destructor.
virtual void dump(std::ostream &strm) const
dumps information about this transformation object for debugging purposes
W10nJsonTransform(libdap::DDS *dds, BESDataHandlerInterface &dhi, const std::string &localfile)
Constructor that creates transformation object from the specified DataDDS object to the specified fil...
STL class.
STL class.