///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2019- Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ////////////////////////////////////////////////////////////////////////////////// #include "RiaGrpcCommandService.h" #include "RiaGrpcCallbacks.h" #include "RicfSetTimeStep.h" #include "cafAssert.h" #include "cafPdmDefaultObjectFactory.h" #include "cafPdmDataValueField.h" #include "cafPdmValueField.h" #include using namespace rips; using namespace google::protobuf; // Windows may define GetMessage as a Macro and this is in direct conflict with the gRPC GetMessage calls. #ifdef WIN32 #ifdef GetMessage #undef GetMessage #endif #endif //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- grpc::Status RiaGrpcCommandService::Execute(grpc::ServerContext* context, const CommandParams* request, CommandReply* reply) { auto requestDescriptor = request->GetDescriptor(); CommandParams::ParamsCase paramsCase = request->params_case(); if (paramsCase != CommandParams::PARAMS_NOT_SET) { auto grpcOneOfMessage = requestDescriptor->FindFieldByNumber((int)paramsCase); CAF_ASSERT(grpcOneOfMessage->type() == FieldDescriptor::TYPE_MESSAGE); const Message& params = request->GetReflection()->GetMessage(*request, grpcOneOfMessage); QString grpcOneOfMessageName = QString::fromStdString(grpcOneOfMessage->name()); auto pdmObjectHandle = caf::PdmDefaultObjectFactory::instance()->create(grpcOneOfMessageName); auto commandHandle = dynamic_cast(pdmObjectHandle); if (commandHandle) { auto subMessageDescriptor = grpcOneOfMessage->message_type(); int numParameters = subMessageDescriptor->field_count(); for (int i = 0; i < numParameters; ++i) { auto parameter = subMessageDescriptor->field(i); if (parameter) { QString parameterName = QString::fromStdString(parameter->name()); auto pdmValueFieldHandle = dynamic_cast(pdmObjectHandle->findField(parameterName)); if (pdmValueFieldHandle) { assignPdmFieldValue(pdmValueFieldHandle, params, parameter); } } } RicfCommandResponse response = commandHandle->execute(); if (response.status() == RicfCommandResponse::COMMAND_ERROR) { return grpc::Status(grpc::FAILED_PRECONDITION, response.message().toStdString()); } else if (response.status() == RicfCommandResponse::COMMAND_WARNING) { context->AddInitialMetadata("warning", response.message().toStdString()); } assignResultToReply(response.result(), reply); return Status::OK; } } return grpc::Status(grpc::NOT_FOUND, "Command not found"); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RiaGrpcCommandService::createCallbacks() { typedef RiaGrpcCommandService Self; return {new RiaGrpcUnaryCallback(this, &Self::Execute, &Self::RequestExecute)}; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template caf::PdmField* RiaGrpcCommandService::dataValueField(caf::PdmValueField* valueField) { caf::PdmField* dataValField = dynamic_cast*>(valueField); CAF_ASSERT(dataValField); return dataValField; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template const caf::PdmField* RiaGrpcCommandService::constDataValueField(const caf::PdmValueField* valueField) { const caf::PdmField* dataValField = dynamic_cast*>(valueField); CAF_ASSERT(dataValField); return dataValField; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiaGrpcCommandService::assignPdmFieldValue(caf::PdmValueField* pdmValueField, const Message& params, const FieldDescriptor* paramDescriptor) { FieldDescriptor::Type fieldDataType = paramDescriptor->type(); const Reflection* reflection = params.GetReflection(); switch (fieldDataType) { case FieldDescriptor::TYPE_BOOL: { auto value = reflection->GetBool(params, paramDescriptor); auto dataField = dataValueField(pdmValueField); dataField->setValue(value); break; } case FieldDescriptor::TYPE_INT32: { if (paramDescriptor->is_repeated()) { RepeatedFieldRef repeatedField = reflection->GetRepeatedFieldRef(params, paramDescriptor); auto dataField = dataValueField>(pdmValueField); dataField->setValue(std::vector(repeatedField.begin(), repeatedField.end())); } else { int value = reflection->GetInt32(params, paramDescriptor); auto dataField = dataValueField(pdmValueField); dataField->setValue(value); } break; } case FieldDescriptor::TYPE_UINT32: { uint value = reflection->GetUInt32(params, paramDescriptor); auto dataField = dataValueField(pdmValueField); dataField->setValue(value); break; } case FieldDescriptor::TYPE_STRING: { if (paramDescriptor->is_repeated()) { RepeatedFieldRef repeatedField = reflection->GetRepeatedFieldRef(params, paramDescriptor); std::vector stringVector; for (const std::string& string : repeatedField) { stringVector.push_back(QString::fromStdString(string)); } auto dataField = dataValueField>(pdmValueField); dataField->setValue(stringVector); } else { auto value = QString::fromStdString(reflection->GetString(params, paramDescriptor)); auto dataField = dataValueField(pdmValueField); dataField->setValue(value); } break; } case FieldDescriptor::TYPE_FLOAT: { auto value = reflection->GetFloat(params, paramDescriptor); auto dataField = dataValueField(pdmValueField); dataField->setValue(value); break; } case FieldDescriptor::TYPE_DOUBLE: { auto value = reflection->GetDouble(params, paramDescriptor); auto dataField = dataValueField(pdmValueField); dataField->setValue(value); break; } case FieldDescriptor::TYPE_ENUM: { auto value = reflection->GetEnumValue(params, paramDescriptor); pdmValueField->setFromQVariant(QVariant(value)); break; } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiaGrpcCommandService::assignGrpcFieldValue(google::protobuf::Message* reply, const google::protobuf::FieldDescriptor* fieldDescriptor, const caf::PdmValueField* pdmValueField) { FieldDescriptor::Type fieldDataType = fieldDescriptor->type(); QVariant qValue = pdmValueField->toQVariant(); auto reflection = reply->GetReflection(); switch (fieldDataType) { case FieldDescriptor::TYPE_BOOL: { reflection->SetBool(reply, fieldDescriptor, qValue.toBool()); break; } case FieldDescriptor::TYPE_INT32: { reflection->SetInt32(reply, fieldDescriptor, qValue.toInt()); break; } case FieldDescriptor::TYPE_UINT32: { reflection->SetUInt32(reply, fieldDescriptor, qValue.toUInt()); break; } case FieldDescriptor::TYPE_INT64: { reflection->SetInt64(reply, fieldDescriptor, qValue.toLongLong()); break; } case FieldDescriptor::TYPE_UINT64: { reflection->SetUInt64(reply, fieldDescriptor, qValue.toULongLong()); break; } case FieldDescriptor::TYPE_STRING: { reflection->SetString(reply, fieldDescriptor, qValue.toString().toStdString()); break; } case FieldDescriptor::TYPE_FLOAT: { reflection->SetFloat(reply, fieldDescriptor, qValue.toFloat()); break; } case FieldDescriptor::TYPE_DOUBLE: { reflection->SetDouble(reply, fieldDescriptor, qValue.toDouble()); break; } case FieldDescriptor::TYPE_ENUM: { reflection->SetEnumValue(reply, fieldDescriptor, qValue.toInt()); break; } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiaGrpcCommandService::assignResultToReply(const caf::PdmObject* result, CommandReply* reply) { if (!result) { reply->set_allocated_emptyresult(new Empty); return; } QString resultType = result->classKeyword(); auto replyDescriptor = reply->GetDescriptor(); auto oneofDescriptor = replyDescriptor->FindOneofByName("result"); const FieldDescriptor* matchingOneOf = nullptr; for (int fieldIndex = 0; fieldIndex < oneofDescriptor->field_count(); ++fieldIndex) { auto fieldDescriptor = oneofDescriptor->field(fieldIndex); if (fieldDescriptor->name() == resultType.toStdString()) { matchingOneOf = fieldDescriptor; break; } } CAF_ASSERT(matchingOneOf); Message* message = reply->GetReflection()->MutableMessage(reply, matchingOneOf); CAF_ASSERT(message); auto resultDescriptor = message->GetDescriptor(); for (int fieldIndex = 0; fieldIndex < resultDescriptor->field_count(); ++fieldIndex) { auto fieldDescriptor = resultDescriptor->field(fieldIndex); const auto pdmField = dynamic_cast(result->findField(QString::fromStdString(fieldDescriptor->name()))); assignGrpcFieldValue(message, fieldDescriptor, pdmField); } } static bool RiaGrpcCommandService_init = RiaGrpcServiceFactory::instance()->registerCreator(typeid(RiaGrpcCommandService).hash_code());