bes Updated for version 3.20.13
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
315{
316}
317
327void W10nJsonTransform::dump(ostream &strm) const
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().length()>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().length() > 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
error thrown if there is a user syntax error in the request or any other user error
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...