Flow123d  release_3.0.0-1124-g41e620f
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
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_impl(stream, static_cast<const Type::Record *>(type) );
147  } else
148  if (typeid(*type) == typeid(Type::Record)) {
149  print_impl(stream, static_cast<const Type::Record *>(type) );
150  } else
151  if (typeid(*type) == typeid(Type::Array)) {
152  print_impl(stream, static_cast<const Type::Array *>(type) );
153  } else
154  if (typeid(*type) == typeid(Type::Abstract)) {
155  print_impl(stream, static_cast<const Type::Abstract *>(type) );
156  } else
157  if (typeid(*type) == typeid(Type::AdHocAbstract)) {
158  print_impl(stream, static_cast<const Type::AdHocAbstract *>(type) );
159  } else
160  if (typeid(*type) == typeid(Type::Selection)) {
161  print_impl(stream, static_cast<const Type::Selection *>(type) );
162  } else
163  if (typeid(*type) == typeid(Type::Integer)) {
164  print_impl(stream, static_cast<const Type::Integer *>(type) );
165  } else
166  if (typeid(*type) == typeid(Type::Double)) {
167  print_impl(stream, static_cast<const Type::Double *>(type) );
168  } else
169  if (typeid(*type) == typeid(Type::Bool)) {
170  print_impl(stream, static_cast<const Type::Bool *>(type) );
171  } else
172  if (typeid(*type) == typeid(Type::Parameter)) {
173  print_impl(stream, static_cast<const Type::Parameter *>(type) );
174  } else {
175  const Type::FileName * file_name_type = dynamic_cast<const Type::FileName *>(type);
176  if (file_name_type != NULL ) {
177  print_impl(stream, file_name_type );
178  return;
179  }
180 
181  const Type::String * string_type = dynamic_cast<const Type::String *>(type);
182  if (string_type != NULL ) {
183  print_impl(stream, string_type );
184  return;
185  }
186 
187  // default -> error
188  THROW( Type::ExcUnknownDescendant() << Type::EI_TypeName(typeid(type).name()) );
189  }
190 }
191 
192 
193 void OutputBase::write_default_value(std::ostream& stream, Default dft) {
194  if (dft.is_obligatory() || dft.is_optional()) {
195  stream << "<" << dft.value() << ">";
196  } else {
197  stream << "\"" << dft.value() << "\"";
198  }
199 }
200 
201 void OutputBase::write_description(std::ostream& stream, const string& str,
202  unsigned int padding, unsigned int hash_count) {
203  string s = str;
204  boost::replace_all(s, "\\$", "$");
205 
206  boost::tokenizer<boost::char_separator<char> > line_tokenizer(s, boost::char_separator<char>("\n"));
207  boost::tokenizer<boost::char_separator<char> >::iterator it;
208 
209  // For every \n add padding at beginning of the next line.
210  for(it = line_tokenizer.begin(); it != line_tokenizer.end(); ++it) {
211  stream << endl;
212  stream << setw(padding) << "";
213  stream << std::setfill('#') << setw(hash_count) << "" << std::setfill(' ') << " " << *it;
214  }
215 }
216 
217 
219  processed_types_hash_.clear();
220  full_hash_ = 0;
221 }
222 
223 
224 bool OutputBase::was_written(std::size_t hash)
225 {
226  bool in_set = ( processed_types_hash_.find(hash) != processed_types_hash_.end() );
227  if (! in_set) processed_types_hash_.insert(hash);
228  return in_set;
229 }
230 
232  TypeBase::TypeHash &generic_type_hash, TypeBase::json_string &parameter_map_to_json) {
233  attr_map = *( type->attributes_.get() );
234  generic_type_hash = type->generic_type_hash_;
235  if (type->parameter_map_.size()) {
236  parameter_map_to_json = type->print_parameter_map_to_json( type->parameter_map_ );
237  }
238 }
239 
240 
241 
242 
243 /*******************************************************************
244  * implementation of OutputText
245  */
246 
247 ostream& OutputText::print(ostream& stream) {
248  doc_type_ = full_record;
249  clear_processed_types();
250 
251  print_base(stream, type_);
252  return stream;
253 }
254 
255 void OutputText::print_impl(ostream& stream, const Record *type) {
256  ASSERT(type->is_finished())(type->type_name())(type->class_name()).warning("Printing documentation of unfinished type.");
257  switch (doc_type_) {
258  case key_record:
259  stream << "" << type->class_name() << " '" << type->type_name() << "' (" << type->size() << " keys).";
260  break;
261  case full_record:
262  TypeBase::TypeHash hash=type->content_hash();
263  if (! was_written(hash)) {
264  // header
265  stream << endl;
266  stream << "" << type->class_name() << " '" << type->type_name() << "'";
267  // parent record
268  /*std::shared_ptr<Abstract> parent_ptr;
269  get_parent_ptr(*type, parent_ptr);
270  if (parent_ptr) {
271  stream << ", implementation of " << parent_ptr->type_name();
272  }*/
273 
274  // reducible to key
275  Record::KeyIter key_it = type->auto_conversion_key_iter();
276  if (key_it != type->end()) {
277  stream << ", reducible to key '" << key_it->key_ << "'";
278  }
279  stream << "" << " (" << type->size() << " keys).";
280  write_description(stream, OutputBase::get_record_description(type), 0);
281  stream << endl;
282  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << endl;
283  // keys
284  doc_type_ = key_record;
285  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
286  size_setw_ = it->key_.size() + 3;
287  stream << setw(padding_size) << "" << it->key_ << " = ";
288  write_default_value(stream, it->default_);
289  stream << endl;
290  stream << setw(padding_size + size_setw_) << "" <<"#### is ";
291  print_base(stream, it->type_.get());
292  write_description(stream, it->description_, padding_size+size_setw_);
293  stream << endl;
294  }
295  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << " " << type->type_name() << endl;
296  // Full documentation of embedded record types.
297  doc_type_ = full_record;
298  }
299  break;
300  }
301 }
302 void OutputText::print_impl(ostream& stream, const Array *type) {
303  std::shared_ptr<TypeBase> array_type;
304  get_array_type(*type, array_type);
305  switch (doc_type_) {
306  case key_record:
307  unsigned int lower_size, upper_size;
308  get_array_sizes(*type, lower_size, upper_size);
309  stream << "Array, size limits: [" << lower_size << ", " << upper_size << "] of type: " << endl;
310  stream << setw(padding_size + size_setw_) << "" << "#### ";
311  print_base(stream, array_type.get());
312  break;
313  case full_record:
314  print_base(stream, array_type.get());
315  break;
316  }
317 }
318 
319 
320 void OutputText::print_impl(ostream& stream, const Abstract *type) {
321  // Print documentation of abstract record
322  switch (doc_type_) {
323  case key_record:
324  stream << "Abstract '" << type->type_name() << "' with "<< type->child_size() << " descendants.";
325  break;
326  case full_record:
327  TypeBase::TypeHash hash=type->content_hash();
328  if (! was_written(hash) ) {
329  // header
330  stream << endl;
331  stream << "" << "Abstract '" << type->type_name() << "' with " << type->child_size() << " descendants.";
332  write_description(stream, OutputBase::get_abstract_description( type ), 0);
333  stream << endl;
334  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << endl;
335  // descendants
336  doc_type_ = key_record;
337  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
338  size_setw_ = 0;
339  stream << setw(padding_size) << "";
340  stream << "" << "Record '" << (*it).type_name() << "'";
341  write_description(stream, OutputBase::get_record_description( &(*it) ), padding_size+size_setw_);
342  stream << endl;
343  }
344  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << " " << type->type_name() << endl;
345  // Full documentation of embedded record types.
346  doc_type_ = full_record;
347  }
348  break;
349  }
350 }
351 
352 
353 void OutputText::print_impl(ostream& stream, const AdHocAbstract *type) {
354  // Print documentation of adhoc abstract record
355  if (doc_type_ == key_record) {
356  stream << "AdHocAbstract";
357  /*string parent_name;
358  get_adhoc_parent_name(type, parent_name);
359  stream << "AdHocAbstract" << endl;
360  stream << setw(padding_size + size_setw_) << "";
361  stream << "#### Derived from Abstract '" << parent_name << "', ";
362  stream << "added Records: ";
363  {
364  Abstract::ChildDataIter parent_it = get_adhoc_parent_data(type);
365  bool add_comma = false;
366  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
367  if ((*it).type_name() == (*parent_it).type_name()) {
368  ++parent_it;
369  } else {
370  if (add_comma) stream << ", ";
371  else add_comma = true;
372  stream << "'" << (*it).type_name() << "'";
373  }
374  }
375  }*/
376  }
377 }
378 void OutputText::print_impl(ostream& stream, const Selection *type) {
379  ASSERT(type->is_finished())(type->type_name()).warning("Printing documentation of unfinished Input::Type::Selection.");
380  switch (doc_type_) {
381  case key_record:
382  stream << "Selection '" << type->type_name() << "' of " << type->size() << " values.";
383  break;
384  case full_record:
385  TypeBase::TypeHash hash=type->content_hash();
386  if (! was_written(hash) ) {
387  stream << endl << "Selection '" << type->type_name() << "' of " << type->size() << " values.";
388  write_description(stream, OutputBase::get_selection_description( type ), 0);
389  stream << endl;
390  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << endl;
391  // keys
392  for (Selection::keys_const_iterator it = type->begin(); it != type->end(); ++it) {
393  stream << setw(padding_size) << "" << it->key_ << " = " << it->value;
394  if (it->description_ != "") {
395  stream << endl;
396  stream << setw(padding_size + it->key_.size() + 3) << "" << "# " << it->description_ << "";
397  }
398  stream << endl;
399  }
400  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << " " << type->type_name() << endl;
401  }
402  break;
403  }
404 }
405 void OutputText::print_impl(ostream& stream, const Integer *type) {
406  if (doc_type_ == key_record) {
407  int lower_bound, upper_bound;
408  get_integer_bounds(*type, lower_bound, upper_bound);
409  stream << "Integer in [" << lower_bound << ", " << upper_bound << "]";
410  }
411 }
412 void OutputText::print_impl(ostream& stream, const Double *type) {
413  if (doc_type_ == key_record) {
414  double lower_bound, upper_bound;
415  get_double_bounds(*type, lower_bound, upper_bound);
416  stream << "Double in [" << lower_bound << ", " << upper_bound << "]";
417  }
418 }
419 void OutputText::print_impl(ostream& stream, const Bool *type) {
420  if (doc_type_ == key_record) {
421  stream << "Bool";
422  }
423 }
424 void OutputText::print_impl(ostream& stream, const String *type) {
425  if (doc_type_ == key_record) {
426  stream << "String (generic)";
427  }
428 }
429 void OutputText::print_impl(ostream& stream, const FileName *type) {
430  if (doc_type_ == key_record) {
431  stream << "FileName of ";
432  switch (type->get_file_type()) {
433  case ::FilePath::input_file:
434  stream << "input file";
435  break;
436  case ::FilePath::output_file:
437  stream << "output file";
438  break;
439  default:
440  stream << "file with unknown type";
441  break;
442  }
443  }
444 }
445 
446 
447 
448 void OutputText::print_impl(ostream& stream, const Parameter *type) {
449  ASSERT_DBG(false).error("Parameter appears in the IST. Check where Instance is missing.");
450 }
451 
452 
453 
454 
455 /*******************************************************************
456  * implementation of OutputJSONMachine
457  */
458 
460 : OutputBase()
461 {
462  rev_num_data_ = rev_num_data;
463 
464  format_head="{ \"version\" :";
465  format_inner=",\n\"ist_nodes\" : [\n";
466  format_full_hash="{}],\n";
467  format_tail="}\n";
468 }
469 
470 
471 
473 : OutputJSONMachine(rev_num_data)
474 {
475  root_type_ = root_type;
476  root_type_.finish();
477 }
478 
479 
480 std::string OutputJSONMachine::escape_description(std::string desc) {
481  static std::vector< std::pair<std::regex, std::string> > rewrite_rules = {
482  // replace single slash with two slashes
483  {std::regex("\\\\"), "\\\\"},
484  // replace quote with slash quote
485  {std::regex("\\\""), "\\\""},
486  // replace special chars with escaped slash + special chars
487  {std::regex("\\n"), "\\n"},
488  {std::regex("\\t"), "\\t"},
489  {std::regex("\\r"), "\\r"}
490  };
491 
492 
493  std::string tmp = std::string(desc);
494 
495  for (auto rewrite_rule : rewrite_rules) {
496  tmp = std::regex_replace(tmp, rewrite_rule.first, rewrite_rule.second);
497  }
498 
499  return tmp;
500 }
501 
502 
503 ostream& OutputJSONMachine::print(ostream& stream) {
506 
507  stream << format_head;
508  print_program_info(stream);
509  stream << format_inner;
510 
511  print_base( stream, &root_type_);
512  /*
513  for (Input::TypeRepository<Selection>::TypeRepositoryMapIter it = Input::TypeRepository<Selection>::get_instance().begin();
514  it != Input::TypeRepository<Selection>::get_instance().end(); ++it) {
515  print_base( stream, it->second.get() );
516  }
517  for (Input::TypeRepository<Abstract>::TypeRepositoryMapIter it = Input::TypeRepository<Abstract>::get_instance().begin();
518  it != Input::TypeRepository<Abstract>::get_instance().end(); ++it) {
519  print_base( stream, it->second.get() );
520  }
521  for (Input::TypeRepository<Record>::TypeRepositoryMapIter it = Input::TypeRepository<Record>::get_instance().begin();
522  it != Input::TypeRepository<Record>::get_instance().end(); ++it) {
523  print_base( stream, it->second.get() );
524  }
525 */
526  stream << format_full_hash;
527  print_full_hash(stream);
528  stream << format_tail;
529  return stream;
530 }
531 
532 std::string print_attributes(TypeBase::attribute_map attribute_map) {
533  stringstream stream;
534 
535  if (attribute_map.size() == 0) return "\"attributes\" : {}";
536 
537  stream << "\"attributes\" : {" << endl; // print map of attributes
538  for (auto it=attribute_map.begin(); it!=attribute_map.end(); ++it) {
539  if (it != attribute_map.begin()) {
540  stream << "," << endl;
541  }
542  stream << "\"" << it->first << "\" : " << it->second;
543  }
544  stream << endl << "}";
545 
546  return stream.str();
547 }
548 
549 
550 void OutputJSONMachine::print_type_header(ostream &stream, const TypeBase *type) {
551  stream << "{" << endl;
552  stream << "\"id\" : " << type->hash_str() << "," << endl;
553  stream << "\"input_type\" : \"" + type->class_name() + "\"," << endl;
554  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
555 
556  // write data of parameters and attributes
557  TypeBase::attribute_map attr_map;
558  TypeBase::TypeHash generic_type_hash;
559  TypeBase::json_string parameter_map_to_json;
560  get_attr_and_param_data(type, attr_map, generic_type_hash, parameter_map_to_json);
561  // print hash of generic type and parameters into separate keys
562  if (generic_type_hash != TypeBase::none_hash) { // print hash of generic type into separate keys
563  stream << "\"generic_type\" : " << TypeBase::hash_str(generic_type_hash) << "," << endl;
564  }
565  if (parameter_map_to_json.size()) { // parameters into separate keys
566  stream << "\"parameters\" : " << parameter_map_to_json << "," << endl;
567  }
568  stream << print_attributes(attr_map);
569 }
570 
571 
572 void OutputJSONMachine::print_impl(ostream& stream, const Record *type) {
573  if (typeid(*type) == typeid(Type::Tuple)) {
574  print_generic<Tuple>(stream, type);
575  } else {
576  print_generic<Record>(stream, type);
577  }
578 
579  TypeBase::TypeHash hash=type->content_hash();
580  if (was_written(hash)) return;
581 
582  print_type_header(stream, type);
583  stream << "," << endl << "\"description\" : \"" <<
584  escape_description( OutputBase::get_record_description(type) ) << "\"," << endl;
585 
586  // parent records, implemented abstracts
588  get_parent_vec(*type, parent_vec);
589  if (parent_vec.size()) {
590  stream << "\"implements\" : [ ";
591  bool add_comma = false;
592  for (auto &parent : parent_vec) {
593  if (add_comma) stream << ", ";
594  else add_comma = true;
595  stream << parent->hash_str();
596  }
597  stream << " ]," << endl;
598  }
599 
600  // reducible to key
601  Record::KeyIter key_it = type->auto_conversion_key_iter();
602  if (key_it != type->end()) {
603  stream << "\"reducible_to_key\" : \"" << key_it->key_ << "\"," << endl;
604  }
605 
606  stream << "\"keys\" : [" << endl;
607 
609  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
610  string dft_type, dft_value;
611  get_default(it, dft_type, dft_value);
612  if (dft_type != "value at declaration")
613  dft_value = "\"" + escape_description(dft_value) + "\"";
614 
615  if (it != type->begin()) {
616  stream << "," << endl;
617  }
618  stream << "{ \"key\" : \"" << it->key_ << "\"," << endl;
619  stream << "\"description\" : \"" <<
620  escape_description(it->description_) << "\"," << endl;
621  stream << "\"default\" : { "
622  <<"\"type\" : \"" << dft_type << "\"," << endl
623  <<"\"value\" : " << dft_value << " }," << endl;
624  stream << "\"type\" : " << it->type_->hash_str() << "," << endl;
625  stream << print_attributes(it->attributes);
626  stream << "}";
627  }
628 
629  stream << "]" << endl;
630  stream << "},";
631 
632  // Full documentation of embedded record types.
634  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
635  print_base(stream, it->type_.get());
636  }
637 
638  boost::hash_combine(full_hash_, hash);
639 }
640 
641 
642 
643 void OutputJSONMachine::print_impl(ostream& stream, const Array *type) {
644  TypeBase::TypeHash hash=type->content_hash();
645  if (was_written(hash)) return;
646 
647  unsigned int lower_size, upper_size;
648  std::shared_ptr<TypeBase> array_type;
649 
650  get_array_sizes(*type, lower_size, upper_size);
651  get_array_type(*type, array_type);
652 
653  print_type_header(stream, type);
654  stream << "," << endl;
655  stream << "\"range\" : [" << lower_size << ", " << upper_size << "]," << endl;
656  stream << "\"subtype\" : " << array_type->hash_str() << endl;
657  stream << "}," << endl;
658 
659  print_base(stream, array_type.get());
660 
661  boost::hash_combine(full_hash_, hash);
662 }
663 
664 
665 
666 void OutputJSONMachine::print_impl(ostream& stream, const Abstract *type) {
667  print_generic<Abstract>(stream, type);
668 
669  TypeBase::TypeHash hash=type->content_hash();
670  if (was_written(hash)) return;
671 
672  print_type_header(stream, type);
673  stream << "," << endl;
674  stream << "\"description\" : \"" <<
676 
677  print_abstract_record_keys(stream, type);
678  stream << "},";
679 
680  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
681  print_base(stream, &*it);
682  }
683 
684  boost::hash_combine(full_hash_, hash);
685 }
686 
687 
688 void OutputJSONMachine::print_impl(ostream& stream, const AdHocAbstract *type) {
689  print_generic<AdHocAbstract>(stream, type);
690 
691  TypeBase::TypeHash hash=type->content_hash();
692  if (was_written(hash)) return;
693 
694  string parent_name;
695  get_adhoc_parent_name(type, parent_name);
696  print_type_header(stream, type);
697  stream << "," << endl;
698  print_abstract_record_keys(stream, dynamic_cast<const Type::Abstract *>(type));
699  stream << "},";
700 
701  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
702  print_base(stream, &*it);
703  }
704 
705  boost::hash_combine(full_hash_, hash);
706 }
707 
708 
709 
710 void OutputJSONMachine::print_abstract_record_keys(ostream& stream, const Abstract *type) {
711 
712  // Print documentation of abstract record
713  const Record * desc = type->get_default_descendant();
714 
715  // default descendant
716  if (desc) {
717  stream << "\"default_descendant\" : " << desc->hash_str() << "," << endl;
718  }
719  stream << "\"implementations\" : [" << endl;
720  for (Abstract::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
721  if (it != type->begin_child_data())
722  stream << "," << endl;
723  stream << "" << it->hash_str() << "";
724  }
725  stream << "]";
726 
727 }
728 
729 
730 
731 
732 
733 void OutputJSONMachine::print_impl(ostream& stream, const Selection *type) {
734  print_generic<Selection>(stream, type);
735 
736  TypeBase::TypeHash hash=type->content_hash();
737  if (was_written(hash)) return;
738 
739  print_type_header(stream, type);
740  stream << "," << endl;
741  stream << "\"description\" : \"" <<
743 
744  stream << "\"values\" : [" << endl;
745  for (Selection::keys_const_iterator it = type->begin(); it != type->end(); ++it) {
746  if (it != type->begin()) {
747  stream << "," << endl;
748  }
749  stream << "{ \"name\" : \"" << it->key_ << "\"," << endl;
750  stream << "\"description\" : \"" << escape_description(it->description_) << "\"," << endl;
751  stream << print_attributes(it->attributes_) << endl;
752  stream << "}";
753  }
754 
755  stream << "]" << endl;
756  stream << "},";
757 
758  boost::hash_combine(full_hash_, hash);
759 }
760 
761 
762 void OutputJSONMachine::print_impl(ostream& stream, const Integer *type) {
763  TypeBase::TypeHash hash=type->content_hash();
764  if (was_written(hash)) return;
765 
766  int lower, upper;
767  get_integer_bounds(*type, lower, upper);
768 
769  print_type_header(stream, type);
770  stream << "," << endl;
771  stream << "\"range\" : [" << lower << ", " << upper << "]" << endl;
772  stream << "},";
773 
774  boost::hash_combine(full_hash_, hash);
775 }
776 
777 
778 void OutputJSONMachine::print_impl(ostream& stream, const Double *type) {
779  TypeBase::TypeHash hash=type->content_hash();
780  if (was_written(hash)) return;
781 
782  double lower, upper;
783  get_double_bounds(*type, lower, upper);
784 
785  print_type_header(stream, type);
786  stream << "," << endl;
787  stream << "\"range\" : [" << lower << ", " << upper << "]" << endl;
788  stream << "},";
789 
790  boost::hash_combine(full_hash_, hash);
791 }
792 
793 
794 void OutputJSONMachine::print_impl(ostream& stream, const Bool *type) {
795  TypeBase::TypeHash hash=type->content_hash();
796  if (was_written(hash)) return;
797 
798  print_type_header(stream, type);
799  stream << "},";
800 
801  boost::hash_combine(full_hash_, hash);
802 }
803 
804 
805 void OutputJSONMachine::print_impl(ostream& stream, const String *type) {
806  TypeBase::TypeHash hash=type->content_hash();
807  if (was_written(hash)) return;
808 
809  print_type_header(stream, type);
810  stream << "},";
811 
812  boost::hash_combine(full_hash_, hash);
813 }
814 
815 
816 void OutputJSONMachine::print_impl(ostream& stream, const FileName *type) {
817  TypeBase::TypeHash hash=type->content_hash();
818  if (was_written(hash)) return;
819 
820  print_type_header(stream, type);
821  stream << "," << endl;
822  stream << "\"file_mode\" : \"";
823  switch (type->get_file_type()) {
824  case ::FilePath::input_file:
825  stream << "input\"";
826  break;
827  case ::FilePath::output_file:
828  stream << "output\"";
829  break;
830  }
831 
832  stream << endl << "},";
833 
834  boost::hash_combine(full_hash_, hash);
835 }
836 
837 
838 
839 void OutputJSONMachine::print_impl(ostream& stream, const Parameter *type) {
840  TypeBase::TypeHash hash=type->content_hash();
841  if (was_written(hash)) return;
842 
843  print_type_header(stream, type);
844  stream << endl << "},";
845 
846  boost::hash_combine(full_hash_, hash);
847 }
848 
849 
850 
852  string build_date = string(__DATE__) + ", " + string(__TIME__);
853 
854  stream << "{" << endl;
855  stream << "\"flow123d_commit\" : \"" << rev_num_data_.revision << "\"," << endl;
856  stream << "\"flow123d_version\" : \"" << rev_num_data_.version << "\"," << endl;
857  stream << "\"date\" : \"" << build_date << "\"" << endl;
858  stream << "}";
859 }
860 
861 
862 
863 void OutputJSONMachine::print_full_hash(ostream& stream) {
864  stream << "\"IST_hash\" : " << TypeBase::hash_str( full_hash_ ) << endl;
865 }
866 
867 
868 
869 
870 
871 
872 std::ostream& operator<<(std::ostream& stream, OutputText type_output) {
873  return type_output.print(stream) << endl;
874 }
875 
876 
877 std::ostream& operator<<(std::ostream& stream, OutputJSONMachine type_output) {
878  return type_output.print(stream) << endl;
879 }
880 
881 
882 } // closing namespace Type
883 } // 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:480
std::int64_t lower_bound_
Minimal value of Integer.
Definition: type_base.hh:528
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:224
std::string print_attributes(TypeBase::attribute_map attribute_map)
Definition: type_output.cc:532
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:227
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:193
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:459
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
Abstract linear system class.
Definition: balance.hh:37
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:218
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:618
#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:255
std::shared_ptr< attribute_map > attributes_
map of type attributes (e. g. input_type, name etc.)
Definition: type_base.hh:305
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:863
Class for declaration of the integral input data.
Definition: type_base.hh:490
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:346
double upper_bound_
Maximal value of Integer.
Definition: type_base.hh:576
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:314
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:436
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:550
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:710
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:541
void print_program_info(ostream &stream)
Print actual version of program.
Definition: type_output.cc:851
ostream & print(ostream &stream) override
Performs output of the documentation into given stream.
Definition: type_output.cc:503
Printout only basic data.
Definition: type_output.hh:83
std::int64_t upper_bound_
Maximal value of Integer.
Definition: type_base.hh:529
ostream & print(ostream &stream) override
Performs output of the documentation into given stream.
Definition: type_output.cc:247
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:311
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:201
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:231
#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:575
std::string json_string
String stored in JSON format.
Definition: type_base.hh:106
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
static const TypeHash none_hash
Definition: type_base.hh:103
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:589
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:459
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:572
virtual string type_name() const override
Implements Type::TypeBase::type_name.