OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
W10nJsonTransform.cc
Go to the documentation of this file.
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 
44 #include <DDS.h>
45 #include <Type.h>
46 #include <Structure.h>
47 #include <Constructor.h>
48 #include <Array.h>
49 #include <Grid.h>
50 #include <Str.h>
51 #include <Sequence.h>
52 #include <Str.h>
53 #include <Url.h>
54 
55 #include <BESDebug.h>
56 #include <BESInternalError.h>
57 #include <BESContextManager.h>
58 #include <BESSyntaxUserError.h>
59 
60 #include <w10n_utils.h>
61 
62 
63 
68 template<typename T> unsigned int W10nJsonTransform::json_simple_type_array_worker(ostream *strm, T *values, unsigned int indx, vector<unsigned int> *shape, unsigned int currentDim, bool flatten){
69 
70  if(currentDim==0 || !flatten)
71  *strm << "[";
72 
73  unsigned int currentDimSize = (*shape)[currentDim];
74 
75  for(unsigned int i=0; i<currentDimSize ;i++){
76  if(currentDim < shape->size()-1){
77  BESDEBUG(W10N_DEBUG_KEY, "json_simple_type_array_worker() - Recursing! indx: " << indx
78  << " currentDim: " << currentDim
79  << " currentDimSize: " << currentDimSize
80  << endl);
81  indx = json_simple_type_array_worker<T>(strm,values,indx,shape,currentDim+1, flatten);
82  if(i+1 != currentDimSize)
83  *strm << ", ";
84  }
85  else {
86  if(i)
87  *strm << ", ";
88  if(typeid(T) == typeid(std::string)){
89  // Strings need to be escaped to be included in a JSON object.
90  std::string val = ((std::string *) values)[indx++];
91  *strm << "\"" << w10n::escape_for_json( val )<< "\"";
92  }
93  else {
94  *strm << values[indx++];
95  }
96  }
97  }
98 
99  if(currentDim==0 || !flatten)
100  *strm << "]";
101 
102  return indx;
103 }
104 
105 void W10nJsonTransform::json_array_starter(ostream *strm, libdap::Array *a, std::string indent){
106 
107 
108  bool found_w10n_callback = false;
109  std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY,found_w10n_callback);
110  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
111 
112 
113  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - Processing Array of " << a->var()->type_name() << endl);
114 
115 
116  if(found_w10n_callback){
117  *strm << w10n_callback << "(";
118  }
119 
120  *strm << "{" << endl;
121 
122  std::string child_indent = indent + _indent_increment;
123 
124  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - Writing variable metadata..." << endl);
125 
126  writeVariableMetadata(strm,a,child_indent);
127  *strm << "," << endl;
128 
129  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - Writing variable data..." << endl);
130 
131  // Data
132  *strm << child_indent << "\"data\": ";
133 
134 }
135 void W10nJsonTransform::json_array_ender(ostream *strm, std::string indent){
136 
137  bool found_w10n_meta_object = false;
138  std::string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,found_w10n_meta_object);
139  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array_ender() - w10n_meta_object: "<< w10n_meta_object << endl);
140 
141  bool found_w10n_callback = false;
142  std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY,found_w10n_callback);
143  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
144 
145  std::string child_indent = indent + _indent_increment;
146 
147 
148  if(found_w10n_meta_object)
149  *strm << "," << endl << child_indent << w10n_meta_object << endl;
150  else
151  *strm << endl;
152 
153  *strm << indent << "}" << endl;
154 
155  if(found_w10n_callback){
156  *strm << ")";
157  }
158 
159  *strm << endl;
160 
161 
162 
163 }
168 template<typename T> void W10nJsonTransform::json_simple_type_array_sender(ostream *strm, libdap::Array *a){
169 
170  bool found_w10n_flatten = false;
171  std::string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY,found_w10n_flatten);
172  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array_sender() - w10n_flatten: "<< w10n_flatten << endl);
173 
174  int numDim = a->dimensions(true);
175  vector<unsigned int> shape(numDim);
176  long length = w10n::computeConstrainedShape(a, &shape);
177 
178  T *src = new T[length];
179  a->value(src);
180  unsigned int indx = json_simple_type_array_worker(strm, src, 0, &shape, 0, found_w10n_flatten);
181  delete src;
182 
183  if(length != indx)
184  BESDEBUG(W10N_DEBUG_KEY, "json_simple_type_array_sender() - indx NOT equal to content length! indx: " << indx << " length: " << length << endl);
185 
186 }
187 
188 
193 void W10nJsonTransform::json_string_array_sender(ostream *strm, libdap::Array *a){
194 
195  bool found_w10n_flatten = false;
196  std::string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY,found_w10n_flatten);
197  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array_sender() - w10n_flatten: "<< w10n_flatten << endl);
198 
199  int numDim = a->dimensions(true);
200  vector<unsigned int> shape(numDim);
201  long length = w10n::computeConstrainedShape(a, &shape);
202 
203  // The string type utilizes a specialized version of libdap:Array.value()
204  vector<std::string> sourceValues;
205  a->value(sourceValues);
206  unsigned int indx = json_simple_type_array_worker(strm, (std::string *)(&sourceValues[0]), 0, &shape, 0, found_w10n_flatten);
207 
208  if(length != indx)
209  BESDEBUG(W10N_DEBUG_KEY, "json_simple_type_array_sender() - indx NOT equal to content length! indx: " << indx << " length: " << length << endl);
210 
211 }
212 
213 
218 template<typename T>void W10nJsonTransform::json_simple_type_array(ostream *strm, libdap::Array *a, std::string indent){
219 
220 #if 0
221  bool found_w10n_meta_object = false;
222  string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,found_w10n_meta_object);
223  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_meta_object: "<< w10n_meta_object << endl);
224 
225  bool found_w10n_callback = false;
226  string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY,found_w10n_callback);
227  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
228 
229  bool found_w10n_flatten = false;
230  string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY,found_w10n_flatten);
231  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_flatten: "<< w10n_flatten << endl);
232 
233  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - Processing Array of " << a->var()->type_name() << endl);
234 
235 
236  if(found_w10n_callback){
237  *strm << w10n_callback << "(";
238  }
239 
240 
241  *strm << "{" << endl;
242 
243  string child_indent = indent + _indent_increment;
244 
245  int numDim = a->dimensions(true);
246  vector<unsigned int> shape(numDim);
247  long length = w10n::computeConstrainedShape(a, &shape);
248 
249  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - Writing variable metadata..." << endl);
250 
251  writeVariableMetadata(strm,a,child_indent);
252  *strm << "," << endl;
253 
254  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - Writing variable data..." << endl);
255 
256  // Data
257  *strm << child_indent << "\"data\": ";
258  unsigned int indx;
259 
260  T *src = new T[length];
261  a->value(src);
262  indx = json_simple_type_array_worker(strm, src, 0, &shape, 0, found_w10n_flatten);
263  delete src;
264 
265  if(length != indx)
266  BESDEBUG(W10N_DEBUG_KEY, "json_simple_type_array() - indx NOT equal to content length! indx: " << indx << " length: " << length << endl);
267 
268  if(found_w10n_meta_object)
269  *strm << "," << endl << child_indent << w10n_meta_object << endl;
270  else
271  *strm << endl;
272 
273  *strm << indent << "}" << endl;
274 
275  if(found_w10n_callback){
276  *strm << ")";
277  }
278 
279  *strm << endl;
280 
281 #endif
282 
283  json_array_starter(strm,a, indent);
284  json_simple_type_array_sender<T>(strm,a);
285  json_array_ender(strm, indent);
286 
287 }
288 
289 
294 void W10nJsonTransform::json_string_array(ostream *strm, libdap::Array *a, std::string indent){
295 
296 #if 0
297  bool found_w10n_meta_object = false;
298  string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,found_w10n_meta_object);
299  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array_string() - w10n_meta_object: "<< w10n_meta_object << endl);
300 
301  bool found_w10n_callback = false;
302  string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY,found_w10n_callback);
303  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array_string() - w10n_callback: "<< w10n_callback << endl);
304 
305  bool found_w10n_flatten = false;
306  string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY,found_w10n_flatten);
307  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array_string() - w10n_flatten: "<< w10n_flatten << endl);
308 
309  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array_string() - Processing Array of " << a->var()->type_name() << endl);
310 
311 
312  if(found_w10n_callback){
313  *strm << w10n_callback << "(";
314  }
315 
316  *strm << "{" << endl;
317 
318  string child_indent = indent + _indent_increment;
319 
320  int numDim = a->dimensions(true);
321  vector<unsigned int> shape(numDim);
322  long length = w10n::computeConstrainedShape(a, &shape);
323 
324  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array_string() - Writing variable metadata..." << endl);
325 
326  writeVariableMetadata(strm,a,child_indent);
327  *strm << "," << endl;
328 
329  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array_string() - Writing variable data..." << endl);
330 
331  // Data
332  *strm << child_indent << "\"data\": ";
333  unsigned int indx;
334 
335  // The string type utilizes a specialized version of libdap:Array.value()
336  vector<std::string> sourceValues;
337  a->value(sourceValues);
338  indx = json_simple_type_array_worker(strm, (std::string *)(&sourceValues[0]), 0, &shape, 0, found_w10n_flatten);
339 
340 
341  if(length != indx)
342  BESDEBUG(W10N_DEBUG_KEY, "json_simple_type_array_string() - indx NOT equal to content length! indx: " << indx << " length: " << length << endl);
343 
344 
345  if(found_w10n_meta_object)
346  *strm << "," << endl << child_indent << w10n_meta_object << endl;
347  else
348  *strm << endl;
349 
350  *strm << indent << "}" << endl;
351 
352  if(found_w10n_callback){
353  *strm << ")";
354  }
355 
356  *strm << endl;
357 
358 #endif
359 
360  json_array_starter(strm,a, indent);
361  json_string_array_sender(strm,a);
362  json_array_ender(strm, indent);
363 
364 }
365 
366 
370 void W10nJsonTransform::writeDatasetMetadata(ostream *strm, libdap::DDS *dds, std::string indent){
371 
372  // Name
373  *strm << indent << "\"name\": \""<< dds->get_dataset_name() << "\"," << endl;
374 
375  //Attributes
376  writeAttributes(strm, dds->get_attr_table(), indent);
377  *strm << "," << endl;
378 
379 }
380 
381 
386 void W10nJsonTransform::writeVariableMetadata(ostream *strm, libdap::BaseType *bt, std::string indent){
387 
388  // Name
389  *strm << indent << "\"name\": \""<< bt->name() << "\"," << endl;
390  libdap::BaseType *var = bt;
391 
392 
393  // w10n type
394  if(bt->type() == libdap::dods_array_c){
395  libdap::Array *a = (libdap::Array *)bt;
396  var = a->var();
397  }
398  if(!var->is_constructor_type())
399  *strm << indent << "\"type\": \""<< var->type_name() << "\"," << endl;
400 
401  //Attributes
402  writeAttributes(strm, bt->get_attr_table(), indent);
403 
404 
405 
406 
407 }
408 
409 
410 
411 
423 W10nJsonTransform::W10nJsonTransform(libdap::DDS *dds, BESDataHandlerInterface &dhi, const std::string &localfile) :
424  _dds(dds), _localfile(localfile), _indent_increment(" "), _ostrm(0), _usingTempFile(false)
425 {
426  if (!_dds){
427  std::string msg = "W10nJsonTransform: ERROR! A null DDS reference was passed to the constructor";
428  BESDEBUG(W10N_DEBUG_KEY, msg << endl);
429  throw BESInternalError(msg, __FILE__, __LINE__);
430  }
431 
432  if (_localfile.empty()){
433  std::string msg = "W10nJsonTransform: An empty local file name passed to constructor";
434  BESDEBUG(W10N_DEBUG_KEY, msg << endl);
435  throw BESInternalError(msg, __FILE__, __LINE__);
436  }
437 }
438 
439 W10nJsonTransform::W10nJsonTransform(libdap::DDS *dds, BESDataHandlerInterface &dhi, std::ostream *ostrm) :
440  _dds(dds), _localfile(""), _indent_increment(" "), _ostrm(ostrm), _usingTempFile(false)
441 {
442  if (!_dds){
443  std::string msg = "W10nJsonTransform: ERROR! A null DDS reference was passed to the constructor";
444  BESDEBUG(W10N_DEBUG_KEY, msg << endl);
445  throw BESInternalError(msg, __FILE__, __LINE__);
446  }
447 
448  if (!_ostrm){
449  std::string msg = "W10nJsonTransform: ERROR! A null std::ostream pointer was passed to the constructor";
450  BESDEBUG(W10N_DEBUG_KEY, msg << endl);
451  throw BESInternalError(msg, __FILE__, __LINE__);
452  }
453 }
454 
460 {
461 }
462 
472 void W10nJsonTransform::dump(ostream &strm) const
473 {
474  strm << BESIndent::LMarg << "W10nJsonTransform::dump - (" << (void *) this << ")" << endl;
476  strm << BESIndent::LMarg << "temporary file = " << _localfile << endl;
477  if(_dds != 0){
478  _dds->print(strm);
479  }
481 }
482 
483 
488 void W10nJsonTransform::writeAttributes(ostream *strm, libdap::AttrTable &attr_table, std::string indent){
489 
490  std::string child_indent = indent + _indent_increment;
491 
492  // Start the attributes block
493  *strm << indent << "\"attributes\": [";
494 
495 
496 // if(attr_table.get_name().length()>0)
497 // *strm << endl << child_indent << "{\"name\": \"name\", \"value\": \"" << attr_table.get_name() << "\"},";
498 
499 
500  // Only do more if there are actually attributes in the table
501  if(attr_table.get_size() != 0) {
502  *strm << endl;
503  libdap::AttrTable::Attr_iter begin = attr_table.attr_begin();
504  libdap::AttrTable::Attr_iter end = attr_table.attr_end();
505 
506 
507  for(libdap::AttrTable::Attr_iter at_iter=begin; at_iter !=end; at_iter++){
508 
509  switch (attr_table.get_attr_type(at_iter)){
510  case libdap::Attr_container:
511  {
512  libdap::AttrTable *atbl = attr_table.get_attr_table(at_iter);
513 
514  // not first thing? better use a comma...
515  if(at_iter != begin )
516  *strm << "," << endl;
517 
518  // Attribute Containers need to be opened and then a recursive call gets made
519  *strm << child_indent << "{" << endl;
520 
521  // If the table has a name, write it out as a json property.
522  if(atbl->get_name().length()>0)
523  *strm << child_indent + _indent_increment << "\"name\": \"" << atbl->get_name() << "\"," << endl;
524 
525 
526  // Recursive call for child attribute table.
527  writeAttributes(strm, *atbl, child_indent + _indent_increment);
528  *strm << endl << child_indent << "}";
529 
530  break;
531 
532  }
533  default:
534  {
535  // not first thing? better use a comma...
536  if(at_iter != begin)
537  *strm << "," << endl;
538 
539  // Open attribute object, write name
540  *strm << child_indent << "{\"name\": \""<< attr_table.get_name(at_iter) << "\", ";
541 
542  // Open value array
543  *strm << "\"value\": [";
544  vector<std::string> *values = attr_table.get_attr_vector(at_iter);
545  // write values
546  for(std::vector<std::string>::size_type i=0; i<values->size() ;i++){
547 
548  // not first thing? better use a comma...
549  if(i>0)
550  *strm << ",";
551 
552  // Escape the double quotes found in String and URL type attribute values.
553  if(attr_table.get_attr_type(at_iter) == libdap::Attr_string || attr_table.get_attr_type(at_iter) == libdap::Attr_url){
554  *strm << "\"";
555  std::string value = (*values)[i] ;
556  *strm << w10n::escape_for_json(value) ;
557  *strm << "\"";
558  }
559  else {
560 
561  *strm << (*values)[i] ;
562  }
563 
564  }
565  // close value array
566  *strm << "]}";
567  break;
568  }
569 
570  }
571  }
572  *strm << endl << indent;
573 
574  }
575 
576  // close AttrTable JSON
577 
578  *strm << "]";
579 
580 
581 
582 }
583 
584 std::ostream *W10nJsonTransform::getOutputStream(){
585  // used to ensure the _ostrm is closed only when it's a temp file
586  _usingTempFile = false;
587  std::fstream _tempFile;
588 
589  if (!_ostrm) {
590  _tempFile.open(_localfile.c_str(), std::fstream::out);
591  if (!_tempFile){
592  std::string msg = "Could not open temp file: " + _localfile;
593  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::getOutputStream() - ERROR! "<< msg << endl);
594  throw BESInternalError(msg, __FILE__, __LINE__);
595  }
596  _ostrm = &_tempFile;
597  _usingTempFile = true;
598  }
599 
600  return _ostrm;
601 }
602 
603 void W10nJsonTransform::releaseOutputStream(){
604  if (_usingTempFile){
605  ((std::fstream *)_ostrm)->close();
606  _ostrm = 0;
607  }
608 }
609 
610 
612 
613  std::ostream *strm = getOutputStream();
614  try {
615  sendW10nMetaForDDS(strm, _dds, "");
616  releaseOutputStream();
617  }
618  catch (...) {
619  releaseOutputStream();
620  throw;
621  }
622 
623 }
624 
625 
626 
627 void W10nJsonTransform::sendW10nMetaForDDS(ostream *strm, libdap::DDS *dds, std::string indent){
628 
629 
630 
631  bool found_w10n_meta_object = false;
632  std::string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,found_w10n_meta_object);
633  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_meta_object: "<< w10n_meta_object << endl);
634 
635  bool found_w10n_callback = false;
636  std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY,found_w10n_callback);
637  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
638 
639 
643  vector<libdap::BaseType *> leaves;
644  vector<libdap::BaseType *> nodes;
645 
646  libdap::DDS::Vars_iter vi = dds->var_begin();
647  libdap::DDS::Vars_iter ve = dds->var_end();
648  for (; vi != ve; vi++) {
649  libdap::BaseType *v = *vi;
650  if (v->send_p()) {
651  libdap::Type type = v->type();
652  if(type == libdap::dods_array_c){
653  type = v->var()->type();
654  }
655  if(v->is_constructor_type() ||
656  (v->is_vector_type() && v->var()->is_constructor_type())){
657  nodes.push_back(v);
658  }
659  else {
660  leaves.push_back(v);
661  }
662  }
663  }
664 
665  if(found_w10n_callback){
666  *strm << w10n_callback << "(";
667  }
668 
669 
670  // Declare the top level node
671  *strm << "{" << endl ;
672  std::string child_indent = indent + _indent_increment;
673 
674  // Write the top level node's metadata (name & attributes)
675  writeDatasetMetadata(strm, dds, child_indent);
676 
677 
678 
679  // Write down the leaves
680  *strm << child_indent << "\"leaves\": [";
681  if(leaves.size() > 0)
682  *strm << endl;
683  for(std::vector<libdap::BaseType *>::size_type l=0; l< leaves.size(); l++){
684  libdap::BaseType *v = leaves[l];
685  BESDEBUG(W10N_DEBUG_KEY, "Processing LEAF: " << v->name() << endl);
686  if( l>0 ){
687  *strm << "," << endl ;
688  }
689 
690  sendW10nMetaForVariable(strm, v, child_indent + _indent_increment,false);
691  }
692  if(leaves.size()>0)
693  *strm << endl << child_indent;
694  *strm << "]," << endl;
695 
696 
697  // Write down the child nodes
698  *strm << child_indent << "\"nodes\": [";
699  if(nodes.size() > 0)
700  *strm << endl;
701  for(std::vector<libdap::BaseType *>::size_type n=0; n< nodes.size(); n++){
702  libdap::BaseType *v = nodes[n];
703  BESDEBUG(W10N_DEBUG_KEY, "Processing NODE: " << v->name() << endl);
704  if( n>0 ){
705  *strm << "," << endl ;
706  }
707  sendW10nMetaForVariable(strm, v, child_indent + _indent_increment,false);
708  }
709  if(nodes.size()>0)
710  *strm << endl << child_indent;
711 
712  *strm << "]";
713 
714 
715  if(found_w10n_meta_object)
716  *strm << "," << endl << child_indent << w10n_meta_object << endl;
717  else
718  *strm << endl;
719 
720  *strm << "}";
721 
722  if(found_w10n_callback){
723  *strm << ")";
724  }
725 
726  *strm << endl;
727 
728 
729 }
730 
731 void W10nJsonTransform::sendW10nMetaForVariable(ostream *strm, libdap::BaseType *bt, std::string indent, bool isTop){
732 
733 
734 
735  bool found_w10n_meta_object = false;
736  std::string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,found_w10n_meta_object);
737  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_meta_object: "<< w10n_meta_object << endl);
738 
739  bool found_w10n_callback = false;
740  std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY,found_w10n_callback);
741  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
742 
743  bool found_w10n_flatten = false;
744  std::string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY,found_w10n_flatten);
745  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_flatten: "<< w10n_flatten << endl);
746 
747 
748  bool found_w10n_traverse = false;
749  std::string w10n_traverse = BESContextManager::TheManager()->get_context(W10N_TRAVERSE_KEY,found_w10n_traverse);
750  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_traverse: "<< w10n_traverse << endl);
751 
752 
753 
754  if(isTop && found_w10n_callback){
755  *strm << w10n_callback << "(";
756  }
757 
758 
759  *strm << indent << "{" << endl;\
760 
761  std::string child_indent = indent + _indent_increment;
762 
763  writeVariableMetadata(strm,bt,child_indent);
764 
765 
766  if(bt->type() == libdap::dods_array_c){
767  *strm << "," << endl;
768 
769  libdap::Array *a = (libdap::Array *) bt;
770  int numDim = a->dimensions(true);
771  vector<unsigned int> shape(numDim);
772  long length = w10n::computeConstrainedShape(a, &shape);
773 
774  if(found_w10n_flatten){
775  *strm << child_indent << "\"shape\": [" << length << "]";
776 
777  }
778  else {
779  *strm << child_indent << "\"shape\": [";
780  for(std::vector<unsigned int>::size_type i=0; i<shape.size() ;i++){
781  if(i>0)
782  *strm << ",";
783  *strm << shape[i];
784  }
785  *strm << "]";
786  }
787  }
788  else {
789  if(bt->is_constructor_type() && (found_w10n_traverse || isTop)){
790  *strm << "," << endl;
791 
792  libdap::Constructor *ctor = (libdap::Constructor *)bt;
793 
794  vector<libdap::BaseType *> leaves;
795  vector<libdap::BaseType *> nodes;
796  libdap::Constructor::Vars_iter vi = ctor->var_begin();
797  libdap::Constructor::Vars_iter ve = ctor->var_end();
798  for (; vi != ve; vi++) {
799  libdap::BaseType *v = *vi;
800  if (v->send_p()) {
801  libdap::Type type = v->type();
802  if(type == libdap::dods_array_c){
803  type = v->var()->type();
804  }
805  if(v->is_constructor_type() ||
806  (v->is_vector_type() && v->var()->is_constructor_type())){
807  nodes.push_back(v);
808  }
809  else {
810  leaves.push_back(v);
811  }
812  }
813  }
814 
815  // Write down the leaves
816  *strm << child_indent << "\"leaves\": [";
817  if(leaves.size() > 0)
818  *strm << endl;
819  for(std::vector<libdap::BaseType *>::size_type l=0; l< leaves.size(); l++){
820  libdap::BaseType *v = leaves[l];
821  BESDEBUG(W10N_DEBUG_KEY, "Processing LEAF: " << v->name() << endl);
822  if( l>0 ){
823  *strm << "," ;
824  *strm << endl ;
825  }
826 
827  sendW10nMetaForVariable(strm, v, child_indent + _indent_increment,false);
828  }
829  if(leaves.size()>0)
830  *strm << endl << child_indent;
831  *strm << "]," << endl;
832 
833 
834  // Write down the child nodes
835  *strm << child_indent << "\"nodes\": [";
836  if(nodes.size() > 0)
837  *strm << endl;
838  for(std::vector<libdap::BaseType *>::size_type n=0; n< nodes.size(); n++){
839  libdap::BaseType *v = nodes[n];
840  BESDEBUG(W10N_DEBUG_KEY, "Processing NODE: " << v->name() << endl);
841  if( n>0 ){
842  *strm << "," << endl ;
843  }
844  sendW10nMetaForVariable(strm, v, child_indent + _indent_increment,false);
845  }
846  if(nodes.size()>0)
847  *strm << endl << child_indent;
848 
849  *strm << "]";
850 
851 
852 
853  }
854  else {
855  if(!bt->is_constructor_type()){
856  // *strm << endl;
857  // *strm << "," << endl;
858  // *strm << child_indent << "\"shape\": [1]";
859  }
860 
861  }
862  }
863 
864  if(isTop && found_w10n_meta_object){
865  *strm << "," << endl << child_indent << w10n_meta_object << endl;
866  }
867 
868 
869 
870  *strm << endl << indent << "}";
871 
872  if(isTop && found_w10n_callback){
873  *strm << ")";
874  }
875 
876 }
877 
878 
879 
880 
881 
882 void W10nJsonTransform::sendW10nMetaForVariable(std::string &vName, bool isTop){
883 
884 
885  libdap::BaseType *bt = _dds->var(vName);
886 
887  if(!bt){
888  std::string msg = "The dataset does not contain a variable named '" + vName +"'";
889  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << msg << endl);
890  throw BESSyntaxUserError(msg, __FILE__, __LINE__);
891  }
892 
893  std::ostream *strm = getOutputStream();
894  try {
895  sendW10nMetaForVariable(strm, bt, "", isTop);
896  *strm << endl;
897  releaseOutputStream();
898  }
899  catch (...) {
900  releaseOutputStream();
901  throw;
902  }
903 
904 }
905 
906 
907 
908 
909 void W10nJsonTransform::sendW10nDataForVariable(std::string &vName){
910 
911 
912  libdap::BaseType *bt = _dds->var(vName);
913 
914  if(!bt){
915  std::string msg = "The dataset does not contain a variable named '" + vName +"'";
916  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nDataForVariable() - ERROR! " << msg << endl);
917  throw BESSyntaxUserError(msg, __FILE__, __LINE__);
918  }
919 
920  std::ostream *strm = getOutputStream();
921  try {
922  sendW10nDataForVariable(strm, bt, "");
923  releaseOutputStream();
924  }
925  catch (...) {
926  releaseOutputStream();
927  throw;
928  }
929 
930 }
931 
932 void W10nJsonTransform::sendW10nDataForVariable(ostream *strm, libdap::BaseType *bt, std::string indent){
933 
934  if(bt->is_simple_type()){
935 
936  sendW10nData(strm, bt, indent);
937 
938  }
939  else if(bt->type()==libdap::dods_array_c && bt->var()->is_simple_type()){
940  sendW10nData(strm, (libdap::Array *)bt, indent);
941 
942  }
943  else {
944  std::string msg = "The variable '" + bt->name() +"' is not a simple type or an Array of simple types. ";
945  msg += "The w10n protocol does not support the transmission of data for complex types.";
946  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nDataForVariable() - ERROR! " << msg << endl);
947  throw BESSyntaxUserError(msg, __FILE__, __LINE__);
948  }
949 
950 
951 }
952 
953 
958 void W10nJsonTransform::sendW10nData(ostream *strm, libdap::BaseType *b, std::string indent){
959 
960  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nData() - Sending data for simple type "<< b->name() << endl);
961 
962  bool found_w10n_meta_object = false;
963  std::string w10n_meta_object = BESContextManager::TheManager()->get_context(W10N_META_OBJECT_KEY,found_w10n_meta_object);
964  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_meta_object: "<< w10n_meta_object << endl);
965 
966  bool found_w10n_callback = false;
967  std::string w10n_callback = BESContextManager::TheManager()->get_context(W10N_CALLBACK_KEY,found_w10n_callback);
968  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_callback: "<< w10n_callback << endl);
969 
970  bool found_w10n_flatten = false;
971  std::string w10n_flatten = BESContextManager::TheManager()->get_context(W10N_FLATTEN_KEY,found_w10n_flatten);
972  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::json_simple_type_array() - w10n_flatten: "<< w10n_flatten << endl);
973 
974 
975 
976 
977 
978  std::string child_indent = indent + _indent_increment;
979 
980  if(found_w10n_callback){
981  *strm << w10n_callback << "(";
982  }
983 
984 
985  *strm << "{" << endl;
986 
987  writeVariableMetadata(strm,b,child_indent);
988  *strm << "," << endl;
989 
990 
991  *strm << child_indent << "\"data\": ";
992 
993  if(b->type() == libdap::dods_str_c || b->type() == libdap::dods_url_c ){
994  libdap::Str *strVar = (libdap::Str *)b;
995  *strm << "\"" << w10n::escape_for_json(strVar->value()) << "\"";
996  }
997  else {
998  b->print_val(*strm, "", false);
999  }
1000 
1001 
1002 
1003  if(found_w10n_meta_object)
1004  *strm << "," << endl << child_indent << w10n_meta_object << endl;
1005  else
1006  *strm << endl;
1007 
1008  *strm << "}";
1009 
1010  if(found_w10n_callback){
1011  *strm << ")";
1012  }
1013  *strm << endl;
1014 
1015 
1016  // *strm << "]";
1017 
1018 }
1019 
1020 
1021 void W10nJsonTransform::sendW10nData(ostream *strm, libdap::Array *a, std::string indent){
1022 
1023 
1024  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::transform() - Processing Array. "
1025  << " a->type_name(): " << a->type_name()
1026  << " a->var()->type_name(): " << a->var()->type_name()
1027  << endl);
1028 
1029  switch(a->var()->type()){
1030  // Handle the atomic types - that's easy!
1031  case libdap::dods_byte_c:
1032  json_simple_type_array<libdap::dods_byte>(strm,a,indent);
1033  break;
1034 
1035  case libdap::dods_int16_c:
1036  json_simple_type_array<libdap::dods_int16>(strm,a,indent);
1037  break;
1038 
1039  case libdap::dods_uint16_c:
1040  json_simple_type_array<libdap::dods_uint16>(strm,a,indent);
1041  break;
1042 
1043  case libdap::dods_int32_c:
1044  json_simple_type_array<libdap::dods_int32>(strm,a,indent);
1045  break;
1046 
1047  case libdap::dods_uint32_c:
1048  json_simple_type_array<libdap::dods_uint32>(strm,a,indent);
1049  break;
1050 
1051  case libdap::dods_float32_c:
1052  json_simple_type_array<libdap::dods_float32>(strm,a,indent);
1053  break;
1054 
1055  case libdap::dods_float64_c:
1056  json_simple_type_array<libdap::dods_float64>(strm,a,indent);
1057  break;
1058 
1059  case libdap::dods_str_c:
1060  {
1061  json_string_array(strm,a,indent);
1062  break;
1063 #if 0
1064  string s = (string) "W10nJsonTransform: Arrays of String objects not a supported return type.";
1065  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
1066  throw BESInternalError(s, __FILE__, __LINE__);
1067  break;
1068 #endif
1069  }
1070 
1071  case libdap::dods_url_c:
1072  {
1073  json_string_array(strm,a,indent);
1074  break;
1075 
1076 #if 0
1077  string s = (string) "W10nJsonTransform: Arrays of URL objects not a supported return type.";
1078  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
1079  throw BESInternalError(s, __FILE__, __LINE__);
1080  break;
1081 #endif
1082  }
1083 
1084  case libdap::dods_structure_c:
1085  {
1086  std::string s = (std::string) "W10nJsonTransform: Arrays of Structure objects not a supported return type.";
1087  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
1088  throw BESInternalError(s, __FILE__, __LINE__);
1089  break;
1090  }
1091  case libdap::dods_grid_c:
1092  {
1093  std::string s = (std::string) "W10nJsonTransform: Arrays of Grid objects not a supported return type.";
1094  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
1095  throw BESInternalError(s, __FILE__, __LINE__);
1096  break;
1097  }
1098 
1099  case libdap::dods_sequence_c:
1100  {
1101  std::string s = (std::string) "W10nJsonTransform: Arrays of Sequence objects not a supported return type.";
1102  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
1103  throw BESInternalError(s, __FILE__, __LINE__);
1104  break;
1105  }
1106 
1107  case libdap::dods_array_c:
1108  {
1109  std::string s = (std::string) "W10nJsonTransform: Arrays of Array objects not a supported return type.";
1110  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
1111  throw BESInternalError(s, __FILE__, __LINE__);
1112  break;
1113  }
1114  case libdap::dods_int8_c:
1115  case libdap::dods_uint8_c:
1116  case libdap::dods_int64_c:
1117  case libdap::dods_uint64_c:
1118  // case libdap::dods_url4_c:
1119  case libdap::dods_enum_c:
1120  case libdap::dods_group_c:
1121  {
1122  std::string s = (std::string) "W10nJsonTransform: DAP4 types not yet supported.";
1123  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
1124  throw BESInternalError(s, __FILE__, __LINE__);
1125  break;
1126  }
1127 
1128  default:
1129  {
1130  std::string s = (std::string) "W10nJsonTransform: Unrecognized type.";
1131  BESDEBUG(W10N_DEBUG_KEY, "W10nJsonTransform::sendW10nMetaForVariable() - ERROR! " << s << endl);
1132  throw BESInternalError(s, __FILE__, __LINE__);
1133  break;
1134  }
1135 
1136  }
1137 
1138 }
1139 
1140 
1141 
exception thrown if inernal error encountered
#define W10N_TRAVERSE_KEY
Definition: W10NNames.h:9
#define W10N_FLATTEN_KEY
Definition: W10NNames.h:7
std::string escape_for_json(const std::string &input)
Definition: w10n_utils.cc:222
#define W10N_META_OBJECT_KEY
Definition: W10NNames.h:6
virtual void sendW10nMetaForDDS()
virtual string get_context(const string &name, bool &found)
retrieve the value of the specified context from the BES
static void Indent()
Definition: BESIndent.cc:38
error thrown if there is a user syntax error in the request or any other user error ...
#define W10N_CALLBACK_KEY
Definition: W10NNames.h:8
static ostream & LMarg(ostream &strm)
Definition: BESIndent.cc:73
#define W10N_DEBUG_KEY
Definition: W10NNames.h:4
static BESContextManager * TheManager()
long computeConstrainedShape(libdap::Array *a, std::vector< unsigned int > *shape)
Definition: w10n_utils.cc:296
Structure storing information used by the BES to handle the request.
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
static void UnIndent()
Definition: BESIndent.cc:44
virtual void dump(std::ostream &strm) const
dumps information about this transformation object for debugging purposes
virtual ~W10nJsonTransform()
Destructor.
W10nJsonTransform(libdap::DDS *dds, BESDataHandlerInterface &dhi, const std::string &localfile)
Constructor that creates transformation object from the specified DataDDS object to the specified fil...