22 #include "cafAssert.h"
23 #include "cafJsonDataType.h"
24 #include "cafLogger.h"
25 #include "cafMethodHandle.h"
27 #include "cafObjectFactory.h"
28 #include "cafObjectJsonSpecializations.h"
30 #include <nlohmann/json.hpp>
38 template <
class CallbackT>
42 std::function<CallbackT> m_callback;
45 template <
typename Result,
typename... ArgTypes>
49 using Callback = std::function<Result( ArgTypes... )>;
51 Result operator()( ArgTypes... args )
const
53 CAFFA_ASSERT( m_callback );
54 if (
auto accessor = this->accessor(); accessor )
56 auto serializedMethod = toJson( args... ).dump();
57 CAFFA_DEBUG(
"Serialized method: " << serializedMethod );
58 auto serialisedResult = accessor->execute( serializedMethod );
59 CAFFA_DEBUG(
"Got serialized result: " << serialisedResult );
60 return resultFromJsonString( serialisedResult, accessor->objectFactory() );
62 return m_callback( args... );
70 std::string
execute(
const std::string& jsonArgumentsString )
const override
72 return executeJson( nlohmann::json::parse( jsonArgumentsString ) ).dump();
75 std::string schema()
const override {
return this->jsonSchema().dump(); }
77 Result resultFromJsonString(
const std::string& jsonResultString, ObjectFactory* objectFactory )
const
79 CAFFA_DEBUG(
"Attempting to get a value of type " << JsonDataType<Result>::type()
80 <<
" from JSON: " << jsonResultString );
81 nlohmann::json jsonResult;
82 if ( !jsonResultString.empty() )
84 jsonResult = nlohmann::json::parse( jsonResultString );
86 return jsonToValue<Result>( jsonResult, objectFactory );
89 nlohmann::json toJson( ArgTypes... args )
const
91 auto jsonMethod = nlohmann::json::object();
92 CAFFA_ASSERT( !keyword().empty() );
94 constexpr std::size_t n =
sizeof...( args );
95 if constexpr ( n > 0 )
97 auto jsonArguments = nlohmann::json::array();
105 jsonArguments.push_back( args );
109 jsonMethod[
"positionalArguments"] = jsonArguments;
114 nlohmann::json jsonSchema()
const override
116 auto jsonMethod = nlohmann::json::object();
117 CAFFA_ASSERT( !keyword().empty() );
118 jsonMethod[
"type"] =
"object";
119 if ( !this->documentation().empty() )
121 jsonMethod[
"description"] = this->documentation();
123 auto jsonProperties = nlohmann::json::object();
124 auto jsonArgumentItems = jsonArgumentSchemaArray( std::index_sequence_for<ArgTypes...>() );
126 if ( !jsonArgumentItems.empty() )
128 auto jsonpositionalArguments = nlohmann::json::object();
129 jsonpositionalArguments[
"type"] =
"array";
130 jsonpositionalArguments[
"minItems"] = jsonArgumentItems.size();
131 jsonpositionalArguments[
"maxItems"] = jsonArgumentItems.size();
133 auto jsonNumberedArgumentItems = nlohmann::json::array();
134 auto jsonLabelledArguments = nlohmann::json::object();
135 jsonLabelledArguments[
"type"] =
"object";
136 auto jsonLabelledArgumentProperties = nlohmann::json::object();
137 for (
const nlohmann::json& argument : jsonArgumentItems )
139 CAFFA_ASSERT( argument.is_object() );
140 auto keyword = argument[
"keyword"].get<std::string>();
141 auto type = argument[
"type"];
142 jsonLabelledArgumentProperties[keyword] = type;
143 jsonNumberedArgumentItems.push_back( type );
145 jsonpositionalArguments[
"items"] = jsonNumberedArgumentItems;
146 jsonProperties[
"positionalArguments"] = jsonpositionalArguments;
147 jsonLabelledArguments[
"properties"] = jsonLabelledArgumentProperties;
148 jsonProperties[
"labelledArguments"] = jsonLabelledArguments;
150 if ( !JsonDataType<Result>::type().empty() )
152 jsonProperties[
"returns"] = JsonDataType<Result>::type();
155 jsonMethod[
"properties"] = jsonProperties;
160 void setCallback( Callback callback ) { this->m_callback = callback; }
163 template <
typename ArgType>
164 requires std::same_as<ArgType, void>
165 static ArgType jsonToValue(
const nlohmann::json& jsonData, ObjectFactory* objectFactory )
170 template <
typename ArgType>
171 requires IsSharedPtr<ArgType>
172 static ArgType jsonToValue(
const nlohmann::json& jsonData, ObjectFactory* objectFactory )
174 JsonSerializer serializer( objectFactory );
175 return std::dynamic_pointer_cast<typename ArgType::element_type>(
176 serializer.createObjectFromString( jsonData.dump() ) );
179 template <
typename ArgType>
180 requires( not IsSharedPtr<ArgType> && not std::same_as<ArgType, void> )
181 static ArgType jsonToValue(
const nlohmann::json& jsonData, ObjectFactory* objectFactory )
183 return jsonData.get<ArgType>();
186 template <
typename ReturnType, std::size_t... Is>
187 requires std::same_as<ReturnType, void>
188 nlohmann::json executeJson(
const nlohmann::json& args, std::index_sequence<Is...> )
const
190 this->operator()( jsonToValue<ArgTypes>( args[Is],
nullptr )... );
192 nlohmann::json returnValue = nlohmann::json::object();
196 template <
typename ReturnType, std::size_t... Is>
197 requires( not std::same_as<ReturnType, void> )
198 nlohmann::json executeJson(
const nlohmann::json& args, std::index_sequence<Is...> )
const
200 return this->operator()( jsonToValue<ArgTypes>( args[Is],
nullptr )... );
203 nlohmann::json executeJson(
const nlohmann::json& jsonMethod )
const
205 auto jsonArguments = nlohmann::json::array();
206 if ( jsonMethod.contains(
"positionalArguments" ) )
208 jsonArguments = jsonMethod[
"positionalArguments"];
210 else if ( jsonMethod.contains(
"labelledArguments" ) )
212 jsonArguments = jsonMethod[
"labelledArguments"];
213 sortArguments( jsonArguments, argumentNames() );
215 auto expectedSize = jsonArgumentSchemaArray( std::index_sequence_for<ArgTypes...>() ).size();
216 if ( jsonArguments.size() != expectedSize )
218 throw std::runtime_error(
"Wrong number of arguments! Got " + std::to_string( jsonArguments.size() ) +
219 ", Expected " + std::to_string( expectedSize ) );
221 return this->executeJson<Result>( jsonArguments, std::index_sequence_for<ArgTypes...>() );
224 void sortArguments( nlohmann::json& jsonMap,
const std::vector<std::string>& argumentNames )
const
226 nlohmann::json sortedArray = nlohmann::json::array();
227 for (
const auto& argumentName : argumentNames )
229 auto it = jsonMap.find( argumentName );
230 if ( it != jsonMap.end() )
232 sortedArray.push_back( *it );
237 sortedArray.insert( sortedArray.end(), jsonMap.begin(), jsonMap.end() );
238 jsonMap.swap( sortedArray );
241 template <
typename... T>
242 void argumentHelper( nlohmann::json& jsonArguments,
const T&... argumentTypes )
const
244 const auto& argumentNames = this->argumentNames();
245 constexpr std::size_t n =
sizeof...( argumentTypes );
246 if constexpr ( n > 0 )
252 nlohmann::json jsonArg = nlohmann::json::object();
253 jsonArg[
"keyword"] = argumentNames[i];
254 jsonArg[
"type"] = argumentTypes;
255 jsonArguments.push_back( jsonArg );
262 template <std::size_t... Is>
263 nlohmann::json jsonArgumentSchemaArray( std::index_sequence<Is...> )
const
265 auto jsonArguments = nlohmann::json::array();
266 argumentHelper( jsonArguments, JsonDataType<ArgTypes>::type()... );
267 return jsonArguments;
Definition: cafMethodHandle.h:56
std::string execute(const std::string &jsonArgumentsString) const override
Definition: cafMethod.h:70
Main Caffa namespace.
Definition: __init__.py:1