5#ifndef LINE_IO_WORKFLOW_READER_H
6#define LINE_IO_WORKFLOW_READER_H
75 throw UnsupportedError(
"workflow_reader: unsupported precedence type '" + s +
76 "'; the wire spells one of pre, pre-AND, pre-OR, post, post-AND, "
77 "post-OR, post-LOOP, post-CACHE");
81inline std::vector<std::string> activity_names_from_json(
const json& arr,
const char* key) {
83 throw InputError(std::string(
"workflow_reader: '") + key +
"' must be an array of "
85 std::vector<std::string> out;
86 out.reserve(arr.size());
87 for (
const json& v : arr) {
89 throw InputError(std::string(
"workflow_reader: '") + key +
90 "' must hold activity NAMES, not objects; the wire references an "
91 "activity by the name its 'activities' entry declares");
92 out.push_back(v.get<std::string>());
99std::vector<T> params_from_json(
const json& obj,
const char* key) {
101 if (!obj.contains(key))
return out;
102 const json& arr = obj.at(key);
105 if (arr.is_number()) {
106 out.push_back(num_traits<T>::from_double(num_from_json(arr)));
110 throw InputError(std::string(
"workflow_reader: '") + key +
111 "' must be a number or an array of numbers");
112 for (
const json& v : arr) out.push_back(num_traits<T>::from_double(num_from_json(v)));
122inline void reject_unknown_workflow_keys(
const json& model) {
123 static const char* kModelKeys[] = {
"type",
"name",
"activities",
"precedences"};
124 static const char* kActKeys[] = {
"name",
"hostDemand"};
125 static const char* kPrecKeys[] = {
"preActs",
"postActs",
"preType",
"postType",
126 "preParams",
"postParams"};
127 auto known = [](
const char*
const* tab, std::size_t n,
const std::string& k) {
128 for (std::size_t i = 0; i < n; ++i)
129 if (k == tab[i])
return true;
132 const std::string why =
133 "', which this reader does not implement. Refusing rather than dropping it: a "
134 "constraint silently discarded here would make to_ph() return a confident law "
135 "for a different workflow";
136 for (
auto it = model.begin(); it != model.end(); ++it)
137 if (!known(kModelKeys,
sizeof(kModelKeys) /
sizeof(*kModelKeys), it.key()))
138 throw UnsupportedError(
"workflow_reader: the model carries '" + it.key() + why);
139 if (model.contains(
"activities"))
140 for (
const json& act : model.at(
"activities"))
141 for (
auto it = act.begin(); it != act.end(); ++it)
142 if (!known(kActKeys,
sizeof(kActKeys) /
sizeof(*kActKeys), it.key()))
144 act.value(
"name", std::string(
"?")) +
"' carries '" +
146 if (model.contains(
"precedences"))
147 for (
const json& prec : model.at(
"precedences"))
148 for (
auto it = prec.begin(); it != prec.end(); ++it)
149 if (!known(kPrecKeys,
sizeof(kPrecKeys) /
sizeof(*kPrecKeys), it.key()))
150 throw UnsupportedError(
"workflow_reader: a precedence carries '" + it.key() +
167 const json& model = root.contains(
"model") ? root.at(
"model") : root;
168 const std::string mtype = model.value(
"type", std::string(
"Workflow"));
169 if (mtype !=
"Workflow")
171 "' is not a Workflow; a Network is read by network_reader.h and an "
172 "Environment by environment_reader.h");
174 detail::reject_unknown_workflow_keys(model);
178 if (model.contains(
"activities")) {
179 for (
const json& act : model.at(
"activities")) {
180 if (!act.contains(
"name"))
181 throw InputError(
"workflow_reader: every activity needs a 'name'");
182 const std::string name = act.at(
"name").get<std::string>();
183 if (act.contains(
"hostDemand"))
184 wf.add_activity(name, detail::dist_from_json<T>(act.at(
"hostDemand")));
193 if (model.contains(
"precedences")) {
194 for (
const json& prec : model.at(
"precedences")) {
195 if (!prec.contains(
"preActs") || !prec.contains(
"postActs"))
196 throw InputError(
"workflow_reader: every precedence needs 'preActs' and "
199 p.
pre_acts = detail::activity_names_from_json(prec.at(
"preActs"),
"preActs");
200 p.
post_acts = detail::activity_names_from_json(prec.at(
"postActs"),
"postActs");
202 detail::precedence_type_from_str(prec.value(
"preType", std::string(
"pre")));
204 detail::precedence_type_from_str(prec.value(
"postType", std::string(
"post")));
205 p.
pre_params = detail::params_from_json<T>(prec,
"preParams");
206 p.
post_params = detail::params_from_json<T>(prec,
"postParams");
207 wf.add_precedence(p);
217 std::ifstream in(path.c_str());
219 throw InputError(
"workflow_reader: cannot open '" + path +
"'");
UnsupportedError(const std::string &what)
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
workflow::Workflow< T > read_workflow_json(const std::string &path)
Read a Workflow model.json off disk.
workflow::Workflow< T > build_workflow_from_json(const detail::json &root)
Build a workflow::Workflow<T> from a parsed model.json envelope.
PrecedenceType
Activity precedence kinds, with the values of MATLAB ActivityPrecedenceType.
Reader for the LINE model.json interchange (a Network model) into a qn::Network<T> built through the ...
static Distrib exp_mean(const T &m)
One precedence of the activity graph.
std::vector< T > pre_params
std::vector< T > post_params
std::vector< std::string > post_acts
std::vector< std::string > pre_acts
An activity workflow reduced to one phase-type law.