https://mooseframework.inl.gov
Loading...
Searching...
No Matches
JsonInputFileFormatter.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "MooseUtils.h"
12
13#include <vector>
14#include <map>
15
17
18std::string
19JsonInputFileFormatter::toString(const nlohmann::json & root)
20{
21 _stream.clear();
22 _stream.str("");
23 for (auto && el : root["blocks"].items())
24 addBlock(el.key(), el.value(), true);
25 return _stream.str();
26}
27
28void
29JsonInputFileFormatter::addLine(const std::string & line,
30 size_t max_line_len,
31 const std::string & comment)
32{
33 if (line.empty() && comment.empty())
34 {
35 _stream << "\n";
36 return;
37 }
38
39 std::string indent(_level * _spaces, ' ');
40 auto doc = MooseUtils::trim(comment);
41 if (doc.empty()) // Not comment so just print out the line normally
42 {
43 _stream << indent << line << "\n";
44 return;
45 }
46
47 // We have a comment so we need to break it up over multiple lines if necessary
48 // and make sure that they all start at the same spot.
49 _stream << indent << line;
50 std::vector<std::string> elements;
51
52 // if the line is empty we can just start the comment right away
53 int extra = 1;
54 if (line.empty())
55 extra = 0;
56
57 // be careful of really long lines.
58 int len = 100 - max_line_len - indent.size();
59 if (len < 0)
60 len = 20;
61
62 MooseUtils::tokenize(doc, elements, len, " \t");
63 std::string first(max_line_len - line.size() + extra, ' ');
64 _stream << first << "# " << elements[0] << "\n";
65 std::string cindent(max_line_len + indent.size() + extra, ' ');
66 for (size_t i = 1; i < elements.size(); ++i)
67 _stream << cindent << "# " << elements[i] << "\n";
68
69 _stream << std::flush;
70}
71
72void
73JsonInputFileFormatter::addBlock(const std::string & name,
74 const nlohmann::json & block,
75 bool toplevel)
76{
77 addLine("");
78 if (toplevel)
79 addLine("[" + name + "]");
80 else
81 addLine("[./" + name + "]");
82
83 _level++;
84 std::string desc = block.contains("description") ? nlohmann::to_string(block["description"]) : "";
85 if (!desc.empty())
86 addLine("", 0, desc);
87
88 if (block.contains("parameters"))
89 addParameters(block["parameters"]);
90
91 if (block.contains("actions"))
92 {
93 // there could be duplicate parameters across actions, last one wins
94 nlohmann::json all_params;
95 auto & actions = block["actions"];
96 for (auto && el : actions.items())
97 {
98 auto & params = el.value()["parameters"];
99 for (auto && param_el : params.items())
100 all_params[param_el.key()] = param_el.value();
101 }
102 addParameters(all_params);
103 }
104
105 if (block.contains("star"))
106 addBlock("*", block["star"]);
107
108 addTypes("subblock_types", block);
109 addTypes("types", block);
110
111 if (block.contains("subblocks"))
112 {
113 auto & subblocks = block["subblocks"];
114 if (!subblocks.is_null())
115 for (auto && el : subblocks.items())
116 addBlock(el.key(), el.value());
117 }
118
119 _level--;
120 if (toplevel)
121 addLine("[]");
122 else
123 addLine("[../]");
124}
125
126void
127JsonInputFileFormatter::addTypes(const std::string & key, const nlohmann::json & block)
128{
129 if (!block.contains(key))
130 return;
131 auto & types = block[key];
132 if (types.is_null())
133 return;
134
135 addLine("");
136 addLine("[./<types>]");
137 _level++;
138 for (auto && el : types.items())
139 addBlock("<" + el.key() + ">", el.value());
140 _level--;
141 addLine("[../]");
142}
143
144void
145JsonInputFileFormatter::addParameters(const nlohmann::json & params)
146{
147 size_t max_name = 0;
148 for (auto & el : params.items())
149 if (el.key().size() > max_name)
150 max_name = el.key().size();
151
152 size_t max_len = 0;
153 std::map<std::string, std::string> lines;
154 for (auto && el : params.items())
155 {
156 auto & name = el.key();
157 auto & param = el.value();
158 auto def =
159 param.contains("default") ? MooseUtils::trim(nlohmann::to_string(param["default"])) : "";
160 if (!def.empty())
161 def = def.substr(1, def.size() - 2);
162 if (def.find(' ') != std::string::npos)
163 def = "'" + def + "'";
164 std::string indent(max_name - name.size(), ' ');
165 std::string required;
166 if (param["required"])
167 required = "(required)";
168 if (def.size() == 0 && required.size() == 0)
169 def = "(no_default)";
170 std::string l = name + indent + " = " + def + required;
171 if (l.size() > max_len)
172 max_len = l.size();
173 lines[name] = l;
174 }
175 for (auto & el : params.items())
176 {
177 auto & name = el.key();
178 auto & param = el.value();
179 auto & l = lines[name];
180 auto desc = nlohmann::to_string(param["description"]);
181 addLine(l, max_len, desc);
182
183 const auto cpp_type = param.contains("cpp_type") ? param["cpp_type"].get<std::string>() : "";
184 const bool is_moose_enum = cpp_type.find("MooseEnum") != std::string::npos ||
185 cpp_type.find("ExecFlagEnum") != std::string::npos;
186
187 if (is_moose_enum)
188 {
189 const auto options_string = MooseUtils::trim(param["options"].get<std::string>());
190 if (!options_string.empty())
191 {
192 std::vector<std::string> options;
193 MooseUtils::tokenize(options_string, options, 1, " ");
194 addLine("", max_len + 1, "Options: " + MooseUtils::join(options, ", "));
195
196 if (param.contains("option_docs") && param["option_docs"].is_object())
197 for (const auto & option : options)
198 {
199 const auto option_doc_key = MooseUtils::toUpper(option);
200 if (param["option_docs"].contains(option_doc_key))
201 addLine("",
202 max_len + 1,
203 option + ": " + param["option_docs"][option_doc_key].get<std::string>());
204 }
205 }
206 }
207
208 const auto doc_unit = nlohmann::to_string(param["doc_unit"]);
209 if (!doc_unit.empty())
210 addLine("", max_len + 1,
211 "Unit: " + doc_unit); // a +1 to account for an empty line
212
213 const auto group = nlohmann::to_string(param["group_name"]);
214 if (!group.empty())
215 addLine("", max_len + 1,
216 "Group: " + group); // a +1 to account for an empty line
217 }
218}
std::string toString(const nlohmann::json &root)
Returns a string representation of the tree in input file format.
void addParameters(const nlohmann::json &params)
Add a comment to the block.
void addBlock(const std::string &name, const nlohmann::json &block, bool top=false)
Adds a new block to the output.
void addLine(const std::string &line, size_t max_line_len=0, const std::string &comment="")
Adds a line to the output.
void addTypes(const std::string &key, const nlohmann::json &block)
Add a dictionary of type blocks to the output.
std::string toUpper(std::string name)
Convert supplied string to upper case.
void tokenize(const std::string &str, std::vector< T > &elements, unsigned int min_len=1, const std::string &delims="/")
This function will split the passed in string on a set of delimiters appending the substrings to the ...
std::string trim(const std::string &str, const std::string &white_space=" \t\n\v\f\r")
Standard scripting language trim function.