bes  Updated for version 3.20.6
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 
40 using std::ostringstream;
41 using std::istringstream;
42 
43 #include <DDS.h>
44 #include <Type.h>
45 #include <Structure.h>
46 #include <Constructor.h>
47 #include <Array.h>
48 #include <Grid.h>
49 #include <Str.h>
50 #include <Sequence.h>
51 #include <Str.h>
52 #include <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 
65 template<typename T>
66 unsigned 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 
97 void 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 }
126 void 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 }
159 template<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[0]);
173  unsigned int indx = json_simple_type_array_worker(strm, &src[0], 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 
185 void 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[0]), 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 
213 template<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 
224 void 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 
234 void 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 
248 void 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 
278 W10nJsonTransform::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 
294 W10nJsonTransform::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 
327 void 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 
342 void 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 
429 std::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 
449 void W10nJsonTransform::releaseOutputStream()
450 {
451  if (_usingTempFile) {
452  ((std::fstream *) _ostrm)->close();
453  _ostrm = 0;
454  }
455 }
456 
457 void 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 
472 void 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 
565 void 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 
696 void 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 
720 void 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 
743 void 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 
768 void 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 
824 void 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 
W10nJsonTransform::dump
virtual void dump(std::ostream &strm) const
dumps information about this transformation object for debugging purposes
Definition: W10nJsonTransform.cc:327
Type
Type
Type of JSON value.
Definition: cmr_module/rapidjson/rapidjson.h:603
BESSyntaxUserError
error thrown if there is a user syntax error in the request or any other user error
Definition: BESSyntaxUserError.h:41
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
W10nJsonTransform::W10nJsonTransform
W10nJsonTransform(libdap::DDS *dds, BESDataHandlerInterface &dhi, const std::string &localfile)
Constructor that creates transformation object from the specified DataDDS object to the specified fil...
Definition: W10nJsonTransform.cc:278
W10nJsonTransform::~W10nJsonTransform
virtual ~W10nJsonTransform()
Destructor.
Definition: W10nJsonTransform.cc:314
BESContextManager::get_context
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
Definition: BESContextManager.cc:77
BESDataHandlerInterface
Structure storing information used by the BES to handle the request.
Definition: BESDataHandlerInterface.h:56