www.mooseframework.org
SONDefinitionFormatter.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* DO NOT MODIFY THIS HEADER */
3 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
4 /* */
5 /* (c) 2010 Battelle Energy Alliance, LLC */
6 /* ALL RIGHTS RESERVED */
7 /* */
8 /* Prepared by Battelle Energy Alliance, LLC */
9 /* Under Contract No. DE-AC07-05ID14517 */
10 /* With the U. S. Department of Energy */
11 /* */
12 /* See COPYRIGHT for full restrictions */
13 /****************************************************************/
14 
15 #include "SONDefinitionFormatter.h"
16 #include "MooseUtils.h"
17 #include "pcrecpp.h"
18 
20 
21 // ******************************** toString ************************************ //
22 // traverse the associated types array of cpp_types and absolute lookup paths and //
23 // transform the paths to work with our parsed hierarchy and store pairs in a map //
24 // of types to paths for use by the ExistsIn rule and store the global/parameters //
25 // object then add root blocks recursively and return constructed stream's string //
26 // ****************************************************************************** //
27 std::string
29 {
30 
31  const std::map<std::string, std::string> json_path_regex_replacement_map = {
32  {"/star/subblock_types/([A-Za-z0-9_]*)/", "/\\1_type/"},
33  {"[A-Za-z0-9_]*/types/([A-Za-z0-9_]*)/", "\\1_type/"},
34  {"/actions/[A-Za-z0-9_]*/parameters/", "/"},
35  {"/parameters/", "/"},
36  {"/subblocks/", "/"}};
37 
38  for (const auto & type : root["global"]["associated_types"].getMemberNames())
39  for (const auto & path_iter : root["global"]["associated_types"][type])
40  {
41  std::string path = path_iter.asString();
42  for (const auto & map_iter : json_path_regex_replacement_map)
43  pcrecpp::RE(map_iter.first).GlobalReplace(map_iter.second, &path);
44  _assoc_types_map[type].push_back(path);
45  }
46 
47  _global_params = root["global"]["parameters"];
48  _stream.clear();
49  _stream.str("");
50  for (const auto & name : root["blocks"].getMemberNames())
51  addBlock(name, root["blocks"][name]);
52  return _stream.str();
53 }
54 
55 // ******************************** addLine ************************************* //
56 // add a single new-line-terminated and indented line to the stream //
57 // ****************************************************************************** //
58 void
59 SONDefinitionFormatter::addLine(const std::string & line)
60 {
61  _stream << std::string(!line.empty() * _level * _spaces, ' ') << line << "\n";
62  return;
63 }
64 
65 // ******************************* addBlock ************************************* //
66 // add parameters and recursively add NormalBlock children and TypeBlock children //
67 // ****************************************************************************** //
68 void
69 SONDefinitionFormatter::addBlock(const std::string & block_name,
70  const JsonVal & block,
71  bool is_typeblock,
72  const std::string & parent_name,
73  const JsonVal & parameters_in,
74  const JsonVal & subblocks_in)
75 {
76 
77  // open block with "_type" appended to the name if this is a TypeBlock because the
78  // parser appends "_type" to the name of blocks with a "type=" parameter specified
79  addLine("'" + block_name + (is_typeblock ? "_type" : "") + "'{");
80  _level++;
81 
82  // decide the actual block [./declarator] name that will be specified later unless
83  // this is a StarBlock and then decide if this is a StarBlock or not for later use
84  // - if TypeBlock : this will be the parent block name
85  // - if NormalBlock : this will be this block name
86  std::string block_decl = (is_typeblock ? parent_name : block_name);
87  bool is_starblock = (block_decl == "*" ? true : false);
88 
89  // - add InputTmpl : the autocomplete template that is used for all block types
90  // - add InputName : if is_typeblock then this will be dropped in after "type="
91  // - add InputType : block type - normal_top / normal_sub / type_top / type_sub
92  // - add InputDefault : block [./declarator] name from above that will be used for
93  // autocompletion of this block unless it is a StarBlock then
94  // [./insert_name_here] will be used because any name is okay
95  addLine("InputTmpl=MooseBlock");
96  addLine("InputName=\"" + block_name + "\"");
97  if (!is_typeblock)
98  addLine(_level == 1 ? "InputType=normal_top" : "InputType=normal_sub");
99  else
100  addLine(_level == 1 ? "InputType=type_top" : "InputType=type_sub");
101  if (!is_starblock)
102  addLine("InputDefault=\"" + block_decl + "\"");
103  else
104  addLine("InputDefault=\"insert_name_here\"");
105 
106  // add Description of block if it exists
107  std::string description = block["description"].asString();
108  pcrecpp::RE("\"").GlobalReplace("'", &description);
109  pcrecpp::RE("[\r\n]").GlobalReplace(" ", &description);
110  if (!description.empty())
111  addLine("Description=\"" + description + "\"");
112 
113  // add MinOccurs : optional because nothing available to specify block requirement
114  addLine("MinOccurs=0");
115 
116  // add MaxOccurs : if a StarBlock then no limit / otherwise maximum one occurrence
117  addLine(is_starblock ? "MaxOccurs=NoLimit" : "MaxOccurs=1");
118 
119  // ensure block has one string declarator node and if this is not a StarBlock then
120  // also ensure that the block [./declarator] is the expected block_decl from above
121  addLine("decl{");
122  _level++;
123  addLine("MinOccurs=1");
124  addLine("MaxOccurs=1");
125  addLine("ValType=String");
126  if (!is_starblock)
127  addLine("ValEnums=[ \"" + block_decl + "\" ]");
128  _level--;
129  addLine("}");
130 
131  // if this block is the GlobalParams block then add a add "*/value" level
132  if (block_name == "GlobalParams")
133  {
134  addLine("'*'{");
135  _level++;
136  addLine("'value'{");
137  addLine("}");
138  _level--;
139  addLine("} % end *");
140  }
141 
142  // store parameters ---
143  // first : start with global parameters as a base
144  // second : add or overwrite with any parameter inheritance
145  // third : add or overwrite with any local RegularParameters
146  // fourth : add or overwrite with any local ActionParameters
147  JsonVal parameters = _global_params;
148  for (const auto & name : parameters_in.getMemberNames())
149  parameters[name] = parameters_in[name];
150  for (const auto & name : block["parameters"].getMemberNames())
151  parameters[name] = block["parameters"][name];
152  for (const auto & act : block["actions"].getMemberNames())
153  for (const auto & param : block["actions"][act]["parameters"].getMemberNames())
154  parameters[param] = block["actions"][act]["parameters"][param];
155 
156  // store NormalBlock children ---
157  // first : start with any NormalBlock inheritance passed in as a base
158  // second : add or overwrite these with any local NormalBlock children
159  // third : add star named child block if it exists
160  JsonVal subblocks = subblocks_in;
161  for (const auto & name : block["subblocks"].getMemberNames())
162  subblocks[name] = block["subblocks"][name];
163  if (block.isMember("star"))
164  subblocks["*"] = block["star"];
165 
166  // store TypeBlock children ---
167  // first : start with ["types"] child block as a base
168  // second : add ["subblock_types"] child block
169  JsonVal typeblocks = block["types"];
170  for (const auto & name : block["subblock_types"].getMemberNames())
171  typeblocks[name] = block["subblock_types"][name];
172 
173  // add parameters ---
174  // if this block has a "type=" parameter with a specified default "type=" name and
175  // if that default is also the name of a ["types"] child block then the parameters
176  // belonging to that default ["types"] child block are added to this block as well
177  // first : start with default ["types"] child block's RegularParameters as a base
178  // second : add or overwrite with default ["types"] child block's ActionParameters
179  // third : add or overwrite with parameters that were stored above for this block
180  // fourth : either add newly stored parameters or add previously stored parameters
181  if (parameters.isMember("type") && parameters["type"].isMember("default") &&
182  block["types"].isMember(parameters["type"]["default"].asString()))
183  {
184  std::string type_default = parameters["type"]["default"].asString();
185  const JsonVal & default_block = block["types"][type_default];
186  JsonVal default_child_params = default_block["parameters"];
187  const JsonVal & default_actions = default_block["actions"];
188  for (const auto & act : default_actions.getMemberNames())
189  for (const auto & param : default_actions[act]["parameters"].getMemberNames())
190  default_child_params[param] = default_actions[act]["parameters"][param];
191  for (const auto & name : parameters.getMemberNames())
192  default_child_params[name] = parameters[name];
193  addParameters(default_child_params);
194  }
195  else
196  addParameters(parameters);
197 
198  // add previously stored NormalBlocks children recursively
199  for (const auto & name : subblocks.getMemberNames())
200  addBlock(name, subblocks[name]);
201 
202  // close block now because the parser stores TypeBlock children at this same level
203  _level--;
204  addLine("} % end block " + block_name + (is_typeblock ? "_type" : ""));
205 
206  // add all previously stored TypeBlock children recursively and pass the parameter
207  // and NormalBlock children added at this level in as inheritance to all TypeBlock
208  // children so that they may each also add them and pass in the name of this block
209  // as well so that all TypeBlock children can add a rule ensuring that their block
210  // [./declarator] is the name of this parent block unless this block is named star
211  for (const auto & name : typeblocks.getMemberNames())
212  addBlock(name, typeblocks[name], true, block_name, parameters, subblocks);
213 }
214 
215 // ***************************** addParameters ********************************** //
216 // add all of the information for each parameter of a block
217 // - parameter :: add ChildAtLeastOne
218 // - parameter :: add InputTmpl
219 // - parameter :: add InputType
220 // - parameter :: add InputName
221 // - parameter :: add Description
222 // - parameter :: add MinOccurs
223 // - parameter :: add MaxOccurs
224 // - parameter's value :: add MinOccurs
225 // - parameter's value :: add MaxOccurs
226 // - parameter's value :: add ValType
227 // - parameter's value :: add ValEnums
228 // - parameter's value :: add InputChoices
229 // - parameter's value :: add ExistsIn
230 // - parameter's value :: add MinValInc
231 // - parameter's value :: add InputDefault
232 // ****************************************************************************** //
233 void
235 {
236 
237  for (const auto & name : params.getMemberNames())
238  {
239 
240  JsonVal param = params[name];
241 
242  // lambda to calculate relative path from the current level to the document root
243  auto backtrack = [](int level) {
244  std::string backtrack_path;
245  for (int i = 0; i < level; ++i)
246  backtrack_path += "../";
247  return backtrack_path;
248  };
249 
250  // capture the cpp_type and basic_type and strip off any unnecessary information
251  std::string cpp_type = param["cpp_type"].asString();
252  std::string basic_type = param["basic_type"].asString();
253  bool is_array = false;
254  if (cpp_type == "FunctionExpression" || basic_type.compare(0, 6, "Array:") == 0)
255  is_array = true;
256  pcrecpp::RE(".+<([A-Za-z0-9_' ':]*)>.*").GlobalReplace("\\1", &cpp_type);
257  pcrecpp::RE("(Array:)*(.*)").GlobalReplace("\\2", &basic_type);
258 
259  // *** ChildAtLeastOne of parameter
260  // if parameter is required and no default exists then outside its level specify
261  // ChildAtLeastOne = [ "backtrack/GlobalParams/name/value" "name/value" ]
262  bool required = param["required"].asBool();
263  std::string def = MooseUtils::trim(param["default"].asString());
264  if (required && def.empty())
265  addLine("ChildAtLeastOne=[ \"" + backtrack(_level) + "GlobalParams/" + name +
266  "/value\" \"" + name + "/value\"" + " ]");
267 
268  // *** open parameter
269  addLine("'" + name + "'" + "{");
270  _level++;
271 
272  // *** InputTmpl of parameter
273  addLine("InputTmpl=MooseParam");
274 
275  // *** InputType of parameter
276  if (is_array)
277  addLine("InputType=key_array");
278  else
279  addLine("InputType=key_value");
280 
281  // *** InputName of parameter
282  addLine("InputName=\"" + name + "\"");
283 
284  // *** Description of parameter
285  std::string description = param["description"].asString();
286  pcrecpp::RE("\"").GlobalReplace("'", &description);
287  pcrecpp::RE("[\r\n]").GlobalReplace(" ", &description);
288  if (!description.empty())
289  addLine("Description=\"" + description + "\"");
290 
291  // *** MinOccurs / MaxOccurs of parameter
292  addLine("MinOccurs=0");
293  addLine("MaxOccurs=1");
294 
295  // *** open parameter's value
296  addLine("'value'{");
297  _level++;
298 
299  // *** MinOccurs / MaxOccurs of parameter's value
300  addLine("MinOccurs=1");
301  addLine(is_array ? "MaxOccurs=NoLimit" : "MaxOccurs=1");
302 
303  // *** ValType of parameter's value
304  if (basic_type == "Integer")
305  addLine("ValType=Int");
306  else if (basic_type == "Real")
307  addLine("ValType=Real");
308  else
309  addLine("ValType=String");
310 
311  // *** ValEnums / InputChoices of parameter's value
312  if (basic_type.find("Boolean") != std::string::npos)
313  addLine("ValEnums=[ true false 1 0 ]");
314  else
315  {
316  std::string options = param["options"].asString();
317  if (!options.empty())
318  {
319  pcrecpp::RE(" ").GlobalReplace("\" \"", &options);
320  if (!param["out_of_range_allowed"].asBool())
321  addLine("ValEnums=[ \"" + options + "\" ]");
322  else
323  addLine("InputChoices=[ \"" + options + "\" ]");
324  }
325  }
326 
327  // *** ExistsIn of parameter's value
328  // add any reserved_values and if this parameter's above transformed cpp_type is
329  // "FunctionName" then add an ExpressionsAreOkay flag and check if there are any
330  // paths associated with the cpp_type in the map that was built before traversal
331  // then add those paths relative to this node here as well
332  std::string paths;
333  for (const auto & reserved : param["reserved_values"])
334  paths += "EXTRA:\"" + reserved.asString() + "\" ";
335  if (cpp_type == "FunctionName")
336  paths += "EXTRA:\"ExpressionsAreOkay\" ";
337  for (const auto & path : _assoc_types_map[cpp_type])
338  paths += "\"" + backtrack(_level) + path + "/decl\" ";
339  if (!paths.empty())
340  addLine("ExistsIn=[ " + paths + "]");
341 
342  // *** MinValInc of parameter's value
343  if (cpp_type.compare(0, 8, "unsigned") == 0 && basic_type == "Integer")
344  addLine("MinValInc=0");
345 
346  // *** InputDefault of parameter's value
347  if (!def.empty())
348  addLine("InputDefault=\"" + def + "\"");
349 
350  // *** close parameter's value
351  _level--;
352  addLine("}");
353 
354  // *** close parameter
355  _level--;
356  addLine("} % end parameter " + name);
357  }
358 }
void addParameters(const JsonVal &params)
adds all parameters from a given block
moosecontrib::Json::Value JsonVal
std::string toString(const JsonVal &root)
returns a string representation of the tree in input file format
std::map< std::string, std::vector< std::string > > _assoc_types_map
void addLine(const std::string &line)
adds a line to the output with the proper indentation automatically
void addBlock(const std::string &block_name, const JsonVal &block, bool is_typeblock=false, const std::string &parent_name="", const JsonVal &parameters_in=JsonVal::null, const JsonVal &subblocks_in=JsonVal::null)
adds a new block to the output
MatType type
std::string trim(const std::string &str, const std::string &white_space=" \t\n\v\f\r")
Standard scripting language trim function.
Definition: MooseUtils.C:95