From 8678cf27b96d40f33463d616efad98e06f99355e Mon Sep 17 00:00:00 2001 From: Will Barnett Date: Tue, 12 Mar 2024 09:22:28 +0000 Subject: [PATCH] Moved tool functions and conversion function invocation to ToolsManager and FunctionRegistry as part of mdenet/educationplatform#40 --- platform/src/FunctionRegistry.js | 74 +++++++- platform/src/Playground.js | 316 +------------------------------ platform/src/ToolsManager.js | 276 +++++++++++++++++++++++---- 3 files changed, 317 insertions(+), 349 deletions(-) diff --git a/platform/src/FunctionRegistry.js b/platform/src/FunctionRegistry.js index b8867b4..262fe36 100644 --- a/platform/src/FunctionRegistry.js +++ b/platform/src/FunctionRegistry.js @@ -1,8 +1,16 @@ -import {arrayEquals} from "./Utility.js" +import {arrayEquals, jsonRequestConversion, jsonRequest} from "./Utility.js" class FunctionRegistry { register = []; +toolsManager; + + /** + * @param {ToolsManager} theToolsManager - the tools manager + */ + constructor(theToolsManager){ + this.toolsManager = theToolsManager; + } registerFunction( inputParameterTypes, outputParameterType, functionId ){ @@ -14,7 +22,7 @@ register = []; this.register.push( entry ); } - lookupFunction(inputParameterTypes, outputParameterType){ + find(inputParameterTypes, outputParameterType){ let foundEntry; @@ -33,7 +41,7 @@ register = []; } - lookupFunctionsPartialMatch(inputParameterTypes, outputParameterType){ + findPartial(inputParameterTypes, outputParameterType){ let foundEntries; @@ -51,6 +59,66 @@ register = []; } } + /** + * Resolves the id of an action function to the function itself + * + * @param {string} functionId + */ + resolve(functionId){ + return this.toolsManager.getActionFunction(functionId) + } + + /** + * Requests the conversion function from the remote tool service + * + * @param {Object} parameters + * @param {ActionFunction} converstionFunction + * @param {String} parameterName name of the parameter + * @returns Promise for the translated data + */ + requestTranslation(parameters, conversionFunction, parameterName){ + + let parametersJson = JSON.stringify(parameters); + + return jsonRequestConversion(conversionFunction.getPath(), parametersJson, parameterName); + } + + /** + * + * @param {string} functionId url of the function to call + * @param {Object} parameters object containing the parameters request data + * @returns + */ + call(functionId, parameters ){ + + let actionFunction = this.toolsManager.getActionFunction(functionId); + let parametersJson = JSON.stringify(parameters); + + let requestPromise = jsonRequest(actionFunction.getPath(), parametersJson) + + return requestPromise; + } + + /** + * Prepares the input parameters and requests the type translation for the given function id + * + * @param {string} functionId the id of the action function + * @param {Object} typeValuesMap an object mapping action functions paramter types as keys to input values + * @param {string} parameterName name of the parameter + * @returns Promise for the translated data + * + */ + callConversion( functionId, typeValuesMap, parameterName ){ + let conversionRequestData = {}; + let conversionFunction = this.toolsManager.getActionFunction(functionId); + + // Populate parameters for the conversion request + for( const param of conversionFunction.getParameters() ){ + conversionRequestData[param.name] = typeValuesMap[param.type]; + } + + return this.requestTranslation(conversionRequestData, conversionFunction, parameterName); + } } export { FunctionRegistry }; \ No newline at end of file diff --git a/platform/src/Playground.js b/platform/src/Playground.js index 0cb8714..2ed0870 100644 --- a/platform/src/Playground.js +++ b/platform/src/Playground.js @@ -33,7 +33,7 @@ import { Button } from './Button.js'; import { Preloader } from './Preloader.js'; import { Layout } from './Layout.js'; import { PlaygroundUtility } from './PlaygroundUtility.js'; -import { jsonRequest, jsonRequestConversion, ARRAY_ANY_ELEMENT, urlParamPrivateRepo } from './Utility.js'; +import { jsonRequest, urlParamPrivateRepo } from './Utility.js'; const TOKEN_HANDLER_URL = TOKEN_SERVER_URL || "http://127.0.0.1:10000"; const COMMON_UTILITY_URL = window.location.href.replace(window.location.search,"") + "common/utility.json"; @@ -138,7 +138,7 @@ function initializeActivity(){ if (errors.length==0){ // An activity configuration has been provided - toolsManager = new ToolsManager(); + toolsManager = new ToolsManager(errorNotification); activityManager = new ActivityManager( (toolsManager.getPanelDefinition).bind(toolsManager), fileHandler ); activityManager.initializeActivities(); errors = errors.concat(activityManager.getConfigErrors()); @@ -406,316 +406,6 @@ function getPanelTitle(panelId) { return $("#" + panelId)[0].dataset.titleCaption; } -/** - * Invokes an action function by placing requests to all the required external tool functions - * - * TODO: To be moved to the ToolManager issue #40 - * - * @param {string} functionId the id of tool function - * @param {Map} parameterMap map from parameter name to its value and type - * @returns {Promise} promise to result of the action function - */ -function invokeActionFunction(functionId, parameterMap){ - - let actionFunction = toolsManager.functionRegistry_resolve(functionId); - - let parameterPromises = []; - - for ( const paramName of parameterMap.keys() ){ /* TODO add defensive checks that every required value - is provided issue #57 */ - - let actionFunctionParam = actionFunction.getParameters().find( p => p.name === paramName); - - /* Check the given parameter types against the those of the requested action function. - If required, request conversion from available tool functions */ - let givenParameter = parameterMap.get(paramName); - - if (givenParameter.type != actionFunctionParam.type){ - //Types don't match so try and convert - let convertedValue; - - const metamodelId = actionFunction.getInstanceOfParamName(paramName); - - if(metamodelId==null){ - // Convert with no metamodel to consider - convertedValue = convert( givenParameter.value, givenParameter.type, - actionFunctionParam.type, paramName ); // TODO issue #58 remove paramName - - } else { - // Convert considering metamodel - const givenMetamodel = parameterMap.get(metamodelId); - - convertedValue = convertIncludingMetamodel( givenParameter.value , givenParameter.type, - givenMetamodel.value, givenMetamodel.type, - actionFunctionParam.type, paramName ); // TODO issue #58 remove paramName - } - - parameterPromises.push(convertedValue); - - } else { - // Matching types add values to promise for synchronisation - let value = new Promise( function (resolve) { - let parameterData = {}; - - parameterData.name = paramName; - parameterData.data = givenParameter.value; - - resolve(parameterData); - }); - - parameterPromises.push(value); - } - } - - // Invoke the actionFunction on compeletion of any conversions - let actionFunctionPromise = new Promise(function (resolve, reject) { - - Promise.all( parameterPromises ).then( (values) => { - let actionRequestData = {}; - - //Populate the transformed parameters - for ( const param of actionFunction.getParameters() ){ - - const panelConfig = parameterMap.get(param.name); - - if (panelConfig == undefined){ - // Set unused parameters in the request to undefined as the epsilon backend function expects them all. - actionRequestData[param.name] = "undefined"; - - } else { - let parameterData = values.find(val => (val.name === param.name) ); - - actionRequestData[param.name] = parameterData.data; - } - } - - let resultPromise = functionRegistry_call(functionId, actionRequestData); - - resolve(resultPromise); - - }).catch( (err) => { - - reject(err); - }); - - }); - - return actionFunctionPromise; -} - - - -/** - * Converts a source value to a target type using the available conversion functions - * - * TODO: To be moved to the ToolManager issue #40 - * - * @param {string} sourceValue - * @param {string} sourceType - * @param {string} targetType - * @param {string} parameterName name of the parameter for request - * @returns {Promise} promise for the converted paramter value - */ -function convert(sourceValue, sourceType, targetType, parameterName){ - - let parameterPromise; - let typesPanelValuesMap = {}; // Types have to be distinct for mapping to the conversion function's paramters - typesPanelValuesMap[sourceType]= sourceValue; - - let conversionFunctionId = functionRegistry_find( Object.keys(typesPanelValuesMap), targetType ); - - if (conversionFunctionId != null){ - //There is a matching conversion function - parameterPromise = functionRegistry_callConversion(conversionFunctionId, typesPanelValuesMap, parameterName); - - } else { - parameterPromise = null; - errorNotification("No conversion function available for input types:" + Object.keys(typesPanelValuesMap).toString() ) - } - - return parameterPromise; -} - - -/** - * Converts a source value to a target type using the available conversion functions taking - * into consideration the related metamodel. - * - * TODO: To be moved to the ToolManager issue #40 - * - * @param {string} sourceValue - * @param {string} sourceType - * @param {string} metamodelValue - * @param {string} metamodelType - * @param {string} targetType - * @param {string} parameterName name of the parameter for request - * @returns {Promise} promise for the converted paramter value - */ -async function convertIncludingMetamodel(sourceValue, sourceType, metamodelValue, metamodelType, targetType, parameterName){ - let parameterPromise; - let typesPanelValuesMap = {}; // Types have to be distinct for mapping to the conversion function's paramters - typesPanelValuesMap[sourceType]= sourceValue; - - let conversionFunctionId; - - let potentialConversionFunctions = functionRegistry_findPartial( [sourceType, ARRAY_ANY_ELEMENT], targetType); - - //check for a conversion function with the metamodel type - conversionFunctionId = await selectConversionFunctionConvertMetamodel( metamodelType, metamodelValue, potentialConversionFunctions, - false, parameterName, typesPanelValuesMap) - - if (conversionFunctionId==null){ - //no conversion found so check for a conversion function but consider conversions of the metamodel - conversionFunctionId = await selectConversionFunctionConvertMetamodel(metamodelType, metamodelValue, potentialConversionFunctions, - true, parameterName, typesPanelValuesMap); - } - - if (conversionFunctionId != null){ - //There is a matching conversion function - parameterPromise = functionRegistry_callConversion(conversionFunctionId, typesPanelValuesMap, parameterName); - - } else { - parameterPromise = null; - errorNotification("No conversion function available for input types:" + Object.keys(typesPanelValuesMap).toString() ) - } - - return parameterPromise; -} - - -/** - * For the given list of conversion function ids to check, finds the first conversion function with matching metamodel dependency. - * Optionally conversions of the metamodel are considered from the conversion functions available to the tools manager and - * the metamodel type. If available, the metamodel value is converted to the required type. - * - * @param {string} metamodelType the metamodel type - * @param {string} metamodelValue the metamodel value - * @param {string[]} conversionFunctions list of conversion function ids to check - * @param {boolean} convertMetamodel when true try to convert the metamodel using a remote tool service conversion function - * available to the ToolsManager. - * @param {string} parameterName the name of the parameter to use when convering the metamodel. - * @param {string[]} typeValueMap the type values map the metamodel input value is added to if a conversion function is found - * @returns {string} the id of a conversion function to use, null if none found. - */ -async function selectConversionFunctionConvertMetamodel(metamodelType, metamodelValue, conversionFunctions, convertMetamodel, parameterName, typeValueMap){ - let conversionFunctionId; - let functionsToCheck = [...conversionFunctions] - - while ( conversionFunctionId==null && functionsToCheck.length > 0){ - let functionId = functionsToCheck.pop(); - let conversionFunction = toolsManager.getActionFunction(functionId); - - // Lookup the conversion function's metamodel type - let metamodelName = conversionFunction.getInstanceOfParamName( conversionFunction.getParameters()[0].name ); - - if(metamodelName==null){ - metamodelName = conversionFunction.getInstanceOfParamName( conversionFunction.getParameters()[1].name ); - } - - const targetMetamodelType = conversionFunction.getParameterType(metamodelName); - - if (!convertMetamodel){ - // Check for conversion functions with matching metamodels only - - if (targetMetamodelType==metamodelType) { - //Conversion function found so use the panel value - - conversionFunctionId = functionId; - typeValueMap[metamodelType]= metamodelValue; - } - - } else { - // Check for conversion functions converting metamodel if possible - let metamodelConversionFunctionId = toolsManager.getConversionFunction( [metamodelType], targetMetamodelType ); - - if (metamodelConversionFunctionId != null){ - - conversionFunctionId = functionId; - - //convert metamodel - let metamodelTypeValueMap = {}; - metamodelTypeValueMap[metamodelType]=metamodelValue; // The found conversion function is expected to have one parameter - - let convertedValue = await functionRegistry_callConversion(metamodelConversionFunctionId, metamodelTypeValueMap, parameterName); - - typeValueMap[targetMetamodelType]= convertedValue.data; - } - } - } - - return conversionFunctionId; -} - -/** - * Prepares the input parameters and requests the type translation for the given function id - * - * TODO: To be moved to the FunctionRegistry issue #40 - * - * @param {string} functionId the id of the action function - * @param {Object} typeValuesMap an object mapping action functions paramter types as keys to input values - * @param {string} parameterName name of the parameter - * @returns Promise for the translated data - * - */ -function functionRegistry_callConversion( functionId, typeValuesMap, parameterName ){ - let conversionRequestData = {}; - let conversionFunction = toolsManager.getActionFunction(functionId); - - // Populate parameters for the conversion request - for( const param of conversionFunction.getParameters() ){ - conversionRequestData[param.name] = typeValuesMap[param.type]; - } - - return requestTranslation(conversionRequestData, conversionFunction, parameterName); -} - -/** - * - * @param {string} functionId url of the function to call - * @param {Object} parameters object containing the parameters request data - * @returns - */ -function functionRegistry_call(functionId, parameters ){ - - let actionFunction = toolsManager.getActionFunction(functionId); - let parametersJson = JSON.stringify(parameters); - - let requestPromise = jsonRequest(actionFunction.getPath(), parametersJson) - - return requestPromise; -} - - -/** - * Requests the conversion function from the remote tool service - * - * @param {Object} parameters - * @param {ActionFunction} converstionFunction - * @param {String} parameterName name of the parameter - * @returns Promise for the translated data - */ -function requestTranslation(parameters, conversionFunction, parameterName){ - - let parametersJson = JSON.stringify(parameters); - - return jsonRequestConversion(conversionFunction.getPath(), parametersJson, parameterName); -} - -/** - * TODO: Temporary wrapper called function to be renamed and to be moved to the FunctionRegistry issue #40 - */ -function functionRegistry_find(inputsParamTypes, outputParamType){ - return toolsManager.getConversionFunction( inputsParamTypes, outputParamType ); -} - -/** - * TODO: Temporary wrapper called function to be renamed and to be moved to the FunctionRegistry issue #40 - */ -function functionRegistry_findPartial(inputsParamTypes, outputParamType){ - return toolsManager.getPartiallyMatchingConversionFunctions( inputsParamTypes, outputParamType ); -} - - /** * Handle the response from the remote tool service @@ -882,7 +572,7 @@ function runAction(source, sourceButton) { //actionRequestData.outputLanguage = outputLanguage; // Call backend conversion and service functions - let actionResultPromise = invokeActionFunction(buttonConfig.actionfunction, parameterMap) + let actionResultPromise = toolsManager.invokeActionFunction(buttonConfig.actionfunction, parameterMap) actionResultPromise.catch( () => { errorNotification("There was an error translating action function parameter types."); diff --git a/platform/src/ToolsManager.js b/platform/src/ToolsManager.js index 0ec8792..60657ce 100644 --- a/platform/src/ToolsManager.js +++ b/platform/src/ToolsManager.js @@ -1,21 +1,25 @@ -import { parseConfigFile } from "./Utility.js"; +import { parseConfigFile, ARRAY_ANY_ELEMENT } from "./Utility.js"; import { FunctionRegistry } from "../src/FunctionRegistry.js" import { ActionFunction } from "./ActionFunction.js"; import { ToolConfigValidator } from "./ToolConfigValidator.js"; import { EducationPlatformError } from "./EducationPlatformError.js"; class ToolManager { - toolId; toolsUrls; configErrors = []; configValidator; tools = {}; functionRegister; + errorNotification; - constructor(){ + /** + * @param {function(String)} errorNotifier - the function to call to display an error + */ + constructor(errorNotifier){ this.configValidator= new ToolConfigValidator(); - this.functionRegister= new FunctionRegistry(); + this.functionRegister= new FunctionRegistry(this); + this.errorNotification = errorNotifier; } setToolsUrls(urls){ @@ -40,7 +44,6 @@ class ToolManager { } - /** * Fetches the tools from the tools url and populates tool's * functions and panel definitions. @@ -220,8 +223,6 @@ class ToolManager { } - - /** * Finds the action function for an action function Id * @param {*} actionFuntionId @@ -243,18 +244,6 @@ class ToolManager { } - - /** - * Resolves the id of an action function to the function itself - * - * TODO: To be moved to the FunctionRegistry issue #40 - * - * @param {string} functionId - */ - functionRegistry_resolve(functionId){ - return this.getActionFunction(functionId) - } - hasPanelDefinition(panelDefId){ @@ -310,28 +299,249 @@ class ToolManager { } + /** + * Returns the errors found parsing and validating the tool configuration files + * @returns array of errors + */ + getConfigErrors(){ + return this.configErrors; + } + + /** - * Returns the id of the registered function with matching input and output parameters. - * @param {*} inputsParamTypes - * @param {*} outputParamType - * @returns The id of a matching function + * Invokes an action function by placing requests to all the required external tool functions + * + * @param {string} functionId the id of tool function + * @param {Map} parameterMap map from parameter name to its value and type + * @returns {Promise} promise to result of the action function */ - getConversionFunction(inputsParamTypes, outputParamType){ + invokeActionFunction(functionId, parameterMap){ + + let actionFunction = this.functionRegister.resolve(functionId); + + let parameterPromises = []; + + for ( const paramName of parameterMap.keys() ){ /* TODO add defensive checks that every required value + is provided issue #57 */ + + let actionFunctionParam = actionFunction.getParameters().find( p => p.name === paramName); + + /* Check the given parameter types against the those of the requested action function. + If required, request conversion from available tool functions */ + let givenParameter = parameterMap.get(paramName); + + if (givenParameter.type != actionFunctionParam.type){ + //Types don't match so try and convert + let convertedValue; + + const metamodelId = actionFunction.getInstanceOfParamName(paramName); + + if(metamodelId==null){ + // Convert with no metamodel to consider + convertedValue = this.convert( givenParameter.value, givenParameter.type, + actionFunctionParam.type, paramName ); // TODO issue #58 remove paramName + + } else { + // Convert considering metamodel + const givenMetamodel = parameterMap.get(metamodelId); + + convertedValue = this.convertIncludingMetamodel( givenParameter.value , givenParameter.type, + givenMetamodel.value, givenMetamodel.type, + actionFunctionParam.type, paramName ); // TODO issue #58 remove paramName + } + + parameterPromises.push(convertedValue); + + } else { + // Matching types add values to promise for synchronisation + let value = new Promise( function (resolve) { + let parameterData = {}; + + parameterData.name = paramName; + parameterData.data = givenParameter.value; - return this.functionRegister.lookupFunction(inputsParamTypes, outputParamType); + resolve(parameterData); + }); + + parameterPromises.push(value); + } + } + + // Invoke the actionFunction on compeletion of any conversions + let actionFunctionPromise = new Promise((resolve, reject) => { + + Promise.all( parameterPromises ).then( (values) => { + let actionRequestData = {}; + + //Populate the transformed parameters + for ( const param of actionFunction.getParameters() ){ + + const panelConfig = parameterMap.get(param.name); + + if (panelConfig == undefined){ + // Set unused parameters in the request to undefined as the epsilon backend function expects them all. + actionRequestData[param.name] = "undefined"; + + } else { + let parameterData = values.find(val => (val.name === param.name) ); + + actionRequestData[param.name] = parameterData.data; + } + } + + let resultPromise = this.functionRegister.call(functionId, actionRequestData); + + resolve(resultPromise); + + }).catch( (err) => { + + reject(err); + }); + + }); + + return actionFunctionPromise; } - getPartiallyMatchingConversionFunctions(inputsParamTypes, outputParamType){ + /** + * Converts a source value to a target type using the available conversion functions + * + * @param {string} sourceValue + * @param {string} sourceType + * @param {string} targetType + * @param {string} parameterName name of the parameter for request + * @returns {Promise} promise for the converted paramter value + */ + convert(sourceValue, sourceType, targetType, parameterName){ - return this.functionRegister.lookupFunctionsPartialMatch(inputsParamTypes, outputParamType); - } + let parameterPromise; + let typesPanelValuesMap = {}; // Types have to be distinct for mapping to the conversion function's paramters + typesPanelValuesMap[sourceType]= sourceValue; - /** - * Returns the errors found parsing and validating the tool configuration files - * @returns array of errors + let conversionFunctionId = this.functionRegister.find( Object.keys(typesPanelValuesMap), targetType ); + + if (conversionFunctionId != null){ + //There is a matching conversion function + parameterPromise = this.functionRegister.callConversion(conversionFunctionId, typesPanelValuesMap, parameterName); + + } else { + parameterPromise = null; + + this.errorNotification("No conversion function available for input types:" + Object.keys(typesPanelValuesMap).toString() ) + } + + return parameterPromise; + } + + + /** + * Converts a source value to a target type using the available conversion functions taking + * into consideration the related metamodel. + * + * TODO: To be moved to the ToolManager issue #40 + * + * @param {string} sourceValue + * @param {string} sourceType + * @param {string} metamodelValue + * @param {string} metamodelType + * @param {string} targetType + * @param {string} parameterName name of the parameter for request + * @returns {Promise} promise for the converted paramter value */ - getConfigErrors(){ - return this.configErrors; + async convertIncludingMetamodel(sourceValue, sourceType, metamodelValue, metamodelType, targetType, parameterName){ + let parameterPromise; + let typesPanelValuesMap = {}; // Types have to be distinct for mapping to the conversion function's paramters + typesPanelValuesMap[sourceType]= sourceValue; + + let conversionFunctionId; + + let potentialConversionFunctions = this.functionRegister.findPartial( [sourceType, ARRAY_ANY_ELEMENT], targetType); + + //check for a conversion function with the metamodel type + conversionFunctionId = await this.selectConversionFunctionConvertMetamodel( metamodelType, metamodelValue, potentialConversionFunctions, + false, parameterName, typesPanelValuesMap) + + if (conversionFunctionId==null){ + //no conversion found so check for a conversion function but consider conversions of the metamodel + conversionFunctionId = await this.selectConversionFunctionConvertMetamodel(metamodelType, metamodelValue, potentialConversionFunctions, + true, parameterName, typesPanelValuesMap); + } + + if (conversionFunctionId != null){ + //There is a matching conversion function + parameterPromise = this.functionRegister.callConversion(conversionFunctionId, typesPanelValuesMap, parameterName); + + } else { + parameterPromise = null; + + this.errorNotification("No conversion function available for input types:" + Object.keys(typesPanelValuesMap).toString() ) + } + + return parameterPromise; + } + + + /** + * For the given list of conversion function ids to check, finds the first conversion function with matching metamodel dependency. + * Optionally conversions of the metamodel are considered from the conversion functions available to the tools manager and + * the metamodel type. If available, the metamodel value is converted to the required type. + * + * @param {string} metamodelType the metamodel type + * @param {string} metamodelValue the metamodel value + * @param {string[]} conversionFunctions list of conversion function ids to check + * @param {boolean} convertMetamodel when true try to convert the metamodel using a remote tool service conversion function + * available to the ToolsManager. + * @param {string} parameterName the name of the parameter to use when convering the metamodel. + * @param {string[]} typeValueMap the type values map the metamodel input value is added to if a conversion function is found + * @returns {string} the id of a conversion function to use, null if none found. + */ + async selectConversionFunctionConvertMetamodel(metamodelType, metamodelValue, conversionFunctions, convertMetamodel, parameterName, typeValueMap){ + let conversionFunctionId; + let functionsToCheck = [...conversionFunctions] + + while ( conversionFunctionId==null && functionsToCheck.length > 0){ + let functionId = functionsToCheck.pop(); + let conversionFunction = this.getActionFunction(functionId); + + // Lookup the conversion function's metamodel type + let metamodelName = conversionFunction.getInstanceOfParamName( conversionFunction.getParameters()[0].name ); + + if(metamodelName==null){ + metamodelName = conversionFunction.getInstanceOfParamName( conversionFunction.getParameters()[1].name ); + } + + const targetMetamodelType = conversionFunction.getParameterType(metamodelName); + + if (!convertMetamodel){ + // Check for conversion functions with matching metamodels only + + if (targetMetamodelType==metamodelType) { + //Conversion function found so use the panel value + + conversionFunctionId = functionId; + typeValueMap[metamodelType]= metamodelValue; + } + + } else { + // Check for conversion functions converting metamodel if possible + let metamodelConversionFunctionId = this.functionRegister.find( [metamodelType], targetMetamodelType ); + + if (metamodelConversionFunctionId != null){ + + conversionFunctionId = functionId; + + //convert metamodel + let metamodelTypeValueMap = {}; + metamodelTypeValueMap[metamodelType]=metamodelValue; // The found conversion function is expected to have one parameter + + let convertedValue = await this.functionRegister.callConversion(metamodelConversionFunctionId, metamodelTypeValueMap, parameterName); + + typeValueMap[targetMetamodelType]= convertedValue.data; + } + } + } + + return conversionFunctionId; } }