Flow123d  release_2.1.0-84-g6a13a75
reader_to_storage.hh
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 reader_to_storage.hh
15  * @brief
16  */
17 
18 #ifndef READER_TO_STORAGE_HH_
19 #define READER_TO_STORAGE_HH_
20 
21 
22 #include <sstream>
23 
25 
26 #include "input/input_exception.hh"
27 #include "input/storage.hh"
28 #include "input/path_base.hh"
29 
30 #include "system/file_path.hh"
31 
32 
33 namespace Input {
34 
35 using namespace std;
36 
37 
38 
39 /// Possible formats of input files.
40 typedef enum {
43 } FileFormat;
44 
45 
46 
47 /**
48  * @brief Enum of possible input types.
49  *
50  * Values in @p json_type_names must be stored in same order.
51  */
52 typedef enum {
54 } ValueTypes;
55 
56 
57 
58 /**
59  * @brief Reader for (slightly) modified input files.
60  *
61  * This class implements a reader of modified input file format (JSON or YAML). The modifications include
62  * shell-like comments (using hash '#' character), this is implemented in comment_filter.hh, optional quoting of
63  * keys in JSON objects that do not contain spaces, and possibility to use '=' instead of ':'. So you can write:
64  * @code
65  * { key1="text", key2=2, "key 3"=4 }
66  * @endcode
67  * Note, however, that our input interface allows only C identifiers for keys. The reader use json_spirit library
68  * (based on Spirit parser from Boost) with slightly modified grammar.
69  *
70  * The input file is at first read and parsed by json_spirit. Then ReaderToStorage pass through tree with parsed data along
71  * with passing through declaration tree. The input data are check against declaration and stored in the Storage tree.
72  *
73  * Accessor to the root record is provided by ReaderToStorage::get_root_interface<T> method template.
74  *
75  * @ingroup input
76  */
78 public:
79  /*
80  * Exceptions.
81  */
82  /// General exception during conversion from JSON tree to storage.
83  TYPEDEF_ERR_INFO(EI_InputType, string );
84  TYPEDEF_ERR_INFO(EI_File, const string);
85  TYPEDEF_ERR_INFO(EI_Specification, const string);
86  TYPEDEF_ERR_INFO(EI_Format, const string);
87  TYPEDEF_ERR_INFO(EI_JSON_Type, const string);
88  TYPEDEF_ERR_INFO( EI_ErrorAddress, string);
89  TYPEDEF_ERR_INFO( EI_TransposeIndex, unsigned int);
90  TYPEDEF_ERR_INFO( EI_TransposeAddress, string);
91  DECLARE_INPUT_EXCEPTION( ExcInputError, << "Error in input file: " << EI_File::qval << " at address: " << EI_ErrorAddress::qval << "\n"
92  << EI_Specification::val << "\n"
93  << EI_Format::val << " type: " << EI_JSON_Type::qval << "\n"
94  << "Expected type:\n" << EI_InputType::val );
95 
96 
97  TYPEDEF_ERR_INFO( EI_JSONLine, unsigned int);
98  TYPEDEF_ERR_INFO( EI_JSONColumn, unsigned int);
99  TYPEDEF_ERR_INFO( EI_JSONReason, string);
100  DECLARE_INPUT_EXCEPTION( ExcNotJSONFormat, << "Not valid JSON file " << EI_File::qval << ". Error at line "
101  << EI_JSONLine::val << " : col " << EI_JSONColumn::val
102  << " ; reason: " << EI_JSONReason::val << "\n" );
103 
104  TYPEDEF_ERR_INFO( EI_InputErrorMessage, const string);
105  TYPEDEF_ERR_INFO( EI_RecordName, const string);
106  DECLARE_INPUT_EXCEPTION( ExcAutomaticConversionError, << "Error during automatic conversion of "
107  << EI_RecordName::val << " record.\n " << EI_InputErrorMessage::val << "\n" );
108 
109 
110  /**
111  * @brief Read a storage from input stream.
112  *
113  * Parameter @p root_type provides input type tree declaration. See @p read_from_stream for details.
114  */
115  ReaderToStorage(const FilePath &in_file, Type::TypeBase &root_type);
116 
117  /// Read a storage from string (e.g. complex default value).
118  ReaderToStorage( const string &default_str, Type::TypeBase &root_type, FileFormat format);
119 
120  /**
121  * @brief Returns the root accessor.
122  *
123  * The template type \p T should correspond to the kind of the input type at root of the declaration tree.
124  */
125  template <class T>
126  T get_root_interface() const;
127 
128 
129  /**
130  * @brief Default constructor.
131  *
132  * Provides common initialization for public constructors.
133  */
134  ReaderToStorage();
135 
136  /**
137  * @brief This method actually reads the given stream \p in
138  *
139  * Checks the data just read against the declaration tree given by \p root_type, and
140  * store the data into private storage tree using \p StorageBase classes.
141  */
142  void read_stream(istream &in, const Type::TypeBase &root_type, FileFormat format);
143 
144 protected:
145 
146  /// Getter for root of the storage tree.
147  StorageBase *get_storage();
148 
149 
150  /**
151  * @brief Create storage of given @p type.
152  *
153  * Check correctness of the input given by json_spirit or YAML-cpp node at head() of PathBase @p p
154  * against type specification @p type. Die on input error (and return NULL).
155  * For correct input, creates the storage tree and returns pointer to its root node.
156  */
157  StorageBase * make_storage(PathBase &p, const Type::TypeBase *type);
158 
159  StorageBase * make_storage(PathBase &p, const Type::Record *record); ///< Create storage of Type::Record type
160  StorageBase * make_storage(PathBase &p, const Type::Abstract *abstr_rec); ///< Create storage of Type::Abstract type
161  StorageBase * make_storage(PathBase &p, const Type::Array *array); ///< Create storage of Type::Array type
162  StorageBase * make_storage(PathBase &p, const Type::Tuple *tuple); ///< Create storage of Type::Tuple type
163  StorageBase * make_storage(PathBase &p, const Type::Selection *selection); ///< Create storage of Type::Selection type
164  StorageBase * make_storage(PathBase &p, const Type::Bool *bool_type); ///< Create storage of Type::Bool type
165  StorageBase * make_storage(PathBase &p, const Type::Integer *int_type); ///< Create storage of Type::Integer type
166  StorageBase * make_storage(PathBase &p, const Type::Double *double_type); ///< Create storage of Type::Double type
167  StorageBase * make_storage(PathBase &p, const Type::String *string_type); ///< Create storage of Type::String type
168 
169  /// Apply transposition and create storage of Type::Array type
170  StorageBase * make_transposed_storage(PathBase &p, const Type::TypeBase *type);
171 
172  /// Apply conversion to one element storage of Type::Array type
173  StorageBase * make_autoconversion_array_storage(PathBase &p, const Type::Array *array, StorageBase *item);
174 
175  /// Apply automatic conversion of Type::Record type
176  StorageBase * record_automatic_conversion(PathBase &p, const Type::Record *record);
177 
178  /// Apply automatic conversion of Type::Abstract type
179  StorageBase * abstract_automatic_conversion(PathBase &p, const Type::Abstract *abstr_rec);
180 
181  /// Dispatch according to @p type and create corresponding storage from the given string.
182  StorageBase * make_storage_from_default( const string &dflt_str, std::shared_ptr<Type::TypeBase> type);
183 
184 
185  /// Storage of the read and checked input data
187 
188  /// Root of the declaration tree of the data in the storage.
190 
191  /**
192  * @brief Flag signed that "expected" transposed part of input tree is processed.
193  *
194  * We set this flag if input tree contains another type at position where Array
195  * is expected. This type must correspond with type_of_value of Array.
196  *
197  * Subsequently:
198  * 1. We set @p transpose_index_ to value '0' (transposition of first Array item).
199  * 2. We retrieve whole subtree and find Array types that are located at position
200  * where other type is expected (type_of_value of found Array must corresponds
201  * with excepted type).
202  * We create storage corresponding with subtree (unexpected Arrays are replaced
203  * by item at position given by @p transpose_index_.
204  * 3. Together with paragraph 2 we store sizes of found Arrays to
205  * @p transpose_array_sizes_.
206  * 4. We check sizes stored in transpose_array_sizes_ (all must be in equal
207  * and may not be equal to zero). This size determines size of transposed Array
208  * type.
209  * 5. We repeat paragraph 2 for all items of transposed Array (gradual increase of
210  * @p transpose_index_).
211  */
213 
214  /// Index of processed item in transposed part of input tree.
215  unsigned int transpose_index_;
216 
217  /// Helper vector what allows check sizes of all transposed Arrays.
219 
220  friend class Type::Default;
221 
222 };
223 
224 
225 
226 
227 
228 
229 
230 
231 
232 
233 
234 } // namespace Input
235 
236 
237 
238 #endif /* READER_TO_STORAGE_HH_ */
bool try_transpose_read_
Flag signed that "expected" transposed part of input tree is processed.
Base of classes for declaring structure of the input data.
Definition: type_base.hh:93
Base class for nodes of a data storage tree.
Definition: storage.hh:68
unsigned int transpose_index_
Index of processed item in transposed part of input tree.
FileFormat
Possible formats of input files.
vector< unsigned int > transpose_array_sizes_
Helper vector what allows check sizes of all transposed Arrays.
Reader for (slightly) modified input files.
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:56
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
Base abstract class used by ReaderToStorage class to iterate over the input tree. ...
Definition: path_base.hh:39
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
bool read_stream(Istream_type &is, Value_type &value)
const Type::TypeBase * root_type_
Root of the declaration tree of the data in the storage.
Class for declaration of the integral input data.
Definition: type_base.hh:483
Class for declaration of inputs sequences.
Definition: type_base.hh:339
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:534
Class for declaration of polymorphic Record.
Dedicated class for storing path to input and output files.
Definition: file_path.hh:48
Tuple type proxy class.
Definition: type_tuple.hh:45
TYPEDEF_ERR_INFO(EI_InputType, const string)
Record type proxy class.
Definition: type_record.hh:177
ValueTypes
Enum of possible input types.
DECLARE_INPUT_EXCEPTION(ExcInputMessage,<< EI_Message::val)
Simple input exception that accepts just string message.
Class for declaration of the input data that are in string format.
Definition: type_base.hh:582
Template for classes storing finite set of named values.
StorageBase * storage_
Storage of the read and checked input data.