Flow123d  3.9.0-44fe12069
type_abstract.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_abstract.cc
15  * @brief
16  */
17 
18 #include "input_type.hh"
19 #include "type_repository.hh"
20 #include "attribute_lib.hh"
21 
22 #include "system/system.hh"
23 #include "input/storage.hh"
24 #include <boost/functional/hash.hpp>
25 
26 #include <stddef.h> // for NULL
27 #include <algorithm> // for find
28 //
29 
30 #include <boost/functional/hash/hash.hpp> // for hash_combine
31 #include <map> // for _Rb_tree_iterator
32 #include <memory> // for shared_ptr
33 #include <string> // for basic_string
34 #include <utility> // for make_pair, pair
35 #include <vector> // for vector
36 #include "input/storage.hh" // for StorageBase
37 #include "input/type_abstract.hh" // for Abstract, Abst...
38 #include "input/type_base.hh" // for ExcWrongDefault
39 #include "input/type_generic.hh" // for ExcGenericWith...
40 #include "input/type_record.hh" // for Record, Default
41 #include "input/type_selection.hh" // for Selection
42 #include "system/asserts.hh" // for Assert, ASSERT
43 #include "system/exceptions.hh" // for ExcGenericWith...
44 
45 
46 
47 namespace Input {
48 namespace Type {
49 
50 using namespace std;
51 
52 
53 /************************************************
54  * implementation of Abstract
55  */
56 
58 : child_data_( std::make_shared<ChildData>( "EmptyAbstract", "" ) )
59 {
60  close();
61  finish();
62 }
63 
64 
65 
67 : TypeBase( other ), child_data_(other.child_data_)
68 {}
69 
70 
71 
72 Abstract::Abstract(const string & type_name_in, const string & description)
73 : child_data_( std::make_shared<ChildData>( type_name_in, description ) )
74 {}
75 
76 
78 {
79  TypeHash seed=0;
80  boost::hash_combine(seed, "Abstract");
81  boost::hash_combine(seed, type_name());
82  boost::hash_combine(seed, child_data_->description_);
83  for (auto &param : parameter_map_) {
84  boost::hash_combine(seed, param.first );
85  boost::hash_combine(seed, param.second );
86  }
87  boost::hash_combine(seed, this->generic_type_hash_);
88  //boost::hash_combine(seed, child_data_->generic_content_hash_);
89  //for( Record &key : child_data_->list_of_childs) {
90  // boost::hash_combine(seed, key.content_hash() );
91  //}
92  return seed;
93 }
94 
95 
96 
97 Abstract & Abstract::allow_auto_conversion(const string &type_default) {
98  ASSERT_PERMANENT(!child_data_->closed_)(type_name()).error("Can not specify default value for TYPE key as the Abstract is closed.");
99  child_data_->selection_default_=Default("\""+type_default+"\""); // default record is closed; other constructor creates the zero item
100  return *this;
101 }
102 
103 
104 
105 const Record & Abstract::get_descendant(const string& name) const
106 {
107  ASSERT(child_data_->selection_of_childs->is_finished()).error();
108  return child_data_->list_of_childs[ child_data_->selection_of_childs->name_to_int(name) ];
109 }
110 
111 
112 
114  if ( have_default_descendant() ) {
115  int sel_val = child_data_->selection_default_.get_storage( child_data_->selection_of_childs )->get_int();
116  return &( get_descendant( child_data_->selection_of_childs->int_to_name(sel_val) ) );
117  }
118  return NULL;
119 }
120 
121 
122 
124 {
125  return * child_data_->selection_of_childs;
126 }
127 
128 
129 unsigned int Abstract::child_size() const {
130  return child_data_->list_of_childs.size();
131 }
132 
133 
135 {
136  ASSERT(child_data_->closed_).error();
137 
138  if (std::find(child_data_->list_of_childs.begin(), child_data_->list_of_childs.end(), subrec) == child_data_->list_of_childs.end()) {
139  child_data_->selection_of_childs->add_value(child_data_->list_of_childs.size(), subrec.type_name());
140  child_data_->list_of_childs.push_back(subrec);
141  }
142 
143  subrec.derive_from(*this);
144 
145  return 1;
146 }
147 
148 
150  ASSERT(finish_type != FinishStatus::none_).error();
151  ASSERT(finish_type != FinishStatus::in_perform_).error();
152  ASSERT(child_data_->finish_status_ != FinishStatus::in_perform_)(this->type_name()).error("Recursion in the IST element of type Abstract.");
153 
154  if (this->is_finished()) return child_data_->finish_status_;
155 
156  ASSERT(child_data_->closed_)(this->type_name()).error();
157 
158  child_data_->selection_of_childs->close();
159  child_data_->selection_of_childs->finish();
160 
161  child_data_->finish_status_ = FinishStatus::in_perform_;
162 
163  for (auto &child : child_data_->list_of_childs) {
164  if ((finish_type != FinishStatus::generic_) && child.is_root_of_generic_subtree())
165  THROW( ExcGenericWithoutInstance() << EI_Object(child.type_name()) );
166  child.finish(finish_type);
167  ASSERT(child.is_finished()).error();
168  }
169 
170  // check validity of possible default value of TYPE key
171  if ( have_default_descendant() ) {
172  try {
173  child_data_->selection_default_.check_validity(child_data_->selection_of_childs);
174  } catch (ExcWrongDefault & e) {
175  e << EI_Desc("Default value for TYPE key do not match any descendant of Abstract.")
176  << EI_DefaultStr( child_data_->selection_default_.value() ) << EI_TypeName(this->type_name());
177  throw;
178  } catch (ExcWrongDefaultJSON & e) {
179  e << EI_DefaultStr( child_data_->selection_default_.value() ) << EI_TypeName(this->type_name());
180  throw;
181  }
182  }
183 
184  child_data_->finish_status_ = finish_type;
185 
186  return (child_data_->finish_status_);
187 }
188 
189 
191  child_data_->closed_=true;
193 }
194 
195 
197  return child_data_->finish_status_;
198 }
199 
200 
201 bool Abstract::is_finished() const {
202  return (child_data_->finish_status_ != FinishStatus::none_) && (child_data_->finish_status_ != FinishStatus::in_perform_);
203 }
204 
205 
206 bool Abstract::is_closed() const {
207  return child_data_->closed_;
208 }
209 
210 
211 string Abstract::type_name() const {
212  return child_data_->type_name_;
213 }
214 
215 
216 string Abstract::class_name() const {
217  return "Abstract";
218 }
219 
220 
222  return child_data_->selection_default_;
223 }
224 
226  // obligatory value if default is not set, see @p selection_default_
227  if ( !child_data_->selection_default_.is_obligatory() ) {
228  if ( child_data_->selection_default_.has_value_at_declaration() ) {
229  return true;
230  }
231  }
232  return false;
233 }
234 
235 
236 
238  Abstract abstract = this->deep_copy();
239  ParameterMap parameter_map;
240 
241 
242  // Set close flag - add_child method required closed child_data
243  abstract.child_data_->closed_ = true;
244  // make instances of all descendant records and add them into instance of abstract
245  for (auto &child : child_data_->list_of_childs) {
246  MakeInstanceReturnType inst = child.make_instance(vec);
247  abstract.add_child( static_cast<Record &>( *(inst.first) ) );
248  ParameterMap other_map = inst.second;
249  parameter_map.insert(other_map.begin(), other_map.end());
250  }
251  // Unset close flag - necessary for set parameters
252  abstract.child_data_->closed_ = false;
253 
254  // Set parameters and generic type as attributes
255  abstract.parameter_map_ = parameter_map;
256  abstract.generic_type_hash_ = this->content_hash();
257  TypeBase::set_generic_attributes(parameter_map);
258 
259  return std::make_pair( std::make_shared<Abstract>(abstract.close()), parameter_map );
260 }
261 
262 
264  Abstract abstract = Abstract();
265  abstract.child_data_ = std::make_shared<Abstract::ChildData>(*this->child_data_);
266  abstract.child_data_->closed_ = false;
267  abstract.child_data_->finish_status_ = FinishStatus::none_;
268  abstract.child_data_->list_of_childs.clear();
269  abstract.child_data_->selection_of_childs = std::make_shared<Selection>(this->type_name() + "_TYPE_selection");
270  abstract.copy_attributes(*attributes_);
271 
272  abstract.generic_type_hash_ = this->generic_type_hash_;
273  abstract.parameter_map_ = this->parameter_map_;
274  return abstract;
275 }
276 
277 
280  return *this;
281 }
282 
283 
285  this->add_attribute_(key, value);
286  return *this;
287 }
288 
289 
290 
291 /*Abstract &Abstract::set_generic_content_hash(TypeHash generic_content_hash) {
292  child_data_->generic_content_hash_ = generic_content_hash;
293  return *this;
294 }*/
295 
296 
298  return child_data_->list_of_childs.begin();
299 }
300 
302  return child_data_->list_of_childs.end();
303 }
304 
305 
306 Abstract::ChildData::ChildData(const string &name, const string &description)
307 : selection_of_childs( std::make_shared<Selection> (name + "_TYPE_selection") ),
308  description_(description),
309  type_name_(name),
310  finish_status_(FinishStatus::none_),
311  closed_(false),
312  selection_default_(Default::obligatory())
313 {}
314 
315 
316 /************************************************
317  * implementation of AdHocAbstract
318  */
319 
321 : Abstract("Derived AdHocAbstract", "This description doesn't have print out."),
322  ancestor_(ancestor)
323 {
324  //test default descendant of ancestor
325  const Record * default_desc = ancestor.get_default_descendant();
326  if (default_desc) {
327  allow_auto_conversion( default_desc->type_name() );
328  }
329 
330  this->close();
331 
332 }
333 
334 
336 {
337  Abstract::add_child(subrec);
338 
339  return *this;
340 }
341 
342 
344 {
345  if (this->is_finished()) return child_data_->finish_status_;
346 
347  const_cast<Abstract &>(ancestor_).finish(finish_type);
348 
349  //test default descendant of ancestor
350  const Record * default_desc = ancestor_.get_default_descendant();
351  if (default_desc) {
352  allow_auto_conversion( default_desc->type_name() );
353  }
354 
355  for (Abstract::ChildDataIter it = ancestor_.child_data_->list_of_childs.begin(); it != ancestor_.child_data_->list_of_childs.end(); ++it) {
356  child_data_->selection_of_childs->add_value(child_data_->list_of_childs.size(), (*it).type_name());
357  child_data_->list_of_childs.push_back(*it);
358  }
359 
360  return Abstract::finish(finish_type);
361 }
362 
363 
365  TypeHash seed=0;
366  boost::hash_combine(seed, "AdHocAbstract");
367  boost::hash_combine(seed, type_name());
368  boost::hash_combine(seed, child_data_->description_);
369  boost::hash_combine(seed, ancestor_.type_name());
370 
371  return seed;
372 }
373 
374 
376  return "AdHocAbstract";
377 }
378 
379 
380 
381 } // closing namespace Type
382 } // closing namespace Input
383 
384 
Input::Type::in_perform_
@ in_perform_
Definition: type_base.hh:76
Input::Type::Abstract::get_default_descendant
const Record * get_default_descendant() const
Returns default descendant.
Definition: type_abstract.cc:113
Armor::vec
ArmaVec< double, N > vec
Definition: armor.hh:885
Input::Type::FinishStatus
FinishStatus
Definition: type_base.hh:74
Input::Type::Record::type_name
string type_name() const override
Implements Type::TypeBase::type_name.
Definition: type_record.cc:317
type_abstract.hh
Input::Type::Abstract::AdHocAbstract
friend class AdHocAbstract
Definition: type_abstract.hh:64
Input
Abstract linear system class.
Definition: balance.hh:40
ASSERT
#define ASSERT(expr)
Definition: asserts.hh:350
Input::Type::AdHocAbstract::class_name
string class_name() const override
Override Type::TypeBase::class_name.
Definition: type_abstract.cc:375
asserts.hh
Definitions of ASSERTS.
Input::Type::TypeBase::MakeInstanceReturnType
std::pair< std::shared_ptr< TypeBase >, ParameterMap > MakeInstanceReturnType
Return type of make_instance methods, contains instance of generic type and map of used parameters.
Definition: type_base.hh:111
Input::Type::TypeBase::add_attribute_
void add_attribute_(std::string name, json_string val)
Add attribute of given name to attribute map.
Definition: type_base.cc:134
Input::TypeRepository::get_instance
static TypeRepository & get_instance()
Return singleton instance of class.
Definition: type_repository.hh:59
value
static constexpr bool value
Definition: json.hpp:87
Input::Type::Abstract::is_closed
virtual bool is_closed() const override
Returns true if data_ is closed.
Definition: type_abstract.cc:206
Input::Type::none_
@ none_
Definition: type_base.hh:75
Input::Type::TypeBase::root_of_generic_subtree_
bool root_of_generic_subtree_
flag is true if type should be root of generic subtree
Definition: type_base.hh:301
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
std::vector
Definition: doxy_dummy_defs.hh:7
system.hh
type_base.hh
Input::Type::Abstract::get_type_selection
const Selection & get_type_selection() const
Returns reference to Selection type of the implicit key TYPE.
Definition: type_abstract.cc:123
type_selection.hh
storage.hh
exceptions.hh
type_record.hh
Input::Type::TypeBase::parameter_map_
ParameterMap parameter_map_
map of parameters if type is part of generic subtree
Definition: type_base.hh:307
Input::Type::Abstract::finish
FinishStatus finish(FinishStatus finish_type=FinishStatus::regular_) override
Finish declaration of the Abstract type.
Definition: type_abstract.cc:149
Input::Type::TypeBase::attributes_
std::shared_ptr< attribute_map > attributes_
map of type attributes (e. g. input_type, name etc.)
Definition: type_base.hh:298
Input::Type::Abstract::class_name
string class_name() const override
Override Type::TypeBase::class_name.
Definition: type_abstract.cc:216
Input::Type::Abstract::root_of_generic_subtree
Abstract & root_of_generic_subtree()
Definition: type_abstract.cc:278
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
Input::Type::Record::derive_from
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:196
Input::Type::Abstract::child_size
unsigned int child_size() const
Returns number of descendants in the child_data_.
Definition: type_abstract.cc:129
Input::Type::Abstract::ChildDataIter
std::vector< Record >::const_iterator ChildDataIter
Public typedef of constant iterator into array of keys.
Definition: type_abstract.hh:122
Input::Type::Abstract::get_selection_default
Default & get_selection_default() const
Definition: type_abstract.cc:221
Input::Type::Abstract::end_child_data
ChildDataIter end_child_data() const
Container-like access to the descendants of the Abstract.
Definition: type_abstract.cc:301
attribute_lib.hh
Input::Type::AdHocAbstract
Class for declaration of polymorphic Record.
Definition: type_abstract.hh:269
ASSERT_PERMANENT
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:347
type_generic.hh
Input::Type::Abstract::add_attribute
Abstract & add_attribute(std::string key, TypeBase::json_string value)
Frontend to TypeBase::add_attribute_.
Definition: type_abstract.cc:284
Input::Type::Abstract
Class for declaration of polymorphic Record.
Definition: type_abstract.hh:62
Input::Type::Abstract::deep_copy
Abstract deep_copy() const
Create deep copy of Abstract (copy all data stored in shared pointers etc.)
Definition: type_abstract.cc:263
Input::Type::Abstract::begin_child_data
ChildDataIter begin_child_data() const
Container-like access to the descendants of the Abstract.
Definition: type_abstract.cc:297
Input::Type::Abstract::ChildData::ChildData
ChildData(const string &name, const string &description)
Constructor.
Definition: type_abstract.cc:306
type_repository.hh
Input::Type::TypeBase::generic_type_hash_
TypeHash generic_type_hash_
hash string of generic type if type is derived, or empty string
Definition: type_base.hh:304
Input::Type::Abstract::ChildData
Actual data of the abstract record.
Definition: type_abstract.hh:71
Input::Type::Selection
Template for classes storing finite set of named values.
Definition: type_selection.hh:65
std::map< std::string, TypeHash >
Input::Type::Abstract::is_finished
virtual bool is_finished() const override
Implements TypeBase::is_finished.
Definition: type_abstract.cc:201
Input::Type::Abstract::make_instance
virtual MakeInstanceReturnType make_instance(std::vector< ParameterPair > vec=std::vector< ParameterPair >()) override
Definition: type_abstract.cc:237
Input::Type
Definition: balance.hh:41
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
Input::Type::Abstract::get_descendant
const Record & get_descendant(const string &name) const
Returns reference to the inherited Record with given name.
Definition: type_abstract.cc:105
Input::Type::AdHocAbstract::add_child
AdHocAbstract & add_child(Record &subrec)
Add inherited Record.
Definition: type_abstract.cc:335
input_type.hh
Input::Type::Abstract::content_hash
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_abstract.cc:77
Input::Type::Abstract::child_data_
std::shared_ptr< ChildData > child_data_
Actual data of the Abstract.
Definition: type_abstract.hh:253
Input::Type::Abstract::Abstract
Abstract()
Default constructor.
Definition: type_abstract.cc:57
Input::Type::Abstract::type_name
virtual string type_name() const override
Implements Type::TypeBase::type_name.
Definition: type_abstract.cc:211
Input::Type::generic_
@ generic_
Definition: type_base.hh:78
std
Definition: doxy_dummy_defs.hh:5
Input::Type::TypeBase::json_string
std::string json_string
String stored in JSON format.
Definition: type_base.hh:99
Input::Type::AdHocAbstract::finish
FinishStatus finish(FinishStatus finish_type=FinishStatus::regular_) override
Finish declaration of the AdHocAbstract type.
Definition: type_abstract.cc:343
Input::Type::AdHocAbstract::ancestor_
const Abstract & ancestor_
Reference to ancestor Abstract.
Definition: type_abstract.hh:299
Input::Type::Abstract::have_default_descendant
bool have_default_descendant() const
Check if type has set value of default descendants.
Definition: type_abstract.cc:225
Input::Type::Abstract::add_child
int add_child(Record &subrec)
Add inherited Record.
Definition: type_abstract.cc:134
Input::TypeRepository::add_type
std::shared_ptr< T > add_type(const T &type)
Add type to TypeRepository if doesn't exist there or get existing type with same TypeHash.
Definition: type_repository.hh:109
Input::Type::TypeBase
Base of classes for declaring structure of the input data.
Definition: type_base.hh:92
Input::Type::AdHocAbstract::content_hash
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_abstract.cc:364
Input::Type::TypeBase::set_generic_attributes
void set_generic_attributes(ParameterMap param_map)
Definition: type_base.cc:173
Input::Type::Abstract::allow_auto_conversion
Abstract & allow_auto_conversion(const string &type_default)
Allows shorter input of the Abstract providing the default value to the "TYPE" key.
Definition: type_abstract.cc:97
Input::Type::Abstract::close
Abstract & close()
Close the Abstract and add its to type repository (see TypeRepository::add_type).
Definition: type_abstract.cc:190
Input::Type::Abstract::finish_status
virtual FinishStatus finish_status() const override
Implements TypeBase::finish_status.
Definition: type_abstract.cc:196
Input::Type::TypeBase::TypeHash
std::size_t TypeHash
Type returned by content_hash methods.
Definition: type_base.hh:95