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