Caffa  1.1.0
C++ Application Framework for Embedded Systems with introspection
cafObjectHandle.h
1 // ##################################################################################################
2 //
3 // Custom Visualization Core library
4 // Copyright (C) 2011-2013 Ceetron AS
5 // Copyright (C) 2013- Ceetron Solutions AS
6 // Copyright (C) 2021-2022 3D-Radar AS
7 // Copyright (C) 2022- Kontur AS
8 //
9 // GNU Lesser General Public License Usage
10 // This library is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation; either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful, but WITHOUT ANY
16 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 // FITNESS FOR A PARTICULAR PURPOSE.
18 //
19 // See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
20 // for more details.
21 //
22 // ##################################################################################################
23 
24 #pragma once
25 
26 #include "cafAssert.h"
27 #include "cafFieldHandle.h"
28 #include "cafJsonDataType.h"
29 #include "cafLogger.h"
30 #include "cafMethodHandle.h"
31 #include "cafObjectCapability.h"
32 #include "cafPortableDataType.h"
33 #include "cafSignal.h"
34 #include "cafStringTools.h"
35 
36 #include <array>
37 #include <list>
38 #include <memory>
39 #include <set>
40 #include <string_view>
41 #include <type_traits>
42 #include <vector>
43 
44 namespace caffa
45 {
46 class FieldCapability;
47 class ObjectFactory;
48 class Inspector;
49 class Editor;
50 
55 {
56 public:
57  using InheritanceStackType = std::vector<std::string>;
58  using Ptr = std::shared_ptr<ObjectHandle>;
59  using ConstPtr = std::shared_ptr<const ObjectHandle>;
60 
61  ObjectHandle();
62  virtual ~ObjectHandle() noexcept;
63 
64  // TODO: Once compilers support constexpr std::vector and std::string these can be made constexpr
65  static std::string classKeywordStatic() { return "ObjectHandle"; }
66  virtual std::string classKeyword() const { return classKeywordStatic(); }
67 
68  virtual InheritanceStackType classInheritanceStack() const { return { classKeywordStatic() }; }
69 
70  static bool matchesClassKeyword( const std::string& classKeyword, const InheritanceStackType& inheritanceStack )
71  {
72  return std::any_of( inheritanceStack.begin(),
73  inheritanceStack.end(),
74  [&classKeyword]( const std::string& testKeyword ) { return classKeyword == testKeyword; } );
75  }
76 
77  static constexpr bool isValidCharacter( char c )
78  {
79  return caffa::StringTools::isalpha( c ) || caffa::StringTools::isdigit( c ) || c == '_' || c == ':';
80  }
81 
86  static constexpr bool isValidKeyword( const std::string_view& type )
87  {
88  if ( type == "keyword" ) return false;
89 
90  if ( caffa::StringTools::isdigit( type[0] ) ) return false;
91 
92  auto end = std::find( type.begin(), type.end(), '\0' );
93 
94  auto validCount = std::count_if( type.cbegin(), end, ObjectHandle::isValidCharacter );
95  auto invalidCount =
96  std::count_if( type.cbegin(), end, []( auto c ) { return !ObjectHandle::isValidCharacter( c ); } );
97 
98  return validCount > 0u && invalidCount == 0u;
99  }
100 
101  virtual std::string classDocumentation() const { return ""; }
102 
107  std::list<FieldHandle*> fields() const;
108 
113  std::list<MethodHandle*> methods() const;
114 
120  FieldHandle* findField( const std::string& keyword ) const;
121 
127  MethodHandle* findMethod( const std::string& keyword ) const;
128 
133  void addCapability( std::unique_ptr<ObjectCapability> capability )
134  {
135  m_capabilities.push_back( std::move( capability ) );
136  }
137 
142  template <typename CapabilityType>
143  CapabilityType* capability() const
144  {
145  for ( auto& cap : m_capabilities )
146  {
147  CapabilityType* capability = dynamic_cast<CapabilityType*>( cap.get() );
148  if ( capability ) return capability;
149  }
150  return nullptr;
151  }
152 
153  virtual std::string uuid() const { return ""; }
154  virtual void setUuid( const std::string& ) {}
155 
162  virtual ObjectHandle::Ptr deepClone( caffa::ObjectFactory* optionalObjectFactory = nullptr ) const = 0;
163 
166  virtual void initAfterRead(){};
167 
168  void disconnectObserverFromAllSignals( SignalObserver* observer );
169 
174  void accept( Inspector* visitor ) const;
175 
180  void accept( Editor* visitor );
181 
182 protected:
186  void addField( FieldHandle* field, const std::string& keyword );
187 
191  void addMethod( MethodHandle* method, const std::string& keyword, MethodHandle::Type type );
192 
193 private:
194  ObjectHandle( const ObjectHandle& ) = delete;
195  ObjectHandle& operator=( const ObjectHandle& ) = delete;
196 
197  // Fields
198  std::map<std::string, FieldHandle*> m_fields;
199 
200  // Methods
201  std::map<std::string, MethodHandle*> m_methods;
202 
203  // Capabilities
204  std::vector<std::unique_ptr<ObjectCapability>> m_capabilities;
205 };
206 
207 template <typename T>
208 concept DerivesFromObjectHandle = std::is_base_of<ObjectHandle, T>::value;
209 
210 template <typename T>
211 struct is_shared_ptr : std::false_type
212 {
213 };
214 template <typename T>
215 struct is_shared_ptr<std::shared_ptr<T>> : std::true_type
216 {
217 };
218 
219 template <typename T>
220 concept IsSharedPtr = is_shared_ptr<T>::value;
221 
225 template <DerivesFromObjectHandle DataType>
226 struct PortableDataType<DataType>
227 {
228  static std::string name() { return std::string( "object::" ) + DataType::classKeywordStatic(); }
229 };
230 
234 template <DerivesFromObjectHandle DataType>
235 struct PortableDataType<std::vector<DataType>>
236 {
237  static std::string name() { return std::string( "object[]::" ) + DataType::classKeywordStatic(); }
238 };
239 
243 template <IsSharedPtr DataType>
244 struct PortableDataType<DataType>
245 {
246  static std::string name()
247  {
248  static_assert( DerivesFromObjectHandle<typename DataType::element_type> );
249  return std::string( "object::" ) + DataType::element_type::classKeywordStatic();
250  }
251 };
252 
256 template <IsSharedPtr DataType>
257 struct PortableDataType<std::vector<DataType>>
258 {
259  static std::string name()
260  {
261  static_assert( DerivesFromObjectHandle<typename DataType::element_type> );
262  return std::string( "object[]::" ) + DataType::element_type::classKeywordStatic();
263  }
264 };
265 
269 template <DerivesFromObjectHandle DataType>
270 struct JsonDataType<DataType>
271 {
272  static nlohmann::json type()
273  {
274  auto object = nlohmann::json::object();
275  object["$ref"] = std::string( "#/schemas/" ) + DataType::classKeywordStatic();
276  return object;
277  }
278 };
279 
283 template <IsSharedPtr DataType>
284 struct JsonDataType<DataType>
285 {
286  static nlohmann::json type()
287  {
288  auto object = nlohmann::json::object();
289  object["$ref"] = std::string( "#/schemas/" ) + DataType::element_type::classKeywordStatic();
290  return object;
291  }
292 };
293 
294 } // namespace caffa
Definition: cafVisitor.h:43
Base class for all fields, making it possible to handle them generically.
Definition: cafFieldHandle.h:23
Definition: cafVisitor.h:32
Definition: cafMethodHandle.h:56
Definition: cafObjectFactory.h:39
Definition: cafObjectHandle.h:55
virtual void initAfterRead()
Definition: cafObjectHandle.h:166
void accept(Inspector *visitor) const
Definition: cafObjectHandle.cpp:138
static constexpr bool isValidKeyword(const std::string_view &type)
Definition: cafObjectHandle.h:86
CapabilityType * capability() const
Definition: cafObjectHandle.h:143
void addMethod(MethodHandle *method, const std::string &keyword, MethodHandle::Type type)
Definition: cafObjectHandle.cpp:106
std::list< FieldHandle * > fields() const
Definition: cafObjectHandle.cpp:51
std::list< MethodHandle * > methods() const
Definition: cafObjectHandle.cpp:64
void addCapability(std::unique_ptr< ObjectCapability > capability)
Definition: cafObjectHandle.h:133
FieldHandle * findField(const std::string &keyword) const
Definition: cafObjectHandle.cpp:120
void addField(FieldHandle *field, const std::string &keyword)
Definition: cafObjectHandle.cpp:91
MethodHandle * findMethod(const std::string &keyword) const
Definition: cafObjectHandle.cpp:129
virtual ObjectHandle::Ptr deepClone(caffa::ObjectFactory *optionalObjectFactory=nullptr) const =0
Deep clone the object using an optional object factory.
Definition: cafSignal.h:63
Definition: cafSignal.h:80
Main Caffa namespace.
Definition: __init__.py:1
Definition: cafPortableDataType.h:35
Definition: cafObjectHandle.h:212