// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkInvoker.h" #include "vtkLogger.h" #include "vtkObjectFactory.h" #include "vtksys/SystemTools.hxx" // clang-format off #include "vtk_nlohmannjson.h" // for json #include VTK_NLOHMANN_JSON(json.hpp) // for json // clang-format on #include VTK_ABI_NAMESPACE_BEGIN class vtkInvoker::vtkInternals { public: std::unordered_map Handlers; }; //------------------------------------------------------------------------------ vtkStandardNewMacro(vtkInvoker); //------------------------------------------------------------------------------ vtkInvoker::vtkInvoker() : Internals(new vtkInternals()) { } //------------------------------------------------------------------------------ vtkInvoker::~vtkInvoker() = default; //------------------------------------------------------------------------------ void vtkInvoker::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); const auto& internals = (*this->Internals); os << "No. of handlers: " << internals.Handlers.size() << '\n'; for (const auto& item : internals.Handlers) { os << item.first << ": function pointer (" << item.second.target_type().name() << ")\n"; } } //------------------------------------------------------------------------------ nlohmann::json vtkInvoker::Invoke( const vtkTypeUInt32& identifier, const std::string& methodName, const nlohmann::json& args) { if (auto objectBase = this->Context->GetObjectAtId(identifier)) { auto* objectPtr = objectBase.GetPointer(); const auto& typeId = typeid(*objectPtr); if (const auto& f = this->GetHandler(typeId)) { vtkVLog(this->GetInvokerLogVerbosity(), << "Invoke method=\'" << methodName.c_str() << "\', args=\'" << args.dump().c_str() << "\'"); return f(this, objectPtr, methodName.c_str(), args); } else { vtkErrorMacro( << "Cannot invoke method on object with type " "{ .name=" << typeId.name() << " .hashCode=" << typeId.hash_code() << " }" " because a handler was not found. Check stack trace to see how we got here."); } } else { vtkWarningMacro(<< "Cannot invoke method \'" << methodName.c_str() << "\' on an object (id=" << identifier << ") that does not exist"); } return { { "Success", false } }; } //------------------------------------------------------------------------------ void vtkInvoker::RegisterHandler(const std::type_info& type, HandlerType invoker) { auto& internals = (*this->Internals); vtkVLog(this->GetInvokerLogVerbosity(), << "Register invoker at { .name=" << type.name() << " .hashCode=" << type.hash_code() << " }"); internals.Handlers[type.hash_code()] = invoker; } //------------------------------------------------------------------------------ vtkInvoker::HandlerType vtkInvoker::GetHandler(const std::type_info& type) const { const auto& internals = (*this->Internals); auto iter = internals.Handlers.find(type.hash_code()); if (iter != internals.Handlers.end()) { return iter->second; } return nullptr; } //------------------------------------------------------------------------------ bool vtkInvoker::UnRegisterHandler(const std::type_info& type) { return this->Internals->Handlers.erase(type.hash_code()) != 0; } //------------------------------------------------------------------------------ void vtkInvoker::SetInvokerLogVerbosity(vtkLogger::Verbosity verbosity) { this->InvokerLogVerbosity = verbosity; } //------------------------------------------------------------------------------ vtkLogger::Verbosity vtkInvoker::GetInvokerLogVerbosity() { // initialize the log verbosity if it is invalid. if (this->InvokerLogVerbosity == vtkLogger::VERBOSITY_INVALID) { this->InvokerLogVerbosity = vtkLogger::VERBOSITY_TRACE; // Find an environment variable that specifies logger verbosity const char* verbosityKey = "VTK_INVOKER_LOG_VERBOSITY"; if (vtksys::SystemTools::HasEnv(verbosityKey)) { const char* verbosityCStr = vtksys::SystemTools::GetEnv(verbosityKey); const auto verbosity = vtkLogger::ConvertToVerbosity(verbosityCStr); if (verbosity > vtkLogger::VERBOSITY_INVALID) { this->InvokerLogVerbosity = verbosity; } } } return this->InvokerLogVerbosity; } VTK_ABI_NAMESPACE_END