1 #pragma once
2 
3 #include <nlohmann/json.hpp>
4 
5 namespace analyzer
6 {
7 
8 /** @brief An abstract class for service event, also known as a callout. */
9 class Callout
10 {
11   public:
12     /** Each callout will have a priority indicating when to issue the required
13      *  service action. Details below. */
14     enum Priority
15     {
16         /** Serivce is mandatory. */
17         HIGH,
18 
19         /** Serivce medium priority callouts one at a time, in order, until the
20          *  issue is resolved. */
21         MED,
22 
23         MED_A, ///< Same as PRI_MED, except replace all A's as a group.
24         MED_B, ///< Same as PRI_MED, except replace all B's as a group.
25         MED_C, ///< Same as PRI_MED, except replace all C's as a group.
26 
27         /** If servicing all high and medium priority callouts did not resolve
28          *  the issue, service low priority callouts one at a time, in order,
29          *  until the issue is resolved. */
30         LOW,
31     };
32 
33   public:
34     /** @brief Pure virtual destructor. */
35     virtual ~Callout() = 0;
36 
37   protected:
38     /**
39      * @brief Constructor from components.
40      * @param p The callout priority.
41      */
42     explicit Callout(Priority p) : iv_priority(p) {}
43 
44   private:
45     /** The callout priority. */
46     const Priority iv_priority;
47 
48   protected:
49     /**
50      * @brief Appends the callout priority to the end of the given json object.
51      * @param j The json object for a single callout.
52      */
53     void addPriority(nlohmann::json& j) const
54     {
55         // clang-format off
56         static const std::map<Priority, std::string> m =
57         {
58             {HIGH,  "H"},
59             {MED,   "M"},
60             {MED_A, "A"},
61             {MED_B, "B"},
62             {MED_C, "C"},
63             {LOW,   "L"},
64         };
65         // clang-format on
66 
67         j.emplace("Priority", m.at(iv_priority));
68     }
69 
70   public:
71     /**
72      * @brief Appends a json object representing this callout to the end of the
73      *        given json object.
74      * @param j The json object containing all current callouts for a PEL.
75      */
76     virtual void getJson(nlohmann::json&) const = 0;
77 };
78 
79 // Pure virtual destructor must be defined.
80 inline Callout::~Callout() {}
81 
82 /** @brief A service event requiring hardware replacement. */
83 class HardwareCallout : public Callout
84 {
85   public:
86     /**
87      * @brief Constructor from components.
88      * @param i_locationCode The location code of the hardware callout.
89      * @param i_priority     The callout priority.
90      */
91     HardwareCallout(const std::string& i_locationCode, Priority i_priority) :
92         Callout(i_priority), iv_locationCode(i_locationCode)
93     {}
94 
95   private:
96     /** The hardware location code. */
97     const std::string iv_locationCode;
98 
99   public:
100     void getJson(nlohmann::json& j) const override
101     {
102         nlohmann::json c = {{"LocationCode", iv_locationCode}};
103         addPriority(c);
104         j.emplace_back(c);
105     }
106 };
107 
108 /**
109  * @brief A service event requiring a special procedure to be handled by a
110  *        service engineer.
111  */
112 class ProcedureCallout : public Callout
113 {
114   public:
115     /** Supported service procedures. */
116     enum Procedure
117     {
118         NEXTLVL, ///< Contact next level support.
119     };
120 
121   public:
122     /**
123      * @brief Constructor from components.
124      * @param i_procedure The location code of the hardware callout.
125      * @param i_priority     The callout priority.
126      */
127     ProcedureCallout(Procedure i_procedure, Priority i_priority) :
128         Callout(i_priority), iv_procedure(i_procedure)
129     {}
130 
131   private:
132     /** The callout priority. */
133     const Procedure iv_procedure;
134 
135   public:
136     void getJson(nlohmann::json& j) const override
137     {
138         // clang-format off
139         static const std::map<Procedure, std::string> m =
140         {
141             {NEXTLVL, "NEXTLVL"},
142         };
143         // clang-format on
144 
145         nlohmann::json c = {{"Procedure", m.at(iv_procedure)}};
146         addPriority(c);
147         j.emplace_back(c);
148     }
149 };
150 
151 /**
152  * @brief A service event requiring hardware to be guarded.
153  */
154 class Guard
155 {
156   public:
157     /** Supported guard types. */
158     enum Type
159     {
160         NONE,      ///< Do not guard
161         FATAL,     ///< Guard on fatal error (cannot recover resource)
162         NON_FATAL, ///< Guard on non-fatal error (can recover resource)
163     };
164 
165   public:
166     /**
167      * @brief Constructor from components.
168      * @param i_path The hardware path to guard.
169      * @param i_type The guard type.
170      */
171     Guard(const std::string& i_path, Type i_type) :
172         iv_path(i_path), iv_type(i_type)
173     {}
174 
175   private:
176     /** The hardware path to guard. */
177     const std::string iv_path;
178 
179     /** The guard type. */
180     const Type iv_type;
181 
182   public:
183     void getJson(nlohmann::json& j) const
184     {
185         // clang-format off
186         static const std::map<Type, std::string> m =
187         {
188             {NONE,      "NONE"},
189             {FATAL,     "FATAL"},
190             {NON_FATAL, "NON_FATAL"},
191         };
192         // clang-format on
193 
194         nlohmann::json c = {{"Path", iv_path}, {"Type", m.at(iv_type)}};
195         j.emplace_back(c);
196     }
197 };
198 
199 /**
200  * @brief Data regarding required service actions based on the hardware error
201  *        analysis.
202  */
203 class ServiceData
204 {
205   public:
206     /** @brief Default constructor. */
207     ServiceData() = default;
208 
209     /** @brief Destructor. */
210     ~ServiceData() = default;
211 
212     /** @brief Copy constructor. */
213     ServiceData(const ServiceData&) = default;
214 
215     /** @brief Assignment operator. */
216     ServiceData& operator=(const ServiceData&) = default;
217 
218   private:
219     /** The list of callouts that will be added to a PEL. */
220     std::vector<std::shared_ptr<Callout>> iv_calloutList;
221 
222     /** The list of hardware guard requests. Some information will be added to
223      * the PEL, but the actual guard record will be created after submitting the
224      * PEL. */
225     std::vector<std::shared_ptr<Guard>> iv_guardList;
226 
227   public:
228     /** Add a callout to the list. */
229     void addCallout(const std::shared_ptr<Callout>& i_callout)
230     {
231         iv_calloutList.push_back(i_callout);
232     }
233 
234     /** Add a guard request to the list. */
235     void addGuard(const std::shared_ptr<Guard>& i_guard)
236     {
237         iv_guardList.push_back(i_guard);
238     }
239 
240     /**
241      * @brief Iterates the callout list and returns the json attached to each
242      *        callout in the list.
243      * @param o_json The returned json data.
244      */
245     void getCalloutList(nlohmann::json& o_json) const
246     {
247         o_json.clear(); // Ensure we are starting with a clean list.
248 
249         for (const auto& c : iv_calloutList)
250         {
251             c->getJson(o_json);
252         }
253     }
254 
255     /**
256      * @brief Iterates the guard list and returns the json attached to each
257      *        guard request in the list.
258      * @param o_json The returned json data.
259      */
260     void getGuardList(nlohmann::json& o_json) const
261     {
262         o_json.clear(); // Ensure we are starting with a clean list.
263 
264         for (const auto& g : iv_guardList)
265         {
266             g->getJson(o_json);
267         }
268     }
269 };
270 
271 } // namespace analyzer
272