Caffa  1.1.0
C++ Application Framework for Embedded Systems with introspection
cafField.h
1 // ##################################################################################################
2 //
3 // Caffa
4 // Copyright (C) 2011-2013 Ceetron AS
5 // Copyright (C) 2021 3D-Radar AS
6 // Copyright (C) 2022- Kontur AS
7 //
8 // GNU Lesser General Public License Usage
9 // This library is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU Lesser General Public License as published by
11 // the Free Software Foundation; either version 2.1 of the License, or
12 // (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful, but WITHOUT ANY
15 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 // FITNESS FOR A PARTICULAR PURPOSE.
17 //
18 // See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
19 // for more details.
20 //
21 // ##################################################################################################
22 #pragma once
23 
24 #include "cafDataField.h"
25 #include "cafFieldValidator.h"
26 
27 #include "cafAssert.h"
28 #include "cafDataFieldAccessor.h"
29 
30 #include "cafLogger.h"
31 
32 #include <stdexcept>
33 #include <vector>
34 
35 namespace caffa
36 {
37 class ObjectHandle;
38 
39 //==================================================================================================
42 //==================================================================================================
43 
44 template <typename DataType>
45 class Field : public TypedField<DataType>
46 {
47 public:
50 
51  Field()
52  : m_fieldDataAccessor( std::make_unique<DirectStorageAccessor>() )
53  {
54  }
55 
56  explicit Field( const Field& other ) = delete;
57 
58  explicit Field( const DataType& fieldValue )
59  : m_fieldDataAccessor( std::make_unique<DirectStorageAccessor>( fieldValue ) )
60  {
61  }
62 
63  Field( std::unique_ptr<DataAccessor> accessor )
64  : m_fieldDataAccessor( std::move( accessor ) )
65  {
66  }
67 
68  ~Field() noexcept override {}
69 
70  // Assignment
71 
72  Field& operator=( const Field& other ) = delete;
73 
74  Field& operator=( const DataType& fieldValue )
75  {
76  this->setValue( fieldValue );
77  return *this;
78  }
79 
80  // Basic access
81 
82  DataType value() const override
83  {
84  CAFFA_ASSERT( this->isInitialized() );
85 
86  if ( !m_fieldDataAccessor )
87  {
88  std::string errorMessage = "Failed to get value for '" + this->keyword() + "': Field is not accessible";
89  CAFFA_ERROR( errorMessage );
90  throw std::runtime_error( errorMessage );
91  }
92 
93  try
94  {
95  return m_fieldDataAccessor->value();
96  }
97  catch ( const std::exception& e )
98  {
99  std::string errorMessage = "Failed to get value for '" + this->keyword() + "': " + e.what();
100  CAFFA_ERROR( errorMessage );
101  throw std::runtime_error( errorMessage );
102  }
103  }
104 
105  void setValue( const DataType& fieldValue ) override
106  {
107  CAFFA_ASSERT( this->isInitialized() );
108 
109  if ( !m_fieldDataAccessor )
110  {
111  std::string errorMessage = "Failed to set value for '" + this->keyword() + "': Field is not accessible";
112  CAFFA_ERROR( errorMessage );
113  throw std::runtime_error( errorMessage );
114  }
115 
116  try
117  {
118  for ( const auto& validator : m_valueValidators )
119  {
120  if ( auto [status, message] = validator->validate( fieldValue ); !status )
121  {
122  CAFFA_ASSERT( !message.empty() );
123  if ( validator->failureSeverity() == FieldValidatorInterface::FailureSeverity::VALIDATOR_ERROR ||
124  validator->failureSeverity() == FieldValidatorInterface::FailureSeverity::VALIDATOR_CRITICAL )
125  {
126  throw std::runtime_error( message );
127  }
128  else
129  {
130  CAFFA_WARNING( message );
131  }
132  }
133  }
134  m_fieldDataAccessor->setValue( fieldValue );
135  }
136  catch ( const std::exception& e )
137  {
138  std::string errorMessage = "Failed to set value for '" + this->keyword() + "': " + e.what();
139  CAFFA_ERROR( errorMessage );
140  throw std::runtime_error( errorMessage );
141  }
142  }
143 
144  // Access operators
145 
146  /*Conversion */
147  operator DataType() const { return this->value(); }
148  DataType operator()() const { return this->value(); }
149  DataType operator*() const { return this->value(); }
150 
151  auto operator<=>( const DataType& fieldValue ) const { return this->value() <=> fieldValue; }
152 
153  bool isReadable() const override { return m_fieldDataAccessor != nullptr && m_fieldDataAccessor->hasGetter(); }
154  bool isWritable() const override { return m_fieldDataAccessor != nullptr && m_fieldDataAccessor->hasSetter(); }
155 
156  // Replace accessor
157  void setAccessor( std::unique_ptr<DataAccessor> accessor ) { m_fieldDataAccessor = std::move( accessor ); }
158 
159  void setUntypedAccessor( std::unique_ptr<DataFieldAccessorInterface> accessor ) override
160  {
161  if ( accessor )
162  {
163  std::unique_ptr<DataAccessor> typedAccessor( dynamic_cast<DataAccessor*>( accessor.release() ) );
164  CAFFA_ASSERT( typedAccessor );
165  setAccessor( std::move( typedAccessor ) );
166  }
167  else
168  {
169  setAccessor( nullptr );
170  }
171  }
172 
173  std::vector<const FieldValidator<DataType>*> valueValidators() const
174  {
175  std::vector<const FieldValidator<DataType>*> allValidators;
176  for ( const auto& validator : m_valueValidators )
177  {
178  allValidators.push_back( validator.get() );
179  }
180  return allValidators;
181  }
182 
183  std::vector<FieldValidator<DataType>*> valueValidators()
184  {
185  std::vector<FieldValidator<DataType>*> allValidators;
186  for ( auto& validator : m_valueValidators )
187  {
188  allValidators.push_back( validator.get() );
189  }
190  return allValidators;
191  }
192 
193  void addValidator( std::unique_ptr<FieldValidator<DataType>> valueValidator )
194  {
195  m_valueValidators.push_back( std::move( valueValidator ) );
196  }
197 
198  void clearValidators() { m_valueValidators.clear(); }
199 
200 public:
201  std::optional<DataType> defaultValue() const { return m_defaultValue; }
202  void setDefaultValue( const DataType& val ) { m_defaultValue = val; }
203 
204  bool operator==( const Field<DataType>& rhs ) const = delete;
205  auto operator<=>( const Field<DataType>& rhs ) const = delete;
206 
207 protected:
208  std::unique_ptr<DataAccessor> m_fieldDataAccessor;
209  std::vector<std::unique_ptr<FieldValidator<DataType>>> m_valueValidators;
210  std::optional<DataType> m_defaultValue;
211 };
212 
213 } // End of namespace caffa
Used to validate the value of data fields Implementations need the the validate method as well as rea...
Definition: cafFieldValidator.h:94
bool isReadable() const override
Definition: cafField.h:153
Abstract but typed data field accessor. Inherit to create different storage mechanisms.
Definition: cafDataFieldAccessor.h:42
Definition: cafDataField.h:40
Definition: cafField.h:45
bool isWritable() const override
Definition: cafField.h:154
Main Caffa namespace.
Definition: cafApplication.h:30
Direct storage accessor, which stores data values in local memory.
Definition: cafDataFieldAccessor.h:86