///////////////////////////////////////////////////////////////////////////////// // // 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 "RicfReplaceCase.h" #include "RicfSetTimeStep.h" #include "cafAssert.h" #include "cafPdmDataValueField.h" #include "cafPdmDefaultObjectFactory.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 ) { RicfMultiCaseReplace* multiCaseReplaceCommand = dynamic_cast( commandHandle ); if ( multiCaseReplaceCommand ) { CAF_ASSERT( request->has_replacemultiplecases() ); auto replaceMultipleCasesRequest = request->replacemultiplecases(); std::map caseIdFileMap; for ( auto caseGridFilePair : replaceMultipleCasesRequest.casepairs() ) { caseIdFileMap.insert( std::make_pair( caseGridFilePair.caseid(), QString::fromStdString( caseGridFilePair.newgridfile() ) ) ); } multiCaseReplaceCommand->setCaseReplacePairs( caseIdFileMap ); } else { 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(); if ( paramDescriptor->is_repeated() && fieldDataType != FieldDescriptor::TYPE_INT32 && fieldDataType != FieldDescriptor::TYPE_STRING ) { CAF_ASSERT( false && "Only integer and string vectors are implemented as command arguments" ); } 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( Message* reply, const FieldDescriptor* fieldDescriptor, const caf::PdmValueField* pdmValueField ) { if ( fieldDescriptor->is_repeated() ) { CAF_ASSERT( false && "Assigning vector results to Command Results is not yet implemented" ); } 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() );