Flow123d
json_to_storage.cc
Go to the documentation of this file.
1 /*
2  * json_to_storage.cc
3  *
4  * Created on: May 7, 2012
5  * Author: jb
6  */
7 
8 #include <boost/iostreams/device/file.hpp>
9 #include <boost/iostreams/filtering_stream.hpp>
10 
11 #include "json_to_storage.hh"
12 #include "input/comment_filter.hh"
13 
15 
16 namespace Input {
17 using namespace std;
18 using namespace internal;
19 
20 
21 
22 /********************************************
23  * Implementation of internal::JSONPath
24  */
25 
26 
27 JSONPath::JSONPath(const Node& root_node)
28 {
29  path_.push_back( make_pair( (int)(-1), string("/") ) );
30  nodes_.push_back( &root_node );
31 }
32 
33 const JSONPath::Node * JSONPath::down(unsigned int index)
34 {
35  const Node * head_node = nodes_.back();
36  const json_spirit::mArray &array = head_node->get_array(); // the type should be checked in make_storage
37 
38  if ( index >= array.size()) return NULL;
39  path_.push_back( make_pair( index, string("") ) );
40  nodes_.push_back( &( array[index] ) );
41 
42  return nodes_.back();
43 }
44 
45 
46 const JSONPath::Node * JSONPath::down(const string& key)
47 {
48  const Node * head_node = nodes_.back();
49  const json_spirit::mObject &obj = head_node->get_obj(); // the type should be checked in make_storage
50 
51  json_spirit::mObject::const_iterator it = obj.find(key);
52  if (it == obj.end()) {
53  return NULL;
54  } else {
55  path_.push_back( make_pair( (int)(-1), key) );
56  nodes_.push_back( &( it->second ) );
57  }
58  return nodes_.back();
59 }
60 
61 
63 {
64  if (path_.size() > 1) {
65  path_.pop_back();
66  nodes_.pop_back();
67  }
68 }
69 
71  path_.resize(1);
72  nodes_.resize(1);
73 }
74 
75 
76 bool JSONPath::get_ref_from_head(string & ref_address)
77 {
78  const Node * head_node = nodes_.back();
79  if (head_node->type() != json_spirit::obj_type) return false;
80  const json_spirit::mObject &obj = head_node->get_obj();
81  if (obj.size() != 1) return false;
82  if (obj.begin()->first != "REF") return false;
83 
84  const Node &ref_node = obj.begin()->second;
85  if (ref_node.type() != json_spirit::str_type) {
86  THROW( ExcRefOfWrongType() << EI_ErrorAddress(*this) );
87 
88  }
89  ref_address = ref_node.get_str();
90  return true;
91 }
92 
93 
94 /**
95  * This returns path to reference given by address in ref_address.
96  *
97  */
98 JSONPath JSONPath::find_ref_node(const string& ref_address)
99 {
100  namespace ba = boost::algorithm;
101 
102  JSONPath ref_path(*this);
103 
104  string::size_type pos = 0;
105  string::size_type new_pos = 0;
106  string address = ref_address + '/';
107  string tmp_str;
108  bool relative_ref = false;
109 
110  std::set<string>::iterator it = previous_references_.find(ref_address);
111  if (it == previous_references_.end()) {
112  ref_path.previous_references_.insert(ref_address);
113  } else {
114  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
115  << EI_Specification("cannot follow reference") );
116  }
117 
118  while ( ( new_pos=address.find('/',pos) ) != string::npos ) {
119  tmp_str = address.substr(pos, new_pos - pos);
120  // DBGMSG("adr: '%s' tstr '%s' pos:%d npos:%d\n", address.c_str(), tmp_str.c_str(), pos, new_pos );
121  if (pos==0 && tmp_str == "") {
122  // absolute path
123  ref_path.go_to_root();
124 
125  } else if ( ba::all( tmp_str, ba::is_digit()) ) {
126  // integer == index in array
127  if (ref_path.head() -> type() != json_spirit::array_type) {
128  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
129  << EI_Specification("there should be Array") );
130  }
131 
132  if ( ref_path.down( atoi(tmp_str.c_str()) ) == NULL) {
133  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
134  << EI_Specification("index out of size of Array") );
135  }
136 
137  } else if (tmp_str == "..") {
138  relative_ref = true;
139  if (ref_path.level() <= 0 ) {
140  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
141  << EI_Specification("can not go up from root") );
142  }
143  ref_path.up();
144 
145  } else {
146  if (ref_path.head() -> type() != json_spirit::obj_type)
147  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
148  << EI_Specification("there should be Record") );
149  if ( ref_path.down(tmp_str) == NULL )
150  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
151  << EI_Specification("key '"+tmp_str+"' not found") );
152  }
153  pos = new_pos+1;
154  }
155  if (relative_ref) {
156  xprintf(Msg, "Key '%s' is set to value of key '%s'\n", this->str().c_str(), ref_path.str().c_str());
157  }
158  return ref_path;
159 }
160 
161 
162 
163 void JSONPath::output(ostream &stream) const {
164  if (level() == 0) {
165  stream << "/";
166  return;
167  }
168 
169  for(vector< pair<int, string> >::const_iterator it = path_.begin()+1; it != path_.end(); ++it) {
170  if ( it->first < 0 ) {
171  stream << "/" << it->second;
172  } else {
173  stream << "/" << it->first;
174  }
175  }
176 }
177 
178 
179 
180 string JSONPath::str() {
181  stringstream ss;
182  output(ss);
183  return ss.str();
184 }
185 
186 
187 
189  previous_references_.insert(str());
190  /*cout << "PUT ADDRESS: " << previous_references_.size() << " " << str() << endl;
191  for (std::set<string>::iterator it = previous_references_.begin(); it!=previous_references_.end(); ++it)
192  cout << (*it) << " - ";
193  cout << endl << endl; */
194 }
195 
196 
197 
198 std::ostream& operator<<(std::ostream& stream, const JSONPath& path) {
199  path.output(stream);
200  return stream;
201 }
202 
203 
204 /********************************************
205  * Implementation of public part of JSONToStorage
206  */
207 
209 : storage_(nullptr),
210  root_type_(nullptr)
211 {
212  /* from json_spirit_value.hh:
213  * enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };
214  */
215  json_type_names.push_back("JSON object");
216  json_type_names.push_back("JSON array");
217  json_type_names.push_back("JSON string");
218  json_type_names.push_back("JSON bool");
219  json_type_names.push_back("JSON int");
220  json_type_names.push_back("JSON real");
221  json_type_names.push_back("JSON null");
222 }
223 
224 
225 
226 JSONToStorage::JSONToStorage(istream &in, const Type::TypeBase &root_type)
227 : JSONToStorage()
228 {
229  read_stream(in,root_type);
230 }
231 
232 
233 
234 JSONToStorage::JSONToStorage( const string &str, const Type::TypeBase &root_type)
235 : JSONToStorage()
236 {
237  try {
238  istringstream is(str);
239  read_stream(is, root_type);
240  } catch (ExcNotJSONFormat &e) {
241  e << EI_File("STRING: "+str); throw;
242  }
243 }
244 
245 
246 
247 void JSONToStorage::read_stream(istream &in, const Type::TypeBase &root_type)
248 {
249  namespace io = boost::iostreams;
250  ASSERT(storage_==nullptr," ");
251 
252  // finish all lazy input types
254 
255  io::filtering_istream filter_in;
256 
257  filter_in.push(uncommenting_filter());
258  filter_in.push(in);
259 
260  JSONPath::Node node;
261 
262 
263  try {
264  json_spirit::read_or_throw( filter_in, node);
265  } catch (json_spirit::Error_position &e ) {
266  THROW( ExcNotJSONFormat() << EI_JSONLine(e.line_) << EI_JSONColumn(e.column_) << EI_JSONReason(e.reason_));
267  }
268 
269  JSONPath root_path(node);
270 
271  root_type_ = &root_type;
272  storage_ = make_storage(root_path, root_type_);
273 
274  ASSERT( storage_ != nullptr, "Internal error in JSON reader, the storage pointer is NULL after reading the stream.\n");
275 }
276 
277 
278 
279 
280 
281 
282 /********************************************
283  * Implementation of private part of JSONToStorage - make_storage dispatch
284  */
285 
286 
288 {
289  ASSERT(type != NULL, "Can not dispatch, NULL pointer to TypeBase.\n");
290 
291  // first check reference
292  string ref_address;
293  if (p.get_ref_from_head(ref_address)) {
294  // todo: mark passed references and check cyclic references
295 
296  // dereference and take data from there
297  JSONPath ref_path = p.find_ref_node(ref_address);
298  return make_storage( ref_path, type );
299  }
300  //p.put_address();
301 
302  // return Null storage if there is null on the current location
303  if (p.head()->type() == json_spirit::null_type)
304  return new StorageNull();
305 
306  // dispatch types
307  if (typeid(*type) == typeid(Type::Record)) {
308  return make_storage(p, static_cast<const Type::Record *>(type) );
309  } else
310  if (typeid(*type) == typeid(Type::Array)) {
311  return make_storage(p, static_cast<const Type::Array *>(type) );
312  } else
313  if (typeid(*type) == typeid(Type::Integer)) {
314  return make_storage(p, static_cast<const Type::Integer *>(type) );
315  } else
316  if (typeid(*type) == typeid(Type::Double)) {
317  return make_storage(p, static_cast<const Type::Double *>(type) );
318  } else
319  if (typeid(*type) == typeid(Type::Bool)) {
320  return make_storage(p, static_cast<const Type::Bool *>(type) );
321  } else
322  if (typeid(*type) == typeid(Type::Selection)) {
323  return make_storage(p, static_cast<const Type::Selection *>(type) );
324  } else {
325  const Type::AbstractRecord * abstract_record_type = dynamic_cast<const Type::AbstractRecord *>(type);
326  if (abstract_record_type != NULL ) return make_storage(p, abstract_record_type );
327 
328  const Type::String * string_type = dynamic_cast<const Type::String *>(type);
329  if (string_type != NULL ) return make_storage(p, string_type );
330 
331  // default -> error
332  xprintf(Err,"Unknown descendant of TypeBase class, name: %s\n", typeid(type).name());
333  }
334 
335  return new StorageNull();
336 }
337 
338 
340 {
341  if (p.head()->type() == json_spirit::obj_type) {
342  const json_spirit::mObject & j_map = p.head()->get_obj();
343  std::set<string> keys_to_processed;
344  json_spirit::mObject::const_iterator map_it;
345  std::set<string>::iterator set_it;
346 
347  for( map_it = j_map.begin(); map_it != j_map.end(); ++map_it) {
348  keys_to_processed.insert(map_it->first);
349  }
350 
351  StorageArray *storage_array = new StorageArray(record->size());
352  // check individual keys
353  for( Type::Record::KeyIter it= record->begin(); it != record->end(); ++it) {
354  // remove processed key from keys_to_processed
355  set_it = keys_to_processed.find(it->key_);
356  if (set_it != keys_to_processed.end()) {
357  keys_to_processed.erase(set_it);
358  }
359 
360  if (p.down(it->key_) != NULL) {
361  // key on input => check & use it
362  storage_array->new_item(it->key_index, make_storage(p, it->type_.get()) );
363  p.up();
364  } else {
365  // key not on input
366  if (it->default_.is_obligatory() ) {
367  THROW( ExcInputError() << EI_Specification("Missing obligatory key '"+ it->key_ +"'.")
368  << EI_ErrorAddress(p) << EI_InputType(record->desc()) );
369  } else if (it->default_.has_value_at_declaration() ) {
370  storage_array->new_item(it->key_index,
371  make_storage_from_default( it->default_.value(), it->type_.get() ) );
372  } else { // defalut - optional or default at read time
373  // set null
374  storage_array->new_item(it->key_index, new StorageNull() );
375  }
376  }
377  }
378 
379  for( set_it = keys_to_processed.begin(); set_it != keys_to_processed.end(); ++set_it) {
380  xprintf(Warn, "Key '%s' in record '%s' was not retrieved from input JSON file.\n", (*set_it).c_str(), record->type_name().c_str() );
381  }
382 
383  return storage_array;
384 
385  } else {
386 
387 
388  Type::Record::KeyIter auto_key_it = record->auto_conversion_key_iter();
389  if ( auto_key_it != record->end() ) {
390  // try auto conversion
391  //stringstream ss;
392  //ss << p;
393  //xprintf(Warn, "Automatic conversion to record at address: %s\n", ss.str().c_str() );
394 
395  StorageArray *storage_array = new StorageArray(record->size());
396  for( Type::Record::KeyIter it= record->begin(); it != record->end(); ++it) {
397  if ( it == auto_key_it ) {
398  // one key is initialized by input
399  storage_array->new_item(it->key_index, make_storage(p, it->type_.get()) );
400  } else if (it->default_.has_value_at_declaration() ) {
401  // other key from default values
402  storage_array->new_item(it->key_index,
403  make_storage_from_default( it->default_.value(), it->type_.get() ) );
404  } else { // defalut - optional or default at read time
405  ASSERT( ! it->default_.is_obligatory() ,
406  "Obligatory key: '%s' in auto-convertible record, wrong check during finish().", it->key_.c_str());
407  // set null
408  storage_array->new_item(it->key_index, new StorageNull() );
409  }
410  }
411 
412  return storage_array;
413 
414  } else {
415  THROW( ExcInputError() << EI_Specification("The value should be 'JSON object', but we found: ")
416  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType( record->desc()) );
417  }
418  }
419  // possibly construction of reduced record
420 
421  return NULL;
422 }
423 
424 
425 
427 {
428  if (p.head()->type() == json_spirit::obj_type) {
429 
430  JSONPath type_path(p);
431  if ( type_path.down("TYPE") == NULL ) {
432  if ( ! abstr_rec->begin()->default_.has_value_at_declaration() ) {
433  THROW( ExcInputError() << EI_Specification("Missing key 'TYPE' in AbstractRecord.") << EI_ErrorAddress(p) << EI_InputType(abstr_rec->desc()) );
434  } // else auto conversion
435  } else {
436  try {
437  // convert to base type to force type dispatch and reference chatching
438  const Type::TypeBase * type_of_type = &( abstr_rec->get_type_selection() );
439  unsigned int descendant_index = make_storage(type_path, type_of_type )->get_int();
440  return make_storage(p, &( abstr_rec->get_descendant(descendant_index) ) );
441  } catch(Type::Selection::ExcSelectionKeyNotFound &e) {
442 
443  THROW( ExcInputError() << EI_Specification("Wrong TYPE='"+Type::EI_KeyName::ref(e)+"' of AbstractRecord.") << EI_ErrorAddress(p) << EI_InputType(abstr_rec->desc()) );
444  }
445  }
446  } else {
447  if ( ! abstr_rec->begin()->default_.has_value_at_declaration() ) {
448  THROW( ExcInputError() << EI_Specification("The value should be 'JSON object', but we found: ")
449  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(abstr_rec->desc()) );
450  } // else auto conversion
451  }
452 
453  // perform automatic conversion
454  //stringstream ss;
455  //ss << p;
456  // xprintf(Warn, "Automatic conversion to abstract record at address: %s\n", ss.str().c_str() );
457 
458  const Type::Record *default_child = abstr_rec->get_default_descendant();
459  if (! default_child) THROW(ExcInputError()
460  << EI_Specification("Auto conversion of AbstractRecord not allowed.\n")
461  << EI_ErrorAddress(p)
462  << EI_InputType(abstr_rec->desc())
463  );
464  return make_storage(p, default_child );
465 }
466 
467 
468 
470 {
471 
472  if (p.head()->type() == json_spirit::array_type) {
473  const json_spirit::mArray & j_array = p.head()->get_array();
474  if ( array->match_size( j_array.size() ) ) {
475  // copy the array and check type of values
476  StorageArray *storage_array = new StorageArray(j_array.size());
477  for( unsigned int idx=0; idx < j_array.size(); idx++) {
478  p.down(idx);
479  const Type::TypeBase &sub_type = array->get_sub_type();
480  storage_array->new_item(idx, make_storage(p, &sub_type) );
481  p.up();
482  }
483  return storage_array;
484 
485  } else {
486  THROW( ExcInputError()
487  << EI_Specification("Do not fit into size limits of the Array.")
488  << EI_ErrorAddress(p) << EI_InputType(array->desc()) );
489  }
490  } else {
491  // try automatic conversion to array with one element
492  if ( array->match_size( 1 ) ) {
493  StorageArray *storage_array = new StorageArray(1);
494  const Type::TypeBase &sub_type = array->get_sub_type();
495  storage_array->new_item(0, make_storage(p, &sub_type) );
496 
497  return storage_array;
498  } else {
499  THROW( ExcInputError() << EI_Specification("Automatic conversion to array not allowed. The value should be 'JSON array', but we found: ")
500  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(array->desc()) );
501  }
502  }
503 
504  return NULL;
505 }
506 
507 
508 
510 {
511  string item_name;
512  if (p.head()->type() == json_spirit::str_type) {
513  try {
514  item_name = p.head()->get_str();
515  int value = selection->name_to_int( item_name );
516  return new StorageInt( value );
517  } catch (Type::Selection::ExcSelectionKeyNotFound &exc) {
518  THROW( ExcInputError() << EI_Specification("Wrong value '" + item_name + "' of the Selection.")
519  << EI_ErrorAddress(p) << EI_JSON_Type( "" ) << EI_InputType(selection->desc()) );
520  }
521  }
522 
523  THROW( ExcInputError() << EI_Specification("The value should be 'JSON string', but we found: ")
524  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(selection->desc()) );
525 
526  return NULL;
527 }
528 
529 
530 
532 {
533  if (p.head()->type() == json_spirit::bool_type) {
534  return new StorageBool( p.head()->get_bool() );
535  } else {
536  THROW( ExcInputError() << EI_Specification("The value should be 'JSON bool', but we found: ")
537  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(bool_type->desc()) );
538  }
539  return NULL;
540 }
541 
542 
543 
545 {
546  if (p.head()->type() == json_spirit::int_type) {
547  int value = p.head()->get_int();
548  int_type->match(value);
549  if (int_type->match(value)) {
550  return new StorageInt( value );
551  } else {
552  THROW( ExcInputError() << EI_Specification("Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(int_type->desc()) );
553  }
554 
555  } else {
556  THROW( ExcInputError() << EI_Specification("The value should be 'JSON int', but we found: ")
557  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(int_type->desc()) );
558 
559  }
560  return NULL;
561 }
562 
563 
564 
566 {
567  double value;
568 
569  if (p.head()->type() == json_spirit::real_type) {
570  value = p.head()->get_real();
571  } else if (p.head()->type() == json_spirit::int_type) {
572  value = p.head()->get_int();
573  } else {
574  THROW( ExcInputError() << EI_Specification("The value should be 'JSON real', but we found: ")
575  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(double_type->desc()) );
576  }
577 
578  if (double_type->match(value)) {
579  return new StorageDouble( value );
580  } else {
581  THROW( ExcInputError() << EI_Specification("Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(double_type->desc()) );
582  }
583 
584  return NULL;
585 }
586 
587 
588 
590 {
591  if (p.head()->type() == json_spirit::str_type) {
592  string value = p.head()->get_str();
593  if (string_type->match(value))
594  return new StorageString( value );
595  else
596  THROW( ExcInputError() << EI_Specification("Output file can not be given by absolute path: '" + value + "'")
597  << EI_ErrorAddress(p) << EI_JSON_Type("") << EI_InputType(string_type->desc()) );
598  } else {
599  THROW( ExcInputError() << EI_Specification("The value should be 'JSON string', but we found: ")
600  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(string_type->desc()) );
601 
602  }
603  return NULL;
604 }
605 
606 
607 
609  try {
610  /*
611  // Possible simplification of this method (need default strings to be valid JSON)
612  JSONToStorage tmp_storage(dflt_str, *type);
613  return tmp_storage.storage_;
614  */
615 
616  // an auto-convertible AbstractRecord can be initialized form default value
617  const Type::AbstractRecord *a_record = dynamic_cast<const Type::AbstractRecord *>(type);
618  if (a_record != NULL ) {
619  if (a_record->begin()->default_.has_value_at_declaration() ) // a_record->bagin() ... TYPE key
620  return make_storage_from_default( dflt_str, a_record->get_default_descendant() );
621  else
622  xprintf(PrgErr,"Can not initialize (non-auto-convertible) AbstractRecord '%s' by default value\n", type->type_name().c_str());
623  } else
624  if (typeid(*type) == typeid(Type::Record) ) {
625  // an auto-convertible Record can be initialized form default value
626  const Type::Record *record = static_cast<const Type::Record *>(type);
627  Type::Record::KeyIter auto_key_it = record->auto_conversion_key_iter();
628  if ( auto_key_it != record->end() ) {
629  StorageArray *storage_array = new StorageArray(record->size());
630  for( Type::Record::KeyIter it= record->begin(); it != record->end(); ++it) {
631  if ( it == auto_key_it ) {
632  // one key is initialized by the record default string
633  storage_array->new_item(it->key_index, make_storage_from_default(dflt_str, it->type_.get()) );
634  } else {
635 
636  ASSERT( ! it->default_.is_obligatory(),
637  "Missing default value for key: '%s' in auto-convertible record, wrong check during finish().", it->key_.c_str());
638 
639  if (it->default_.has_value_at_declaration() ) {
640  storage_array->new_item(it->key_index,
641  make_storage_from_default( it->default_.value(), it->type_.get() ) );
642  } else { // defalut - optional or default at read time
643  // set null
644  storage_array->new_item(it->key_index, new StorageNull() );
645  }
646  }
647  }
648 
649  return storage_array;
650  } else {
651  xprintf(PrgErr,"Can not initialize (non-auto-convertible) Record '%s' by default value\n", type->type_name().c_str());
652  }
653  } else
654  if (typeid(*type) == typeid(Type::Array) ) {
655  const Type::Array *array = static_cast<const Type::Array *>(type);
656  if ( array->match_size(1) ) {
657  // try auto conversion to array
658  StorageArray *storage_array = new StorageArray(1);
659  const Type::TypeBase &sub_type = array->get_sub_type();
660  storage_array->new_item(0, make_storage_from_default(dflt_str, &sub_type) );
661  return storage_array;
662  } else {
663  xprintf(PrgErr,"Can not initialize Array '%s' by default value, size 1 not allowed.\n", type->type_name().c_str());
664  }
665 
666  } else
667  if (typeid(*type) == typeid(Type::Integer)) {
668  return new StorageInt( static_cast<const Type::Integer *>(type) ->from_default(dflt_str) );
669  } else
670  if (typeid(*type) == typeid(Type::Double)) {
671  return new StorageDouble( static_cast<const Type::Double *>(type) ->from_default(dflt_str) );
672  } else
673  if (typeid(*type) == typeid(Type::Bool)) {
674  return new StorageBool( static_cast<const Type::Bool *>(type) ->from_default(dflt_str) );
675  } else
676  if (typeid(*type) == typeid(Type::Selection)) {
677  return new StorageInt( static_cast<const Type::Selection *>(type) ->from_default(dflt_str) );
678  } else {
679  const Type::String * string_type = dynamic_cast<const Type::String *>(type);
680  if (string_type != NULL ) return new StorageString( string_type->from_default(dflt_str) );
681 
682  // default error
683  xprintf(PrgErr,"Can not store default value for type: %s\n", typeid(type).name());
684  }
685 
686 
687  } catch (Input::Type::ExcWrongDefault & e) {
688  // message to distinguish exceptions thrown during Default value check at declaration
689  xprintf(Msg, "Wrong default value while reading an input stream:\n");
690  e << EI_KeyName("UNKNOWN KEY");
691  throw;
692  }
693 
694  //return NULL;
695 }
696 
697 
698 
699 } // namespace Input