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