Flow123d  last_with_con_2.0.0-4-g42e6930
type_base.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_base.cc
15  * @brief
16  */
17 
18 #include <limits>
19 #include <ios>
20 #include <map>
21 #include <vector>
22 #include <string>
23 #include <iomanip>
24 
25 #include "system/system.hh"
26 
27 #include <boost/type_traits.hpp>
28 #include <boost/tokenizer.hpp>
29 #include <boost/shared_ptr.hpp>
30 #include <boost/make_shared.hpp>
31 #include <boost/algorithm/string.hpp>
32 #include <boost/functional/hash.hpp>
33 #include <boost/pointer_cast.hpp>
34 
35 
36 #include "input_type.hh"
37 #include "type_output.hh"
38 #include "type_repository.hh"
39 #include "attribute_lib.hh"
41 
42 
43 namespace Input {
44 namespace Type {
45 
46 using namespace std;
47 
48 
49 
50 /*******************************************************************
51  * implementation of TypeBase
52  */
53 
54 
55 
57 : attributes_( std::make_shared<attribute_map>() ), root_of_generic_subtree_(false),
58  generic_type_hash_(0) {}
59 
60 
61 
65 
66 
67 
69 
70 
71 bool TypeBase::is_valid_identifier(const string& key) {
72  namespace ba = boost::algorithm;
73  return ba::all( key, ba::is_lower() || ba::is_digit() || ba::is_any_of("_") );
74 }
75 
76 
77 string TypeBase::desc() const {
78  stringstream ss;
79  ss << OutputText(this);
80  return ss.str();
81 }
82 
83 
84 
94 }
95 
96 
97  std::string TypeBase::hash_str(TypeHash hash) {
98  stringstream ss;
99  ss << "\"" << std::hex << hash << "\"";
100  return ss.str();
101 }
102 
103 
104 
105 
106 void TypeBase::add_attribute_(std::string name, json_string val) {
107  ASSERT(validate_json(val))(name)(val).error("Invalid JSON format of attribute");
108  (*attributes_)[name] = val;
109 }
110 
111 
113  try {
114  json_spirit::mValue node;
115  json_spirit::read_or_throw( str, node);
116  return true;
117  } catch (json_spirit::Error_position &e ) {
118  return false;
119  }
120 }
121 
122 
124  std::stringstream ss;
125  ss << "{";
126  for (ParameterMap::iterator it=parameter_map.begin(); it!=parameter_map.end(); it++) {
127  if (it != parameter_map.begin()) ss << "," << endl;
128  ss << "\"" << (*it).first << "\" : " << TypeBase::hash_str( (*it).second );
129  }
130  ss << "}";
131  return ss.str();
132 }
133 
135  stringstream ss;
136  ss << "[ ";
137  for (ParameterMap::iterator it=parameter_map.begin(); it!=parameter_map.end(); it++) {
138  if (it != parameter_map.begin()) ss << ", ";
139  ss << "\"" << it->first << "\"";
140  }
141  ss << " ]";
142  return ss.str();
143 }
144 
146  // check if the type is really generic (it may be non-generic even if part of a generic subtree)
147  if (parameter_map.size() > 0)
151 }
152 
153 
154 void TypeBase::copy_attributes(attribute_map other_attributes) {
155  attributes_->clear();
156  for(auto &item : other_attributes) {
157  if (item.first[0] != '_') // not internal attribute
158  attributes_->insert(item);
159  }
160 }
161 
162 
163 
164 
165 
166 
167 
168 
169 std::ostream& operator<<(std::ostream& stream, const TypeBase& type) {
170  return ( stream << OutputText(&type) );
171 }
172 
173 
174 
175 /**********************************************************************************
176  * implementation of Type::Array
177  */
178 
180 {
181  TypeHash seed=0;
182  boost::hash_combine(seed, type_name());
183  boost::hash_combine(seed, data_->lower_bound_);
184  boost::hash_combine(seed, data_->upper_bound_);
185  boost::hash_combine(seed, data_->type_of_values_->content_hash() );
186  return seed;
187 }
188 
189 
190 bool Array::finish(bool is_generic) {
191  return data_->finish(is_generic);
192 }
193 
194 
195 
196 bool Array::ArrayData::finish(bool is_generic)
197 {
198  if (finished) return true;
199 
200  if (typeid( *(type_of_values_.get()) ) == typeid(Instance)) type_of_values_ = type_of_values_->make_instance().first;
201  if (!is_generic && type_of_values_->is_root_of_generic_subtree()) THROW( ExcGenericWithoutInstance() << EI_Object(type_of_values_->type_name()) );
202 
203  return (finished = type_of_values_->finish(is_generic) );
204 }
205 
206 
207 
208 string Array::type_name() const {
209  return "array_of_" + data_->type_of_values_->type_name();
210 }
211 
212 
213 
214 bool Array::operator==(const TypeBase &other) const {
215  return typeid(*this) == typeid(other) &&
216  (*data_->type_of_values_ == static_cast<const Array *>(&other)->get_sub_type() );
217 }
218 
219 
220 
222  // Create copy of array, we can't set type from parameter vector directly (it's TypeBase that is not allowed)
223  Array arr = this->deep_copy();
224  // Replace parameter stored in type_of_values_
225  MakeInstanceReturnType inst = arr.data_->type_of_values_->make_instance(vec);
226  arr.data_->type_of_values_ = inst.first;
227  ParameterMap parameter_map = inst.second;
228  // Copy attributes
230 
231  // Set parameters as attribute
232  json_string val = this->print_parameter_map_to_json(parameter_map);
233  ASSERT(this->validate_json(val))(val).error("Invalid JSON format of attribute 'parameters'.");
234  arr.parameter_map_ = parameter_map;
235  arr.generic_type_hash_ = this->content_hash();
236 
237  return std::make_pair( std::make_shared<Array>(arr), parameter_map );
238 }
239 
240 
242  Array arr = Array(Integer()); // Type integer will be overwritten
243  arr.data_ = std::make_shared<Array::ArrayData>(*this->data_);
244  arr.data_->finished = false;
245  return arr;
246 }
247 
248 
249 Array::Array(std::shared_ptr<TypeBase> type, unsigned int min_size, unsigned int max_size)
250 : data_(std::make_shared<ArrayData>(min_size, max_size))
251 {
252  ASSERT_LE(min_size, max_size).error("Wrong limits for size of Input::Type::Array");
253  ASSERT(type->is_closed()).error();
254 
255  data_->type_of_values_ = type;
256 }
257 
258 
259 /**********************************************************************************
260  * implementation and explicit instantiation of Array constructor template
261  */
262 
263 template <class ValueType>
264 Array::Array(const ValueType &type, unsigned int min_size, unsigned int max_size)
265 : Array(std::static_pointer_cast<TypeBase>( std::make_shared<ValueType>(type) ), min_size, max_size)
266 {
267  // ASSERT MESSAGE: The type of declared keys has to be a class derived from TypeBase.
268  BOOST_STATIC_ASSERT( (boost::is_base_of<TypeBase, ValueType >::value) );
269 }
270 
271 // explicit instantiation
272 
273 #define ARRAY_CONSTRUCT(TYPE) \
274 template Array::Array(const TYPE &type, unsigned int min_size, unsigned int max_size)
275 
276 ARRAY_CONSTRUCT(String);
277 ARRAY_CONSTRUCT(Integer);
278 ARRAY_CONSTRUCT(Double);
279 ARRAY_CONSTRUCT(Bool);
280 ARRAY_CONSTRUCT(FileName);
281 ARRAY_CONSTRUCT(Selection);
284 ARRAY_CONSTRUCT(Abstract);
285 ARRAY_CONSTRUCT(Parameter);
286 ARRAY_CONSTRUCT(Instance);
287 
288 
289 /**********************************************************************************
290  * implementation of Type::Scalar ... and descendants.
291  */
292 
293 /**********************************************************************************
294  * implementation of Type::Bool
295  */
296 
297 
299 {
300  TypeHash seed=0;
301  boost::hash_combine(seed, type_name());
302  return seed;
303 }
304 
305 
306 string Bool::type_name() const {
307  return "Bool";
308 }
309 
310 
312  return std::make_pair( std::make_shared<Bool>(*this), ParameterMap() );
313 }
314 
315 /**********************************************************************************
316  * implementation of Type::Integer
317  */
318 
320 {
321  TypeHash seed=0;
322  boost::hash_combine(seed, type_name());
323  boost::hash_combine(seed, lower_bound_);
324  boost::hash_combine(seed, upper_bound_);
325  return seed;
326 }
327 
328 
329 
330 bool Integer::match(std::int64_t value) const {
331  return ( value >=lower_bound_ && value <= upper_bound_);
332 }
333 
334 
335 
336 string Integer::type_name() const {
337  return "Integer";
338 }
339 
340 
342  return std::make_pair( std::make_shared<Integer>(*this), ParameterMap() );
343 }
344 
345 
346 /**********************************************************************************
347  * implementation of Type::Double
348  */
349 
350 
352 {
353  TypeHash seed=0;
354  boost::hash_combine(seed, type_name());
355  boost::hash_combine(seed, lower_bound_);
356  boost::hash_combine(seed, upper_bound_);
357  return seed;
358 }
359 
360 
361 
362 bool Double::match(double value) const {
363  return ( value >=lower_bound_ && value <= upper_bound_);
364 }
365 
366 
367 
368 string Double::type_name() const {
369  return "Double";
370 }
371 
372 
374  return std::make_pair( std::make_shared<Double>(*this), ParameterMap() );
375 }
376 
377 
378 /**********************************************************************************
379  * implementation of Type::FileName
380  */
381 
383 {
384  TypeHash seed=0;
385  boost::hash_combine(seed, type_name());
386  boost::hash_combine(seed, type_);
387  return seed;
388 }
389 
390 
391 
392 
393 
394 string FileName::type_name() const {
395  switch (type_) {
396  case ::FilePath::input_file:
397  return "FileName_input";
398  case ::FilePath::output_file:
399  return "FileName_output";
400  default:
401  return "FileName";
402  }
403 }
404 
405 
406 
407 bool FileName::match(const string &str) const {
408  return (type_ == ::FilePath::input_file) || (str[0] != DIR_DELIMITER); // output files can not be absolute
409 }
410 
411 
412 
414  return std::make_pair( std::make_shared<FileName>(*this), ParameterMap() );
415 }
416 
417 
418 /**********************************************************************************
419  * implementation of Type::String
420  */
421 
422 
424 {
425  TypeHash seed=0;
426  boost::hash_combine(seed, type_name());
427  return seed;
428 }
429 
430 
431 
432 string String::type_name() const {
433  return "String";
434 }
435 
436 
437 
438 
439 bool String::match(const string &str) const {
440  return true;
441 }
442 
443 
444 
446  return std::make_pair( std::make_shared<String>(*this), ParameterMap() );
447 }
448 
449 
450 
451 } // closing namespace Type
452 } // closing namespace Input
453 
454 
455 
bool validate_json(json_string str) const
Check if str is valid JSON string.
Definition: type_base.cc:112
MakeInstanceReturnType make_instance(std::vector< ParameterPair > vec=std::vector< ParameterPair >()) override
Implements TypeBase::make_instance.
Definition: type_base.cc:413
static bool is_valid_identifier(const string &key)
Check that a key is valid identifier.
Definition: type_base.cc:71
Base of classes for declaring structure of the input data.
Definition: type_base.hh:79
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:319
void set_generic_attributes(ParameterMap param_map)
Definition: type_base.cc:145
string type_name() const override
Implements Type::TypeBase::type_name.
Definition: type_base.cc:208
MakeInstanceReturnType make_instance(std::vector< ParameterPair > vec=std::vector< ParameterPair >()) override
Implements TypeBase::make_instance.
Definition: type_base.cc:341
bool is_root_of_generic_subtree()
Indicates if type is marked with flag root_of_generic_subtree_.
Definition: type_base.hh:214
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:382
void copy_attributes(attribute_map other_attributes)
Definition: type_base.cc:154
static string generic_parameters()
std::string hash_str() const
Format the hash of this type.
Definition: type_base.hh:202
bool root_of_generic_subtree_
flag is true if type should be root of generic subtree
Definition: type_base.hh:283
string desc() const
Returns string with Type extensive documentation.
Definition: type_base.cc:77
IntFormatSpec< int, TypeSpec<'x'> > hex(int value)
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:97
virtual TypeHash content_hash() const =0
Hash of the type specification.
Helper class that stores data of generic types.
Definition: type_generic.hh:88
void finish(bool is_root_of_generic_subtree=false)
Finish all stored types.
#define ASSERT_LE(a, b)
Definition of comparative assert macro (Less or Equal)
Definition: asserts.hh:304
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:351
virtual string type_name() const
Returns an identification of the type. Useful for error messages.
Definition: type_base.hh:116
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
std::shared_ptr< attribute_map > attributes_
map of type attributes (e. g. input_type, name etc.)
Definition: type_base.hh:280
Class for declaration of the integral input data.
Definition: type_base.hh:465
void add_attribute_(std::string name, json_string val)
Add attribute of given name to attribute map.
Definition: type_base.cc:106
Class for declaration of inputs sequences.
Definition: type_base.hh:321
void read_or_throw(const std::string &s, mValue &value)
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:289
std::shared_ptr< ArrayData > data_
Handle to the actual array data.
Definition: type_base.hh:411
bool finish(bool is_generic=false)
Finishes initialization of the ArrayData.
Definition: type_base.cc:196
bool match(std::int64_t value) const
Check valid value of Integer.
Definition: type_base.cc:330
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:179
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:423
static void lazy_finish()
Finishes all types registered in type repositories.
Definition: type_base.cc:85
std::map< std::string, TypeHash > ParameterMap
Defines map of used parameters.
Definition: type_base.hh:95
string type_name() const override
Implements Type::TypeBase::type_name.
Definition: type_base.cc:368
TypeBase()
The default constructor.
Definition: type_base.cc:56
bool match(double value) const
Returns true if the given integer value conforms to the Type::Double bounds.
Definition: type_base.cc:362
static string root_of_generic_subtree()
string type_name() const override
Implements Type::TypeBase::type_name.
Definition: type_base.cc:306
bool finish(bool is_generic=false) override
Finishes initialization of the Array type because of lazy evaluation of type_of_values.
Definition: type_base.cc:190
MakeInstanceReturnType make_instance(std::vector< ParameterPair > vec=std::vector< ParameterPair >()) override
Implements TypeBase::make_instance.
Definition: type_base.cc:221
bool operator==(const TypeBase &other) const override
Implements Type::TypeBase::operator== Compares also subtypes.
Definition: type_base.cc:214
virtual MakeInstanceReturnType make_instance(std::vector< ParameterPair > vec=std::vector< ParameterPair >()) override
Implements TypeBase::make_instance.
Definition: type_base.cc:445
string type_name() const override
Implements Type::TypeBase::type_name.
Definition: type_base.cc:336
virtual bool match(const string &value) const
Particular descendants can check validity of the string.
Definition: type_base.cc:439
TypeHash generic_type_hash_
hash string of generic type if type is derived, or empty string
Definition: type_base.hh:286
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:123
bool match(const string &str) const
Checks relative output paths.
Definition: type_base.cc:407
string type_name() const override
Implements Type::TypeBase::type_name.
Definition: type_base.cc:394
virtual string type_name() const override
Implements Type::TypeBase::type_name.
Definition: type_base.cc:432
friend class Array
Definition: type_base.hh:291
Actual data of the Array.
Definition: type_base.hh:329
#define DIR_DELIMITER
Definition: system.hh:44
std::string json_string
String stored in JSON format.
Definition: type_base.hh:85
MakeInstanceReturnType make_instance(std::vector< ParameterPair > vec=std::vector< ParameterPair >()) override
Implements TypeBase::make_instance.
Definition: type_base.cc:311
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:169
TypeHash content_hash() const override
Implements TypeBase::content_hash.
Definition: type_base.cc:298
Class for create text documentation.
Definition: type_output.hh:199
ARRAY_CONSTRUCT(String)
virtual ~TypeBase()
Destructor.
Definition: type_base.cc:68
Array deep_copy() const
Create deep copy of Array.
Definition: type_base.cc:241
json_string print_parameter_map_keys_to_json(ParameterMap param_map) const
Definition: type_base.cc:134
std::size_t TypeHash
Type returned by content_hash methods.
Definition: type_base.hh:82
Array()
Forbids default constructor in order to prevent empty data_.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:45
friend class Record
Definition: type_base.hh:292
MakeInstanceReturnType make_instance(std::vector< ParameterPair > vec=std::vector< ParameterPair >()) override
Implements TypeBase::make_instance.
Definition: type_base.cc:373