$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 #ifndef CLOE_TRIGGER_HPP_
29 #define CLOE_TRIGGER_HPP_
30 
31 #include <memory> // for unique_ptr<>, shared_ptr<>
32 #include <string> // for string
33 #include <utility> // for move
34 #include <vector> // for vector<>
35 
36 #include <cloe/core.hpp> // for Schema, Json, Duration, Error
37 #include <cloe/entity.hpp> // for Entity
38 #include <fable/enum.hpp> // for ENUM_SERIALIZATION
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, JsonType type, bool required = true);
110 
134  InlineSchema(std::string&& desc, std::string&& format, bool required = true)
135  : type_(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  JsonType type() const { return type_; }
152 
159  bool is_enabled() const { return !(required_ && type_ == JsonType::null); }
160 
170  bool is_required() const { return required_; }
171 
194  std::string usage(const std::string& name) const;
195 
196  private:
197  JsonType type_{JsonType::null};
198  bool required_{true};
199  std::string usage_{};
200  std::string desc_{};
201 };
202 
208  public:
224  TriggerSchema(const std::string& name, const std::string& desc)
225  : name_(name), schema_(std::string(desc)), inline_(true) {}
226 
231  TriggerSchema(const std::string& name, const std::string& desc,
232  fable::schema::PropertyList<> props)
233  : name_(name), schema_(std::string(desc), props), inline_(false) {}
234 
239  TriggerSchema(const std::string& name, const std::string& desc, Schema&& s)
240  : name_(name), schema_(std::move(s)), inline_(false) {
241  schema_.set_description(desc);
242  }
243 
248  TriggerSchema(const std::string& name, const std::string& desc, InlineSchema&& usage,
249  fable::schema::PropertyList<> props)
250  : name_(name), schema_(std::string(desc), props), inline_(std::move(usage)) {}
251 
256  TriggerSchema(const std::string& name, const std::string& desc, InlineSchema&& usage,
257  Schema&& init)
258  : name_(name), schema_(std::move(init)), inline_(std::move(usage)) {
259  schema_.set_description(desc);
260  }
261 
266  TriggerSchema(const std::string& name, const std::string& desc, InlineSchema&& usage,
267  const Schema& init)
268  : name_(name), schema_(init), inline_(std::move(usage)) {
269  schema_.set_description(desc);
270  }
271 
272  const std::string& name() const { return name_; }
273  const std::string& description() const { return schema_.description(); }
274  std::string usage_inline() const { return inline_.usage(name_); }
275  Json usage() const { return schema_.usage(); }
276  Json json_schema() const;
277 
278  private:
279  std::string name_;
280  Schema schema_;
281  InlineSchema inline_;
282 };
283 
299 template <typename T>
300 class TriggerFactory : public Entity {
301  public:
302  using Entity::Entity;
303  virtual ~TriggerFactory() noexcept = default;
304 
311  virtual TriggerSchema schema() const { return TriggerSchema{this->name(), this->description()}; }
312 
316  virtual Json json_schema() const { return this->schema().json_schema(); }
317 
323  virtual std::unique_ptr<T> make(const Conf& c) const = 0;
324 
338  virtual std::unique_ptr<T> make(const std::string& s) const {
339  if (s.empty()) {
340  // If the string is empty, then we can probably just assume that a Conf
341  // with nothing inside is as good as if it were the only one. Some
342  // information does go lost this way though.
343  auto c = Conf{
344  {"name", this->name()},
345  };
346  return this->make(c);
347  } else {
348  throw TriggerInvalid(Conf{Json{s}}, "cannot create " + this->name() + " from '" + s + "'");
349  }
350  }
351 };
352 
360 enum class Source {
362  FILESYSTEM,
363 
366  NETWORK,
367 
369  MODEL,
370 
373  TRIGGER,
374 
376  INSTANCE,
377 };
378 
379 // clang-format off
381  {Source::FILESYSTEM, "filesystem"},
382  {Source::NETWORK, "network"},
383  {Source::MODEL, "model"},
384  {Source::TRIGGER, "trigger"},
385  {Source::INSTANCE, "instance"},
386 }))
387 // clang-format on
388 
389 
397 inline bool source_is_transient(Source s) {
398  return (s != Source::FILESYSTEM && s != Source::NETWORK);
399 }
400 
405 class Trigger {
406  public:
407  Trigger(const std::string& label, Source s, EventPtr&& e, ActionPtr&& a);
408  TriggerPtr clone() const;
409 
410  const std::string& label() const { return label_; }
411  Source source() const { return source_; }
412  Duration since() const { return since_; }
413  void set_since(Duration t) { since_ = t; }
414  const Event& event() const { return *event_; }
415  Event& event() { return *event_; }
416  const Action& action() const { return *action_; }
417  Action& action() { return *action_; }
418 
419  bool is_significant() const;
420  bool is_transient() const { return source_is_transient(source_) || is_conceal(); }
421  bool is_conceal() const { return conceal_; }
422  void set_conceal(bool value = true);
423  bool is_sticky() const { return sticky_; }
424  void set_sticky(bool value = true);
425 
426  friend void to_json(Json& j, const Trigger& t);
427 
428  private:
429  std::string label_;
430  Source source_;
431  EventPtr event_;
432  ActionPtr action_;
433  Duration since_{0};
434  bool conceal_{false};
435  bool sticky_{false};
436 };
437 
443  public:
444  explicit TriggerRegistrar(Source s) : source_(s) {}
445  virtual ~TriggerRegistrar() noexcept = default;
446 
447  virtual ActionPtr make_action(const Conf& c) const = 0;
448  virtual EventPtr make_event(const Conf& c) const = 0;
449  virtual TriggerPtr make_trigger(const Conf& c) const = 0;
450 
451  virtual void insert_trigger(const Conf& c) = 0;
452  virtual void insert_trigger(TriggerPtr&& t) = 0;
453 
463  void insert_trigger(const std::string& label, EventPtr&& e, ActionPtr&& a);
464 
465  protected:
466  Source source_;
467 };
468 
487 class Event : public Entity {
488  public:
489  using Entity::Entity;
490  virtual ~Event() noexcept = default;
491 
497  virtual EventPtr clone() const = 0;
498 
503  virtual void to_json(Json&) const = 0;
504  friend void to_json(Json& j, const Event& e);
505 
506  protected:
507  Logger logger() const { return logger::get("cloe/event/" + name()); }
508 };
509 
517 using EventFactoryPtr = std::unique_ptr<EventFactory>;
518 
522 using CallbackExecuter = std::function<void(TriggerPtr&&, const Sync&)>;
523 
542 class Callback {
543  public:
544  virtual ~Callback() noexcept = default;
545 
549  void set_executer(CallbackExecuter exe) { executer_ = exe; }
550 
554  virtual void emplace(TriggerPtr&& t, const Sync& s) = 0;
555 
559  virtual void to_json(Json& j) const = 0;
560  friend void to_json(Json& j, const Callback& c) { c.to_json(j); }
561 
562  protected:
567  void execute(TriggerPtr&& t, const Sync& s);
568 
569  private:
570  CallbackExecuter executer_;
571 };
572 
579 class AliasCallback : public Callback {
580  public:
581  explicit AliasCallback(std::shared_ptr<Callback> owner) : owner_(owner) {}
582  virtual ~AliasCallback() noexcept = default;
583 
587  void emplace(TriggerPtr&& t, const Sync& s) override { owner_->emplace(std::move(t), s); }
588 
592  void to_json(Json&) const override {}
593 
594  private:
595  std::shared_ptr<Callback> owner_;
596 };
597 
616 class Action : public Entity {
617  public:
618  using Entity::Entity;
619  virtual ~Action() noexcept = default;
620 
626  virtual ActionPtr clone() const = 0;
627 
631  virtual void operator()(const Sync&, TriggerRegistrar&) = 0;
632 
645  virtual bool is_significant() const { return true; }
646 
651  virtual void to_json(Json& j) const = 0;
652  friend void to_json(Json& j, const Action& a);
653 
654  protected:
655  Logger logger() const { return logger::get("cloe/action/" + name()); }
656 };
657 
664 using ActionFactoryPtr = std::unique_ptr<ActionFactory>;
665 
666 } // namespace cloe
667 #endif // CLOE_TRIGGER_HPP_
Definition: conf.hpp:74
virtual void to_json(Json &j) const =0
InlineSchema(std::string &&desc, std::string &&format, bool required=true)
Definition: trigger.hpp:134
Definition: trigger.hpp:73
bool is_enabled() const
Definition: trigger.hpp:159
InlineSchema(std::string &&desc)
Definition: trigger.hpp:102
virtual bool is_significant() const
Definition: trigger.hpp:645
virtual TriggerSchema schema() const
Definition: trigger.hpp:311
Definition: trigger.hpp:579
virtual Json json_schema() const
Definition: trigger.hpp:316
virtual std::unique_ptr< T > make(const std::string &s) const
Definition: trigger.hpp:338
Definition: trigger.hpp:442
Definition: trigger.hpp:405
void to_json(Json &) const override
Definition: trigger.hpp:592
Definition: error.hpp:35
Definition: sync.hpp:35
Definition: trigger.hpp:616
Source
Definition: trigger.hpp:360
Definition: coordinator.hpp:36
TriggerSchema(const std::string &name, const std::string &desc, InlineSchema &&usage, Schema &&init)
Definition: trigger.hpp:256
std::chrono::nanoseconds Duration
Definition: duration.hpp:45
void emplace(TriggerPtr &&t, const Sync &s) override
Definition: trigger.hpp:587
Definition: trigger.hpp:60
TriggerSchema(const std::string &name, const std::string &desc, fable::schema::PropertyList<> props)
Definition: trigger.hpp:231
Definition: trigger.hpp:487
Definition: schema.hpp:178
Definition: enum_test.cpp:29
std::function< void(TriggerPtr &&, const Sync &)> CallbackExecuter
Definition: trigger.hpp:522
Definition: trigger.hpp:300
#define ENUM_SERIALIZATION(xType, xMap)
Definition: enum.hpp:52
Definition: entity.hpp:51
JsonType type() const
Definition: trigger.hpp:151
void set_executer(CallbackExecuter exe)
Definition: trigger.hpp:549
TriggerSchema(const std::string &name, const std::string &desc, InlineSchema &&usage, const Schema &init)
Definition: trigger.hpp:266
const std::string & description() const
Definition: trigger.hpp:143
bool is_required() const
Definition: trigger.hpp:170
TriggerSchema(const std::string &name, const std::string &desc, InlineSchema &&usage, fable::schema::PropertyList<> props)
Definition: trigger.hpp:248
Definition: trigger.hpp:542
TriggerSchema(const std::string &name, const std::string &desc)
Definition: trigger.hpp:224
InlineSchema(bool enabled)
Definition: trigger.hpp:97
Definition: trigger.hpp:87
TriggerSchema(const std::string &name, const std::string &desc, Schema &&s)
Definition: trigger.hpp:239
Definition: trigger.hpp:207