22 #include "cafAssert.h" 23 #include "cafJsonDataType.h" 24 #include "cafJsonSerializer.h" 25 #include "cafLogger.h" 26 #include "cafMethodHandle.h" 27 #include "cafObjectFactory.h" 28 #include "cafObjectJsonConversion.h" 29 #include "cafSession.h" 31 #include <nlohmann/json.hpp> 39 template <
class CallbackT>
43 std::function<CallbackT> m_callback;
46 template <
typename Result,
typename... ArgTypes>
50 using Callback = std::function<Result( ArgTypes... )>;
51 using CallbackWithSession = std::function<Result( std::shared_ptr<Session>, ArgTypes... )>;
53 Result operator()( std::shared_ptr<Session> session, ArgTypes... args )
const 55 if ( !m_callbackWithSession )
57 return this->operator()( args... );
60 CAFFA_ASSERT( m_callbackWithSession );
61 CAFFA_ASSERT( !this->accessor() );
62 return m_callbackWithSession( session, args... );
65 Result operator()( ArgTypes... args )
const 67 if (
auto accessor = this->accessor(); accessor )
69 auto serializedMethod = toJson( args... ).dump();
70 CAFFA_DEBUG(
"Serialized method: " << serializedMethod );
71 auto serialisedResult = accessor->execute( serializedMethod );
72 CAFFA_DEBUG(
"Got serialized result: " << serialisedResult );
73 return resultFromJsonString( serialisedResult, accessor->objectFactory() );
75 CAFFA_ASSERT( m_callback );
76 return m_callback( args... );
84 std::string
execute( std::shared_ptr<Session> session,
const std::string& jsonArgumentsString )
const override 86 return executeJson( session, nlohmann::json::parse( jsonArgumentsString ) ).dump();
89 std::string schema()
const override {
return this->jsonSchema().dump(); }
91 Result resultFromJsonString(
const std::string& jsonResultString,
ObjectFactory* objectFactory )
const 93 nlohmann::json jsonResult;
94 if ( !jsonResultString.empty() )
96 jsonResult = nlohmann::json::parse( jsonResultString );
98 return jsonToValue<Result>( jsonResult, objectFactory );
101 nlohmann::json toJson( ArgTypes... args )
const 103 auto jsonMethod = nlohmann::json::object();
104 CAFFA_ASSERT( !keyword().empty() );
106 constexpr std::size_t n =
sizeof...( args );
107 if constexpr ( n > 0 )
109 auto jsonArguments = nlohmann::json::array();
115 [&i, &args, &jsonArguments]
117 jsonArguments.push_back( args );
121 jsonMethod[
"positionalArguments"] = jsonArguments;
126 nlohmann::json jsonSchema()
const 128 auto jsonMethod = nlohmann::json::object();
129 CAFFA_ASSERT( !keyword().empty() );
130 jsonMethod[
"type"] =
"object";
131 if ( !this->documentation().empty() )
133 jsonMethod[
"description"] = this->documentation();
135 auto jsonProperties = nlohmann::json::object();
136 auto jsonArgumentItems = jsonArgumentSchemaArray( std::index_sequence_for<ArgTypes...>() );
138 if ( !jsonArgumentItems.empty() )
140 auto jsonpositionalArguments = nlohmann::json::object();
141 jsonpositionalArguments[
"type"] =
"array";
142 jsonpositionalArguments[
"minItems"] = jsonArgumentItems.size();
143 jsonpositionalArguments[
"maxItems"] = jsonArgumentItems.size();
145 auto jsonNumberedArgumentItems = nlohmann::json::array();
146 auto jsonLabelledArguments = nlohmann::json::object();
147 jsonLabelledArguments[
"type"] =
"object";
148 auto jsonLabelledArgumentProperties = nlohmann::json::object();
149 for (
const nlohmann::json& argument : jsonArgumentItems )
151 CAFFA_ASSERT( argument.is_object() );
152 auto keyword = argument[
"keyword"].get<std::string>();
153 auto type = argument[
"type"];
154 jsonLabelledArgumentProperties[keyword] = type;
155 jsonNumberedArgumentItems.push_back( type );
157 jsonpositionalArguments[
"items"] = jsonNumberedArgumentItems;
158 jsonProperties[
"positionalArguments"] = jsonpositionalArguments;
159 jsonLabelledArguments[
"properties"] = jsonLabelledArgumentProperties;
160 jsonProperties[
"labelledArguments"] = jsonLabelledArguments;
167 jsonMethod[
"properties"] = jsonProperties;
172 void setCallback( Callback callback ) { this->m_callback = callback; }
173 void setCallbackWithSession( CallbackWithSession callback ) { this->m_callbackWithSession = callback; }
176 template <
typename ArgType>
177 requires std::same_as<ArgType, void>
178 static ArgType jsonToValue(
const nlohmann::json& jsonData,
ObjectFactory* objectFactory )
183 template <
typename ArgType>
184 requires IsSharedPtr<ArgType>
185 static ArgType jsonToValue(
const nlohmann::json& jsonData,
ObjectFactory* objectFactory )
188 return std::dynamic_pointer_cast<
typename ArgType::element_type>(
192 template <
typename ArgType>
193 requires( not IsSharedPtr<ArgType> && not std::same_as<ArgType, void> )
194 static ArgType jsonToValue(
const nlohmann::json& jsonData,
ObjectFactory* objectFactory )
196 return jsonData.get<ArgType>();
199 template <
typename ReturnType, std::size_t... Is>
200 requires std::same_as<ReturnType, void>
201 nlohmann::json executeJson( std::shared_ptr<Session> session,
const nlohmann::json& args, std::index_sequence<Is...> )
const 203 this->operator()( session, jsonToValue<ArgTypes>( args[Is],
nullptr )... );
205 nlohmann::json returnValue = nlohmann::json::object();
209 template <
typename ReturnType, std::size_t... Is>
210 requires( not std::same_as<ReturnType, void> )
211 nlohmann::json executeJson( std::shared_ptr<Session> session,
const nlohmann::json& args, std::index_sequence<Is...> )
const 213 return this->operator()( session, jsonToValue<ArgTypes>( args[Is],
nullptr )... );
216 nlohmann::json executeJson( std::shared_ptr<Session> session,
const nlohmann::json& jsonMethod )
const 218 auto jsonArguments = nlohmann::json::array();
219 if ( jsonMethod.contains(
"positionalArguments" ) )
221 jsonArguments = jsonMethod[
"positionalArguments"];
223 else if ( jsonMethod.contains(
"labelledArguments" ) )
225 jsonArguments = jsonMethod[
"labelledArguments"];
226 sortArguments( jsonArguments, argumentNames() );
228 auto expectedSize = jsonArgumentSchemaArray( std::index_sequence_for<ArgTypes...>() ).size();
229 if ( jsonArguments.size() != expectedSize )
231 throw std::runtime_error(
"Wrong number of arguments! Got " + std::to_string( jsonArguments.size() ) +
232 ", Expected " + std::to_string( expectedSize ) );
234 return this->executeJson<Result>( session, jsonArguments, std::index_sequence_for<ArgTypes...>() );
237 void sortArguments( nlohmann::json& jsonMap,
const std::vector<std::string>& argumentNames )
const 239 nlohmann::json sortedArray = nlohmann::json::array();
240 for (
const auto& argumentName : argumentNames )
242 auto it = jsonMap.find( argumentName );
243 if ( it != jsonMap.end() )
245 sortedArray.push_back( *it );
250 sortedArray.insert( sortedArray.end(), jsonMap.begin(), jsonMap.end() );
251 jsonMap.swap( sortedArray );
254 template <
typename... T>
255 void argumentHelper( nlohmann::json& jsonArguments,
const T&... argumentTypes )
const 257 const auto& argumentNames = this->argumentNames();
258 constexpr std::size_t n =
sizeof...( argumentTypes );
259 if constexpr ( n > 0 )
265 nlohmann::json jsonArg = nlohmann::json::object();
266 if ( i < argumentNames.size() )
268 jsonArg[
"keyword"] = argumentNames[i];
270 jsonArg[
"type"] = argumentTypes;
271 jsonArguments.push_back( jsonArg );
278 template <std::size_t... Is>
279 nlohmann::json jsonArgumentSchemaArray( std::index_sequence<Is...> )
const 281 auto jsonArguments = nlohmann::json::array();
283 return jsonArguments;
288 CallbackWithSession m_callbackWithSession;
Definition: cafMethod.h:40
Definition: cafMethodHandle.h:52
Definition: cafObjectFactory.h:36
Definition: cafJsonDataType.h:55
std::string execute(std::shared_ptr< Session > session, const std::string &jsonArgumentsString) const override
Definition: cafMethod.h:84
Definition: cafJsonSerializer.h:38
std::shared_ptr< ObjectHandle > createObjectFromString(const std::string &string) const
Definition: cafJsonSerializer.cpp:391
Main Caffa namespace.
Definition: cafApplication.h:30