$darkmode
trigger.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Robert Bosch GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
27 #pragma once
28 
29 #include <memory> // for unique_ptr<>, shared_ptr<>
30 #include <string> // for string
31 #include <utility> // for move
32 #include <vector> // for vector<>
33 
34 #include <cloe/core.hpp> // for Duration, Error
35 #include <cloe/entity.hpp> // for Entity
36 #include <fable/enum.hpp> // for ENUM_SERIALIZATION
37 #include <fable/json.hpp> // for Json
38 #include <fable/schema.hpp> // for Schema
39 
40 namespace cloe {
41 
42 // Forward declarations:
43 class Sync; // from cloe/sync.hpp
44 
45 // Forward declarations for Trigger:
46 class Event;
47 using EventPtr = std::unique_ptr<Event>;
48 using EventPtrs = std::vector<EventPtr>;
49 class Action;
50 using ActionPtr = std::unique_ptr<Action>;
51 using ActionPtrs = std::vector<ActionPtr>;
52 class Trigger;
53 using TriggerPtr = std::unique_ptr<Trigger>;
54 using TriggerPtrs = std::vector<TriggerPtr>;
55 
60 class TriggerError : public Error {
61  public:
62  using Error::Error;
63  virtual ~TriggerError() noexcept = default;
64 };
65 
73 class TriggerInvalid : public TriggerError {
74  public:
75  TriggerInvalid(const Conf& c, const std::string& what) : TriggerError(what), conf_(c) {}
76  virtual ~TriggerInvalid() noexcept = default;
77 
78  const Conf& conf() const { return conf_; }
79 
80  private:
81  Conf conf_;
82 };
83 
87 struct InlineSchema {
88  public:
97  explicit InlineSchema(bool enabled) : required_(!enabled) {}
98 
102  explicit InlineSchema(std::string desc) : required_(false), desc_(std::move(desc)) {}
103 
109  InlineSchema(std::string desc, fable::JsonType type, bool required = true);
110 
134  InlineSchema(std::string desc, std::string format, bool required = true)
135  : type_(fable::JsonType::string)
136  , required_(required)
137  , usage_(std::move(format))
138  , desc_(std::move(desc)) {}
139 
143  const std::string& description() const { return desc_; }
144 
151  fable::JsonType type() const { return type_; }
152 
159  bool is_enabled() const { return !(required_ && type_ == fable::JsonType::null); }
160 
170  bool is_required() const { return required_; }
171 
194  std::string usage(const std::string& name) const;
195 
196  private:
197  fable::JsonType type_{JsonType::null};
198  bool required_{true};
199  std::string usage_{};
200  std::string desc_{};
201 };
202 
208  public:
224  TriggerSchema(std::string name, std::string desc)
225  : name_(std::move(name)), schema_(std::move(desc)), inline_(true) {}
226 
231  TriggerSchema(std::string name, std::string desc, fable::schema::PropertyList<> props)
232  : name_(std::move(name)), schema_(std::move(desc), std::move(props)), inline_(false) {}
233 
238  TriggerSchema(std::string name, std::string desc, Schema s)
239  : name_(std::move(name)), schema_(std::move(s)), inline_(false) {
240  schema_.set_description(std::move(desc));
241  }
242 
247  TriggerSchema(std::string name, std::string desc, InlineSchema usage,
248  fable::schema::PropertyList<> props)
249  : name_(std::move(name))
250  , schema_(std::move(desc), std::move(props))
251  , inline_(std::move(usage)) {}
252 
257  TriggerSchema(std::string name, std::string desc, InlineSchema usage, Schema init)
258  : name_(std::move(name)), schema_(std::move(init)), inline_(std::move(usage)) {
259  schema_.set_description(std::move(desc));
260  }
261 
262  const std::string& name() const { return name_; }
263  const std::string& description() const { return schema_.description(); }
264  std::string usage_inline() const { return inline_.usage(name_); }
265  fable::Json usage() const { return schema_.usage(); }
266  fable::Json json_schema() const;
267 
268  private:
269  std::string name_;
270  fable::Schema schema_;
271  InlineSchema inline_;
272 };
273 
289 template <typename T>
290 class TriggerFactory : public Entity {
291  public:
292  using Entity::Entity;
293  virtual ~TriggerFactory() noexcept = default;
294 
301  virtual TriggerSchema schema() const { return TriggerSchema{this->name(), this->description()}; }
302 
306  virtual fable::Json json_schema() const { return this->schema().json_schema(); }
307 
313  virtual std::unique_ptr<T> make(const Conf& c) const = 0;
314 
328  virtual std::unique_ptr<T> make(const std::string& s) const {
329  if (s.empty()) {
330  // If the string is empty, then we can probably just assume that a Conf
331  // with nothing inside is as good as if it were the only one. Some
332  // information does go lost this way though.
333  auto c = Conf{
334  {"name", this->name()},
335  };
336  return this->make(c);
337  } else {
339  "cannot create " + this->name() + " from '" + s + "'");
340  }
341  }
342 };
343 
351 enum class Source {
353  FILESYSTEM,
354 
357  NETWORK,
358 
360  MODEL,
361 
364  TRIGGER,
365 
367  INSTANCE,
368 };
369 
370 // clang-format off
372  {Source::FILESYSTEM, "filesystem"},
373  {Source::NETWORK, "network"},
374  {Source::MODEL, "model"},
375  {Source::TRIGGER, "trigger"},
376  {Source::INSTANCE, "instance"},
377 }))
378 // clang-format on
379 
380 
388 inline bool source_is_transient(Source s) {
389  return (s != Source::FILESYSTEM && s != Source::NETWORK);
390 }
391 
396 class Trigger {
397  public:
398  Trigger(const std::string& label, Source s, EventPtr&& e, ActionPtr&& a);
399  TriggerPtr clone() const;
400 
401  const std::string& label() const { return label_; }
402  Source source() const { return source_; }
403  Duration since() const { return since_; }
404  void set_since(Duration t) { since_ = t; }
405  const Event& event() const { return *event_; }
406  Event& event() { return *event_; }
407  const Action& action() const { return *action_; }
408  Action& action() { return *action_; }
409 
410  bool is_significant() const;
411  bool is_transient() const { return source_is_transient(source_) || is_conceal(); }
412  bool is_conceal() const { return conceal_; }
413  void set_conceal(bool value = true);
414  bool is_sticky() const { return sticky_; }
415  void set_sticky(bool value = true);
416 
417  friend void to_json(fable::Json& j, const Trigger& t);
418 
419  private:
420  std::string label_;
421  Source source_;
422  EventPtr event_;
423  ActionPtr action_;
424  Duration since_{0};
425  bool conceal_{false};
426  bool sticky_{false};
427 };
428 
434  public:
435  explicit TriggerRegistrar(Source s) : source_(s) {}
436  virtual ~TriggerRegistrar() noexcept = default;
437 
438  virtual ActionPtr make_action(const Conf& c) const = 0;
439  virtual EventPtr make_event(const Conf& c) const = 0;
440  virtual TriggerPtr make_trigger(const Conf& c) const = 0;
441 
442  virtual void insert_trigger(const Conf& c) = 0;
443  virtual void insert_trigger(TriggerPtr&& t) = 0;
444 
454  void insert_trigger(const std::string& label, EventPtr&& e, ActionPtr&& a);
455 
456  protected:
457  Source source_;
458 };
459 
478 class Event : public Entity {
479  public:
480  using Entity::Entity;
481  virtual ~Event() noexcept = default;
482 
488  virtual EventPtr clone() const = 0;
489 
494  virtual void to_json(fable::Json&) const = 0;
495  friend void to_json(fable::Json& j, const Event& e);
496 
497  protected:
498  Logger logger() const { return logger::get("cloe/event/" + name()); }
499 };
500 
507 using EventFactory = TriggerFactory<Event>;
508 using EventFactoryPtr = std::unique_ptr<EventFactory>;
509 
513 using CallbackExecuter = std::function<void(TriggerPtr&&, const Sync&)>;
514 
533 class Callback {
534  public:
535  virtual ~Callback() noexcept = default;
536 
540  void set_executer(CallbackExecuter exe) { executer_ = exe; }
541 
545  virtual void emplace(TriggerPtr&& t, const Sync& s) = 0;
546 
550  virtual void to_json(fable::Json& j) const = 0;
551  friend void to_json(fable::Json& j, const Callback& c) { c.to_json(j); }
552 
553  protected:
558  void execute(TriggerPtr&& t, const Sync& s);
559 
560  private:
561  CallbackExecuter executer_;
562 };
563 
570 class AliasCallback : public Callback {
571  public:
572  explicit AliasCallback(std::shared_ptr<Callback> owner) : owner_(owner) {}
573  virtual ~AliasCallback() noexcept = default;
574 
578  void emplace(TriggerPtr&& t, const Sync& s) override { owner_->emplace(std::move(t), s); }
579 
583  void to_json(fable::Json&) const override {}
584 
585  private:
586  std::shared_ptr<Callback> owner_;
587 };
588 
607 class Action : public Entity {
608  public:
609  using Entity::Entity;
610  virtual ~Action() noexcept = default;
611 
617  virtual ActionPtr clone() const = 0;
618 
622  virtual void operator()(const Sync&, TriggerRegistrar&) = 0;
623 
636  virtual bool is_significant() const { return true; }
637 
642  virtual void to_json(fable::Json& j) const = 0;
643  friend void to_json(fable::Json& j, const Action& a);
644 
645  protected:
646  Logger logger() const { return logger::get("cloe/action/" + name()); }
647 };
648 
654 using ActionFactory = TriggerFactory<Action>;
655 using ActionFactoryPtr = std::unique_ptr<ActionFactory>;
656 
657 } // namespace cloe
Definition: trigger.hpp:607
Logger logger() const
Definition: trigger.hpp:646
virtual void operator()(const Sync &, TriggerRegistrar &)=0
virtual void to_json(fable::Json &j) const =0
virtual ActionPtr clone() const =0
virtual bool is_significant() const
Definition: trigger.hpp:636
Definition: trigger.hpp:570
void emplace(TriggerPtr &&t, const Sync &s) override
Definition: trigger.hpp:578
void to_json(fable::Json &) const override
Definition: trigger.hpp:583
Definition: trigger.hpp:533
void execute(TriggerPtr &&t, const Sync &s)
Definition: trigger.cpp:111
virtual void emplace(TriggerPtr &&t, const Sync &s)=0
void set_executer(CallbackExecuter exe)
Definition: trigger.hpp:540
virtual void to_json(fable::Json &j) const =0
Definition: entity.hpp:50
const std::string & description() const
Definition: entity.hpp:90
const std::string & name() const
Definition: entity.hpp:67
Definition: error.hpp:35
Definition: trigger.hpp:478
virtual EventPtr clone() const =0
Logger logger() const
Definition: trigger.hpp:498
virtual void to_json(fable::Json &) const =0
Definition: sync.hpp:34
Definition: trigger.hpp:60
Definition: trigger.hpp:290
virtual std::unique_ptr< T > make(const std::string &s) const
Definition: trigger.hpp:328
virtual fable::Json json_schema() const
Definition: trigger.hpp:306
virtual TriggerSchema schema() const
Definition: trigger.hpp:301
virtual std::unique_ptr< T > make(const Conf &c) const =0
Definition: trigger.hpp:73
Definition: trigger.hpp:433
Definition: trigger.hpp:396
Definition: conf.hpp:82
Definition: schema.hpp:173
Json usage() const override
Definition: schema.hpp:253
const std::string & description() const override
Definition: schema.hpp:251
void set_description(std::string s) override
Definition: schema.hpp:252
std::chrono::nanoseconds Duration
Definition: cloe_fwd.hpp:36
#define ENUM_SERIALIZATION(xType, xMap)
Definition: enum.hpp:51
nlohmann::json Json
Definition: fable_fwd.hpp:35
nlohmann::json::value_t JsonType
Definition: json.hpp:78
Definition: trigger.hpp:87
InlineSchema(std::string desc)
Definition: trigger.hpp:102
const std::string & description() const
Definition: trigger.hpp:143
InlineSchema(bool enabled)
Definition: trigger.hpp:97
std::string usage(const std::string &name) const
Definition: trigger.cpp:42
InlineSchema(std::string desc, std::string format, bool required=true)
Definition: trigger.hpp:134
bool is_required() const
Definition: trigger.hpp:170
InlineSchema(std::string desc, fable::JsonType type, bool required=true)
bool is_enabled() const
Definition: trigger.hpp:159
fable::JsonType type() const
Definition: trigger.hpp:151
Definition: trigger.hpp:207
TriggerSchema(std::string name, std::string desc, Schema s)
Definition: trigger.hpp:238
TriggerSchema(std::string name, std::string desc, fable::schema::PropertyList<> props)
Definition: trigger.hpp:231
TriggerSchema(std::string name, std::string desc, InlineSchema usage, Schema init)
Definition: trigger.hpp:257
TriggerSchema(std::string name, std::string desc)
Definition: trigger.hpp:224
TriggerSchema(std::string name, std::string desc, InlineSchema usage, fable::schema::PropertyList<> props)
Definition: trigger.hpp:247
std::function< void(TriggerPtr &&, const Sync &)> CallbackExecuter
Definition: trigger.hpp:513
Source
Definition: trigger.hpp:351
@ INSTANCE
Triggers that are instance of a sticky trigger.
@ MODEL
Triggers that originate from models, such as a simulator binding.
@ FILESYSTEM
Triggers that originate from the filesystem, such as stack files.