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 "cafFieldValidator.h"
25 #include "cafTypedField.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  try
87  {
88  return m_fieldDataAccessor->value();
89  }
90  catch ( const std::exception& e )
91  {
92  std::string errorMessage = "Failed to get value for '" + this->keyword() + "': " + e.what();
93  CAFFA_ERROR( errorMessage );
94  throw std::runtime_error( errorMessage );
95  }
96  }
97  void setValue( const DataType& fieldValue ) override
98  {
99  CAFFA_ASSERT( this->isInitialized() );
100 
101  try
102  {
103  for ( const auto& validator : m_valueValidators )
104  {
105  if ( auto [status, message] = validator->validate( fieldValue ); !status )
106  {
107  CAFFA_ASSERT( !message.empty() );
108  if ( validator->failureSeverity() == FieldValidatorInterface::FailureSeverity::VALIDATOR_ERROR ||
109  validator->failureSeverity() == FieldValidatorInterface::FailureSeverity::VALIDATOR_CRITICAL )
110  {
111  throw std::runtime_error( message );
112  }
113  else
114  {
115  CAFFA_WARNING( message );
116  }
117  }
118  }
119  m_fieldDataAccessor->setValue( fieldValue );
120  }
121  catch ( const std::exception& e )
122  {
123  std::string errorMessage = "Failed to set value for '" + this->keyword() + "': " + e.what();
124  CAFFA_ERROR( errorMessage );
125  throw std::runtime_error( errorMessage );
126  }
127  }
128 
129  // Access operators
130 
131  /*Conversion */
132  operator DataType() const
133  {
134  CAFFA_ASSERT( m_fieldDataAccessor );
135  return this->value();
136  }
137  DataType operator()() const
138  {
139  CAFFA_ASSERT( m_fieldDataAccessor );
140  return this->value();
141  }
142  DataType operator*() const
143  {
144  CAFFA_ASSERT( m_fieldDataAccessor );
145  return this->value();
146  }
147 
148  auto operator<=>( const DataType& fieldValue ) const { return this->value() <=> fieldValue; }
149 
150  // Replace accessor
151  void setAccessor( std::unique_ptr<DataAccessor> accessor ) { m_fieldDataAccessor = std::move( accessor ); }
152 
153  void setUntypedAccessor( std::unique_ptr<DataFieldAccessorInterface> accessor ) override
154  {
155  CAFFA_ASSERT( dynamic_cast<DataAccessor*>( accessor.get() ) != nullptr );
156 
157  std::unique_ptr<DataAccessor> typedAccessor( dynamic_cast<DataAccessor*>( accessor.release() ) );
158  CAFFA_ASSERT( typedAccessor );
159  setAccessor( std::move( typedAccessor ) );
160  }
161 
162  template <typename ValidatorType>
163  const ValidatorType* valueValidator() const
164  {
165  for ( const auto& validator : m_valueValidators )
166  {
167  const ValidatorType* typedValidator = dynamic_cast<const ValidatorType*>( validator.get() );
168  if ( typedValidator ) return typedValidator;
169  }
170  return nullptr;
171  }
172 
173  template <typename ValidatorType>
174  ValidatorType* valueValidator()
175  {
176  for ( auto& validator : m_valueValidators )
177  {
178  const ValidatorType* typedValidator = dynamic_cast<const ValidatorType*>( validator.get() );
179  if ( typedValidator ) return typedValidator;
180  }
181  return nullptr;
182  }
183 
184  std::vector<const FieldValidator<DataType>*> valueValidators() const
185  {
186  std::vector<const FieldValidator<DataType>*> allValidators;
187  for ( const auto& validator : m_valueValidators )
188  {
189  allValidators.push_back( validator.get() );
190  }
191  return allValidators;
192  }
193 
194  std::vector<FieldValidator<DataType>*> valueValidators()
195  {
196  std::vector<FieldValidator<DataType>*> allValidators;
197  for ( auto& validator : m_valueValidators )
198  {
199  allValidators.push_back( validator.get() );
200  }
201  return allValidators;
202  }
203 
204  void addValidator( std::unique_ptr<FieldValidator<DataType>> valueValidator )
205  {
206  m_valueValidators.push_back( std::move( valueValidator ) );
207  }
208 
209  void clearValidators() { m_valueValidators.clear(); }
210 
211 public:
212  std::optional<DataType> defaultValue() const { return m_defaultValue; }
213  void setDefaultValue( const DataType& val ) { m_defaultValue = val; }
214 
215  bool operator==( const Field<DataType>& rhs ) const = delete;
216  auto operator<=>( const Field<DataType>& rhs ) const = delete;
217 
218 protected:
219  std::unique_ptr<DataAccessor> m_fieldDataAccessor;
220  std::vector<std::unique_ptr<FieldValidator<DataType>>> m_valueValidators;
221  std::optional<DataType> m_defaultValue;
222 };
223 
224 } // End of namespace caffa
Abstract but typed data field accessor. Inherit to create different storage mechanisms.
Definition: cafDataFieldAccessor.h:43
Direct storage accessor, which stores data values in local memory.
Definition: cafDataFieldAccessor.h:75
Used to validate the value of data fields Implementations need the the validate method as well as rea...
Definition: cafFieldValidator.h:104
Definition: cafField.h:46
Definition: cafTypedField.h:67
Main Caffa namespace.
Definition: __init__.py:1