bes  Updated for version 3.20.8
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 
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...
Type
Type of JSON value.
Definition: rapidjson.h:664