Flow123d  release_2.1.0-84-g6a13a75
type_output.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file type_output.cc
15  * @brief
16  */
17 
18 #include "input/type_output.hh"
19 #include "input/type_repository.hh"
20 #include "input/type_generic.hh"
21 #include "input/type_tuple.hh"
22 #include "input/type_selection.hh"
23 #include "system/system.hh"
24 #include <boost/algorithm/string/replace.hpp>
25 #include <boost/iostreams/filtering_stream.hpp>
26 #include <boost/iostreams/concepts.hpp>
27 #include <boost/iostreams/operations.hpp> // put
28 
29 
30 #include <string>
31 #include <limits>
32 #include <boost/regex.hpp>
33 
34 namespace Input {
35 namespace Type {
36 
37 using namespace std;
38 
39 
40 /*******************************************************************
41  * implementation of OutputBase
42  */
43 
45 
46 
47 
49 {}
50 
51 
52 
53 void OutputBase::get_integer_bounds(Integer integer, int &lower , int &upper ) {
54  lower = integer.lower_bound_;
55  upper = integer.upper_bound_;
56 }
57 
58 
59 
60 void OutputBase::get_double_bounds(Double dbl, double &lower , double &upper ) {
61  lower = dbl.lower_bound_;
62  upper = dbl.upper_bound_;
63 }
64 
65 
66 
67 void OutputBase::get_array_sizes(Array array, unsigned int &lower , unsigned int &upper ) {
68  lower = array.data_->lower_bound_;
69  upper = array.data_->upper_bound_;
70 }
71 
72 
73 
74 void OutputBase::get_array_type(Array array, std::shared_ptr<TypeBase> &arr_type) {
75  arr_type = array.data_->type_of_values_;
76 }
77 
78 
79 
80 const string & OutputBase::get_record_description(const Record *rec) {
81  return rec->data_->description_;
82 }
83 
84 
85 
86 const string & OutputBase::get_abstract_description(const Abstract *a_rec) {
87  return a_rec->child_data_->description_;
88 }
89 
90 
91 
92 void OutputBase::get_parent_vec(Record rec, std::vector< std::shared_ptr<Abstract> > &parent_vec) {
93  parent_vec = rec.data_->parent_vec_;
94 }
95 
96 
97 
98 void OutputBase::get_default(Record::KeyIter it, string &type, string &value) {
99  value = it->default_.value_;
100  if ( it->default_.is_obligatory() ) {
101  type = "obligatory";
102  } else if ( it->default_.is_optional() ) {
103  type = "optional";
104  } else if ( it->default_.has_value_at_read_time() ) {
105  type = "value at read time";
106  } else {
107  type = "value at declaration";
108  }
109 
110 }
111 
112 
114  return sel->data_->description_;
115 }
116 
117 
118 void OutputBase::get_adhoc_parent_name(const AdHocAbstract *a_rec, string &parent_name) {
119  parent_name = a_rec->ancestor_.type_name();
120 }
121 
122 
124  return a_rec->ancestor_.child_data_->list_of_childs.begin();
125 }
126 
127 template <class T>
128 void OutputBase::print_generic(ostream& stream, const TypeBase *type) {
129  // print possible generic
130  if (type->generic_type_hash_) {
131  const T *gen_type = Input::TypeRepository<T>::get_instance().find_hash(type->generic_type_hash_).get();
132  ASSERT(gen_type)(type->hash_str())(type->type_name());
133  print_base(stream, gen_type);
134  }
135 }
136 void OutputBase::print_base(ostream& stream, const TypeBase *type) {
137 
138  ASSERT(type);
139 
140  if (typeid(*type) == typeid(Type::Tuple)) {
141  print_generic<Tuple>(stream, type);
142  print_impl(stream, static_cast<const Type::Record *>(type) );
143  } else
144  if (typeid(*type) == typeid(Type::Record)) {
145  print_generic<Record>(stream, type);
146  print_impl(stream, static_cast<const Type::Record *>(type) );
147  } else
148  if (typeid(*type) == typeid(Type::Array)) {
149  print_impl(stream, static_cast<const Type::Array *>(type) );
150  } else
151  if (typeid(*type) == typeid(Type::Abstract)) {
152  print_impl(stream, static_cast<const Type::Abstract *>(type) );
153  } else
154  if (typeid(*type) == typeid(Type::AdHocAbstract)) {
155  print_impl(stream, static_cast<const Type::AdHocAbstract *>(type) );
156  } else
157  if (typeid(*type) == typeid(Type::Selection)) {
158  print_impl(stream, static_cast<const Type::Selection *>(type) );
159  } else
160  if (typeid(*type) == typeid(Type::Integer)) {
161  print_impl(stream, static_cast<const Type::Integer *>(type) );
162  } else
163  if (typeid(*type) == typeid(Type::Double)) {
164  print_impl(stream, static_cast<const Type::Double *>(type) );
165  } else
166  if (typeid(*type) == typeid(Type::Bool)) {
167  print_impl(stream, static_cast<const Type::Bool *>(type) );
168  } else
169  if (typeid(*type) == typeid(Type::Parameter)) {
170  print_impl(stream, static_cast<const Type::Parameter *>(type) );
171  } else {
172  const Type::FileName * file_name_type = dynamic_cast<const Type::FileName *>(type);
173  if (file_name_type != NULL ) {
174  print_impl(stream, file_name_type );
175  return;
176  }
177 
178  const Type::String * string_type = dynamic_cast<const Type::String *>(type);
179  if (string_type != NULL ) {
180  print_impl(stream, string_type );
181  return;
182  }
183 
184  // default -> error
185  THROW( Type::ExcUnknownDescendant() << Type::EI_TypeName(typeid(type).name()) );
186  }
187 }
188 
189 
190 void OutputBase::write_default_value(std::ostream& stream, Default dft) {
191  if (dft.is_obligatory() || dft.is_optional()) {
192  stream << "<" << dft.value() << ">";
193  } else {
194  stream << "\"" << dft.value() << "\"";
195  }
196 }
197 
198 void OutputBase::write_description(std::ostream& stream, const string& str,
199  unsigned int padding, unsigned int hash_count) {
200  string s = str;
201  boost::replace_all(s, "\\$", "$");
202 
203  boost::tokenizer<boost::char_separator<char> > line_tokenizer(s, boost::char_separator<char>("\n"));
204  boost::tokenizer<boost::char_separator<char> >::iterator it;
205 
206  // For every \n add padding at beginning of the next line.
207  for(it = line_tokenizer.begin(); it != line_tokenizer.end(); ++it) {
208  stream << endl;
209  stream << setw(padding) << "";
210  stream << std::setfill('#') << setw(hash_count) << "" << std::setfill(' ') << " " << *it;
211  }
212 }
213 
214 
216  processed_types_hash_.clear();
217  full_hash_ = 0;
218 }
219 
220 
221 bool OutputBase::was_written(std::size_t hash)
222 {
223  bool in_set = ( processed_types_hash_.find(hash) != processed_types_hash_.end() );
224  if (! in_set) processed_types_hash_.insert(hash);
225  return in_set;
226 }
227 
229  TypeBase::TypeHash &generic_type_hash, TypeBase::json_string &parameter_map_to_json) {
230  attr_map = *( type->attributes_.get() );
231  generic_type_hash = type->generic_type_hash_;
232  if (type->parameter_map_.size()) {
233  parameter_map_to_json = type->print_parameter_map_to_json( type->parameter_map_ );
234  }
235 }
236 
237 
238 
239 
240 /*******************************************************************
241  * implementation of OutputText
242  */
243 
244 ostream& OutputText::print(ostream& stream) {
245  doc_type_ = full_record;
246  clear_processed_types();
247 
248  print_base(stream, type_);
249  return stream;
250 }
251 
252 void OutputText::print_impl(ostream& stream, const Record *type) {
253  ASSERT(type->is_finished())(type->type_name())(type->class_name()).warning("Printing documentation of unfinished type.");
254  switch (doc_type_) {
255  case key_record:
256  stream << "" << type->class_name() << " '" << type->type_name() << "' (" << type->size() << " keys).";
257  break;
258  case full_record:
259  TypeBase::TypeHash hash=type->content_hash();
260  if (! was_written(hash)) {
261  // header
262  stream << endl;
263  stream << "" << type->class_name() << " '" << type->type_name() << "'";
264  // parent record
265  /*std::shared_ptr<Abstract> parent_ptr;
266  get_parent_ptr(*type, parent_ptr);
267  if (parent_ptr) {
268  stream << ", implementation of " << parent_ptr->type_name();
269  }*/
270 
271  // reducible to key
272  Record::KeyIter key_it = type->auto_conversion_key_iter();
273  if (key_it != type->end()) {
274  stream << ", reducible to key '" << key_it->key_ << "'";
275  }
276  stream << "" << " (" << type->size() << " keys).";
277  write_description(stream, OutputBase::get_record_description(type), 0);
278  stream << endl;
279  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << endl;
280  // keys
281  doc_type_ = key_record;
282  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
283  size_setw_ = it->key_.size() + 3;
284  stream << setw(padding_size) << "" << it->key_ << " = ";
285  write_default_value(stream, it->default_);
286  stream << endl;
287  stream << setw(padding_size + size_setw_) << "" <<"#### is ";
288  print_base(stream, it->type_.get());
289  write_description(stream, it->description_, padding_size+size_setw_);
290  stream << endl;
291  }
292  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << " " << type->type_name() << endl;
293  // Full documentation of embedded record types.
294  doc_type_ = full_record;
295  }
296  break;
297  }
298 }
299 void OutputText::print_impl(ostream& stream, const Array *type) {
300  std::shared_ptr<TypeBase> array_type;
301  get_array_type(*type, array_type);
302  switch (doc_type_) {
303  case key_record:
304  unsigned int lower_size, upper_size;
305  get_array_sizes(*type, lower_size, upper_size);
306  stream << "Array, size limits: [" << lower_size << ", " << upper_size << "] of type: " << endl;
307  stream << setw(padding_size + size_setw_) << "" << "#### ";
308  print_base(stream, array_type.get());
309  break;
310  case full_record:
311  print_base(stream, array_type.get());
312  break;
313  }
314 }
315 
316 
317 void OutputText::print_impl(ostream& stream, const Abstract *type) {
318  // Print documentation of abstract record
319  switch (doc_type_) {
320  case key_record:
321  stream << "Abstract '" << type->type_name() << "' with "<< type->child_size() << " descendants.";
322  break;
323  case full_record:
324  TypeBase::TypeHash hash=type->content_hash();
325  if (! was_written(hash) ) {
326  // header
327  stream << endl;
328  stream << "" << "Abstract '" << type->type_name() << "' with " << type->child_size() << " descendants.";
329  write_description(stream, OutputBase::get_abstract_description( type ), 0);
330  stream << endl;
331  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << endl;
332  // descendants
333  doc_type_ = key_record;
334  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
335  size_setw_ = 0;
336  stream << setw(padding_size) << "";
337  stream << "" << "Record '" << (*it).type_name() << "'";
338  write_description(stream, OutputBase::get_record_description( &(*it) ), padding_size+size_setw_);
339  stream << endl;
340  }
341  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << " " << type->type_name() << endl;
342  // Full documentation of embedded record types.
343  doc_type_ = full_record;
344  }
345  break;
346  }
347 }
348 
349 
350 void OutputText::print_impl(ostream& stream, const AdHocAbstract *type) {
351  // Print documentation of adhoc abstract record
352  if (doc_type_ == key_record) {
353  stream << "AdHocAbstract";
354  /*string parent_name;
355  get_adhoc_parent_name(type, parent_name);
356  stream << "AdHocAbstract" << endl;
357  stream << setw(padding_size + size_setw_) << "";
358  stream << "#### Derived from Abstract '" << parent_name << "', ";
359  stream << "added Records: ";
360  {
361  Abstract::ChildDataIter parent_it = get_adhoc_parent_data(type);
362  bool add_comma = false;
363  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
364  if ((*it).type_name() == (*parent_it).type_name()) {
365  ++parent_it;
366  } else {
367  if (add_comma) stream << ", ";
368  else add_comma = true;
369  stream << "'" << (*it).type_name() << "'";
370  }
371  }
372  }*/
373  }
374 }
375 void OutputText::print_impl(ostream& stream, const Selection *type) {
376  ASSERT(type->is_finished())(type->type_name()).warning("Printing documentation of unfinished Input::Type::Selection.");
377  switch (doc_type_) {
378  case key_record:
379  stream << "Selection '" << type->type_name() << "' of " << type->size() << " values.";
380  break;
381  case full_record:
382  TypeBase::TypeHash hash=type->content_hash();
383  if (! was_written(hash) ) {
384  stream << endl << "Selection '" << type->type_name() << "' of " << type->size() << " values.";
385  write_description(stream, OutputBase::get_selection_description( type ), 0);
386  stream << endl;
387  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << endl;
388  // keys
389  for (Selection::keys_const_iterator it = type->begin(); it != type->end(); ++it) {
390  stream << setw(padding_size) << "" << it->key_ << " = " << it->value;
391  if (it->description_ != "") {
392  stream << endl;
393  stream << setw(padding_size + it->key_.size() + 3) << "" << "# " << it->description_ << "";
394  }
395  stream << endl;
396  }
397  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << " " << type->type_name() << endl;
398  }
399  break;
400  }
401 }
402 void OutputText::print_impl(ostream& stream, const Integer *type) {
403  if (doc_type_ == key_record) {
404  int lower_bound, upper_bound;
405  get_integer_bounds(*type, lower_bound, upper_bound);
406  stream << "Integer in [" << lower_bound << ", " << upper_bound << "]";
407  }
408 }
409 void OutputText::print_impl(ostream& stream, const Double *type) {
410  if (doc_type_ == key_record) {
411  double lower_bound, upper_bound;
412  get_double_bounds(*type, lower_bound, upper_bound);
413  stream << "Double in [" << lower_bound << ", " << upper_bound << "]";
414  }
415 }
416 void OutputText::print_impl(ostream& stream, const Bool *type) {
417  if (doc_type_ == key_record) {
418  stream << "Bool";
419  }
420 }
421 void OutputText::print_impl(ostream& stream, const String *type) {
422  if (doc_type_ == key_record) {
423  stream << "String (generic)";
424  }
425 }
426 void OutputText::print_impl(ostream& stream, const FileName *type) {
427  if (doc_type_ == key_record) {
428  stream << "FileName of ";
429  switch (type->get_file_type()) {
430  case ::FilePath::input_file:
431  stream << "input file";
432  break;
433  case ::FilePath::output_file:
434  stream << "output file";
435  break;
436  default:
437  stream << "file with unknown type";
438  break;
439  }
440  }
441 }
442 
443 
444 
445 void OutputText::print_impl(ostream& stream, const Parameter *type) {
446  ASSERT_DBG(false).error("Parameter appears in the IST. Check where Instance is missing.");
447 }
448 
449 
450 
451 
452 /*******************************************************************
453  * implementation of OutputJSONMachine
454  */
455 
457 : OutputBase()
458 {
459  rev_num_data_ = rev_num_data;
460 
461  format_head="{ \"version\" :";
462  format_inner=",\n\"ist_nodes\" : [\n";
463  format_full_hash="{}],\n";
464  format_tail="}\n";
465 }
466 
467 
468 
470 : OutputJSONMachine(rev_num_data)
471 {
472  root_type_ = root_type;
473  root_type_.finish();
474 }
475 
476 
477 std::string OutputJSONMachine::escape_description(std::string desc) {
478  static std::vector< std::pair<boost::regex, std::string> > rewrite_rules = {
479  // replace single slash with two slashes
480  {boost::regex("\\\\"), "\\\\\\\\"},
481  // replace quote with slash quote
482  {boost::regex("\\\""), "\\\\\""},
483  // replace special chars with escaped slash + special chars
484  {boost::regex("\\n"), "\\\\n"},
485  {boost::regex("\\t"), "\\\\t"},
486  {boost::regex("\\r"), "\\\\r"}
487  };
488 
489 
490  std::string tmp = std::string(desc);
491 
492  for (auto rewrite_rule : rewrite_rules) {
493  tmp = boost::regex_replace(tmp, rewrite_rule.first, rewrite_rule.second);
494  }
495 
496  return tmp;
497 }
498 
499 
500 ostream& OutputJSONMachine::print(ostream& stream) {
503 
504  stream << format_head;
505  print_program_info(stream);
506  stream << format_inner;
507 
508  print_base( stream, &root_type_);
509  /*
510  for (Input::TypeRepository<Selection>::TypeRepositoryMapIter it = Input::TypeRepository<Selection>::get_instance().begin();
511  it != Input::TypeRepository<Selection>::get_instance().end(); ++it) {
512  print_base( stream, it->second.get() );
513  }
514  for (Input::TypeRepository<Abstract>::TypeRepositoryMapIter it = Input::TypeRepository<Abstract>::get_instance().begin();
515  it != Input::TypeRepository<Abstract>::get_instance().end(); ++it) {
516  print_base( stream, it->second.get() );
517  }
518  for (Input::TypeRepository<Record>::TypeRepositoryMapIter it = Input::TypeRepository<Record>::get_instance().begin();
519  it != Input::TypeRepository<Record>::get_instance().end(); ++it) {
520  print_base( stream, it->second.get() );
521  }
522 */
523  stream << format_full_hash;
524  print_full_hash(stream);
525  stream << format_tail;
526  return stream;
527 }
528 
529 std::string print_attributes(TypeBase::attribute_map attribute_map) {
530  stringstream stream;
531 
532  if (attribute_map.size() == 0) return "\"attributes\" : {}";
533 
534  stream << "\"attributes\" : {" << endl; // print map of attributes
535  for (auto it=attribute_map.begin(); it!=attribute_map.end(); ++it) {
536  if (it != attribute_map.begin()) {
537  stream << "," << endl;
538  }
539  stream << "\"" << it->first << "\" : " << it->second;
540  }
541  stream << endl << "}";
542 
543  return stream.str();
544 }
545 
546 
547 void OutputJSONMachine::print_type_header(ostream &stream, const TypeBase *type) {
548  stream << "{" << endl;
549  stream << "\"id\" : " << type->hash_str() << "," << endl;
550  stream << "\"input_type\" : \"" + type->class_name() + "\"," << endl;
551  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
552 
553  // write data of parameters and attributes
554  TypeBase::attribute_map attr_map;
555  TypeBase::TypeHash generic_type_hash;
556  TypeBase::json_string parameter_map_to_json;
557  get_attr_and_param_data(type, attr_map, generic_type_hash, parameter_map_to_json);
558  // print hash of generic type and parameters into separate keys
559  if (generic_type_hash) { // print hash of generic type into separate keys
560  stream << "\"generic_type\" : " << TypeBase::hash_str(generic_type_hash) << "," << endl;
561  }
562  if (parameter_map_to_json.size()) { // parameters into separate keys
563  stream << "\"parameters\" : " << parameter_map_to_json << "," << endl;
564  }
565  stream << print_attributes(attr_map);
566 }
567 
568 
569 void OutputJSONMachine::print_impl(ostream& stream, const Record *type) {
570 
571  TypeBase::TypeHash hash=type->content_hash();
572  if (was_written(hash)) return;
573 
574  print_type_header(stream, type);
575  stream << "," << endl << "\"description\" : \"" <<
576  escape_description( OutputBase::get_record_description(type) ) << "\"," << endl;
577 
578  // parent records, implemented abstracts
580  get_parent_vec(*type, parent_vec);
581  if (parent_vec.size()) {
582  stream << "\"implements\" : [ ";
583  bool add_comma = false;
584  for (auto &parent : parent_vec) {
585  if (add_comma) stream << ", ";
586  else add_comma = true;
587  stream << parent->hash_str();
588  }
589  stream << " ]," << endl;
590  }
591 
592  // reducible to key
593  Record::KeyIter key_it = type->auto_conversion_key_iter();
594  if (key_it != type->end()) {
595  stream << "\"reducible_to_key\" : \"" << key_it->key_ << "\"," << endl;
596  }
597 
598  stream << "\"keys\" : [" << endl;
599 
601  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
602  string dft_type, dft_value;
603  get_default(it, dft_type, dft_value);
604  if (dft_type != "value at declaration")
605  dft_value = "\"" + escape_description(dft_value) + "\"";
606 
607  if (it != type->begin()) {
608  stream << "," << endl;
609  }
610  stream << "{ \"key\" : \"" << it->key_ << "\"," << endl;
611  stream << "\"description\" : \"" <<
612  escape_description(it->description_) << "\"," << endl;
613  stream << "\"default\" : { "
614  <<"\"type\" : \"" << dft_type << "\"," << endl
615  <<"\"value\" : " << dft_value << " }," << endl;
616  stream << "\"type\" : " << it->type_->hash_str() << "," << endl;
617  stream << print_attributes(it->attributes);
618  stream << "}";
619  }
620 
621  stream << "]" << endl;
622  stream << "},";
623 
624  // Full documentation of embedded record types.
626  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
627  print_base(stream, it->type_.get());
628  }
629 
630  boost::hash_combine(full_hash_, hash);
631 }
632 
633 
634 
635 void OutputJSONMachine::print_impl(ostream& stream, const Array *type) {
636  TypeBase::TypeHash hash=type->content_hash();
637  if (was_written(hash)) return;
638 
639  unsigned int lower_size, upper_size;
640  std::shared_ptr<TypeBase> array_type;
641 
642  get_array_sizes(*type, lower_size, upper_size);
643  get_array_type(*type, array_type);
644 
645  print_type_header(stream, type);
646  stream << "," << endl;
647  stream << "\"range\" : [" << lower_size << ", " << upper_size << "]," << endl;
648  stream << "\"subtype\" : " << array_type->hash_str() << endl;
649  stream << "}," << endl;
650 
651  print_base(stream, array_type.get());
652 
653  boost::hash_combine(full_hash_, hash);
654 }
655 
656 
657 
658 void OutputJSONMachine::print_impl(ostream& stream, const Abstract *type) {
659  print_generic<Abstract>(stream, type);
660 
661  TypeBase::TypeHash hash=type->content_hash();
662  if (was_written(hash)) return;
663 
664  print_type_header(stream, type);
665  stream << "," << endl;
666  stream << "\"description\" : \"" <<
668 
669  print_abstract_record_keys(stream, type);
670  stream << "},";
671 
672  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
673  print_base(stream, &*it);
674  }
675 
676  boost::hash_combine(full_hash_, hash);
677 }
678 
679 
680 void OutputJSONMachine::print_impl(ostream& stream, const AdHocAbstract *type) {
681  print_generic<AdHocAbstract>(stream, type);
682 
683  TypeBase::TypeHash hash=type->content_hash();
684  if (was_written(hash)) return;
685 
686  string parent_name;
687  get_adhoc_parent_name(type, parent_name);
688  print_type_header(stream, type);
689  stream << "," << endl;
690  print_abstract_record_keys(stream, dynamic_cast<const Type::Abstract *>(type));
691  stream << "},";
692 
693  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
694  print_base(stream, &*it);
695  }
696 
697  boost::hash_combine(full_hash_, hash);
698 }
699 
700 
701 
702 void OutputJSONMachine::print_abstract_record_keys(ostream& stream, const Abstract *type) {
703 
704  // Print documentation of abstract record
705  const Record * desc = type->get_default_descendant();
706 
707  // default descendant
708  if (desc) {
709  stream << "\"default_descendant\" : " << desc->hash_str() << "," << endl;
710  }
711  stream << "\"implementations\" : [" << endl;
712  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
713  if (it != type->begin_child_data())
714  stream << "," << endl;
715  stream << "" << it->hash_str() << "";
716  }
717  stream << "]";
718 
719 }
720 
721 
722 
723 
724 
725 void OutputJSONMachine::print_impl(ostream& stream, const Selection *type) {
726  print_generic<Selection>(stream, type);
727 
728  TypeBase::TypeHash hash=type->content_hash();
729  if (was_written(hash)) return;
730 
731  print_type_header(stream, type);
732  stream << "," << endl;
733  stream << "\"description\" : \"" <<
735 
736  stream << "\"values\" : [" << endl;
737  for (Selection::keys_const_iterator it = type->begin(); it != type->end(); ++it) {
738  if (it != type->begin()) {
739  stream << "," << endl;
740  }
741  stream << "{ \"name\" : \"" << it->key_ << "\"," << endl;
742  stream << "\"description\" : \"" << escape_description(it->description_) << "\"," << endl;
743  stream << print_attributes(it->attributes_) << endl;
744  stream << "}";
745  }
746 
747  stream << "]" << endl;
748  stream << "},";
749 
750  boost::hash_combine(full_hash_, hash);
751 }
752 
753 
754 void OutputJSONMachine::print_impl(ostream& stream, const Integer *type) {
755  TypeBase::TypeHash hash=type->content_hash();
756  if (was_written(hash)) return;
757 
758  int lower, upper;
759  get_integer_bounds(*type, lower, upper);
760 
761  print_type_header(stream, type);
762  stream << "," << endl;
763  stream << "\"range\" : [" << lower << ", " << upper << "]" << endl;
764  stream << "},";
765 
766  boost::hash_combine(full_hash_, hash);
767 }
768 
769 
770 void OutputJSONMachine::print_impl(ostream& stream, const Double *type) {
771  TypeBase::TypeHash hash=type->content_hash();
772  if (was_written(hash)) return;
773 
774  double lower, upper;
775  get_double_bounds(*type, lower, upper);
776 
777  print_type_header(stream, type);
778  stream << "," << endl;
779  stream << "\"range\" : [" << lower << ", " << upper << "]" << endl;
780  stream << "},";
781 
782  boost::hash_combine(full_hash_, hash);
783 }
784 
785 
786 void OutputJSONMachine::print_impl(ostream& stream, const Bool *type) {
787  TypeBase::TypeHash hash=type->content_hash();
788  if (was_written(hash)) return;
789 
790  print_type_header(stream, type);
791  stream << "},";
792 
793  boost::hash_combine(full_hash_, hash);
794 }
795 
796 
797 void OutputJSONMachine::print_impl(ostream& stream, const String *type) {
798  TypeBase::TypeHash hash=type->content_hash();
799  if (was_written(hash)) return;
800 
801  print_type_header(stream, type);
802  stream << "},";
803 
804  boost::hash_combine(full_hash_, hash);
805 }
806 
807 
808 void OutputJSONMachine::print_impl(ostream& stream, const FileName *type) {
809  TypeBase::TypeHash hash=type->content_hash();
810  if (was_written(hash)) return;
811 
812  print_type_header(stream, type);
813  stream << "," << endl;
814  stream << "\"file_mode\" : \"";
815  switch (type->get_file_type()) {
816  case ::FilePath::input_file:
817  stream << "input\"";
818  break;
819  case ::FilePath::output_file:
820  stream << "output\"";
821  break;
822  }
823 
824  stream << endl << "},";
825 
826  boost::hash_combine(full_hash_, hash);
827 }
828 
829 
830 
831 void OutputJSONMachine::print_impl(ostream& stream, const Parameter *type) {
832  TypeBase::TypeHash hash=type->content_hash();
833  if (was_written(hash)) return;
834 
835  print_type_header(stream, type);
836  stream << endl << "},";
837 
838  boost::hash_combine(full_hash_, hash);
839 }
840 
841 
842 
844  string build_date = string(__DATE__) + ", " + string(__TIME__);
845 
846  stream << "{" << endl;
847  stream << "\"flow123d_commit\" : \"" << rev_num_data_.revision << "\"," << endl;
848  stream << "\"flow123d_version\" : \"" << rev_num_data_.version << "\"," << endl;
849  stream << "\"date\" : \"" << build_date << "\"" << endl;
850  stream << "}";
851 }
852 
853 
854 
855 void OutputJSONMachine::print_full_hash(ostream& stream) {
856  stream << "\"IST_hash\" : " << TypeBase::hash_str( full_hash_ ) << endl;
857 }
858 
859 
860 
861 
862 
863 
864 std::ostream& operator<<(std::ostream& stream, OutputText type_output) {
865  return type_output.print(stream) << endl;
866 }
867 
868 
869 std::ostream& operator<<(std::ostream& stream, OutputJSONMachine type_output) {
870  return type_output.print(stream) << endl;
871 }
872 
873 
874 } // closing namespace Type
875 } // closing namespace Input
std::string escape_description(std::string desc)
Replace slashes, quotes and special chars with escaped format of these chars.
Definition: type_output.cc:477
std::int64_t lower_bound_
Minimal value of Integer.
Definition: type_base.hh:521
Base of classes for declaring structure of the input data.
Definition: type_base.hh:93
unsigned int size() const
Returns number of values in the Selection.
bool was_written(std::size_t hash)
Returns true if the type was printed out.
Definition: type_output.cc:221
std::string print_attributes(TypeBase::attribute_map attribute_map)
Definition: type_output.cc:529
std::vector< struct Key >::const_iterator KeyIter
Public typedef of constant iterator into array of keys.
Definition: type_record.hh:211
std::string hash_str() const
Format the hash of this type.
Definition: type_base.hh:220
std::string format_tail
Tail of the format, printed after all recursive prints are finished.
Definition: type_output.hh:316
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:593
std::vector< Record >::const_iterator ChildDataIter
Public typedef of constant iterator into array of keys.
string type_name() const override
Implements Type::TypeBase::type_name.
Definition: type_record.cc:313
void write_default_value(std::ostream &stream, Default dft)
Write value stored in dft.
Definition: type_output.cc:190
void print_generic(ostream &stream, const TypeBase *type)
Definition: type_output.cc:128
void get_default(Record::KeyIter it, string &type, string &value)
Gets values of default for given record key.
Definition: type_output.cc:98
void get_integer_bounds(Integer integer, int &lower, int &upper)
Gets range of integer.
Definition: type_output.cc:53
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:381
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:56
std::string format_head
Header of the format, printed before call of version print.
Definition: type_output.hh:298
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
std::string format_inner
Inner part of the format, printed before first call of recursive print.
Definition: type_output.hh:304
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:576
virtual string class_name() const
Returns an identification of the class. Useful for output of the documentation.
Definition: type_base.cc:187
std::string format_full_hash
Tail of the format, printed after all recursive prints are finished and before full hash prints...
Definition: type_output.hh:310
void clear_processed_types()
Clear all data of processed types.
Definition: type_output.cc:215
Base abstract class for output description of the Input::Type tree.
Definition: type_output.hh:61
std::shared_ptr< SelectionData > data_
Handle to actual Selection data.
Class for representing parametric types in IST.
Definition: type_generic.hh:52
DocumentationType doc_type_
Type of documentation output.
Definition: type_output.hh:178
Class for create JSON machine readable documentation.
Definition: type_output.hh:248
virtual TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_record.cc:120
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:225
OutputBase()
Constructor.
Definition: type_output.cc:48
static std::string hash_str(TypeHash hash)
Format given hash for output.
Definition: type_base.cc:101
Class for declaration of the input data that are file names.
Definition: type_base.hh:611
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
Class for declaration of polymorphic Record.
Record root_type_
Root type for output.
Definition: type_output.hh:325
void print_impl(ostream &stream, const Record *type)
Implements printout of Record type.
Definition: type_output.cc:252
std::shared_ptr< attribute_map > attributes_
map of type attributes (e. g. input_type, name etc.)
Definition: type_base.hh:298
TypeBase::TypeHash full_hash_
Content hash of full IST, value is used for key IST_hash.
Definition: type_output.hh:185
void print_full_hash(ostream &stream)
Print full_hash_ key.
Definition: type_output.cc:855
Class for declaration of the integral input data.
Definition: type_base.hh:483
KeyIter begin() const
Container-like access to the keys of the Record.
Definition: type_record.hh:570
void get_array_sizes(Array array, unsigned int &lower, unsigned int &upper)
Gets range of array.
Definition: type_output.cc:67
bool is_optional() const
Returns true if the key is optional.
Definition: type_record.hh:136
const Abstract & ancestor_
Reference to ancestor Abstract.
Class for declaration of inputs sequences.
Definition: type_base.hh:339
double upper_bound_
Maximal value of Integer.
Definition: type_base.hh:569
static constexpr bool value
Definition: json.hpp:87
static TypeRepository & get_instance()
Return singleton instance of class.
ParameterMap parameter_map_
map of parameters if type is part of generic subtree
Definition: type_base.hh:307
const string & get_record_description(const Record *rec)
Gets description of the given record type.
Definition: type_output.cc:80
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_generic.cc:53
std::shared_ptr< ArrayData > data_
Handle to the actual array data.
Definition: type_base.hh:429
unsigned int child_size() const
Returns number of descendants in the child_data_.
void print_type_header(ostream &stream, const TypeBase *type)
Print header of a JSON object describing single TypeBase instance.
Definition: type_output.cc:547
Stores version of program and other base data of application.
Definition: type_output.hh:40
RevNumData rev_num_data_
Contains version of program and other base data.
Definition: type_output.hh:318
void print_abstract_record_keys(ostream &stream, const Abstract *type)
Print all keys of Abstract type or AdHocAbstract type.
Definition: type_output.cc:702
void get_double_bounds(Double dbl, double &lower, double &upper)
Gets range of double.
Definition: type_output.cc:60
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:534
void print_program_info(ostream &stream)
Print actual version of program.
Definition: type_output.cc:843
ostream & print(ostream &stream) override
Performs output of the documentation into given stream.
Definition: type_output.cc:500
Printout only basic data.
Definition: type_output.hh:79
std::int64_t upper_bound_
Maximal value of Integer.
Definition: type_base.hh:522
ostream & print(ostream &stream) override
Performs output of the documentation into given stream.
Definition: type_output.cc:244
string type_name() const override
Implements Type::TypeBase::type_name.
bool is_finished() const override
Implements TypeBase::is_finished.
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:413
std::shared_ptr< T > find_hash(Type::TypeBase::TypeHash hash)
TypeHash content_hash() const override
Implements TypeBase::content_hash.
const string & get_abstract_description(const Abstract *a_rec)
Gets description of the given abstract type.
Definition: type_output.cc:86
::FilePath::FileType get_file_type() const
Returns type of the file input/output.
Definition: type_base.cc:557
void print_base(ostream &stream, const TypeBase *type)
Perform resolution according to actual type (using typeid) and call particular print_impl method...
Definition: type_output.cc:136
keys_const_iterator end() const
Container-like access to the keys of the Selection.
const Record * get_default_descendant() const
Returns default descendant.
Class for declaration of polymorphic Record.
Abstract::ChildDataIter get_adhoc_parent_data(const AdHocAbstract *a_rec)
Gets iterator to begin of ancestor_.child_data_ of the given AdHocAbstract type.
Definition: type_output.cc:123
ChildDataIter begin_child_data() const
Container-like access to the descendants of the Abstract.
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:515
TypeHash content_hash() const override
Implements TypeBase::content_hash.
virtual string class_name() const override
Override Type::TypeBase::class_name.
Definition: type_record.cc:319
Printout full documentation.
Definition: type_output.hh:80
void get_adhoc_parent_name(const AdHocAbstract *a_rec, string &parent_name)
Gets ancestor_.type_name of the given AdHocAbstract type.
Definition: type_output.cc:118
std::string revision
Actual revision of application.
Definition: type_output.hh:42
Tuple type proxy class.
Definition: type_tuple.hh:45
TypeHash generic_type_hash_
hash string of generic type if type is derived, or empty string
Definition: type_base.hh:304
FinishStatus finish(FinishStatus finish_type=FinishStatus::regular_) override
Finish declaration of the Record type.
Definition: type_record.cc:240
json_string print_parameter_map_to_json(ParameterMap parameter_map) const
Create JSON output from parameter_map formatted as value of attribute.
Definition: type_base.cc:127
void get_parent_vec(Record rec, std::vector< std::shared_ptr< Abstract > > &parent_vec)
Gets pointer of parent Abstract for given Record.
Definition: type_output.cc:92
TypeHash content_hash() const override
Implements TypeBase::content_hash.
const string & get_selection_description(const Selection *sel)
Gets description of the given selection type.
Definition: type_output.cc:113
void write_description(std::ostream &stream, const string &str, unsigned int padding, unsigned int hash_count=1)
Write out a string with given padding of every new line.
Definition: type_output.cc:198
void get_attr_and_param_data(const TypeBase *type, TypeBase::attribute_map &attr_map, TypeBase::TypeHash &generic_type_hash, TypeBase::json_string &parameter_map_to_json)
Gets data of attributes and parameters of the given type.
Definition: type_output.cc:228
#define ASSERT_DBG(expr)
Definition: asserts.hh:350
KeyIter end() const
Container-like access to the keys of the Record.
Definition: type_record.hh:578
virtual string type_name() const
Returns an identification of the type. Useful for error messages.
Definition: type_base.cc:182
ChildDataIter end_child_data() const
Container-like access to the descendants of the Abstract.
double lower_bound_
Minimal value of Integer.
Definition: type_base.hh:568
std::string json_string
String stored in JSON format.
Definition: type_base.hh:99
virtual ~OutputBase()
Destructor.
Definition: type_output.cc:44
std::ostream & operator<<(std::ostream &stream, const TypeBase &type)
For convenience we provide also redirection operator for output documentation of Input:Type classes...
Definition: type_base.cc:215
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:455
Class for create text documentation.
Definition: type_output.hh:204
Record type proxy class.
Definition: type_record.hh:177
std::string version
Actual version of application.
Definition: type_output.hh:41
const string & value() const
Returns stored value. Possibly empty string.
Definition: type_record.hh:140
std::shared_ptr< ChildData > child_data_
Actual data of the Abstract.
std::vector< struct Key >::const_iterator keys_const_iterator
Public typedef of constant iterator into array of keys.
void get_array_type(Array array, std::shared_ptr< TypeBase > &arr_type)
Gets pointer of inner type for given Array.
Definition: type_output.cc:74
keys_const_iterator begin() const
Container-like access to the keys of the Selection.
std::shared_ptr< RecordData > data_
Data handle.
Definition: type_record.hh:522
bool is_obligatory() const
Returns true if the key is obligatory and thus must be specified on input. No default value is given...
Definition: type_record.hh:132
Class for declaration of the input data that are in string format.
Definition: type_base.hh:582
std::size_t TypeHash
Type returned by content_hash methods.
Definition: type_base.hh:96
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:45
Template for classes storing finite set of named values.
OutputJSONMachine(RevNumData rev_num_data)
Simple constructor.
Definition: type_output.cc:456
bool is_finished() const override
Implements TypeBase::is_finished.
Definition: type_record.cc:228
KeyIter auto_conversion_key_iter() const
Returns iterator to auto-conversion key.
Definition: type_record.cc:331
void print_impl(ostream &stream, const Record *type)
Implements printout of Record type.
Definition: type_output.cc:569
virtual string type_name() const override
Implements Type::TypeBase::type_name.