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