| /////////////////////////////////////////////////////////////////////////////// |
| // // |
| // Copyright (c) 2000-2019 Ericsson Telecom AB // |
| // // |
| // All rights reserved. This program and the accompanying materials // |
| // are made available under the terms of the Eclipse Public License v2.0 // |
| // which accompanies this distribution, and is available at // |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////// |
| // Module: EPTF_CLL_DataSource_Functions |
| // |
| // Purpose: |
| // This module contains the implementation of EPTF_CLL_DataSource functions. |
| // |
| // Module depends on: |
| // <EPTF_CLL_Base_Functions> |
| // <EPTF_CLL_Common_Functions> |
| // <EPTF_CLL_Common_Definitions> |
| // <EPTF_CLL_Variable_Functions> |
| // <EPTF_CLL_Variable_Definitions> |
| // <EPTF_CLL_DataSource_Definitions> |
| // <EPTF_CLL_Semaphore_Functions> |
| // <EPTF_CLL_HashMapStr2Int_Functions> |
| // <EPTF_CLL_HashMap_Functions> |
| // |
| // Module Parameters: |
| // tsp_EPTF_DataSource_maxWaitTime - float - max wait time for response (dafault:10.0) |
| // |
| // Current Owner: |
| // Jozsef Gyurusi (ethjgi) |
| // |
| // Last Review Date: |
| // 2011-02-03 |
| // |
| // Detailed Comments: |
| // This module contains the interface functions for the EPTF_CLL_DataSource. |
| // The DataSource feature makes it possible to access application data |
| // remotely using "feature name", "ptc name" as the dataSource ID and |
| // "data element" and "parameters" to get the data for a given data type. |
| // The data value is a variable name that contains the value of the data. |
| // The variable is created locally in the background with the given refresh rate. |
| // An example: |
| // ExecCtrl registers itself as a dataSource with "ExecCtrl" as the feature name |
| // and "MyExecCtrl" as ptc name. Its handler function can provide data for example |
| // for the Scenarios in a given entity group. This means that the <f_EPTF_DataSource_getData> |
| // function will return a variable name that contains this list of scenarios. The dataElement |
| // parameter in this case is "ScenariosOfEGrp" and the parameter can be "EG1" to get the scenario list |
| // for this entity group. The handler function registered in ExecCtrl has to be able to |
| // process the "ScenariosOfEGrp" dataelement with the "EG1" as parameter. |
| // |
| // Public functions: |
| // <f_EPTF_DataSource_init_CT> |
| // <f_EPTF_DataSource_getData> |
| // <f_EPTF_DataSource_getDataValue> |
| // <f_EPTF_DataSource_getDataValue_nonblocking> |
| // <f_EPTF_DataSource_setDataValue> |
| // <f_EPTF_DataSource_setDataValue_nonblocking> |
| // <f_EPTF_DataSource_getData_nonBlocking> |
| // <f_EPTF_DataSource_checkData> |
| // <f_EPTF_DataSource_checkData_nonblocking> |
| // <f_EPTF_DataSource_checkDataValue_nonblocking> |
| // <f_EPTF_DataSource_enableUpdate> |
| // <f_EPTF_DataSource_disableUpdate> |
| // <f_EPTF_DataSource_getRequestPartsFromParams> |
| // <f_EPTF_DataSource_getSizeOfDataValue> |
| // <f_EPTF_DataSource_getHelpTEXT> |
| // <f_EPTF_DataSource_getHelpJSON> |
| // <f_EPTF_DataSource_getHelpApidoc> |
| // <f_EPTF_DataSource_handleHelp> |
| // <f_EPTF_DataSource_getCondition> |
| // <f_EPTF_DataSource_getCondition_nonBlocking> |
| // <f_EPTF_DataSource_registerReadyCallback> |
| // <f_EPTF_DataSource_getParams> |
| // <f_EPTF_DataSource_extractParams> |
| // <f_EPTF_DataSource_replaceParams> |
| // |
| // DataSource with CLI: |
| // <f_EPTF_DataSource_CLI_init_CT> |
| // |
| // All other functions in this module are private! |
| // |
| /////////////////////////////////////////////////////////////// |
| |
| module EPTF_CLL_DataSource_Functions { |
| |
| import from EPTF_CLL_Base_Functions all; |
| //import from EPTF_CLL_Common_Functions all; |
| import from EPTF_CLL_Common_Definitions all; |
| import from EPTF_CLL_Variable_Functions all; |
| import from EPTF_CLL_Variable_Definitions all; |
| import from EPTF_CLL_DataSource_Definitions all; |
| import from EPTF_CLL_Semaphore_Functions all; |
| import from EPTF_CLL_HashMapStr2Int_Functions all; |
| import from EPTF_CLL_Logging_Functions all; |
| import from EPTF_CLL_HashMap_Functions all; |
| import from EPTF_CLL_Logging_Definitions all; |
| import from EPTF_CLL_CLI_Definitions all; |
| import from EPTF_CLL_CLI_Functions all; |
| import from ttcn_ericsson_se_protocolModules_xtdp_xtdl all; |
| |
| friend module EPTF_CLL_DataSourceClient_Functions; |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_init_CT |
| // |
| // Purpose: |
| // Init function for DataSource_CT |
| // |
| // Parameters: |
| // *in charstring pl_selfName* - the name of the component |
| // |
| // Return Value: |
| // - |
| // |
| // Detailed Comments: |
| // Has to be called before any other DataSource |
| // function is used |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_init_CT(in charstring pl_selfName) runs on EPTF_DataSource_CT { |
| if (v_EPTF_DataSource_initialized) { |
| return; |
| } |
| f_EPTF_Base_init_CT(pl_selfName); |
| f_EPTF_Var_init_CT(pl_selfName); |
| f_EPTF_Semaphore_init_CT(pl_selfName); |
| f_EPTF_HashMap_init_CT(pl_selfName); |
| |
| v_DataSource_handler := activate(as_EPTF_DataSource_EventHandler()); |
| v_EPTF_DataSource_initialized := true; |
| f_EPTF_Base_registerCleanup(refers(f_EPTF_DataSource_cleanup_CT)); |
| |
| v_EPTF_DataSource_DataHandler_List := {}; |
| v_EPTF_DataSource_DataHandlerHash := f_EPTF_str2int_HashMap_New(c_EPTF_DataSource_dataHandlerHashName); |
| v_EPTF_DataSource_DataHandlerHash_NoPTCName := f_EPTF_str2int_HashMap_New(c_EPTF_DataSource_dataHandlerHashName_NoPTCName); |
| v_EPTF_DataSource_dataValue_List := {}; |
| v_EPTF_DataSource_dataValueHash := f_EPTF_str2int_HashMap_New(c_EPTF_DataSource_dataValueHashName); |
| v_EPTF_DataSource_pendingGetDataHash := f_EPTF_str2int_HashMap_New(c_EPTF_DataSource_pendingGetDataHashName); |
| |
| // create the iterator variable for c_EPTF_DataSource_dataElement_Sources, initial value: my source name (I am also a dataSource): |
| var integer vl_varIdx; |
| f_EPTF_Var_newCharstringlist(c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_Sources, {c_EPTF_DataSource_sourceId}, vl_varIdx); |
| // create the PTCs variable for DataSource itself: |
| var charstring pl_dataVarName := c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_PTCs&"."&c_EPTF_DataSource_sourceId; |
| f_EPTF_Var_newCharstringlist(pl_dataVarName, {f_EPTF_Base_selfName()}, vl_varIdx); |
| |
| |
| v_EPTF_DataSource_Msg_List := {}; |
| v_EPTF_DataSource_GetDataHandler_DB := {}; |
| v_EPTF_DataSource_GetDataValueHandler_DB := {}; |
| |
| v_EPTF_DataSource_Msg_GetData_Buffer := {}; |
| v_EPTF_DataSource_Msg_GetData_BufferStartIdx := 0; |
| v_EPTF_DataSource_nofPendingGetData := 0; |
| v_EPTF_DataSource_getDataMsgClusters := {}; |
| v_EPTF_DataSource_getDataMsgClusters_BufferEmpty := true; |
| } |
| |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_compare |
| // |
| // Purpose: |
| // Compares two EPTF_DataSource_Param arguments by their paramName. |
| // |
| // Parameters: |
| // *in* <EPTF_DataSource_Param> *pl_par1* - the first parameter to compare |
| // *in* <EPTF_DataSource_Param> *pl_par2* - the second parameter to compare |
| // |
| // Return Value: |
| // integer - The function returns an integer greater than, equal to, or |
| // less than 0, if the string pointed to by pl_par1.paramName is greater |
| // than, equal to, or less than the string pointed to by pl_par2.paramName |
| // respectively. |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // Works similar to strcmp. For more details see its man page (man strcmp). |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| private external function f_EPTF_DataSource_compare(in EPTF_DataSource_Param pl_par1, in EPTF_DataSource_Param pl_par2) return integer; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_bubblesort |
| // |
| // Purpose: |
| // Sorts the argument in increasing order using the bubble-sort algorithm. |
| // |
| // Parameters: |
| // *inout* <EPTF_DataSource_Params> *pl_list* - the list of parameters to sort, |
| // When the function returns it will be sorted by a bubble-sort algorithm. |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // The parameters are sorted by thier paramNames lexically. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_EPTF_DataSource_bubblesort(inout EPTF_DataSource_Params pl_list) { |
| var integer n := sizeof(pl_list); |
| var integer k; |
| var integer bound := n-1; |
| var EPTF_DataSource_Param t; |
| var integer last_swap; |
| |
| while (bound!=0) { |
| last_swap := 0; |
| for ( k:=0; k<bound; k:=k+1 ) { |
| t := pl_list[k]; // t is a maximum of A[0]..A[k] |
| if ( f_EPTF_DataSource_compare(t,pl_list[k+1])>0 ) { |
| pl_list[k] := pl_list[k+1]; pl_list[k+1] := t; //swap |
| last_swap := k; // mark the last swap position |
| }//if |
| }//for |
| bound:=last_swap; // elements after bound already sorted |
| }//while |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_sortParams |
| // |
| // Purpose: |
| // Orders the given parameters lexicographically with respect to the paramNames; |
| // |
| // Parameters: |
| // *inout* <EPTF_DataSource_Params> *pl_params* - contains the parameters to sort. |
| // When the function returns it will be sorted |
| // |
| // Return Value: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| /////////////////////////////////////////////////////////// |
| friend function f_EPTF_DataSource_sortParams(inout EPTF_DataSource_Params pl_params) { |
| f_EPTF_DataSource_bubblesort(pl_params); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getData |
| // |
| // Purpose: |
| // To get the name of the variable that contains the value of the given data |
| // |
| // Parameters: |
| // *out charstring pl_dataVarName* - this is the name of the variable |
| // that stores the values of the data on the local component |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_element* - the type of data |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames |
| // *in* <EPTF_Var_SubscriptionMode> - pl_subscriptionMode - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // Default: tsp_EPTF_DataSource_subscriptionMode |
| // *in integer* - pl_refreshRate - the refresh rate for the subscription. |
| // default: tsp_EPTF_DataSource_refreshRate |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero in case of failure to show that the pl_dataVarName is not valid |
| // |
| // Detailed Comments: |
| // This function will make a request for the given data source and return the name of the |
| // variable that contains the value of the data. |
| // |
| // How it works: |
| // The request is forwarded to the appropriate DataSourceClient which registered |
| // the source and ptc name. On the client the handler function registered by |
| // <f_EPTF_DataSourceClient_registerData> for the given pl_source and pl_ptcName is called. |
| // The pl_params are passed to it as additional arguments. |
| // The handler function returns a charstring which is set in the pl_dataVarName |
| // argument. The error code returned by the handler function is returned by this function. |
| // A local variable is created which is subscribed to the variable returned by the handler. |
| // The name of the local variable is returned by this function in the pl_dataVarName argument. |
| // In case of non-zero return value the pl_dataVarName parameter may contain an error message. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getData( |
| out charstring pl_dataVarName, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode := tsp_EPTF_DataSource_subscriptionMode, |
| in integer pl_refreshRate := tsp_EPTF_DataSource_refreshRate |
| ) runs on EPTF_DataSource_CT return integer { |
| f_EPTF_DataSource_sortParams(pl_params); |
| |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| var integer vl_errorCode := f_EPTF_DataSource_handleBuiltInDataElements( |
| pl_dataVarName, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| ); // internal elements handled successfully, or an error occured |
| if (vl_errorCode!=0) { |
| //append general text: |
| pl_dataVarName := log2str(%definitionId&": Invalid iterator or externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)&"\n:"&pl_dataVarName; |
| f_EPTF_DataSource_warning(pl_dataVarName); |
| } |
| return vl_errorCode; |
| } |
| |
| pl_dataVarName := ""; |
| var integer vl_localDataVarId; |
| var EPTF_Var_CT vl_ownerCompRef; |
| var charstring vl_remoteDataVarName; // for nonzero error code it contains the error message |
| //find if pl_dataVarName already exists |
| var charstring vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params); |
| var integer vl_dataValueId; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) { |
| |
| if (vl_dataValueId==-1) { |
| // PTC name is not given, but should be specified |
| pl_dataVarName := ""; |
| return 1; |
| } |
| |
| vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId); |
| |
| // check if var exists: it is needed because checkData does not create it, but stores it in the hashMap |
| // if var is not subscribed, subscribe is needed => no error if variable is not found |
| if(f_EPTF_Var_checkSubscriptionMode(vl_localDataVarId,pl_subscriptionMode)) { |
| return 0; |
| } |
| vl_remoteDataVarName := v_EPTF_DataSource_dataValue_List[vl_dataValueId].remoteDataVarName; |
| vl_ownerCompRef := v_EPTF_DataSource_dataValue_List[vl_dataValueId].ownerCompRef; |
| } else { |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // set ownerCompRef (ptcName is not "" here): |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered")); |
| return 3; |
| } else { |
| if (vl_counter>1) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified")); |
| return 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| |
| // set ptcName: |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered")); |
| return 4; |
| } |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered")); |
| return 1; |
| } |
| } |
| } |
| |
| // here if pl_dataVarName != "" : only subscribe required |
| // if pl_dataVarName == "" : have to send message to client, because no local data was found |
| |
| var integer vl_errorCode := 0; |
| if (pl_dataVarName=="") { |
| // dataVarName was not found in hashMaps, have to send request to client: |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getData:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(vl_ownerCompRef))); |
| // wait for response |
| if (f_EPTF_Semaphore_waitForUnlock(vl_getDataId,tsp_EPTF_DataSource_maxWaitTime)) { |
| // max wait time expired before response received: |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Communication error: No response received for getData message: ",vl_getDataId)); |
| pl_dataVarName := ""; |
| return -1; |
| } |
| |
| // copy the values from the message database because it might be possible that they will be overwritten because |
| // the semaphore is released and there is a blocking statement before they are used: |
| vl_errorCode := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.errorCode; |
| //var EPTF_DataSourceClient_CT vl_ownerCompRef := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.ownerCompRef; // value in message is not used |
| vl_remoteDataVarName := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.dataVarName; |
| |
| // this will always be true if errorCode == 0: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) { |
| vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId); |
| } |
| } |
| |
| // if returned error code is 0 (no error) subscibe to the provider data variable: |
| if (vl_errorCode==0) { |
| |
| // here the local variable exists: was created when getData response was received |
| f_EPTF_Var_resubscribeRemote( |
| vl_ownerCompRef, |
| vl_remoteDataVarName, |
| pl_subscriptionMode, |
| vl_localDataVarId, |
| pl_dataVarName, |
| pl_refreshRate |
| ); |
| } else { |
| pl_dataVarName := vl_remoteDataVarName; // pass on the error message |
| //append general text: |
| pl_dataVarName := log2str(%definitionId&": Invalid iterator or externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)&"\n:"&pl_dataVarName; |
| f_EPTF_DataSource_warning(pl_dataVarName); |
| pl_dataVarName := ""; |
| } |
| |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getDataValue |
| // |
| // Purpose: |
| // To get the value of the given data |
| // |
| // Parameters: |
| // *out* <EPTF_Var_DirectContent> *pl_dataValue* - this is the value of the data requested |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_element* - the type of data |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero in case of failure to show that the pl_dataValue is not valid |
| // |
| // Detailed Comments: |
| // This function will make a request for the given data source and return the value of the data. |
| // |
| // How it works: |
| // The request is forwarded to the appropriate DataSourceClient which registered |
| // the source and ptc name. On the client the handler function registered by |
| // <f_EPTF_DataSourceClient_registerDataValue> for the given pl_source and pl_ptcName is called. |
| // The pl_params are passed to it as additional arguments. |
| // The handler function returns a value together with the error code. |
| // These values are returned by this function in the pl_dataValue parameter and its return value. |
| // |
| // In case of nonzero return value pl_dataValue may contain an error message. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getDataValue( |
| out EPTF_Var_DirectContent pl_dataValue, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_Filter pl_filter := c_EPTF_DataSource_Filter_empty |
| ) runs on EPTF_DataSource_CT return integer { |
| |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| var integer vl_errorCode := f_EPTF_DataSource_handleBuiltInDataValues( |
| pl_dataValue, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter |
| ); // internal elements handled successfully, or an error occured |
| if (vl_errorCode!=0) { |
| if (not ischosen(pl_dataValue.charstringVal)) { |
| pl_dataValue := {charstringVal := "Error info: "&ttcn2string(pl_dataValue)}; // error message was not present => set it to the string value of provided value |
| } |
| //append general text: |
| pl_dataValue.charstringVal := log2str(%definitionId&": Invalid iterator or externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)& |
| "\nReason: "&pl_dataValue.charstringVal; |
| f_EPTF_DataSource_warning(pl_dataValue.charstringVal&"\nError code: "&int2str(vl_errorCode)); |
| } |
| return vl_errorCode; |
| } |
| |
| var EPTF_Var_CT vl_ownerCompRef; |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // set ownerCompRef (ptcName is not "" here): |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered")); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered"); |
| return 3; |
| } else { |
| if (vl_counter>1) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified")); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified"); |
| return 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| |
| // set ptcName: |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered")); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered") |
| return 4; |
| } |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered")); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered"); |
| return 1; |
| } |
| } |
| |
| // Now have to send message to client to get the value |
| |
| var integer vl_errorCode := 0; |
| // have to send request to client: |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getDataValue:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(vl_ownerCompRef))); |
| // wait for response |
| if (f_EPTF_Semaphore_waitForUnlock(vl_getDataId,tsp_EPTF_DataSource_maxWaitTime)) { |
| // max wait time expired before response received: |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Communication error: No response received for getData message: ",vl_getDataId)); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Communication error: No response received for getData message: ",vl_getDataId); |
| return -1; |
| } |
| |
| // copy the values from the message database because it might be possible that they will be overwritten because |
| // the semaphore is released and there is a blocking statement before they are used: |
| vl_errorCode := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValueResponse.errorCode; |
| pl_dataValue := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValueResponse.dataValue; |
| //var EPTF_DataSourceClient_CT vl_ownerCompRef := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.ownerCompRef; // value in message is not used |
| |
| // if returned error code is non-0, update the error message: |
| if (vl_errorCode!=0) { |
| if (not ischosen(pl_dataValue.charstringVal)) { |
| pl_dataValue := {charstringVal := "Error info: "&ttcn2string(pl_dataValue)}; // error message was not present => set it to the string value of provided value |
| //append general text: |
| pl_dataValue.charstringVal := log2str(%definitionId&": Invalid iterator or externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)& |
| "\nReason: "&pl_dataValue.charstringVal; |
| } |
| f_EPTF_DataSource_warning(pl_dataValue.charstringVal&"\nError code: "&int2str(vl_errorCode)); |
| } |
| |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getDataValue_nonblocking |
| // |
| // Purpose: |
| // To get the value of a given data in non-blocking way. |
| // The specified handler is called when the response arrives. |
| // |
| // Parameters: |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_element* - the type of data |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames |
| // *in* <EPTF_DataSource_GetDataValueHandler> *pl_getDataValueHandler* - the handler function (with user arguments) to call |
| // when response is received |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero in case of the request is not valid |
| // |
| // Detailed Comments: |
| // This function will make a request for the given data source and return the value of the data. |
| // |
| // How it works: |
| // The request is forwarded to the appropriate DataSourceClient which registered |
| // the source and ptc name. On the client the handler function registered by |
| // <f_EPTF_DataSourceClient_registerDataValue> for the given pl_source and pl_ptcName is called. |
| // The pl_params are passed to it as additional arguments. |
| // The handler function returns a value together with the error code. |
| // These values are passed to the given handler in pl_getDataValueHandler. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getDataValue_nonblocking( |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_Filter pl_filter := c_EPTF_DataSource_Filter_empty, |
| in EPTF_DataSource_GetDataValueHandler pl_getDataValueHandler := cg_EPTF_DataSource_GetDataValueHandler_null |
| ) runs on EPTF_DataSource_CT return integer { |
| var EPTF_Var_DirectContent vl_dataValue; |
| var integer vl_errorCode := 0; |
| |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| vl_errorCode := f_EPTF_DataSource_handleBuiltInDataValues_nonblocking( |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter, |
| pl_getDataValueHandler |
| ); // internal elements handled successfully, or an error occured |
| return vl_errorCode; |
| } |
| |
| var EPTF_Var_CT vl_ownerCompRef := null; |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // set ownerCompRef (ptcName is not "" here): |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered")); |
| vl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered"); |
| vl_errorCode := 3; |
| } else { |
| if (vl_counter>1) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified")); |
| vl_dataValue.charstringVal := log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified"); |
| vl_errorCode := 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| |
| // set ptcName: |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered")); |
| vl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered") |
| vl_errorCode := 4; |
| } else { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered")); |
| vl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered"); |
| vl_errorCode := 1; |
| } |
| } |
| } |
| |
| if (vl_errorCode!=0) { |
| // call handler: |
| if (pl_getDataValueHandler.getDataValueHandler!=null) { |
| |
| pl_getDataValueHandler.getDataValueHandler.apply( |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_dataValue := vl_dataValue, // the value of the data. In case errorCode!=0: it contains the error message as charstringVal |
| // user data |
| pl_userData := pl_getDataValueHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } else { |
| |
| // Now have to send message to client to get the value |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| v_EPTF_DataSource_GetDataValueHandler_DB[vl_getDataId] := pl_getDataValueHandler; |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getDataValue:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(vl_ownerCompRef))); |
| } |
| |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_setDataValue |
| // |
| // Purpose: |
| // To set the value of a given data |
| // |
| // Parameters: |
| // *inout* <EPTF_Var_DirectContent> *pl_dataValue* - this is the value of the data requested |
| // after call, it will return the changed value that might be different |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_element* - the type of data |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames |
| // *in* <EPTF_CharstringList> *pl_indexList* - in case of list-type values the elements of this parameter |
| // are the indexes in the list-type data for which the values should be set |
| // For elementary type values this argument is not used |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero in case of setting the value is unsuccessful |
| // |
| // Detailed Comments: |
| // This function will make a request for the given data source and return the new value of the data. |
| // |
| // How it works: |
| // The request is forwarded to the appropriate DataSourceClient which registered |
| // the source and ptc name. On the client the handler function registered by |
| // <f_EPTF_DataSourceClient_registerSetDataValue> for the given pl_source and pl_ptcName is called. |
| // The pl_params are passed to it as additional arguments. |
| // The handler function returns the new value together with the error code. |
| // The new value is then returned in pl_dataValue, and the error code in the return value of this function. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_setDataValue( |
| inout EPTF_Var_DirectContent pl_dataValue, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_IntegerList pl_indexList := {} |
| ) runs on EPTF_DataSource_CT return integer { |
| |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| return f_EPTF_DataSource_handleBuiltInSetDataValue( |
| pl_dataValue, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| ); // internal elements handled successfully, or an error occured |
| } |
| |
| var EPTF_Var_CT vl_ownerCompRef; |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // set ownerCompRef (ptcName is not "" here): |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered")); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered"); |
| return 3; |
| } else { |
| if (vl_counter>1) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified")); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified"); |
| return 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| |
| // set ptcName: |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered")); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered"); |
| return 4; |
| } |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered")); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered"); |
| return 1; |
| } |
| } |
| |
| // Now have to send message to client to set the value |
| |
| var integer vl_errorCode := 0; |
| // have to send request to client: |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{setDataValue:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_dataValue, |
| pl_indexList |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(vl_ownerCompRef))); |
| // wait for response |
| if (f_EPTF_Semaphore_waitForUnlock(vl_getDataId,tsp_EPTF_DataSource_maxWaitTime)) { |
| // max wait time expired before response received: |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Communication error: No response received for getData message: ",vl_getDataId)); |
| return -1; |
| } |
| |
| // copy the values from the message database because it might be possible that they will be overwritten because |
| // the semaphore is released and there is a blocking statement before they are used: |
| vl_errorCode := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValueResponse.errorCode; |
| pl_dataValue := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValueResponse.dataValue; |
| //var EPTF_DataSourceClient_CT vl_ownerCompRef := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.ownerCompRef; // value in message is not used |
| |
| // if returned error code is non-0, update the error message: |
| if (vl_errorCode!=0) { |
| if (not ischosen(pl_dataValue.charstringVal)) { |
| pl_dataValue := {charstringVal := "Error info: "&ttcn2string(pl_dataValue)}; // error message was not present => set it to the string value of provided value |
| } |
| //append general text: |
| pl_dataValue.charstringVal := log2str(%definitionId&": Read-only data or invalid iterator, externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)& |
| "\nReason: "&pl_dataValue.charstringVal; |
| f_EPTF_DataSource_warning(pl_dataValue.charstringVal&"\nError code: "&int2str(vl_errorCode)); |
| } |
| |
| return vl_errorCode; |
| } |
| |
| //FIXME: schedule handler call if data is already available |
| // (=return statements) |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_setDataValue_nonblocking |
| // |
| // Purpose: |
| // To set the value of a given data in non-blocking way. |
| // The specified handler is called when the response arrives. |
| // |
| // Parameters: |
| // *in* <EPTF_Var_DirectContent> *pl_dataValue* - this is the value of the data requested |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_element* - the type of data |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames |
| // *in* <EPTF_CharstringList> *pl_indexList* - in case of list-type values the elements of this parameter |
| // are the indexes in the list-type data for which the values should be set |
| // For elementary type values this argument is not used |
| // *in* <EPTF_DataSource_GetDataValueHandler> - pl_setDataValueHandler - the handler function (with user arguments) to call |
| // when response is received |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero in case of the request is not valid |
| // |
| // Detailed Comments: |
| // This function will make a request for the given data source and call the specified handler with the new value of the data. |
| // |
| // How it works: |
| // The request is forwarded to the appropriate DataSourceClient which registered |
| // the source and ptc name. On the client the handler function registered by |
| // <f_EPTF_DataSourceClient_registerSetDataValue> for the given pl_source and pl_ptcName is called. |
| // The pl_params are passed to it as additional arguments. |
| // The handler function returns the new value together with the error code returned by the handler function. |
| // Then the specified handler pl_setDataValueHandler is called with these values. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_setDataValue_nonblocking( |
| in EPTF_Var_DirectContent pl_dataValue, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_IntegerList pl_indexList := {}, |
| in EPTF_DataSource_GetDataValueHandler pl_setDataValueHandler := cg_EPTF_DataSource_GetDataValueHandler_null |
| ) runs on EPTF_DataSource_CT return integer { |
| |
| var EPTF_Var_DirectContent vl_dataValue := pl_dataValue; |
| var integer vl_errorCode; |
| |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| // f_EPTF_DataSource_handleBuiltInSetDataValue is nonblocking |
| vl_errorCode := f_EPTF_DataSource_handleBuiltInSetDataValue( |
| vl_dataValue, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| ); // internal elements handled successfully, or an error occured |
| |
| // call handler: |
| if (pl_setDataValueHandler.getDataValueHandler!=null) { |
| |
| pl_setDataValueHandler.getDataValueHandler.apply( |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_setDataValueHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| |
| vl_errorCode := 0; |
| var EPTF_Var_CT vl_ownerCompRef := null; |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // set ownerCompRef (ptcName is not "" here): |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered")); |
| vl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered"); |
| vl_errorCode := 3; |
| } else { |
| if (vl_counter>1) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified")); |
| vl_dataValue.charstringVal := log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified"); |
| vl_errorCode := 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| |
| // set ptcName: |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered")); |
| vl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered"); |
| vl_errorCode := 4; |
| } |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered")); |
| vl_dataValue.charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered"); |
| vl_errorCode := 1; |
| } |
| if (vl_errorCode!=0) { |
| // call handler: |
| if (pl_setDataValueHandler.getDataValueHandler!=null) { |
| |
| pl_setDataValueHandler.getDataValueHandler.apply( |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_setDataValueHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| } |
| // have to send request to client to set the value |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| v_EPTF_DataSource_GetDataValueHandler_DB[vl_getDataId] := pl_setDataValueHandler; |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{setDataValue:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| vl_dataValue, |
| pl_indexList |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(vl_ownerCompRef))); |
| |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getData_nonBlocking |
| // |
| // Purpose: |
| // To get the name of the variable that contains the value of a given data in non-blocking way. |
| // The specified handler is called when the response arrives. |
| // |
| // Parameters: |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_element* - the type of data |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames |
| // *in* <EPTF_DataSource_GetDataHandler> - pl_getDataHandler - the handler function (with user arguments) to call |
| // when response is received |
| // // *in* <EPTF_Var_SubscriptionMode> - pl_subscriptionMode - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // // Default: tsp_EPTF_DataSource_subscriptionMode |
| // // *in integer* - pl_refreshRate - the refresh rate for the subscription. |
| // // default: tsp_EPTF_DataSource_refreshRate |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero if dataSource request is not valid. In both cases the handler will be called. |
| // |
| // Detailed Comments: |
| // Sends a request to the main DataSourceClient_CT component |
| // to request the EPTF Variable name for the given dataSource. |
| // On the component that registered the source and ptc name |
| // the handler function registered by <f_EPTF_DataSourceClient_registerData> |
| // for the given pl_source and pl_ptcName is called. |
| // The pl_params are passed to it as additional arguments. |
| // |
| // When the response arrives from the client, the |
| // given pl_getDataHandler handler function is called with all information received. |
| // A local variable is created which stores the current value of the dataSource, |
| // but this variable is not subscribed to the data owner. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getData_nonBlocking( |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_GetDataHandler pl_getDataHandler := cg_EPTF_DataSource_GetDataHandler_null |
| // in EPTF_Var_SubscriptionMode pl_subscriptionMode := tsp_EPTF_DataSource_subscriptionMode, |
| // in integer pl_refreshRate := tsp_EPTF_DataSource_refreshRate |
| ) runs on EPTF_DataSource_CT return integer { |
| var charstring pl_dataVarName; |
| f_EPTF_DataSource_sortParams(pl_params); |
| |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| var integer vl_errorCode := f_EPTF_DataSource_handleBuiltInDataElements( |
| pl_dataVarName, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| ); // internal elements handled successfully, or an error occured |
| |
| // call handler: |
| if (pl_getDataHandler.getDataHandler!=null) { |
| var integer vl_localDataVarId := f_EPTF_Var_getId(pl_dataVarName); |
| var EPTF_Var_DirectContent vl_dataValue := {unknownVal:={omit}}; |
| if(vl_localDataVarId!=-1) { |
| f_EPTF_Var_getContent(vl_localDataVarId,vl_dataValue); |
| } |
| pl_getDataHandler.getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_source, |
| pl_ptcName := f_EPTF_Base_selfName(), // response may fill this if it was "" |
| pl_element := pl_element, |
| pl_params := pl_params, |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_remoteDataVarName := pl_dataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := self, // reference to the remote component |
| pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_getDataHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| |
| pl_dataVarName := ""; |
| |
| var integer vl_errorCode; |
| var EPTF_Var_CT vl_ownerCompRef; |
| var charstring vl_remoteDataVarName; // for nonzero error code it contains the error message |
| var integer vl_localDataVarId; |
| var EPTF_Var_DirectContent vl_dataValue; |
| |
| //find if pl_dataVarName already exists |
| var charstring vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params); |
| var integer vl_dataValueId; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) { |
| |
| |
| if (vl_dataValueId==-1) { |
| // PTC name is not given, but should be specified |
| vl_errorCode := 1; |
| vl_remoteDataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": PTC name is not given, but should be specified since more than one PTC exist with the same source."); |
| |
| vl_ownerCompRef := null; |
| vl_localDataVarId := -1; |
| vl_dataValue := {unknownVal:={omit}}; |
| |
| } else { |
| |
| // pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId); |
| vl_errorCode := 0; |
| vl_remoteDataVarName := v_EPTF_DataSource_dataValue_List[vl_dataValueId].remoteDataVarName; |
| vl_ownerCompRef := v_EPTF_DataSource_dataValue_List[vl_dataValueId].ownerCompRef; |
| vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| vl_dataValue := {unknownVal:={omit}}; |
| if(vl_localDataVarId!=-1) { |
| f_EPTF_Var_getContent(vl_localDataVarId,vl_dataValue); |
| } |
| } |
| |
| // call handler: |
| if (pl_getDataHandler.getDataHandler!=null) { |
| |
| pl_getDataHandler.getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_source, |
| pl_ptcName := pl_ptcName, // response may fill this if it was "" |
| pl_element := pl_element, |
| pl_params := pl_params, |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_remoteDataVarName := vl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := vl_ownerCompRef, // reference to the remote component |
| pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_getDataHandler.userData // user specific data given at the request |
| ); |
| |
| } |
| return vl_errorCode; |
| |
| } else { |
| |
| vl_errorCode := 0; |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // set ownerCompRef (ptcName is not "" here): |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| pl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered"); |
| f_EPTF_DataSource_warning(pl_dataVarName); |
| vl_errorCode := 3; |
| } else { |
| if (vl_counter>1) { |
| pl_dataVarName := log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified"); |
| f_EPTF_DataSource_warning(pl_dataVarName); |
| vl_errorCode := 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| |
| // set ptcName: |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| pl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered"); |
| f_EPTF_DataSource_warning(pl_dataVarName); |
| vl_errorCode := 4; |
| } else { |
| pl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered"); |
| f_EPTF_DataSource_warning(pl_dataVarName); |
| vl_errorCode := 1; |
| } |
| } |
| } |
| |
| if (vl_errorCode!=0) { |
| // call handler: |
| if (pl_getDataHandler.getDataHandler!=null) { |
| |
| vl_remoteDataVarName := pl_dataVarName; |
| vl_ownerCompRef := null; |
| vl_localDataVarId := -1; |
| vl_dataValue := {unknownVal:={omit}}; |
| |
| pl_getDataHandler.getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_source, |
| pl_ptcName := pl_ptcName, // response may fill this if it was "" |
| pl_element := pl_element, |
| pl_params := pl_params, |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_remoteDataVarName := vl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := vl_ownerCompRef, // reference to the remote component |
| pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_getDataHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| |
| } |
| |
| // here if pl_dataVarName != "" : only subscribe required |
| // if pl_dataVarName == "" : have to send message to client, because no local data was found |
| |
| vl_errorCode := 0; |
| if (pl_dataVarName=="") { |
| // dataVarName was not found in hashMaps, have to send request to client: |
| //recalculate vl_dataValueIdStr with given PTCName: |
| vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params); |
| var integer vl_getDataId; |
| // check if there is a pending request: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_pendingGetDataHash,vl_dataValueIdStr,vl_getDataId)) { |
| v_EPTF_DataSource_GetDataHandler_DB[vl_getDataId] := v_EPTF_DataSource_GetDataHandler_DB[vl_getDataId] & {pl_getDataHandler}; |
| } else { |
| |
| //FIXME: use FBQ instead of semaphore: |
| vl_getDataId := f_EPTF_Semaphore_new(); |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_pendingGetDataHash,vl_dataValueIdStr,vl_getDataId); |
| v_EPTF_DataSource_GetDataHandler_DB[vl_getDataId] := {pl_getDataHandler}; |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getData:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(vl_ownerCompRef))); |
| } |
| } |
| |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_checkData |
| // |
| // Purpose: |
| // To check if the value of a given data exists. Returns the variable name |
| // of the dataSource. |
| // |
| // Parameters: |
| // *out charstring pl_dataVarName* - this is the name of the variable |
| // that stores the values of the data on the local component |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_element* - the type of data |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero if pl_dataVarName is not valid |
| // |
| // Detailed Comments: |
| // This function is almost the same as <f_EPTF_DataSource_getData>, but |
| // does not subscribe to the provider variable and does not check the subscription. |
| // It only checks if the source variable is there on the source component. |
| // The returned variable might not exist even if the error code is zero. |
| // For non-zero error code, pl_dataVarName contains the error message |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_checkData( |
| out charstring pl_dataVarName, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {} |
| ) runs on EPTF_DataSource_CT return integer { |
| f_EPTF_DataSource_sortParams(pl_params); |
| |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| return f_EPTF_DataSource_handleBuiltInDataElements( |
| pl_dataVarName, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| ); // internal elements handled successfully, or an error occured |
| } |
| |
| pl_dataVarName := ""; |
| var EPTF_Var_CT vl_ownerCompRef; |
| //find if pl_dataVarName already exists |
| var charstring vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params); |
| var integer vl_dataValueId; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) { |
| |
| if (vl_dataValueId==-1) { |
| // PTC name is not given, but should be specified |
| pl_dataVarName := ""; |
| return 1; |
| } |
| |
| var integer vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId); |
| return 0; |
| } else { |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // set ownerCompRef (ptcName is not "" here): |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| pl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered"); |
| f_EPTF_DataSource_debug(pl_dataVarName); |
| return 3; |
| } else { |
| if (vl_counter>1) { |
| pl_dataVarName := log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified"); |
| f_EPTF_DataSource_debug(pl_dataVarName); |
| return 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| |
| // set ptcName: |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| pl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered"); |
| f_EPTF_DataSource_debug(pl_dataVarName); |
| return 4; |
| } |
| pl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered"); |
| f_EPTF_DataSource_debug(pl_dataVarName); |
| return 1; |
| } |
| } |
| } |
| |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getData:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(vl_ownerCompRef))); |
| // wait for response |
| if (f_EPTF_Semaphore_waitForUnlock(vl_getDataId,tsp_EPTF_DataSource_maxWaitTime)) { |
| // max wait time expired before response received: |
| f_EPTF_DataSource_debug(log2str(%definitionId&": Communication error: No response received for getData message: ",vl_getDataId)); |
| pl_dataVarName := ""; |
| return -1; |
| } |
| |
| // copy the values from the message database because it might be possible that they will be overwritten because |
| // the semaphore is released and there is a blocking statement before they are used: |
| var integer vl_errorCode := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.errorCode; |
| //var EPTF_DataSourceClient_CT vl_ownerCompRef := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.ownerCompRef; // value in message is not used |
| var charstring vl_remoteDataVarName := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.dataVarName; |
| |
| // this will always be true if errorCode == 0: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) { |
| var integer vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId); |
| } |
| |
| // // remove the stored data from the dataBase: |
| // // by removing the returned varname from a hashmap, and clearing the stored variable name: |
| // if(vl_errorCode==0) { |
| // vl_dataValueIdStr2 := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.dataSource&"@"&v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.ptcName& |
| // "."&v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.dataElement&":"&log2str(v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.params); |
| // |
| // if(f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr2,vl_dataValueId)) { |
| // f_EPTF_str2int_HashMap_Erase(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr2); |
| // v_EPTF_DataSource_dataValue_List[vl_dataValueId] := {""}; |
| // } |
| // } |
| // |
| |
| // if returned error code is 0 (no error) check if the data variable is present on the provider: |
| if (vl_errorCode==0) { |
| // var charstring vl_localVarName := "EPTF_DataSource_"&vl_remoteDataVarName&"."&vl_dataValueIdStr; |
| // var integer vl_localVarIdx; |
| // if (not f_EPTF_Var_isPresentRemote( |
| // v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef, |
| // vl_remoteDataVarName |
| // )) { |
| // pl_dataVarName := log2str(%definitionId&": Cannot find the data variable of the dataSource: "& |
| // "The variable does not exist for dataSource ",pl_source, " ptcName ",pl_ptcName, " element ", pl_element, " params ", pl_params); |
| // f_EPTF_DataSource_debug(pl_dataVarName); |
| // return 5; |
| // } |
| // pl_dataVarName := vl_localVarName; |
| } else { |
| pl_dataVarName := vl_remoteDataVarName; // pass on the error message |
| //append general text: |
| pl_dataVarName := log2str(%definitionId&": Invalid iterator or externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)&"\n:"&pl_dataVarName; |
| f_EPTF_DataSource_debug(pl_dataVarName); |
| } |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_checkData_nonblocking |
| // |
| // Purpose: |
| // To check if the value of a given data exists in non-blocking way. |
| // The specified handler is called when the response arrives. |
| // |
| // Parameters: |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_element* - the type of data |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames |
| // *in* <EPTF_DataSource_GetDataHandler> - pl_checkDataHandler - the handler function (with user arguments) to call |
| // when response is received |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero if pl_dataVarName is not valid or data does not exist |
| // |
| // Detailed Comments: |
| // This function is almost the same as <f_EPTF_DataSource_checkData>, but |
| // does not subscribe to the provider variable and does not check the subscription. |
| // It only checks if the source variable is there on the source component. |
| // The variable with the name passed to the handler might not exist locally even if the error code is zero. |
| // For non-zero error code, pl_dataVarName of the handler contains the error message. |
| // The specified handler pl_checkDataHandler is called with the response data |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_checkData_nonblocking( |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_GetDataHandler pl_checkDataHandler := cg_EPTF_DataSource_GetDataHandler_null |
| ) runs on EPTF_DataSource_CT return integer { |
| var charstring vl_dataVarName; |
| var integer vl_errorCode; |
| f_EPTF_DataSource_sortParams(pl_params); |
| |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| // f_EPTF_DataSource_handleBuiltInDataElements is a nonblocking currently |
| vl_errorCode := f_EPTF_DataSource_handleBuiltInDataElements( |
| vl_dataVarName, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| ); // internal elements handled successfully, or an error occured |
| |
| |
| // call handler: |
| if (pl_checkDataHandler.getDataHandler!=null) { |
| var integer vl_localDataVarId := f_EPTF_Var_getId(vl_dataVarName); |
| var EPTF_Var_DirectContent vl_dataValue := {unknownVal:={omit}}; |
| if(vl_localDataVarId!=-1) { |
| f_EPTF_Var_getContent(vl_localDataVarId,vl_dataValue); |
| } |
| pl_checkDataHandler.getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_source, |
| pl_ptcName := f_EPTF_Base_selfName(), // response may fill this if it was "" |
| pl_element := pl_element, |
| pl_params := pl_params, |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_remoteDataVarName := vl_dataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := self, // reference to the remote component |
| pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_checkDataHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| |
| vl_dataVarName := ""; |
| var EPTF_Var_CT vl_ownerCompRef; |
| var charstring vl_remoteDataVarName; // for nonzero error code it contains the error message |
| var integer vl_localDataVarId; |
| var EPTF_Var_DirectContent vl_dataValue; |
| |
| //find if vl_dataVarName already exists |
| var charstring vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params); |
| var integer vl_dataValueId; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) { |
| |
| if (vl_dataValueId==-1) { |
| // PTC name is not given, but should be specified |
| vl_ownerCompRef := null; |
| vl_remoteDataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": PTC name is not given, but should be specified since more than one PTC exist with the same source."); |
| vl_errorCode := 1; |
| } else { |
| |
| // pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId); |
| vl_errorCode := 0; |
| vl_remoteDataVarName := v_EPTF_DataSource_dataValue_List[vl_dataValueId].remoteDataVarName; |
| vl_ownerCompRef := v_EPTF_DataSource_dataValue_List[vl_dataValueId].ownerCompRef; |
| vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| vl_dataValue := {unknownVal:={omit}}; |
| if(vl_localDataVarId!=-1) { |
| f_EPTF_Var_getContent(vl_localDataVarId,vl_dataValue); |
| } |
| } |
| |
| // call handler: |
| if (pl_checkDataHandler.getDataHandler!=null) { |
| |
| pl_checkDataHandler.getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_source, |
| pl_ptcName := pl_ptcName, // response may fill this if it was "" |
| pl_element := pl_element, |
| pl_params := pl_params, |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_remoteDataVarName := vl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := vl_ownerCompRef, // reference to the remote component |
| pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_checkDataHandler.userData // user specific data given at the request |
| ); |
| |
| } |
| return vl_errorCode; |
| |
| } else { |
| |
| vl_errorCode := 0; |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // set ownerCompRef (ptcName is not "" here): |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| vl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered"); |
| f_EPTF_DataSource_debug(vl_dataVarName); |
| vl_errorCode := 3; |
| } else { |
| if (vl_counter>1) { |
| vl_dataVarName := log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified"); |
| f_EPTF_DataSource_debug(vl_dataVarName); |
| vl_errorCode := 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| |
| // set ptcName: |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| vl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered"); |
| f_EPTF_DataSource_debug(vl_dataVarName); |
| vl_errorCode := 4; |
| } |
| vl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered"); |
| f_EPTF_DataSource_debug(vl_dataVarName); |
| vl_errorCode := 1; |
| } |
| } |
| |
| if (vl_errorCode!=0) { |
| // call handler: |
| if (pl_checkDataHandler.getDataHandler!=null) { |
| |
| vl_remoteDataVarName := vl_dataVarName; |
| vl_ownerCompRef := null; |
| vl_localDataVarId := -1; |
| vl_dataValue := {unknownVal:={omit}}; |
| |
| pl_checkDataHandler.getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_source, |
| pl_ptcName := pl_ptcName, // response may fill this if it was "" |
| pl_element := pl_element, |
| pl_params := pl_params, |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_remoteDataVarName := vl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := vl_ownerCompRef, // reference to the remote component |
| pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_checkDataHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| } |
| |
| var integer vl_getDataId; |
| // dataVarName was not found in hashMaps, have to send request to client: |
| //recalculate vl_dataValueIdStr with given PTCName: |
| vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params); |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_pendingGetDataHash,vl_dataValueIdStr,vl_getDataId)) { |
| v_EPTF_DataSource_GetDataHandler_DB[vl_getDataId] := v_EPTF_DataSource_GetDataHandler_DB[vl_getDataId] & {pl_checkDataHandler}; |
| } else { |
| //FIXME: use FBQ instead of semaphore: |
| vl_getDataId := f_EPTF_Semaphore_new(); |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_pendingGetDataHash,vl_dataValueIdStr,vl_getDataId); |
| v_EPTF_DataSource_GetDataHandler_DB[vl_getDataId] := {pl_checkDataHandler}; |
| |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getData:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(vl_ownerCompRef))); |
| } |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_checkDataValue_nonblocking |
| // |
| // Purpose: |
| // To check if the value of a given data exists in non-blocking way. |
| // The specified handler is called when the response arrives. |
| // |
| // Parameters: |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_element* - the type of data |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames |
| // *in* <EPTF_DataSource_GetDataValueHandler> - pl_checkDataValueHandler - the handler function (with user arguments) to call |
| // when response is received |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero if the request is not valid |
| // |
| // Detailed Comments: |
| // This function is almost the same as <f_EPTF_DataSource_checkData_nonblocking>, but |
| // getDataValue is used instead of getData when checking the data value. |
| // It only checks if the source variable is there on the source component. |
| // The variable with the name passed to the handler might not exist locally even if the error code is zero. |
| // For non-zero error code, pl_dataVarName of the handler contains the error message. |
| // |
| // The function <f_EPTF_DataSource_getDataValue_nonblocking> makes this function depricated. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_checkDataValue_nonblocking( |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_GetDataValueHandler pl_checkDataValueHandler := cg_EPTF_DataSource_GetDataValueHandler_null |
| ) runs on EPTF_DataSource_CT return integer { |
| var charstring vl_dataVarName; |
| var integer vl_errorCode; |
| f_EPTF_DataSource_sortParams(pl_params); |
| |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| // f_EPTF_DataSource_handleBuiltInDataElements is a nonblocking currently |
| // FIXME: use f_EPTF_DataSource_handleBuiltInDataValues_nonblocking here? |
| vl_errorCode := f_EPTF_DataSource_handleBuiltInDataElements( |
| vl_dataVarName, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params |
| ); // internal elements handled successfully, or an error occured |
| |
| |
| // call handler: |
| if (pl_checkDataValueHandler.getDataValueHandler!=null) { |
| var integer vl_localDataVarId := f_EPTF_Var_getId(vl_dataVarName); |
| var EPTF_Var_DirectContent vl_dataValue := {unknownVal:={omit}}; |
| if(vl_localDataVarId!=-1) { |
| f_EPTF_Var_getContent(vl_localDataVarId,vl_dataValue); |
| } |
| pl_checkDataValueHandler.getDataValueHandler.apply( |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_checkDataValueHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| |
| vl_dataVarName := ""; |
| var EPTF_Var_CT vl_ownerCompRef; |
| var charstring vl_remoteDataVarName; // for nonzero error code it contains the error message |
| var integer vl_localDataVarId; |
| var EPTF_Var_DirectContent vl_dataValue; |
| |
| //find if vl_dataVarName already exists |
| var charstring vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params); |
| var integer vl_dataValueId; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) { |
| |
| if (vl_dataValueId==-1) { |
| // PTC name is not given, but should be specified |
| vl_ownerCompRef := null; |
| vl_remoteDataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": PTC name is not given, but should be specified since more than one PTC exist with the same source."); |
| vl_errorCode := 1; |
| } else { |
| |
| // pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId); |
| vl_errorCode := 0; |
| vl_remoteDataVarName := v_EPTF_DataSource_dataValue_List[vl_dataValueId].remoteDataVarName; |
| vl_ownerCompRef := v_EPTF_DataSource_dataValue_List[vl_dataValueId].ownerCompRef; |
| vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| vl_dataValue := {unknownVal:={omit}}; |
| if(vl_localDataVarId!=-1) { |
| f_EPTF_Var_getContent(vl_localDataVarId,vl_dataValue); |
| } |
| } |
| |
| // call handler: |
| if (pl_checkDataValueHandler.getDataValueHandler!=null) { |
| |
| pl_checkDataValueHandler.getDataValueHandler.apply( |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_checkDataValueHandler.userData // user specific data given at the request |
| ); |
| |
| } |
| return vl_errorCode; |
| |
| } else { |
| |
| vl_errorCode := 0; |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // set ownerCompRef (ptcName is not "" here): |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| vl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered"); |
| f_EPTF_DataSource_debug(vl_dataVarName); |
| vl_errorCode := 3; |
| } else { |
| if (vl_counter>1) { |
| vl_dataVarName := log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified"); |
| f_EPTF_DataSource_debug(vl_dataVarName); |
| vl_errorCode := 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| |
| // set ptcName: |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| vl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered"); |
| f_EPTF_DataSource_debug(vl_dataVarName); |
| vl_errorCode := 4; |
| } |
| vl_dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered"); |
| f_EPTF_DataSource_debug(vl_dataVarName); |
| vl_errorCode := 1; |
| } |
| } |
| |
| if (vl_errorCode!=0) { |
| // call handler: |
| if (pl_checkDataValueHandler.getDataValueHandler!=null) { |
| |
| vl_remoteDataVarName := vl_dataVarName; |
| vl_ownerCompRef := null; |
| vl_localDataVarId := -1; |
| vl_dataValue := {unknownVal:={omit}}; |
| |
| pl_checkDataValueHandler.getDataValueHandler.apply( |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_checkDataValueHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| } |
| |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getDataValue:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| omit |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(vl_ownerCompRef))); |
| v_EPTF_DataSource_GetDataValueHandler_DB[vl_getDataId] := pl_checkDataValueHandler; |
| |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_enableUpdate |
| // |
| // Purpose: |
| // Enables updating of the data source variable, i.e. |
| // it subscribes the local variable to the source |
| // |
| // Parameters: |
| // *in charstring pl_localDataVarName* - this is the name of the local variable |
| // that stores the values of the data on the local component |
| // *in* <EPTF_Var_SubscriptionMode> - pl_subscriptionMode - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // Default: tsp_EPTF_DataSource_subscriptionMode |
| // *in integer* - pl_refreshRate - the refresh rate for the subscription. |
| // default: tsp_EPTF_DataSource_refreshRate |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero if pl_localDataVarName is not valid |
| // |
| // Detailed Comments: |
| // This function can be called after a <f_EPTF_DataSource_getData_nonBlocking> |
| // to subscribe the local datasource variable to the source variable, since that function does not do it. |
| // To cancel the update call <f_EPTF_DataSource_disableUpdate> |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_enableUpdate( |
| in charstring pl_localDataVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode := tsp_EPTF_DataSource_subscriptionMode, |
| in integer pl_refreshRate := tsp_EPTF_DataSource_refreshRate |
| ) runs on EPTF_DataSource_CT return integer { |
| var integer vl_dataValueId := f_EPTF_DataSource_getDataValueId(pl_localDataVarName); |
| |
| if (vl_dataValueId==-1) { |
| return 1; //error; |
| } |
| |
| var integer vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| |
| |
| if(f_EPTF_Var_checkSubscriptionMode(vl_localDataVarId,pl_subscriptionMode)) { |
| return 0; // already subscribed |
| } |
| |
| var charstring vl_remoteDataVarName := v_EPTF_DataSource_dataValue_List[vl_dataValueId].remoteDataVarName; |
| var EPTF_Var_CT vl_ownerCompRef := v_EPTF_DataSource_dataValue_List[vl_dataValueId].ownerCompRef; |
| |
| |
| f_EPTF_Var_resubscribeRemote( |
| vl_ownerCompRef, |
| vl_remoteDataVarName, |
| pl_subscriptionMode, |
| vl_localDataVarId, |
| pl_localDataVarName, |
| pl_refreshRate |
| ); |
| return 0; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_disableUpdate |
| // |
| // Purpose: |
| // Disabled updating of the data source variable, i.e. |
| // it unsubscribes the local variable from the source |
| // |
| // Parameters: |
| // *in charstring pl_localDataVarName* - this is the name of the local variable |
| // that stores the values of the data on the local component |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero if pl_localDataVarName is not valid |
| // |
| // Detailed Comments: |
| // This function can be called after a <f_EPTF_DataSource_enableUpdate> |
| // to unsubscribe the local dataSource variable from the source variable. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_disableUpdate( |
| in charstring pl_localDataVarName |
| ) runs on EPTF_DataSource_CT return integer { |
| var integer vl_dataValueId := f_EPTF_DataSource_getDataValueId(pl_localDataVarName); |
| |
| if (vl_dataValueId==-1) { |
| return 1; //error; |
| } |
| |
| var integer vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| |
| f_EPTF_Var_unsubscribe(vl_localDataVarId); |
| return 0; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getDataValueId |
| // |
| // Purpose: |
| // Returns the ID of the data value |
| // |
| // Parameters: |
| // *in charstring pl_localDataVarName* - this is the name of the local variable |
| // that stores the values of the data on the local component |
| // |
| // Return Value: |
| // integer - the ID of the data value if OK, -1 if pl_dataVarName is not valid |
| // |
| // Detailed Comments: |
| // This function returns a unique ID for a datasource |
| // based on the local variable name that stores its value. |
| // To get the local variable name for a datasource use <f_EPTF_DataSource_checkData> |
| // or <f_EPTF_DataSource_getData>. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_DataSource_getDataValueId( |
| in charstring pl_localDataVarName |
| ) runs on EPTF_DataSource_CT return integer { |
| var integer vl_dataValueId := -1; |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,pl_localDataVarName,vl_dataValueId)) { |
| vl_dataValueId := -1; |
| } |
| return vl_dataValueId; |
| } |
| |
| private function f_EPTF_DataSource_getHandlerId( |
| in charstring pl_source, |
| in charstring pl_ptcName := "" |
| ) runs on EPTF_DataSource_CT return integer { |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // try to find without PTC name if pl_ptcName=="": |
| var integer vl_counter; |
| if (pl_ptcName=="") { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_debug(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, ": Source is not registered")); |
| return -3; |
| } else { |
| if (vl_counter>1) { |
| f_EPTF_DataSource_debug(log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified")); |
| return -2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| } |
| } |
| } else { |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_debug(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, ": Source is not registered")); |
| return -4; |
| } |
| f_EPTF_DataSource_debug(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": Source with the given PTC name is not registered")); |
| return -1; |
| } |
| } |
| return vl_handlerId; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getRequestPartsFromParams |
| // |
| // Purpose: |
| // To extract parts of a request when they are in the params of another request like sizeOf |
| // |
| // Parameters: |
| // *in EPTF_DataSource_Params pl_outerParams* - the params of the original request |
| // *out charstring pl_source* - the source of the request described in the params |
| // *out charstring pl_ptcName* - the ptc name |
| // *out charstring pl_element* - the element |
| // *out charstring pl_params* - the params |
| // |
| // Return Value: |
| // integer - the error code |
| // |
| // Detailed Comments: |
| // This function obtains the request contained in the parameters of another request. |
| // The parameters should contain the source, element and optionally the ptc name. |
| // If they are missing, an empty string will be returned. |
| // Additionally ParamName and ParamValue pairs should come one after the other |
| // to describe the parameters of the request. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getRequestPartsFromParams( |
| in EPTF_DataSource_Params pl_outerParams, |
| out charstring pl_source, |
| out charstring pl_ptcName, |
| out charstring pl_element, |
| out EPTF_DataSource_Params pl_params |
| ) return integer { |
| var integer vl_errorCode := 0; |
| var EPTF_CharstringList vl_result; |
| f_EPTF_DataSource_extractParams(pl_outerParams, |
| {c_EPTF_DataSource_paramNameSource, |
| c_EPTF_DataSource_paramNamePTCName, |
| c_EPTF_DataSource_paramNameElement}, |
| vl_result); |
| pl_source := vl_result[0]; |
| pl_ptcName := vl_result[1]; |
| pl_element := vl_result[2]; |
| pl_params := {}; |
| |
| // extract the params: |
| for(var integer i:=0; i<sizeof(pl_outerParams); i:=i+1) { |
| if (pl_outerParams[i].paramName == c_EPTF_DataSource_paramNameParamName) { |
| pl_params[sizeof(pl_params)] := {paramName := pl_outerParams[i].paramValue, paramValue := ""}; |
| i:=i+1; // jump to the next item which should be paramValue: |
| if (pl_outerParams[i].paramName == c_EPTF_DataSource_paramNameParamValue) { |
| pl_params[sizeof(pl_params)-1].paramValue := pl_outerParams[i].paramValue |
| } else { |
| // f_EPTF_DataSource_warning(%definitionId& ": "&c_EPTF_DataSource_paramNameParamValue&" is not specified for "& |
| // c_EPTF_DataSource_paramNameParamName&": "&pl_params[i-1].paramValue&" in the condition "&c_EPTF_DataSource_condition_dataElementPresent); |
| // f_EPTF_DataSource_warning(%definitionId&": Invalid condition or parameter: "& |
| // "\nSource: "&pl_source& |
| // "\nPTC : "&pl_ptcName & |
| // "\nMethod : " &pl_method& |
| // "\nParams: " & log2str(pl_params)); |
| vl_errorCode := 1; // invalid parameters |
| } |
| } |
| } |
| |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getSizeOfDataValue |
| // |
| // Purpose: |
| // To get the size of an iterator. |
| // |
| // Parameters: |
| // *in EPTF_Var_DirectContent pl_dataValue* - the dataValue |
| // |
| // Return Value: |
| // integer - the size of the dataValue |
| // |
| // Detailed Comments: |
| // When the dataValue is a list (integer, charstring or float), |
| // its size will be returned. |
| // For single elements, 1 is returned. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getSizeOfDataValue(in EPTF_Var_DirectContent pl_dataValue) return integer { |
| var integer vl_size; |
| if (ischosen(pl_dataValue.charstringlistVal)) { |
| vl_size := sizeof(pl_dataValue.charstringlistVal); |
| } else if (ischosen(pl_dataValue.integerlistVal)) { |
| vl_size := sizeof(pl_dataValue.integerlistVal); |
| } else if (ischosen(pl_dataValue.floatlistVal)) { |
| vl_size := sizeof(pl_dataValue.floatlistVal); |
| } else { |
| vl_size := 1; |
| } |
| return vl_size; |
| } |
| |
| private function f_EPTF_DataSource_getOwnerCompRef( |
| in charstring pl_source, |
| inout charstring pl_ptcName, |
| out EPTF_Var_CT pl_ownerCompRef |
| ) runs on EPTF_DataSource_CT return integer { |
| var integer vl_handlerId := f_EPTF_DataSource_getHandlerId(pl_source, pl_ptcName); |
| if (vl_handlerId >= 0) { |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| pl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| return 0; |
| } else { |
| return vl_handlerId; |
| } |
| } |
| |
| private function f_EPTF_DataSource_getHelpForAllElements( |
| in charstring pl_source := "", |
| in charstring pl_element := "", |
| out EPTF_DataSource_Help pl_helpForAllElements |
| ) runs on EPTF_DataSource_CT { |
| var EPTF_CharstringList vl_sources := {}; |
| if (pl_source!="") { |
| vl_sources := {pl_source} |
| } else { |
| var charstring vl_sourcesVarName := c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_Sources; |
| var integer vl_sourceVarIdx := f_EPTF_Var_getId(vl_sourcesVarName); |
| if (vl_sourceVarIdx!=-1) { |
| vl_sources := f_EPTF_Var_getCharstringlistValue(vl_sourceVarIdx); |
| } |
| } |
| |
| pl_helpForAllElements := {{}} |
| |
| for(var integer i:=0; i<sizeof(vl_sources); i:=i+1) { |
| |
| var charstring vl_source := vl_sources[i]; |
| |
| // find the first PTCName for the given source |
| var charstring vl_ptcName := ""; |
| var charstring vl_PTCsVarName := c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_PTCs&"."&vl_source; |
| var integer vl_PTCSVarIdx := f_EPTF_Var_getId(vl_PTCsVarName); |
| if (vl_PTCSVarIdx!=-1) { |
| var EPTF_CharstringList vl_ptcs := f_EPTF_Var_getCharstringlistValue(vl_PTCSVarIdx); |
| if (sizeof(vl_ptcs)>0) { |
| vl_ptcName := vl_ptcs[0]; |
| |
| var EPTF_Var_DirectContent vl_dataValue; |
| var integer vl_errorCode; |
| if (vl_source==c_EPTF_DataSource_sourceId) { |
| var octetstring vl_encodedValue; |
| vl_errorCode := f_EPTF_DataSource_encHelpJSON({vl_source,c_EPTF_DataSource_help},vl_encodedValue); |
| vl_dataValue := {octetstringVal := vl_encodedValue} |
| } else { |
| vl_errorCode := f_EPTF_DataSource_getDataValue( |
| pl_dataValue := vl_dataValue, |
| pl_source := vl_source, |
| pl_ptcName := vl_ptcName, |
| pl_element := c_EPTF_DataSource_dataElement_Help, |
| pl_params := { |
| {c_EPTF_DataSource_paramNameHelpFormat,c_EPTF_DataSource_helpFormatJSON} |
| } |
| ); |
| } |
| |
| if (vl_errorCode != 0) { |
| // put help entry for erroneous dataelement |
| var charstring vl_errorMsg := ""; |
| if (isbound(vl_dataValue)) { |
| if (ischosen(vl_dataValue.charstringVal)) { |
| vl_errorMsg := vl_dataValue.charstringVal; |
| } else if (ischosen(vl_dataValue.octetstringVal)){ |
| vl_errorMsg := oct2char(vl_dataValue.octetstringVal); |
| } |
| } |
| var EPTF_DataSource_Help_DataElementChildren vl_errorInHelp := {{ |
| dataElement := { |
| name := "CorruptHelpInfo", |
| valueType := charstringType, |
| typeDescriptor := omit, |
| description := "Help information is corrupt for source \""&vl_source&"\". "&vl_errorMsg |
| } |
| }} |
| |
| var octetstring vl_encodedValue; |
| vl_errorCode := f_EPTF_DataSource_encHelpJSON({vl_source,vl_errorInHelp},vl_encodedValue); |
| vl_dataValue := {octetstringVal := vl_encodedValue} |
| } |
| |
| if (vl_errorCode == 0) { |
| if (ischosen(vl_dataValue.octetstringVal)) { |
| var EPTF_DataSource_Help_DataElements vl_help := f_EPTF_DataSource_decHelpJSON(vl_dataValue.octetstringVal); |
| var EPTF_DataSource_Help_DataElementChildren vl_helpFiltered := vl_help.dataElements; |
| |
| // filter out the element given: |
| if (pl_element!="") { |
| vl_helpFiltered := f_EPTF_DataSource_filterHelpForElement(pl_element,vl_help.dataElements); |
| } |
| if (vl_helpFiltered!={}) { |
| pl_helpForAllElements.sources := pl_helpForAllElements.sources&{{vl_source,vl_helpFiltered}}; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getHelpJSON |
| // |
| // Purpose: |
| // To get help in JSON format for a given source and element |
| // |
| // Parameters: |
| // *in* *charstring* *pl_source* - the source name to get help for. |
| // If not specified, help for all sources will be returned |
| // *in* *charstring* *pl_element* - the element name to get help for. |
| // If not specified, help for all elements will be returned |
| // |
| // Return Value: |
| // octetstring - the help in JSON format |
| // |
| // Detailed Comments: |
| // In no source and element is given, it returns the help |
| // for all sources and all elements |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getHelpJSON( |
| in charstring pl_source := "", |
| in charstring pl_element := "" |
| ) runs on EPTF_DataSource_CT return octetstring { |
| var octetstring vl_helpJson := ''O; |
| var EPTF_DataSource_Help vl_helpForAllElements; |
| f_EPTF_DataSource_getHelpForAllElements( |
| pl_source := pl_source, |
| pl_element := pl_element, |
| pl_helpForAllElements := vl_helpForAllElements |
| ); |
| |
| vl_helpJson := f_EPTF_DataSource_encAllHelpJSON(vl_helpForAllElements); |
| return vl_helpJson; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getHelpTEXT |
| // |
| // Purpose: |
| // To get human readable help text for a given source and element |
| // |
| // Parameters: |
| // *in* *charstring* *pl_source* - the source name to get help for. |
| // If not specified, help for all sources will be returned |
| // *in* *charstring* *pl_element* - the element name to get help for. |
| // If not specified, help for all elements will be returned |
| // |
| // Return Value: |
| // charstring - help in readable text format |
| // |
| // Detailed Comments: |
| // In no source and element is given, it returns the help |
| // for all sources and all elements |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getHelpTEXT( |
| in charstring pl_source := "", |
| in charstring pl_element := "" |
| ) runs on EPTF_DataSource_CT return charstring { |
| var charstring vl_helpText := ""; |
| var EPTF_DataSource_Help vl_helpForAllElements; |
| f_EPTF_DataSource_getHelpForAllElements( |
| pl_source := pl_source, |
| pl_element := pl_element, |
| pl_helpForAllElements := vl_helpForAllElements |
| ); |
| |
| vl_helpText := f_EPTF_DataSource_encAllHelpTEXT(vl_helpForAllElements); |
| return vl_helpText; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getHelpApidoc |
| // |
| // Purpose: |
| // To get human readable help text for a given source and element |
| // |
| // Parameters: |
| // *in* *charstring* *pl_source* - the source name to get help for. |
| // If not specified, help for all sources will be returned |
| // *in* *charstring* *pl_element* - the element name to get help for. |
| // If not specified, help for all elements will be returned |
| // |
| // Return Value: |
| // charstring - help in readable text format |
| // |
| // Detailed Comments: |
| // In no source and element is given, it returns the help |
| // for all sources and all elements |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getHelpApidoc( |
| in charstring pl_source := "", |
| in charstring pl_element := "" |
| ) runs on EPTF_DataSource_CT return charstring { |
| var charstring vl_helpApiDoc := ""; |
| var EPTF_DataSource_Help vl_helpForAllElements; |
| f_EPTF_DataSource_getHelpForAllElements( |
| pl_source := pl_source, |
| pl_element := pl_element, |
| pl_helpForAllElements := vl_helpForAllElements |
| ); |
| |
| vl_helpApiDoc := f_EPTF_DataSource_encAllHelpApidoc(vl_helpForAllElements); |
| |
| return "/////////////////////////////////////////////////////////////////////////////// |
| // // |
| // Copyright (c) 2000-2019 Ericsson Telecom AB // |
| // // |
| // All rights reserved. This program and the accompanying materials // |
| // are made available under the terms of the Eclipse Public License v2.0 // |
| // which accompanies this distribution, and is available at // |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////// |
| // Module: EPTF_CLL_DataSource_Apidoc |
| // |
| // Purpose: |
| // This module contains the description of all CLL data elements. |
| // |
| // Current Owner: |
| // EKISTAM |
| // |
| // Last Review Date: |
| // 2015-xx-xx |
| // |
| // Detailed Comments: |
| // This file contains the description of all CLL data elements |
| /////////////////////////////////////////////////////////////// |
| |
| // This is a generated file, do not edit! |
| " & vl_helpApiDoc; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_encAllHelpJSON |
| // |
| // Purpose: |
| // To encode the help info to JSON format |
| // |
| // Parameters: |
| // *in* <EPTF_DataSource_Help> *pl_help* - the help info about the data elements of different sources |
| // |
| // Return Value: |
| // octetstring - the help in JSON format |
| // |
| // Detailed Comments: |
| // Converts the help information into JSON format. |
| // This can be used by GUI. |
| /////////////////////////////////////////////////////////// |
| private external function f_EPTF_DataSource_encAllHelpJSON(in EPTF_DataSource_Help pl_help) return octetstring |
| with { extension "prototype(convert) encode(JSON) errorbehavior(ALL:WARNING)"}; |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_encAllHelpTEXT |
| // |
| // Purpose: |
| // To encode the help info to TEXT format |
| // |
| // Parameters: |
| // *in* <EPTF_DataSource_Help> *pl_help* - the help info about the data elements of different sources |
| // |
| // Return Value: |
| // octetstring - the help in JSON format |
| // |
| // Detailed Comments: |
| // Converts the help information into JSON format. |
| // This can be used by GUI. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_DataSource_encAllHelpTEXT(in EPTF_DataSource_Help pl_help) return charstring { |
| var charstring vl_helpText := ""; |
| for(var integer i:=0; i<sizeof(pl_help.sources); i:=i+1) { |
| vl_helpText := vl_helpText&f_EPTF_DataSource_encHelpTEXT(pl_help.sources[i]); |
| } |
| return vl_helpText; |
| } |
| |
| private function f_EPTF_DataSource_encAllHelpApidoc(in EPTF_DataSource_Help pl_help) return charstring { |
| var charstring vl_helpApiDoc := ""; |
| for(var integer vl_i:=0; vl_i<sizeof(pl_help.sources); vl_i:=vl_i+1) { |
| vl_helpApiDoc := vl_helpApiDoc&f_EPTF_DataSource_encHelpApidoc(pl_help.sources[vl_i]); |
| } |
| return vl_helpApiDoc; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_encHelpJSON_DTE |
| // |
| // Purpose: |
| // To encode the help info to JSON format, throws DTE on error |
| // |
| // Parameters: |
| // *in* <EPTF_DataSource_Help_DataElements> *pl_dataElementsHelp* - the dataElements help |
| // |
| // Return Value: |
| // octetstring - the help in JSON format |
| // |
| // Detailed Comments: |
| // Converts the dataElements help information into JSON format. |
| // This can be used by GUI. |
| /////////////////////////////////////////////////////////// |
| private external function f_EPTF_DataSource_encHelpJSON_DTE(in EPTF_DataSource_Help_DataElements pl_dataElementsHelp) return octetstring |
| with { extension "prototype(convert) encode(JSON) errorbehavior(ALL:ERROR)"}; |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_encHelpJSON |
| // |
| // Purpose: |
| // To encode the help info to JSON format |
| // |
| // Parameters: |
| // *in* <EPTF_DataSource_Help_DataElements> *pl_dataElementsHelp* - the dataElements help |
| // *out* *octetstring* *pl_encodedValue* - the encoded value |
| // |
| // Return Value: |
| // integer - the error code: 0 if successful, non-zero otherwise |
| // |
| // Detailed Comments: |
| // Converts the dataElements help information into JSON format. |
| // This can be used by GUI. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_DataSource_encHelpJSON(in EPTF_DataSource_Help_DataElements pl_dataElementsHelp, out octetstring pl_encodedValue) return integer { |
| @try { |
| pl_encodedValue := f_EPTF_DataSource_encHelpJSON_DTE(pl_dataElementsHelp); |
| } @catch(dte_msg) { |
| pl_encodedValue := char2oct(%definitionId&": "&log2str(dte_msg)); |
| return 1; // encoding error |
| } |
| return 0; //OK |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_decHelpJSON |
| // |
| // Purpose: |
| // To decode the help info from JSON format |
| // |
| // Parameters: |
| // *in* *octetstring* *pl_encodedDataElementsHelp* - the dataElements help in octetstring as JSON format |
| // |
| // Return Value: |
| // EPTF_DataSource_Help_DataElements - the help in TTCN format |
| // |
| // Detailed Comments: |
| // Converts the dataElements help information from JSON format. |
| /////////////////////////////////////////////////////////// |
| private external function f_EPTF_DataSource_decHelpJSON(in octetstring pl_encodedDataElementsHelp) return EPTF_DataSource_Help_DataElements |
| with { extension "prototype(convert) decode(JSON) errorbehavior(ALL:WARNING)"}; |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_encHelpTEXT |
| // |
| // Purpose: |
| // To encode the help info to human readable help text |
| // |
| // Parameters: |
| // *in* <EPTF_DataSource_Help_DataElements> pl_dataElementsHelp - the dataElements help |
| // |
| // Return Value: |
| // charstring - help in readable text format |
| // |
| // Detailed Comments: |
| // Converts the dataElements help information into human readable format. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_DataSource_encHelpTEXT(in EPTF_DataSource_Help_DataElements pl_dataElementsHelp) return charstring { |
| return "\nSource: \""&pl_dataElementsHelp.source&"\"\n"&f_EPTF_DataSource_getHelpTEXTForDataElements(pl_dataElementsHelp.source, pl_dataElementsHelp.dataElements, " ")&"\n"; |
| } |
| |
| private function f_EPTF_DataSource_getHelpTEXTForDataElements( |
| in charstring pl_source, |
| in EPTF_DataSource_Help_DataElementChildren pl_dataElements, |
| in charstring pl_identationlevel |
| ) return charstring { |
| var charstring vl_helpText := ""; |
| |
| for(var integer i:=0; i<sizeof(pl_dataElements); i:=i+1) { |
| vl_helpText := vl_helpText |
| &"\n"&pl_identationlevel& "DataElement: \""& pl_dataElements[i].dataElement.name&"\"" |
| &"\n"&pl_identationlevel& " ValueType : "& ttcn2string(valueof(EPTF_DataSource_ValueType:pl_dataElements[i].dataElement.valueType)); |
| |
| if (isbound(pl_dataElements[i].dataElement.typeDescriptor) and ispresent(pl_dataElements[i].dataElement.typeDescriptor)) { |
| |
| var charstring vl_typeDescription := "\""&pl_dataElements[i].dataElement.typeDescriptor.typeName&"\" item"; |
| |
| if (isbound(pl_dataElements[i].dataElement.typeDescriptor.isListOf) and isbound(pl_dataElements[i].dataElement.typeDescriptor.isListOf) |
| and true == pl_dataElements[i].dataElement.typeDescriptor.isListOf) { |
| vl_typeDescription := "List of "&vl_typeDescription&"s"; |
| } |
| |
| vl_helpText := vl_helpText |
| &"\n"&pl_identationlevel& " TypeDescr: "& vl_typeDescription; |
| } |
| |
| vl_helpText := vl_helpText |
| &"\n"&pl_identationlevel& " Description: "& pl_dataElements[i].dataElement.description |
| &"\n"&pl_identationlevel& " CLI Example: "& f_EPTF_DataSource_getHelpExampleCLICommand(pl_source, pl_dataElements[i].dataElement) |
| &"\n"&pl_identationlevel& "" |
| &"\n"&pl_identationlevel& " Parameters: "; |
| |
| var charstring vl_parameters := ""; |
| if (isbound(pl_dataElements[i].dataElement.parameters) and ispresent(pl_dataElements[i].dataElement.parameters)) { |
| for (var integer p:=0; p<sizeof(pl_dataElements[i].dataElement.parameters); p:=p+1) { |
| vl_parameters := vl_parameters |
| &"\n"&pl_identationlevel& " Parameter name: \""& pl_dataElements[i].dataElement.parameters[p].name&"\""; |
| |
| if (ischosen(pl_dataElements[i].dataElement.parameters[p].typeDescriptor.valueType)) { |
| vl_parameters := vl_parameters |
| &"\n"&pl_identationlevel& " TypeDescr: "& ttcn2string(valueof(EPTF_DataSource_ValueType:pl_dataElements[i].dataElement.parameters[p].typeDescriptor.valueType)); |
| } else { |
| //reference |
| var charstring vl_reference := "\""&pl_dataElements[i].dataElement.parameters[p].typeDescriptor.reference.typeName&"\" item"; |
| |
| if (isbound(pl_dataElements[i].dataElement.parameters[p].typeDescriptor.reference.isIndexInListOf) |
| and ispresent(pl_dataElements[i].dataElement.parameters[p].typeDescriptor.reference.isIndexInListOf) |
| and true == pl_dataElements[i].dataElement.parameters[p].typeDescriptor.reference.isIndexInListOf) { |
| vl_reference := "Index in the list of "&vl_reference&"s"; |
| } |
| |
| vl_parameters := vl_parameters |
| &"\n"&pl_identationlevel& " TypeDescr: "& vl_reference; |
| |
| } |
| |
| vl_parameters := vl_parameters |
| &"\n"&pl_identationlevel& " Description : "& pl_dataElements[i].dataElement.parameters[p].description |
| &"\n"&pl_identationlevel& " Example Value : \""& pl_dataElements[i].dataElement.parameters[p].exampleValue&"\""; |
| } |
| } |
| if (vl_parameters=="") { |
| vl_parameters := "None." |
| } |
| vl_helpText := vl_helpText |
| &vl_parameters; |
| if (isbound(pl_dataElements[i].children) and ispresent(pl_dataElements[i].children)) { |
| var charstring vl_childInfo := f_EPTF_DataSource_getHelpTEXTForDataElements(pl_source,pl_dataElements[i].children,pl_identationlevel & " "); |
| if (vl_childInfo != "") { |
| vl_helpText := vl_helpText &"\n\n"&pl_identationlevel&" Children: "&vl_childInfo; |
| } |
| } |
| vl_helpText := vl_helpText&"\n"; |
| } |
| return vl_helpText; |
| } |
| |
| private function f_EPTF_DataSource_encHelpApidoc(in EPTF_DataSource_Help_DataElements pl_dataElementsHelp) return charstring { |
| return "\n// Group: \""&pl_dataElementsHelp.source&"\"\n//\ngroup "&pl_dataElementsHelp.source&" {\n"&f_EPTF_DataSource_getHelpApidocForDataElements(pl_dataElementsHelp.source, pl_dataElementsHelp.dataElements, " ")&"} // ~group \n"; |
| } |
| |
| private function f_EPTF_DataSource_getHelpApidocForDataElements( |
| in charstring pl_source, |
| in EPTF_DataSource_Help_DataElementChildren pl_dataElements, |
| in charstring pl_identationlevel |
| ) return charstring { |
| var charstring vl_helpApiDoc := ""; |
| |
| for(var integer i:=0; i<sizeof(pl_dataElements); i:=i+1) { |
| vl_helpApiDoc := vl_helpApiDoc |
| &"\n"&pl_identationlevel& "// Function: \""& pl_dataElements[i].dataElement.name&"\"" |
| &"\n"&pl_identationlevel& "//" |
| &"\n"&pl_identationlevel& "// *Description*: "& pl_dataElements[i].dataElement.description |
| &"\n"&pl_identationlevel& "//" |
| &"\n"&pl_identationlevel& "// *ValueType*: "& ttcn2string(valueof(EPTF_DataSource_ValueType:pl_dataElements[i].dataElement.valueType)); |
| |
| if (isbound(pl_dataElements[i].dataElement.typeDescriptor) and ispresent(pl_dataElements[i].dataElement.typeDescriptor)) { |
| |
| var charstring vl_typeDescription := "\""&pl_dataElements[i].dataElement.typeDescriptor.typeName&"\" item"; |
| |
| if (isbound(pl_dataElements[i].dataElement.typeDescriptor.isListOf) and isbound(pl_dataElements[i].dataElement.typeDescriptor.isListOf) |
| and true == pl_dataElements[i].dataElement.typeDescriptor.isListOf) { |
| vl_typeDescription := "List of "&vl_typeDescription&"s"; |
| } |
| |
| vl_helpApiDoc := vl_helpApiDoc |
| &"\n"&pl_identationlevel& "//" |
| &"\n"&pl_identationlevel& "// *TypeDescriptor*: "& vl_typeDescription; |
| } |
| |
| vl_helpApiDoc := vl_helpApiDoc |
| &"\n"&pl_identationlevel& "//" |
| &"\n"&pl_identationlevel& "// *CLI Example*: "& f_EPTF_DataSource_getHelpExampleCLICommand(pl_source, pl_dataElements[i].dataElement) |
| &"\n"&pl_identationlevel& "//" |
| &"\n"&pl_identationlevel& "// *Parameters*: "; |
| |
| var charstring vl_parameters := ""; |
| if (isbound(pl_dataElements[i].dataElement.parameters) and ispresent(pl_dataElements[i].dataElement.parameters)) { |
| for (var integer p:=0; p<sizeof(pl_dataElements[i].dataElement.parameters); p:=p+1) { |
| vl_parameters := vl_parameters |
| &"\n"&pl_identationlevel& "// - *\""& pl_dataElements[i].dataElement.parameters[p].name&"\"*"; |
| |
| if (ischosen(pl_dataElements[i].dataElement.parameters[p].typeDescriptor.valueType)) { |
| vl_parameters := vl_parameters |
| &"\n"&pl_identationlevel& "// - TypeDescriptor - "& ttcn2string(valueof(EPTF_DataSource_ValueType:pl_dataElements[i].dataElement.parameters[p].typeDescriptor.valueType)); |
| } else { |
| //reference |
| var charstring vl_reference := "\""&pl_dataElements[i].dataElement.parameters[p].typeDescriptor.reference.typeName&"\" item"; |
| |
| if (isbound(pl_dataElements[i].dataElement.parameters[p].typeDescriptor.reference.isIndexInListOf) |
| and ispresent(pl_dataElements[i].dataElement.parameters[p].typeDescriptor.reference.isIndexInListOf) |
| and true == pl_dataElements[i].dataElement.parameters[p].typeDescriptor.reference.isIndexInListOf) { |
| vl_reference := "Index in the list of "&vl_reference&"s"; |
| } |
| |
| vl_parameters := vl_parameters |
| &"\n"&pl_identationlevel& "// - TypeDescriptor - "& vl_reference; |
| |
| } |
| |
| vl_parameters := vl_parameters |
| &"\n"&pl_identationlevel& "// - Description - "& pl_dataElements[i].dataElement.parameters[p].description |
| &"\n"&pl_identationlevel& "// - Example Value - \""& pl_dataElements[i].dataElement.parameters[p].exampleValue&"\"" |
| &"\n"&pl_identationlevel& "//"; |
| } |
| } |
| if (vl_parameters=="") { |
| vl_parameters := "None." |
| } |
| vl_helpApiDoc := vl_helpApiDoc |
| &vl_parameters; |
| if (isbound(pl_dataElements[i].children) and ispresent(pl_dataElements[i].children)) { |
| var charstring vl_childInfo := f_EPTF_DataSource_getHelpApidocForDataElements(pl_source,pl_dataElements[i].children,pl_identationlevel & " "); |
| if (vl_childInfo != "") { |
| vl_helpApiDoc := vl_helpApiDoc &"\n"&pl_identationlevel&"// \n"&vl_childInfo;//Children: |
| } |
| } |
| vl_helpApiDoc := vl_helpApiDoc&"\n"; |
| } |
| return vl_helpApiDoc; |
| } |
| |
| private function f_EPTF_DataSource_getHelpExampleCLICommand( |
| in charstring pl_source, |
| in EPTF_DataSource_Help_DataElement pl_dataElementHelp |
| ) return charstring { |
| var charstring vl_exampleCLICommand := "ds get <datadescription xmlns='http://ttcn.ericsson.se/protocolModules/xtdp/xtdl' element='" |
| &pl_dataElementHelp.name&"' source='"&pl_source&"'> <params> "; |
| if (isbound(pl_dataElementHelp.parameters) and ispresent(pl_dataElementHelp.parameters)) { |
| for(var integer i:=0; i<sizeof(pl_dataElementHelp.parameters); i:=i+1) { |
| vl_exampleCLICommand := vl_exampleCLICommand |
| &" <dataparam name='"&pl_dataElementHelp.parameters[i].name |
| &"' value='"&pl_dataElementHelp.parameters[i].exampleValue&"'/>"; |
| } |
| } |
| vl_exampleCLICommand := vl_exampleCLICommand & " </params> </datadescription>"; |
| return vl_exampleCLICommand; |
| } |
| |
| // returns those elements that correspond to the specified one: |
| private function f_EPTF_DataSource_filterHelpForElement( |
| in charstring pl_element, |
| in EPTF_DataSource_Help_DataElementChildren pl_helpList |
| ) return EPTF_DataSource_Help_DataElementChildren { |
| var EPTF_DataSource_Help_DataElementChildren vl_result := {}; |
| var integer j :=0; |
| for(var integer i:=0; i<sizeof(pl_helpList); i:=i+1) { |
| |
| if (pl_helpList[i].dataElement.name == pl_element or pl_element=="") { |
| vl_result[j].dataElement := pl_helpList[i].dataElement; |
| j:=j+1; |
| } |
| if ((not isbound(pl_helpList[i].children)) or (not ispresent(pl_helpList[i].children))) { |
| pl_helpList[i].children := {}; |
| } |
| vl_result := vl_result & f_EPTF_DataSource_filterHelpForElement(pl_element,pl_helpList[i].children); |
| } |
| return vl_result; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_handleHelp |
| // |
| // Purpose: |
| // This function can be used in the dataHander to return the help info |
| // for a datasource. The DataElement is <c_EPTF_DataSource_dataElement_Help> |
| // |
| // Parameters: |
| // *out* <EPTF_Var_DirectContent> *pl_dataValue* - this is the value of the data |
| // that stores the values of the data on the local component |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in* <EPTF_DataSource_Params> *pl_params* - the parameters of the datasource |
| // *in* <EPTF_DataSource_Help_DataElementChildren> pl_dataElementHelp - the dataElement's help information |
| // |
| // Return Value: |
| // integer - error code, 0 if OK, nonzero in case of error. |
| // When error code is not zero pl_dataValue will contain an error message. |
| // |
| // Detailed Comments: |
| // Converts the dataElements help information into the given format. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_handleHelp( |
| out EPTF_Var_DirectContent pl_dataValue, |
| in charstring pl_source, |
| in EPTF_DataSource_Params pl_params, |
| in EPTF_DataSource_Help_DataElementChildren pl_dataElementHelp |
| ) //runs on EPTF_DataSource_CT //EPTF_DataSourceClient_CT ?? |
| return integer { |
| var EPTF_CharstringList pl_result := {} |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameHelpFormat}, |
| pl_result |
| ); |
| var charstring vl_format; |
| if (sizeof(pl_result)==0) { |
| vl_format := c_EPTF_DataSource_helpFormatJSON; // default format is JSON |
| } else { |
| if(sizeof(pl_result)==1 and (pl_result[0]==c_EPTF_DataSource_helpFormatJSON or pl_result[0]==c_EPTF_DataSource_helpFormatTEXT)) { |
| vl_format := pl_result[0]; |
| } else { |
| // invalid help format |
| pl_dataValue := { charstringVal := log2str(%definitionId&": Invalid help format: ",c_EPTF_DataSource_dataElement_Help, |
| ": Should be one of: ", EPTF_CharstringList:{c_EPTF_DataSource_helpFormatJSON, c_EPTF_DataSource_helpFormatTEXT}) }; |
| return -33; // invalid help format |
| } |
| } |
| if (vl_format==c_EPTF_DataSource_helpFormatJSON) { |
| var octetstring vl_encodedValue; |
| if(0!=f_EPTF_DataSource_encHelpJSON({pl_source,pl_dataElementHelp},vl_encodedValue)) { |
| pl_dataValue := { charstringVal := log2str("Error: Cannot get help for source ",pl_source," params ",log2str(pl_params)," dataElementHelp ",pl_dataElementHelp,": ")&oct2char(vl_encodedValue) }; |
| return -44; |
| } |
| pl_dataValue := { octetstringVal := vl_encodedValue }; |
| } else if (vl_format==c_EPTF_DataSource_helpFormatTEXT){ |
| pl_dataValue := { charstringVal := f_EPTF_DataSource_encHelpTEXT({pl_source,pl_dataElementHelp}) }; |
| } else { |
| // cannot happen: exited earlier with error code -33 |
| } |
| return 0; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_Help_handler |
| // |
| // Purpose: |
| // This function can be used in the dataHander to return the help info |
| // for a datasource. The DataElement is <c_EPTF_DataSource_dataElement_Help> |
| // |
| // Parameters: |
| // *out* <EPTF_Var_DirectContent> *pl_dataValue* - this is the value of the data |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in* <EPTF_DataSource_Params> *pl_params* - the parameters of the datasource |
| // |
| // Return Value: |
| // integer - error code, 0 if OK, nonzero in case of error. |
| // When error code is not zero pl_dataValue will contain an error message. |
| // |
| // Detailed Comments: |
| // Converts the dataElements help information into the given format. |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_DataSource_Help_handler( |
| out EPTF_Var_DirectContent pl_dataValue, |
| in charstring pl_source, |
| in EPTF_DataSource_Params pl_params |
| ) runs on EPTF_DataSource_CT //EPTF_DataSourceClient_CT ?? |
| return integer { |
| var EPTF_CharstringList pl_result := {} |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameHelpFormat}, |
| pl_result |
| ); |
| var charstring vl_format; |
| if (sizeof(pl_result)==0 or sizeof(pl_result)==1 and pl_result[0]=="") { |
| vl_format := c_EPTF_DataSource_helpFormatJSON; // default format is JSON |
| } else if(sizeof(pl_result)==1 and (pl_result[0]==c_EPTF_DataSource_helpFormatJSON or pl_result[0]==c_EPTF_DataSource_helpFormatTEXT)) { |
| vl_format := pl_result[0]; |
| } else { |
| // invalid help format |
| pl_dataValue := { charstringVal := log2str(%definitionId&": Invalid help format: ",pl_result[0], |
| ": Should be one of: ", EPTF_CharstringList:{c_EPTF_DataSource_helpFormatJSON, c_EPTF_DataSource_helpFormatTEXT}) }; |
| return -33; // invalid help format |
| } |
| |
| // source |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameSource}, |
| pl_result |
| ); |
| var charstring vl_source; |
| if (sizeof(pl_result)==0) { |
| vl_source := ""; // default source is 'all' |
| } else if(sizeof(pl_result)==1) { |
| vl_source := pl_result[0]; |
| } |
| |
| // element |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameElement}, |
| pl_result |
| ); |
| var charstring vl_element; |
| if (sizeof(pl_result)==0) { |
| vl_element := ""; // default element is 'all' |
| } else if(sizeof(pl_result)==1) { |
| vl_element := pl_result[0]; |
| } |
| |
| if (vl_format==c_EPTF_DataSource_helpFormatJSON) { |
| pl_dataValue := { octetstringVal := f_EPTF_DataSource_getHelpJSON(vl_source,vl_element) }; |
| } else if (vl_format==c_EPTF_DataSource_helpFormatTEXT){ |
| pl_dataValue := { charstringVal := f_EPTF_DataSource_getHelpTEXT(vl_source,vl_element) }; |
| } else { |
| // cannot happen: exited earlier with error code -33 |
| } |
| return 0; |
| } |
| |
| |
| private function f_EPTF_DataSource_handleBuiltInDataElements( |
| out charstring pl_dataVarName, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {} |
| ) runs on EPTF_DataSource_CT return integer { |
| if (pl_source!=c_EPTF_DataSource_sourceId) { |
| pl_dataVarName := "It should be called with pl_source="&c_EPTF_DataSource_sourceId; |
| return -20; // not DataSource element |
| } |
| |
| pl_dataVarName := ""; // set it to invalid |
| var EPTF_CharstringList pl_result := {} |
| select( pl_element ) |
| { |
| // data element: c_EPTF_DataSource_dataElement_PTCs |
| case(c_EPTF_DataSource_dataElement_PTCs) { |
| if (0 == f_EPTF_DataSource_getParams(pl_params, |
| {c_EPTF_DataSource_paramNameSource}, |
| pl_result, |
| refers(f_EPTF_DataSource_DScheckParams))) { |
| var charstring vl_source := pl_result[0]; |
| pl_dataVarName := c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_PTCs&"."&vl_source; |
| |
| // automatically create var if does not exist: |
| var integer vl_varIdx := f_EPTF_Var_getId(pl_dataVarName); |
| if(vl_varIdx == -1) { |
| f_EPTF_Var_newCharstringlist(pl_dataVarName, {}, vl_varIdx); |
| } |
| } else { |
| // this is just to write previous warning messages as well |
| if (sizeof(pl_params)!=1) { |
| pl_dataVarName := log2str(%definitionId&": Invalid number of parameters for dataSource ",pl_source, " and element ",pl_element, |
| ": Only one parameter has to be specified"); |
| //return 1; // invalid number of params |
| } else if(pl_params[0].paramName != c_EPTF_DataSource_paramNameSource) { |
| pl_dataVarName := log2str(%definitionId&": Invalid name of parameter for dataSource ",pl_source, " and element ",pl_element, |
| ": The name of parameter should be ",c_EPTF_DataSource_paramNameSource); |
| //return 2; // invalid name of params |
| } |
| } |
| } |
| case(c_EPTF_DataSource_dataElement_Sources) { |
| if (0 == f_EPTF_DataSource_getParams(pl_params, |
| {}, |
| pl_result, |
| refers(f_EPTF_DataSource_DScheckParams))) { |
| pl_dataVarName := c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_Sources; |
| var integer vl_varIdx := f_EPTF_Var_getId(pl_dataVarName); |
| |
| // automatically create var if does not exist: |
| if(vl_varIdx == -1) { |
| // cannot be reached, var is created in init function |
| f_EPTF_Var_newCharstringlist(pl_dataVarName, {c_EPTF_DataSource_sourceId}, vl_varIdx); |
| } |
| } else { |
| // this is just to write previous warning messages as well |
| if (sizeof(pl_params)!=0) { |
| pl_dataVarName := log2str(%definitionId&": Invalid number of parameters for dataSource ",pl_source, " and element ",pl_element, |
| ": No parameter has to be specified"); |
| //return 1; // invalid number of params |
| } |
| } |
| } |
| case else |
| { |
| // invalid element |
| pl_dataVarName := log2str(%definitionId&": Invalid dataElement for dataSource ",pl_source, ": ",pl_element, |
| ": Should be one of: ", EPTF_CharstringList:{c_EPTF_DataSource_dataElement_Help, c_EPTF_DataSource_dataElement_PTCs, c_EPTF_DataSource_dataElement_Sources}); |
| return -22; // invalid element |
| } |
| } |
| var integer vl_dataElementVarIdx := f_EPTF_Var_getId(pl_dataVarName); |
| if(vl_dataElementVarIdx == -1){ |
| pl_dataVarName := log2str(%definitionId&": Invalid iterator or externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)&"\n:"&pl_dataVarName; |
| return -1; |
| } |
| return 0; |
| } |
| |
| private function f_EPTF_DataSource_getResponseForGetDataValueMsg( |
| out EPTF_Var_DirectContent pl_dataValue, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_Filter pl_filter := c_EPTF_DataSource_Filter_empty, |
| in EPTF_Var_CT pl_ownerCompRef |
| ) runs on EPTF_DataSource_CT return integer { |
| var integer vl_errorCode := 0; |
| // have to send request to client: |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getDataValue:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(pl_ownerCompRef))); |
| // wait for response |
| if (f_EPTF_Semaphore_waitForUnlock(vl_getDataId,tsp_EPTF_DataSource_maxWaitTime)) { |
| // max wait time expired before response received: |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Communication error: No response received for getData message: ",vl_getDataId)); |
| pl_dataValue.charstringVal := log2str(%definitionId&": Communication error: No response received for getData message: ",vl_getDataId); |
| return -1; |
| } |
| |
| // copy the values from the message database because it might be possible that they will be overwritten because |
| // the semaphore is released and there is a blocking statement before they are used: |
| vl_errorCode := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValueResponse.errorCode; |
| pl_dataValue := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValueResponse.dataValue; |
| //var EPTF_DataSourceClient_CT vl_ownerCompRef := v_EPTF_DataSource_Msg_List[vl_getDataId].dataValue.ownerCompRef; // value in message is not used |
| |
| // if returned error code is non-0, update the error message: |
| if (vl_errorCode!=0) { |
| if (not ischosen(pl_dataValue.charstringVal)) { |
| pl_dataValue := {charstringVal := "Error info: "&ttcn2string(pl_dataValue)}; // error message was not present => set it to the string value of provided value |
| //append general text: |
| pl_dataValue.charstringVal := log2str(%definitionId&": Invalid iterator or externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)& |
| "\nReason: "&pl_dataValue.charstringVal; |
| } |
| f_EPTF_DataSource_warning(pl_dataValue.charstringVal&"\nError code: "&int2str(vl_errorCode)); |
| } |
| |
| return vl_errorCode; |
| } |
| |
| private function f_EPTF_DataSource_getResponseForGetDataValueMsg_nonblocking( |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_Filter pl_filter := c_EPTF_DataSource_Filter_empty, |
| in EPTF_Var_CT pl_ownerCompRef, |
| in EPTF_DataSource_GetDataValueHandler pl_getDataValueHandler |
| ) runs on EPTF_DataSource_CT { |
| |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getDataValue:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter |
| }},f_EPTF_DataSourceClient_downcast(f_EPTF_Base_upcast(pl_ownerCompRef))); |
| v_EPTF_DataSource_GetDataValueHandler_DB[vl_getDataId] := pl_getDataValueHandler; |
| } |
| |
| private function f_EPTF_DataSource_handleBuiltInDataValues( |
| out EPTF_Var_DirectContent pl_dataValue, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_Filter pl_filter := c_EPTF_DataSource_Filter_empty |
| ) runs on EPTF_DataSource_CT return integer { |
| if (pl_source!=c_EPTF_DataSource_sourceId) { |
| return -20; // not DataSource element |
| } |
| |
| var integer vl_errorCode := -1; |
| pl_dataValue := {unknownVal := {omit}}; // set it to invalid |
| |
| select( pl_element ) |
| { |
| case(c_EPTF_DataSource_dataElement_Help) { |
| vl_errorCode := f_EPTF_DataSource_Help_handler(pl_dataValue,pl_source,pl_params); |
| } |
| case(c_EPTF_DataSource_dataElement_sizeOf) { |
| var EPTF_CharstringList vl_result; |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameSource, |
| c_EPTF_DataSource_paramNamePTCName}, |
| vl_result); |
| var charstring vl_source := vl_result[0]; |
| var charstring vl_ptcName := vl_result[1]; |
| |
| if (vl_source == c_EPTF_DataSource_sourceId) { |
| var charstring vl_element; |
| var EPTF_DataSource_Params vl_params; |
| vl_errorCode := f_EPTF_DataSource_getRequestPartsFromParams(pl_params, vl_source, vl_ptcName, vl_element, vl_params); |
| if (vl_errorCode == 0) { |
| var EPTF_Var_DirectContent vl_dataValueResponseForOriginalRequest; |
| vl_errorCode := f_EPTF_DataSource_handleBuiltInDataValues( |
| vl_dataValueResponseForOriginalRequest, |
| vl_source, |
| vl_ptcName, |
| vl_element, |
| vl_params |
| ); |
| if (vl_errorCode == 0) { |
| var integer vl_size := f_EPTF_DataSource_getSizeOfDataValue(vl_dataValueResponseForOriginalRequest); |
| pl_dataValue := {intVal := vl_size}; |
| } else { |
| // could not get the element |
| var charstring vl_msg := "Could not determine the size of the dataelement"; |
| if (ischosen(vl_dataValueResponseForOriginalRequest.charstringVal)) { |
| vl_msg := vl_msg & ": " & vl_dataValueResponseForOriginalRequest.charstringVal; |
| } |
| pl_dataValue := {charstringVal := vl_msg}; |
| } |
| } else { |
| // wrong param format |
| var charstring vl_msg := "Could not determine the size of the dataelement, invalid parameters: " & log2str(pl_params); |
| pl_dataValue := {charstringVal := vl_msg}; |
| } |
| } else { |
| var EPTF_Var_CT vl_ownerCompRef; |
| vl_errorCode := f_EPTF_DataSource_getOwnerCompRef(vl_source, vl_ptcName, vl_ownerCompRef); |
| f_EPTF_DataSource_replaceParams(pl_params, {{paramName := c_EPTF_DataSource_paramNamePTCName, paramValue := vl_ptcName}}); |
| if (vl_errorCode == 0) { |
| return f_EPTF_DataSource_getResponseForGetDataValueMsg( |
| pl_dataValue, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter, |
| vl_ownerCompRef |
| ); |
| } else { |
| pl_dataValue := {charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName)}; |
| return vl_errorCode; |
| } |
| } |
| } |
| case(c_EPTF_DataSource_dataElement_isWritable) { |
| var EPTF_CharstringList vl_result; |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameSource, |
| c_EPTF_DataSource_paramNamePTCName}, |
| vl_result); |
| var charstring vl_source := vl_result[0]; |
| var charstring vl_ptcName := vl_result[1]; |
| |
| if (vl_source == c_EPTF_DataSource_sourceId) { |
| var charstring vl_element; |
| var EPTF_DataSource_Params vl_params; |
| vl_errorCode := f_EPTF_DataSource_getRequestPartsFromParams(pl_params, vl_source, vl_ptcName, vl_element, vl_params); |
| if (vl_errorCode == 0) { |
| // the built in elements are not writable |
| pl_dataValue := {boolVal := false}; |
| } else { |
| // wrong param format |
| var charstring vl_msg := "Could not determine whether the dataelement is writable, invalid parameters: " & log2str(pl_params); |
| pl_dataValue := {charstringVal := vl_msg}; |
| } |
| } else { |
| var EPTF_Var_CT vl_ownerCompRef; |
| vl_errorCode := f_EPTF_DataSource_getOwnerCompRef(vl_source, vl_ptcName, vl_ownerCompRef); |
| f_EPTF_DataSource_replaceParams(pl_params, {{paramName := c_EPTF_DataSource_paramNamePTCName, paramValue := vl_ptcName}}); |
| if (vl_errorCode == 0) { |
| return f_EPTF_DataSource_getResponseForGetDataValueMsg( |
| pl_dataValue, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter, |
| vl_ownerCompRef |
| ); |
| } else { |
| pl_dataValue := {charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName)}; |
| return vl_errorCode; |
| } |
| } |
| } |
| case else |
| { |
| // try to find built-in dataElement: |
| var charstring vl_dataVarName; |
| vl_errorCode := f_EPTF_DataSource_handleBuiltInDataElements(vl_dataVarName,pl_source,pl_ptcName,pl_element,pl_params); |
| if (vl_errorCode==0) { |
| // read dataValue from variable: |
| var integer vl_dataVarIdx := f_EPTF_Var_getId(vl_dataVarName); // var always exists here (errorCode==0) |
| f_EPTF_Var_getContent(vl_dataVarIdx,pl_dataValue); |
| } else { |
| |
| // try to find built-in condition: |
| var boolean vl_conditionValue; |
| vl_errorCode := f_EPTF_DataSource_handleBuiltInConditions(vl_conditionValue,pl_source,pl_ptcName,pl_element,pl_params); |
| if (vl_errorCode==0) { |
| pl_dataValue := {boolVal := vl_conditionValue} |
| } else { |
| // set error message if error code is 11 (no such element): |
| if (vl_errorCode==11 and isbound(vl_dataVarName)) { |
| pl_dataValue := {charstringVal := vl_dataVarName}; |
| } else { |
| pl_dataValue := {charstringVal := log2str("Invalid parameters for condition: ", pl_element)}; |
| } |
| } |
| |
| } |
| } |
| } |
| |
| return vl_errorCode; |
| } |
| |
| private function f_EPTF_DataSource_handleBuiltInDataValues_nonblocking( |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_Filter pl_filter := c_EPTF_DataSource_Filter_empty, |
| in EPTF_DataSource_GetDataValueHandler pl_getDataValueHandler := cg_EPTF_DataSource_GetDataValueHandler_null |
| ) runs on EPTF_DataSource_CT return integer { |
| var EPTF_Var_DirectContent vl_dataValue; |
| if (pl_source!=c_EPTF_DataSource_sourceId) { |
| return -20; // not DataSource element |
| } |
| |
| var integer vl_errorCode := -1; |
| vl_dataValue := {unknownVal := {omit}}; // set it to invalid |
| select( pl_element ) |
| { |
| case(c_EPTF_DataSource_dataElement_Help) { |
| vl_errorCode := f_EPTF_DataSource_Help_handler(vl_dataValue,pl_source,pl_params); |
| } |
| case(c_EPTF_DataSource_dataElement_sizeOf) { |
| vl_errorCode := 0; |
| |
| var EPTF_CharstringList vl_result; |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameSource, |
| c_EPTF_DataSource_paramNamePTCName}, |
| vl_result); |
| var charstring vl_source := vl_result[0]; |
| var charstring vl_ptcName := vl_result[1]; |
| |
| if (vl_source == c_EPTF_DataSource_sourceId) { |
| var charstring vl_element; |
| var EPTF_DataSource_Params vl_params; |
| vl_errorCode := f_EPTF_DataSource_getRequestPartsFromParams(pl_params, vl_source, vl_ptcName, vl_element, vl_params); |
| if (vl_errorCode == 0) { |
| var EPTF_Var_DirectContent vl_dataValueResponseForOriginalRequest; |
| // TODO : call nonblocking version |
| vl_errorCode := f_EPTF_DataSource_handleBuiltInDataValues( |
| vl_dataValueResponseForOriginalRequest, |
| vl_source, |
| vl_ptcName, |
| vl_element, |
| vl_params |
| ); |
| if (vl_errorCode == 0) { |
| var integer vl_size := f_EPTF_DataSource_getSizeOfDataValue(vl_dataValueResponseForOriginalRequest); |
| vl_dataValue := {intVal := vl_size}; |
| } else { |
| // could not get the element |
| var charstring vl_msg := "Could not determine the size of the dataelement"; |
| if (ischosen(vl_dataValueResponseForOriginalRequest.charstringVal)) { |
| vl_msg := vl_msg & ": " & vl_dataValueResponseForOriginalRequest.charstringVal; |
| } |
| vl_dataValue := {charstringVal := vl_msg}; |
| } |
| } else { |
| // wrong param format |
| var charstring vl_msg := "Could not determine the size of the dataelement, invalid parameters: " & log2str(pl_params); |
| vl_dataValue := {charstringVal := vl_msg}; |
| } |
| } else { |
| var EPTF_Var_CT vl_ownerCompRef; |
| vl_errorCode := f_EPTF_DataSource_getOwnerCompRef(vl_source, vl_ptcName, vl_ownerCompRef); |
| f_EPTF_DataSource_replaceParams(pl_params, {{paramName := c_EPTF_DataSource_paramNamePTCName, paramValue := vl_ptcName}}); |
| if (vl_errorCode == 0) { |
| f_EPTF_DataSource_getResponseForGetDataValueMsg_nonblocking( |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter, |
| vl_ownerCompRef, |
| pl_getDataValueHandler |
| ); |
| return 0; // OK |
| } else { |
| vl_dataValue := {charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName)}; |
| } |
| } |
| } |
| case(c_EPTF_DataSource_dataElement_isWritable) { |
| vl_errorCode := 0; |
| |
| var EPTF_CharstringList vl_result; |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameSource, |
| c_EPTF_DataSource_paramNamePTCName}, |
| vl_result); |
| var charstring vl_source := vl_result[0]; |
| var charstring vl_ptcName := vl_result[1]; |
| |
| if (vl_source == c_EPTF_DataSource_sourceId) { |
| var charstring vl_element; |
| var EPTF_DataSource_Params vl_params; |
| vl_errorCode := f_EPTF_DataSource_getRequestPartsFromParams(pl_params, vl_source, vl_ptcName, vl_element, vl_params); |
| if (vl_errorCode == 0) { |
| // the built in elements are not writable |
| vl_dataValue := {boolVal := false}; |
| } else { |
| // wrong param format |
| var charstring vl_msg := "Could not determine whether the dataelement is writable, invalid parameters: " & log2str(pl_params); |
| vl_dataValue := {charstringVal := vl_msg}; |
| } |
| } else { |
| var EPTF_Var_CT vl_ownerCompRef; |
| vl_errorCode := f_EPTF_DataSource_getOwnerCompRef(vl_source, vl_ptcName, vl_ownerCompRef); |
| f_EPTF_DataSource_replaceParams(pl_params, {{paramName := c_EPTF_DataSource_paramNamePTCName, paramValue := vl_ptcName}}); |
| if (vl_errorCode == 0) { |
| f_EPTF_DataSource_getResponseForGetDataValueMsg_nonblocking( |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_filter, |
| vl_ownerCompRef, |
| pl_getDataValueHandler |
| ); |
| return 0; // OK |
| } else { |
| vl_dataValue := {charstringVal := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName)}; |
| } |
| } |
| } |
| case else |
| { |
| // try to find built-in dataElement: |
| var charstring vl_dataVarName; |
| // f_EPTF_DataSource_handleBuiltInDataElements is a nonblocking currently |
| vl_errorCode := f_EPTF_DataSource_handleBuiltInDataElements(vl_dataVarName,pl_source,pl_ptcName,pl_element,pl_params); |
| if (vl_errorCode==0) { |
| // read dataValue from variable: |
| var integer vl_dataVarIdx := f_EPTF_Var_getId(vl_dataVarName); // var always exists here (errorCode==0) |
| f_EPTF_Var_getContent(vl_dataVarIdx,vl_dataValue); |
| } else if (vl_errorCode == -22) { |
| // try to find built-in condition if there was no such dataElement: |
| return f_EPTF_DataSource_handleBuiltInConditionsValue_nonblocking(pl_source,pl_ptcName,pl_element,pl_params,pl_getDataValueHandler); |
| } |
| if (vl_errorCode!=0) { |
| // set error message if error code is non-zero: |
| if (isbound(vl_dataVarName)) { |
| vl_dataValue := {charstringVal := vl_dataVarName}; |
| } |
| } |
| } |
| } |
| |
| if (vl_errorCode!=0) { |
| if (not ischosen(vl_dataValue.charstringVal)) { |
| vl_dataValue := {charstringVal := "Error info: "&ttcn2string(vl_dataValue)}; // error message was not present => set it to the string value of provided value |
| } |
| //append general text: |
| vl_dataValue.charstringVal := log2str(%definitionId&": Invalid iterator or externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)& |
| "\nReason: "&vl_dataValue.charstringVal; |
| f_EPTF_DataSource_warning(vl_dataValue.charstringVal&"\nError code: "&int2str(vl_errorCode)); |
| } |
| |
| // call handler: |
| if (pl_getDataValueHandler.getDataValueHandler!=null) { |
| pl_getDataValueHandler.getDataValueHandler.apply( |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_dataValue := vl_dataValue, // the value of the data. In case errorCode!=0: it contains the error message as charstringVal |
| // user data |
| pl_userData := pl_getDataValueHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| |
| private function f_EPTF_DataSource_handleBuiltInSetDataValue( |
| inout EPTF_Var_DirectContent pl_dataValue, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_IntegerList pl_indexList := {} |
| ) runs on EPTF_DataSource_CT return integer { |
| if (pl_source!=c_EPTF_DataSource_sourceId) { |
| return -20; // not DataSource element |
| } |
| |
| var integer vl_errorCode := -1; |
| vl_errorCode := 1; |
| pl_dataValue := {charstringVal := "Value cannot be changed"}; // set it to invalid |
| return vl_errorCode; |
| } |
| |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getCondition |
| // |
| // Purpose: |
| // To get the value of a given condition specified by the method |
| // |
| // Parameters: |
| // *out boolean pl_conditionValue* - this is the value the given method |
| // returned for the condition |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_method* - the method that should be called to get the condition |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters to pass to the method (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames (does not apply for built-in conditions) |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero if pl_conditionValue is not valid |
| // |
| // Detailed Comments: |
| // The function associated for the given method is called |
| // on the component that registered the source and ptc name. |
| // The params are passed to it as additional arguments. |
| // The handler function returns a boolean which is set in the pl_conditionValue |
| // argument. The error code returned by the handler function is returned by this function |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getCondition( |
| out boolean pl_conditionValue, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_method, |
| in EPTF_DataSource_Params pl_params := {} |
| ) runs on EPTF_DataSource_CT return integer { |
| // do not change the order of the parameters for built-in conditions! |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| return f_EPTF_DataSource_handleBuiltInConditions( |
| pl_conditionValue, |
| pl_source, |
| pl_ptcName, |
| pl_method, |
| pl_params |
| ); // internal commands handled successfully, or an error occured |
| } |
| |
| f_EPTF_DataSource_sortParams(pl_params); |
| //find if pl_dataVarName already exists |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| // try to find without PTC name if pl_ptcName=="": |
| if (pl_ptcName=="") { |
| var integer vl_counter; |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName,": Source is not registered")); |
| return 3; |
| } else { |
| if (vl_counter>1) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified")); |
| return 2; |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| } |
| } |
| } else { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName,": Source is not registered")); |
| return 1; |
| } |
| } |
| |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getCondition:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_method, |
| pl_params |
| }},v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef); |
| // wait for response |
| if (f_EPTF_Semaphore_waitForUnlock(vl_getDataId,tsp_EPTF_DataSource_maxWaitTime)) { |
| // max wait time expired before response received: |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Communication error: No response received for getData message: ",vl_getDataId)); |
| return -1; |
| } |
| |
| // if returned error code is 0 (no error) set the result: |
| if (v_EPTF_DataSource_Msg_List[vl_getDataId].conditionValue.errorCode==0) { |
| pl_conditionValue := v_EPTF_DataSource_Msg_List[vl_getDataId].conditionValue.conditionValue; |
| } |
| |
| return v_EPTF_DataSource_Msg_List[vl_getDataId].conditionValue.errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getCondition_nonBlocking |
| // |
| // Purpose: |
| // To get the value of a given condition specified by the method in non-blocking way. |
| // The specified handler is called when the response arrives. |
| // |
| // Parameters: |
| // *in charstring pl_source* - the name of the dataSource 'feature' |
| // *in charstring pl_ptcName* - the name of the PTC |
| // (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored) |
| // *in charstring pl_method* - the method that should be called to get the condition |
| // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters to pass to the method (default: {}) |
| // The parameters are sorted lexicographically according to the paramNames (does not apply for built-in conditions) |
| // |
| // Return Value: |
| // integer - 0 if OK, nonzero if request is invalid. In this case pl_conditionValue is not valid |
| // |
| // Detailed Comments: |
| // The function associated for the given method is called |
| // on the component that registered the source and ptc name. |
| // The params are passed to it as additional arguments. |
| // The handler function returns a boolean which is set in the pl_conditionValue |
| // argument of the specified pl_getConditionHandler handler. The error code returned by the handler function is |
| // passed to pl_getConditionHandler as well. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getCondition_nonBlocking( |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_method, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_GetConditionHandler pl_getConditionHandler := cg_EPTF_DataSource_GetConditionHandler_null |
| ) runs on EPTF_DataSource_CT return integer { |
| var boolean vl_conditionValue := false; |
| // do not change the order of the parameters for built-in conditions! |
| if (pl_source==c_EPTF_DataSource_sourceId) { |
| var integer vl_errorCode := f_EPTF_DataSource_handleBuiltInConditions_nonblocking( |
| pl_source, |
| pl_ptcName, |
| pl_method, |
| pl_params, |
| pl_getConditionHandler |
| ); // internal commands handled successfully, or an error occured |
| |
| return vl_errorCode; |
| } |
| |
| f_EPTF_DataSource_sortParams(pl_params); |
| //find if pl_dataVarName already exists |
| |
| |
| var integer vl_errorCode := 0; |
| var EPTF_Var_CT vl_ownerCompRef; |
| var charstring vl_remoteDataVarName; // for nonzero error code it contains the error message |
| var integer vl_localDataVarId; |
| var EPTF_Var_DirectContent vl_dataValue; |
| |
| // find handler compref: |
| var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName; |
| var integer vl_handlerId := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| vl_ownerCompRef := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef; |
| } else { |
| // try to find without PTC name if pl_ptcName=="": |
| if (pl_ptcName=="") { |
| var integer vl_counter; |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_source,vl_counter)) { |
| vl_errorCode := 3; |
| vl_remoteDataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName,": Source is not registered"); |
| f_EPTF_DataSource_warning(vl_remoteDataVarName); |
| } else { |
| if (vl_counter>1) { |
| vl_errorCode := 2; |
| vl_remoteDataVarName := log2str(%definitionId&": Cannot get data for dataSource ",pl_source, " and ptcName ",pl_ptcName, |
| ": More than one source component exists with this dataSource, PTC name should be specified"); |
| f_EPTF_DataSource_warning(vl_remoteDataVarName); |
| } else { |
| // this is always successful: |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_source,vl_handlerId)) {/*remove warning*/}; |
| pl_ptcName := v_EPTF_DataSource_DataHandler_List[vl_handlerId].ptcName; |
| } |
| } |
| } else { |
| vl_errorCode := 2; |
| vl_remoteDataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName,": Source is not registered"); |
| f_EPTF_DataSource_warning(vl_remoteDataVarName); |
| } |
| |
| if (vl_errorCode!=0) { |
| // call handler: |
| if (pl_getConditionHandler.getDataHandler!=null) { |
| |
| vl_ownerCompRef := null; |
| vl_localDataVarId := -1; |
| vl_dataValue := {boolVal:=false}; |
| |
| pl_getConditionHandler.getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_source, |
| pl_ptcName := pl_ptcName, // response may fill this if it was "" |
| pl_element := pl_method, |
| pl_params := pl_params, |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_remoteDataVarName := vl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := vl_ownerCompRef, // reference to the remote component |
| pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_getConditionHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| } |
| |
| var integer vl_getDataId := f_EPTF_Semaphore_new(); |
| //use same database as for getData: |
| v_EPTF_DataSource_GetDataHandler_DB[vl_getDataId] := {pl_getConditionHandler}; |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{getCondition:={ |
| vl_getDataId, |
| pl_source, |
| pl_ptcName, |
| pl_method, |
| pl_params |
| }},v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef); |
| |
| return 0; |
| } |
| |
| private external function f_EPTF_DataSource_str2float(in charstring pl_str, out float pl_float) return integer; |
| |
| //convert string to boolean |
| private function f_EPTF_DataSource_str2boolean( |
| in charstring pl_str2convert, |
| out boolean pl_boolValue) |
| return integer { |
| |
| if (pl_str2convert == c_EPTF_DataSource_condition_value_true) { |
| pl_boolValue := true; |
| return 0; |
| } |
| if (pl_str2convert == c_EPTF_DataSource_condition_value_false) { |
| pl_boolValue := false; |
| return 0; |
| } |
| return 1; //wrong param |
| } |
| |
| private function f_EPTF_DataSource_handleBuiltInConditions( |
| out boolean pl_conditionValue, |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_method, |
| in EPTF_DataSource_Params pl_params := {} |
| ) runs on EPTF_DataSource_CT return integer { |
| if (pl_source!=c_EPTF_DataSource_sourceId) { |
| return -10; // not DataSource command |
| } |
| // internal command: "match" |
| var charstring vl_titanBugHack //It's moved out from the blocks to avoid compiler warnings |
| select( pl_method ) |
| { |
| // internal command: "==" |
| case (c_EPTF_DataSource_condition_equal) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| pl_conditionValue := (pl_params[0].paramValue == pl_params[1].paramValue); |
| return 0; |
| } |
| // internal command: "!=" |
| case (c_EPTF_DataSource_condition_notEqual) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| pl_conditionValue := (pl_params[0].paramValue != pl_params[1].paramValue); |
| return 0; |
| } |
| // internal command: ">" |
| case (c_EPTF_DataSource_condition_more) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| var float vl_f1,vl_f2; |
| if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| return 2; // invalid param format |
| } |
| if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| return 2; // invalid param format |
| } |
| pl_conditionValue := (vl_f1 > vl_f2); |
| return 0; |
| } |
| // internal command: ">=" |
| case (c_EPTF_DataSource_condition_notLess) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| var float vl_f1,vl_f2; |
| if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| return 2; // invalid param format |
| } |
| if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| return 2; // invalid param format |
| } |
| pl_conditionValue := (vl_f1 >= vl_f2); |
| return 0; |
| } |
| // internal command: "<" |
| case (c_EPTF_DataSource_condition_less) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| var float vl_f1,vl_f2; |
| if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| return 2; // invalid param format |
| } |
| if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| return 2; // invalid param format |
| } |
| pl_conditionValue := (vl_f1 < vl_f2); |
| return 0; |
| } |
| // internal command: "<=" |
| case (c_EPTF_DataSource_condition_notMore) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| var float vl_f1,vl_f2; |
| if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| return 2; // invalid param format |
| } |
| if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| return 2; // invalid param format |
| } |
| pl_conditionValue := (vl_f1 <= vl_f2); |
| return 0; |
| } |
| // internal command: "match" |
| case (c_EPTF_DataSource_condition_match) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| vl_titanBugHack := pl_params[1].paramValue; |
| pl_conditionValue := match(pl_params[0].paramValue, pattern vl_titanBugHack); |
| return 0; |
| } |
| // internal command: "not match" |
| case (c_EPTF_DataSource_condition_notMatch) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| vl_titanBugHack := pl_params[1].paramValue; |
| pl_conditionValue := not match(pl_params[0].paramValue, pattern vl_titanBugHack); |
| return 0; |
| } |
| // internal command: "and" |
| case (c_EPTF_DataSource_condition_and) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| pl_conditionValue := (pl_params[0].paramValue == "true" and pl_params[1].paramValue == "true"); |
| return 0; |
| } |
| // internal command: "or" |
| case (c_EPTF_DataSource_condition_or) { |
| if (sizeof(pl_params)!=2) { |
| return 1; // invalid number of params |
| } |
| pl_conditionValue := (pl_params[0].paramValue == "true" or pl_params[1].paramValue == "true"); |
| return 0; |
| } |
| // internal command: "not" |
| case (c_EPTF_DataSource_condition_not) { |
| if (sizeof(pl_params)!=1) { |
| return 1; // invalid number of params |
| } |
| pl_conditionValue := (pl_params[0].paramValue == "false"); |
| return 0; |
| } |
| // internal command: "dataElementPresent" |
| case (c_EPTF_DataSource_condition_dataElementPresent) { |
| var EPTF_CharstringList vl_result; |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameSource, |
| c_EPTF_DataSource_paramNamePTCName, |
| c_EPTF_DataSource_paramNameElement}, |
| vl_result); |
| var charstring vl_source := vl_result[0]; |
| var charstring vl_ptcName := vl_result[1]; |
| var charstring vl_element := vl_result[2]; |
| |
| // extract the params: |
| var EPTF_DataSource_Params vl_params := {}; |
| for(var integer i:=0; i<sizeof(pl_params); i:=i+1) { |
| if (pl_params[i].paramName == c_EPTF_DataSource_paramNameParamName) { |
| vl_params[sizeof(vl_params)] := {paramName := pl_params[i].paramValue, paramValue := ""}; |
| i:=i+1; // jump to the next item which should be paramValue: |
| if (pl_params[i].paramName == c_EPTF_DataSource_paramNameParamValue) { |
| vl_params[sizeof(vl_params)-1].paramValue := pl_params[i].paramValue |
| } else { |
| // f_EPTF_DataSource_warning(%definitionId& ": "&c_EPTF_DataSource_paramNameParamValue&" is not specified for "& |
| // c_EPTF_DataSource_paramNameParamName&": "&pl_params[i-1].paramValue&" in the condition "&c_EPTF_DataSource_condition_dataElementPresent); |
| // f_EPTF_DataSource_warning(%definitionId&": Invalid condition or parameter: "& |
| // "\nSource: "&pl_source& |
| // "\nPTC : "&pl_ptcName & |
| // "\nMethod : " &pl_method& |
| // "\nParams: " & log2str(pl_params)); |
| return 1; // invalid parameters |
| } |
| } |
| } |
| var charstring vl_dataVarName := ""; |
| pl_conditionValue := (0 == f_EPTF_DataSource_checkData(vl_dataVarName,vl_source,vl_ptcName,vl_element,vl_params)); |
| return 0; |
| } |
| case else |
| { |
| //Just to avoid compile-time warnings. Hope, it never called. |
| return 11; // unknown internal method |
| } |
| } |
| } |
| |
| private function f_EPTF_DataSource_handleBuiltInConditions_nonblocking( |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_method, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_GetDataHandler pl_checkDataHandler := cg_EPTF_DataSource_GetDataHandler_null |
| ) runs on EPTF_DataSource_CT return integer { |
| var boolean vl_conditionValue; |
| var integer vl_errorCode; |
| if (pl_source!=c_EPTF_DataSource_sourceId) { |
| vl_errorCode := -10; // not DataSource command |
| } |
| // internal command: "match" |
| var charstring vl_titanBugHack //It's moved out from the blocks to avoid compiler warnings |
| select( pl_method ) |
| { |
| // internal command: "==" |
| case (c_EPTF_DataSource_condition_equal) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else{ |
| vl_conditionValue := (pl_params[0].paramValue == pl_params[1].paramValue); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "!=" |
| case (c_EPTF_DataSource_condition_notEqual) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else{ |
| vl_conditionValue := (pl_params[0].paramValue != pl_params[1].paramValue); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: ">" |
| case (c_EPTF_DataSource_condition_more) { |
| var float vl_f1,vl_f2; |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| vl_errorCode := 2; // invalid param format |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| vl_errorCode := 2; // invalid param format |
| }else{ |
| vl_conditionValue := (vl_f1 > vl_f2); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: ">=" |
| case (c_EPTF_DataSource_condition_notLess) { |
| var float vl_f1,vl_f2; |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| vl_errorCode := 2; // invalid param format |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| vl_errorCode := 2; // invalid param format |
| }else{ |
| vl_conditionValue := (vl_f1 >= vl_f2); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "<" |
| case (c_EPTF_DataSource_condition_less) { |
| var float vl_f1,vl_f2; |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| vl_errorCode := 2; // invalid param format |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| vl_errorCode := 2; // invalid param format |
| }else { |
| vl_conditionValue := (vl_f1 < vl_f2); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "<=" |
| case (c_EPTF_DataSource_condition_notMore) { |
| var float vl_f1,vl_f2; |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| vl_errorCode := 2; // invalid param format |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| vl_errorCode := 2; // invalid param format |
| }else{ |
| vl_conditionValue := (vl_f1 <= vl_f2); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "match" |
| case (c_EPTF_DataSource_condition_match) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else{ |
| vl_titanBugHack := pl_params[1].paramValue; |
| vl_conditionValue := match(pl_params[0].paramValue, pattern vl_titanBugHack); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "not match" |
| case (c_EPTF_DataSource_condition_notMatch) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else{ |
| vl_titanBugHack := pl_params[1].paramValue; |
| vl_conditionValue := not match(pl_params[0].paramValue, pattern vl_titanBugHack); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "and" |
| case (c_EPTF_DataSource_condition_and) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| } else { |
| var boolean vl_bool_0; |
| var boolean vl_bool_1; |
| if (0 != f_EPTF_DataSource_str2boolean(pl_params[0].paramValue, vl_bool_0)) { |
| vl_errorCode := 2; // invalid param |
| } else if (0 != f_EPTF_DataSource_str2boolean(pl_params[1].paramValue, vl_bool_1)) { |
| vl_errorCode := 2; // invalid param |
| } else { |
| vl_conditionValue := vl_bool_0 and vl_bool_1; |
| vl_errorCode := 0; |
| } |
| } |
| } |
| // internal command: "or" |
| case (c_EPTF_DataSource_condition_or) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| } else { |
| var boolean vl_bool_0; |
| var boolean vl_bool_1; |
| if (0 != f_EPTF_DataSource_str2boolean(pl_params[0].paramValue, vl_bool_0)) { |
| vl_errorCode := 2; // invalid param |
| } else if (0 != f_EPTF_DataSource_str2boolean(pl_params[1].paramValue, vl_bool_1)) { |
| vl_errorCode := 2; // invalid param |
| } else { |
| vl_conditionValue := vl_bool_0 or vl_bool_1; |
| vl_errorCode := 0; |
| } |
| } |
| } |
| // internal command: "not" |
| case (c_EPTF_DataSource_condition_not) { |
| if (sizeof(pl_params)!=1) { |
| vl_errorCode := 1; // invalid number of params |
| } else { |
| var boolean vl_bool_0; |
| if (0 != f_EPTF_DataSource_str2boolean(pl_params[0].paramValue, vl_bool_0)) { |
| vl_errorCode := 2; // invalid param |
| } else { |
| vl_conditionValue := not vl_bool_0; |
| vl_errorCode := 0; |
| } |
| } |
| } |
| // internal command: "dataElementPresent" |
| case (c_EPTF_DataSource_condition_dataElementPresent) { |
| vl_errorCode := 0; |
| var EPTF_CharstringList vl_result; |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameSource, |
| c_EPTF_DataSource_paramNamePTCName, |
| c_EPTF_DataSource_paramNameElement}, |
| vl_result); |
| var charstring vl_source := vl_result[0]; |
| var charstring vl_ptcName := vl_result[1]; |
| var charstring vl_element := vl_result[2]; |
| |
| // extract the params: |
| var EPTF_DataSource_Params vl_params := {}; |
| for(var integer i:=0; i<sizeof(pl_params); i:=i+1) { |
| if (pl_params[i].paramName == c_EPTF_DataSource_paramNameParamName) { |
| vl_params[sizeof(vl_params)] := {paramName := pl_params[i].paramValue, paramValue := ""}; |
| i:=i+1; // jump to the next item which should be paramValue: |
| if (sizeof(pl_params) > i and pl_params[i].paramName == c_EPTF_DataSource_paramNameParamValue) { |
| vl_params[sizeof(vl_params)-1].paramValue := pl_params[i].paramValue |
| } else { |
| // f_EPTF_DataSource_warning(%definitionId& ": "&c_EPTF_DataSource_paramNameParamValue&" is not specified for "& |
| // c_EPTF_DataSource_paramNameParamName&": "&pl_params[i-1].paramValue&" in the condition "&c_EPTF_DataSource_condition_dataElementPresent); |
| // f_EPTF_DataSource_warning(%definitionId&": Invalid condition or parameter: "& |
| // "\nSource: "&pl_source& |
| // "\nPTC : "&pl_ptcName & |
| // "\nMethod : " &pl_method& |
| // "\nParams: " & log2str(pl_params)); |
| vl_errorCode := 1; // invalid parameters |
| break; |
| } |
| } |
| } |
| if (vl_errorCode == 0) { |
| var integer vl_userHandlerIdx := f_EPTF_Semaphore_new(); |
| v_EPTF_DataSource_GetDataHandler_DB[vl_userHandlerIdx] := {pl_checkDataHandler}; |
| var EPTF_DataSource_GetDataHandler vl_checkDataToConditionForDataElementPresent_handler := { |
| getDataHandler := refers(f_EPTF_DataSource_checkDataToConditionForDataElementPresent_handler), |
| userData := {vl_userHandlerIdx} |
| } |
| vl_errorCode := f_EPTF_DataSource_checkData_nonblocking(vl_source,vl_ptcName,vl_element,vl_params,vl_checkDataToConditionForDataElementPresent_handler); |
| return 0; |
| } |
| } |
| case else |
| { |
| //Just to avoid compile-time warnings. Hope, it never called. |
| vl_errorCode := 11; // unknown internal method |
| } |
| } |
| // call handler: |
| var EPTF_Var_CT vl_ownerCompRef; |
| var charstring vl_remoteDataVarName := ""; // for nonzero error code it contains the error message |
| var integer vl_localDataVarId; |
| var EPTF_Var_DirectContent vl_dataValue; |
| |
| if (pl_checkDataHandler.getDataHandler!=null) { |
| |
| vl_ownerCompRef := null; |
| vl_localDataVarId := -1; |
| if (vl_errorCode == 0) { |
| vl_dataValue := {boolVal:= vl_conditionValue}; |
| } else { |
| vl_dataValue := {boolVal:=false}; |
| } |
| |
| |
| pl_checkDataHandler.getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_source, |
| pl_ptcName := pl_ptcName, // response may fill this if it was "" |
| pl_element := pl_method, |
| pl_params := pl_params, |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_remoteDataVarName := vl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := vl_ownerCompRef, // reference to the remote component |
| pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_checkDataHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| |
| private function f_EPTF_DataSource_checkDataToConditionForDataElementPresent_handler( |
| //request parameters: |
| in charstring pl_source, |
| in charstring pl_ptcName, // response may fill this if it was "" |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params, |
| // reponse parameters: |
| in integer pl_errorCode, // error code in the response |
| in charstring pl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| in EPTF_Var_CT pl_ownerCompRef, // reference to the remote component |
| in integer pl_localDataVarId, // var Id on the local component (contains the current value, not subscribed to remote!) |
| in EPTF_Var_DirectContent pl_dataValue, // the value of the data |
| // user data |
| in EPTF_IntegerList pl_userData // user specific data given at the request |
| ) runs on EPTF_DataSource_CT { |
| var integer vl_userHandlerIdx := pl_userData[0]; |
| |
| for(var integer i:=0; i<sizeof(v_EPTF_DataSource_GetDataHandler_DB[vl_userHandlerIdx]); i:=i+1) { |
| if(v_EPTF_DataSource_GetDataHandler_DB[vl_userHandlerIdx][i].getDataHandler != null){ |
| var boolean vl_conditionValue := pl_errorCode == 0; |
| v_EPTF_DataSource_GetDataHandler_DB[vl_userHandlerIdx][i].getDataHandler.apply( |
| pl_source, |
| pl_ptcName, // response may fill this if it was "" |
| pl_element, |
| pl_params, |
| // reponse parameters: |
| pl_errorCode :=0, // error code in the response |
| pl_remoteDataVarName := pl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := pl_ownerCompRef, // reference to the remote component |
| pl_localDataVarId := -1, // var Id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := {boolVal := vl_conditionValue}, // the value of the data |
| // user data |
| pl_userData := v_EPTF_DataSource_GetDataHandler_DB[vl_userHandlerIdx][i].userData // user specific data given at the request |
| ) |
| } |
| } |
| v_EPTF_DataSource_GetDataHandler_DB[vl_userHandlerIdx] := {}; |
| f_EPTF_Semaphore_delete(vl_userHandlerIdx); |
| } |
| |
| private function f_EPTF_DataSource_handleBuiltInConditionsValue_nonblocking( |
| in charstring pl_source, |
| in charstring pl_ptcName := "", |
| in charstring pl_method, |
| in EPTF_DataSource_Params pl_params := {}, |
| in EPTF_DataSource_GetDataValueHandler pl_checkDataValueHandler := cg_EPTF_DataSource_GetDataValueHandler_null |
| ) runs on EPTF_DataSource_CT return integer { |
| var boolean vl_conditionValue; |
| var integer vl_errorCode; |
| if (pl_source!=c_EPTF_DataSource_sourceId) { |
| vl_errorCode := -10; // not DataSource command |
| } |
| // internal command: "match" |
| var charstring vl_titanBugHack //It's moved out from the blocks to avoid compiler warnings |
| select( pl_method ) |
| { |
| // internal command: "==" |
| case (c_EPTF_DataSource_condition_equal) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else{ |
| vl_conditionValue := (pl_params[0].paramValue == pl_params[1].paramValue); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "!=" |
| case (c_EPTF_DataSource_condition_notEqual) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else{ |
| vl_conditionValue := (pl_params[0].paramValue != pl_params[1].paramValue); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: ">" |
| case (c_EPTF_DataSource_condition_more) { |
| var float vl_f1,vl_f2; |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| vl_errorCode := 2; // invalid param format |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| vl_errorCode := 2; // invalid param format |
| }else{ |
| vl_conditionValue := (vl_f1 > vl_f2); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: ">=" |
| case (c_EPTF_DataSource_condition_notLess) { |
| var float vl_f1,vl_f2; |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| vl_errorCode := 2; // invalid param format |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| vl_errorCode := 2; // invalid param format |
| }else{ |
| vl_conditionValue := (vl_f1 >= vl_f2); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "<" |
| case (c_EPTF_DataSource_condition_less) { |
| var float vl_f1,vl_f2; |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| vl_errorCode := 2; // invalid param format |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| vl_errorCode := 2; // invalid param format |
| }else { |
| vl_conditionValue := (vl_f1 < vl_f2); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "<=" |
| case (c_EPTF_DataSource_condition_notMore) { |
| var float vl_f1,vl_f2; |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[0].paramValue, vl_f1)) { |
| vl_errorCode := 2; // invalid param format |
| }else if (0!=f_EPTF_DataSource_str2float(pl_params[1].paramValue, vl_f2)) { |
| vl_errorCode := 2; // invalid param format |
| }else{ |
| vl_conditionValue := (vl_f1 <= vl_f2); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "match" |
| case (c_EPTF_DataSource_condition_match) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else{ |
| vl_titanBugHack := pl_params[1].paramValue; |
| vl_conditionValue := match(pl_params[0].paramValue, pattern vl_titanBugHack); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "not match" |
| case (c_EPTF_DataSource_condition_notMatch) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| }else{ |
| vl_titanBugHack := pl_params[1].paramValue; |
| vl_conditionValue := not match(pl_params[0].paramValue, pattern vl_titanBugHack); |
| vl_errorCode := 0; |
| } |
| } |
| // internal command: "and" |
| case (c_EPTF_DataSource_condition_and) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| } else { |
| var boolean vl_bool_0; |
| var boolean vl_bool_1; |
| if (0 != f_EPTF_DataSource_str2boolean(pl_params[0].paramValue, vl_bool_0)) { |
| vl_errorCode := 2; // invalid param |
| } else if (0 != f_EPTF_DataSource_str2boolean(pl_params[1].paramValue, vl_bool_1)) { |
| vl_errorCode := 2; // invalid param |
| } else { |
| vl_conditionValue := vl_bool_0 and vl_bool_1; |
| vl_errorCode := 0; |
| } |
| } |
| } |
| // internal command: "or" |
| case (c_EPTF_DataSource_condition_or) { |
| if (sizeof(pl_params)!=2) { |
| vl_errorCode := 1; // invalid number of params |
| } else { |
| var boolean vl_bool_0; |
| var boolean vl_bool_1; |
| if (0 != f_EPTF_DataSource_str2boolean(pl_params[0].paramValue, vl_bool_0)) { |
| vl_errorCode := 2; // invalid param |
| } else if (0 != f_EPTF_DataSource_str2boolean(pl_params[1].paramValue, vl_bool_1)) { |
| vl_errorCode := 2; // invalid param |
| } else { |
| vl_conditionValue := vl_bool_0 or vl_bool_1; |
| vl_errorCode := 0; |
| } |
| } |
| } |
| // internal command: "not" |
| case (c_EPTF_DataSource_condition_not) { |
| if (sizeof(pl_params)!=1) { |
| vl_errorCode := 1; // invalid number of params |
| } else { |
| var boolean vl_bool_0; |
| if (0 != f_EPTF_DataSource_str2boolean(pl_params[0].paramValue, vl_bool_0)) { |
| vl_errorCode := 2; // invalid param |
| } else { |
| vl_conditionValue := not vl_bool_0; |
| vl_errorCode := 0; |
| } |
| } |
| } |
| // internal command: "dataElementPresent" |
| case (c_EPTF_DataSource_condition_dataElementPresent) { |
| vl_errorCode := 0; |
| var EPTF_CharstringList vl_result; |
| f_EPTF_DataSource_extractParams(pl_params, |
| {c_EPTF_DataSource_paramNameSource, |
| c_EPTF_DataSource_paramNamePTCName, |
| c_EPTF_DataSource_paramNameElement}, |
| vl_result); |
| var charstring vl_source := vl_result[0]; |
| var charstring vl_ptcName := vl_result[1]; |
| var charstring vl_element := vl_result[2]; |
| |
| // extract the params: |
| var EPTF_DataSource_Params vl_params := {}; |
| for(var integer i:=0; i<sizeof(pl_params); i:=i+1) { |
| if (pl_params[i].paramName == c_EPTF_DataSource_paramNameParamName) { |
| vl_params[sizeof(vl_params)] := {paramName := pl_params[i].paramValue, paramValue := ""}; |
| i:=i+1; // jump to the next item which should be paramValue: |
| if (sizeof(pl_params) > i and pl_params[i].paramName == c_EPTF_DataSource_paramNameParamValue) { |
| vl_params[sizeof(vl_params)-1].paramValue := pl_params[i].paramValue |
| } else { |
| // f_EPTF_DataSource_warning(%definitionId& ": "&c_EPTF_DataSource_paramNameParamValue&" is not specified for "& |
| // c_EPTF_DataSource_paramNameParamName&": "&pl_params[i-1].paramValue&" in the condition "&c_EPTF_DataSource_condition_dataElementPresent); |
| // f_EPTF_DataSource_warning(%definitionId&": Invalid condition or parameter: "& |
| // "\nSource: "&pl_source& |
| // "\nPTC : "&pl_ptcName & |
| // "\nMethod : " &pl_method& |
| // "\nParams: " & log2str(pl_params)); |
| vl_errorCode := 1; // invalid parameters |
| break; |
| } |
| } |
| } |
| if (vl_errorCode == 0) { |
| var integer vl_userHandlerIdx := f_EPTF_Semaphore_new(); |
| v_EPTF_DataSource_GetDataValueHandler_DB[vl_userHandlerIdx] := pl_checkDataValueHandler; |
| var EPTF_DataSource_GetDataValueHandler vl_checkDataValueToConditionForDataElementPresent_handler := { |
| getDataValueHandler := refers(f_EPTF_DataSource_checkDataValueToConditionForDataElementPresent_handler), |
| userData := {vl_userHandlerIdx} |
| } |
| vl_errorCode := f_EPTF_DataSource_checkDataValue_nonblocking(vl_source,vl_ptcName,vl_element,vl_params,vl_checkDataValueToConditionForDataElementPresent_handler); |
| return 0; |
| } |
| } |
| case else |
| { |
| //Just to avoid compile-time warnings. Hope, it never called. |
| vl_errorCode := 11; // unknown internal method |
| } |
| } |
| // call handler: |
| var EPTF_Var_CT vl_ownerCompRef; |
| var charstring vl_remoteDataVarName := ""; // for nonzero error code it contains the error message |
| var integer vl_localDataVarId; |
| var EPTF_Var_DirectContent vl_dataValue; |
| |
| if (pl_checkDataValueHandler.getDataValueHandler!=null) { |
| |
| vl_ownerCompRef := null; |
| vl_localDataVarId := -1; |
| if (vl_errorCode == 0) { |
| vl_dataValue := {boolVal:= vl_conditionValue}; |
| } else { |
| vl_dataValue := {boolVal:=false}; |
| } |
| |
| |
| pl_checkDataValueHandler.getDataValueHandler.apply( |
| // reponse parameters: |
| pl_errorCode := vl_errorCode, // error code in the response |
| pl_dataValue := vl_dataValue, // the value of the data |
| // user data |
| pl_userData := pl_checkDataValueHandler.userData // user specific data given at the request |
| ); |
| } |
| return vl_errorCode; |
| } |
| |
| private function f_EPTF_DataSource_checkDataValueToConditionForDataElementPresent_handler( |
| // reponse parameters: |
| in integer pl_errorCode, // error code in the response |
| in EPTF_Var_DirectContent pl_dataValue, // the value of the data |
| // user data |
| in EPTF_IntegerList pl_userData // user specific data given at the request |
| ) runs on EPTF_DataSource_CT { |
| var integer vl_userHandlerIdx := pl_userData[0]; |
| |
| if(v_EPTF_DataSource_GetDataValueHandler_DB[vl_userHandlerIdx] != cg_EPTF_DataSource_GetDataValueHandler_null and v_EPTF_DataSource_GetDataValueHandler_DB[vl_userHandlerIdx].getDataValueHandler != null){ |
| var boolean vl_conditionValue := pl_errorCode == 0; |
| v_EPTF_DataSource_GetDataValueHandler_DB[vl_userHandlerIdx].getDataValueHandler.apply( |
| pl_errorCode :=0, // error code in the response |
| pl_dataValue := {boolVal := vl_conditionValue}, // the value of the data |
| // user data |
| pl_userData := v_EPTF_DataSource_GetDataValueHandler_DB[vl_userHandlerIdx].userData // user specific data given at the request |
| ) |
| } |
| |
| v_EPTF_DataSource_GetDataValueHandler_DB[vl_userHandlerIdx] := cg_EPTF_DataSource_GetDataValueHandler_null; |
| f_EPTF_Semaphore_delete(vl_userHandlerIdx); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_registerReadyCallback |
| // |
| // Purpose: |
| // To register a callback function to get notification when the DataSource becomes ready. |
| // |
| // Parameter: |
| // *in* <EPTF_DataSource_Ready_FT> *pl_function* - the callback function to register |
| // |
| // Return Value: |
| // - |
| // |
| // Detailed Comments: |
| // The functions registered are called with the source and PTC name of |
| // the data provider when that provider becames ready. |
| // For example you can set a flag in the callback function to show that |
| // the data source provider is ready. Later you can wait for this flag before |
| // requests are made towards this data source. |
| // Note, that data source requests for example via the function <f_EPTF_DataSource_getData> |
| // for a provider that is not ready will fail (error code!=0 is returned). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_registerReadyCallback( |
| in EPTF_DataSource_Ready_FT pl_function) |
| runs on EPTF_DataSource_CT{ |
| v_EPTF_DataSource_ready_functions[sizeof(v_EPTF_DataSource_ready_functions)] := pl_function; |
| } |
| |
| // /////////////////////////////////////////////////////////// |
| // // Function: f_EPTF_DataSource_getIterator |
| // // |
| // // Purpose: |
| // // To get the value of a given iterator |
| // // |
| // // Parameters: |
| // // *in charstring pl_source* - the name of the dataSource 'feature' |
| // // *in charstring pl_ptcName* - the name of the PTC |
| // // (dataSource+ptcName should be a unigue id of the iterator) |
| // // *in charstring pl_element* - the type of data |
| // // *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {}) |
| // // *out charstring pl_iteratorVarName* - this the name of the variable |
| // // that stores the values of the iterator |
| // // |
| // // Return Value: |
| // // integer - 0 if OK, nonzero if pl_iteratorVarName is not valid |
| // // |
| // // Detailed Comments: |
| // // - |
| // /////////////////////////////////////////////////////////// |
| // public function f_EPTF_DataSource_getIterator( |
| // in charstring pl_source, |
| // in charstring pl_ptcName, |
| // in charstring pl_element, |
| // in EPTF_DataSource_Params pl_params := {}, |
| // out charstring pl_iteratorVarName, |
| // in EPTF_Var_SubscriptionMode pl_subscriptionMode := realtime, |
| // in integer pl_refreshRate := -1 |
| // ) runs on EPTF_DataSource_CT return integer { |
| // return f_EPTF_DataSource_getData(pl_source,pl_ptcName,pl_element,pl_params,pl_iteratorVarName,pl_subscriptionMode,pl_refreshRate) |
| // } |
| |
| private function f_EPTF_DataSource_cleanup_CT() runs on EPTF_DataSource_CT { |
| if (not v_EPTF_DataSource_initialized) { |
| return; |
| } |
| v_EPTF_DataSource_initialized := false; |
| |
| v_EPTF_DataSource_Msg_GetData_Buffer := {}; |
| v_EPTF_DataSource_Msg_GetData_BufferStartIdx := 0; |
| v_EPTF_DataSource_nofPendingGetData := 0; |
| |
| //disconnect(pl_sourceCompRef:EPTF_DataSourceIf,self:EPTF_DataSourceIf); |
| deactivate(v_DataSource_handler); |
| v_DataSource_handler := null; |
| if (v_EPTF_DataSource_DataHandlerHash!=-1) { |
| v_EPTF_DataSource_DataHandlerHash := -1; |
| f_EPTF_str2int_HashMap_Delete(c_EPTF_DataSource_dataHandlerHashName); |
| } |
| if (v_EPTF_DataSource_DataHandlerHash_NoPTCName!=-1) { |
| v_EPTF_DataSource_DataHandlerHash_NoPTCName := -1; |
| f_EPTF_str2int_HashMap_Delete(c_EPTF_DataSource_dataHandlerHashName_NoPTCName); |
| } |
| if (v_EPTF_DataSource_dataValueHash!=-1) { |
| v_EPTF_DataSource_dataValueHash := -1; |
| f_EPTF_str2int_HashMap_Delete(c_EPTF_DataSource_dataValueHashName); |
| } |
| if (v_EPTF_DataSource_pendingGetDataHash!=-1) { |
| v_EPTF_DataSource_pendingGetDataHash := -1; |
| f_EPTF_str2int_HashMap_Delete(c_EPTF_DataSource_pendingGetDataHashName); |
| } |
| } |
| |
| private function f_EPTF_DataSource_handleRegisterData( |
| in EPTF_DataSource_Msg_RegisterData pl_registerData, |
| in EPTF_DataSourceClient_CT pl_ownerCompRef |
| ) runs on EPTF_DataSource_CT { |
| |
| // find handler: |
| var charstring vl_handlerIdStr := pl_registerData.dataSource&"@"&pl_registerData.ptcName; |
| var integer vl_handlerId := -1; |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId)) { |
| vl_handlerId := sizeof(v_EPTF_DataSource_DataHandler_List); |
| v_EPTF_DataSource_DataHandler_List[vl_handlerId] := { |
| pl_registerData.dataSource, |
| pl_registerData.ptcName, |
| pl_ownerCompRef |
| }; |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr,vl_handlerId); |
| } else { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Data ",pl_registerData, |
| " already registered with sender:", v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef)); |
| if (pl_ownerCompRef!=v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef) { |
| f_EPTF_DataSource_error(log2str(%definitionId&": Cannot register data ",pl_registerData," to the sender:",pl_ownerCompRef, |
| ": Already registered to a different owner component: ", v_EPTF_DataSource_DataHandler_List[vl_handlerId].ownerCompRef)); |
| f_EPTF_Base_stopAll(); |
| } |
| return; |
| } |
| var integer vl_counter; |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_registerData.dataSource,vl_counter)) { |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_DataHandlerHash_NoPTCName,pl_registerData.dataSource,vl_handlerId); |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_registerData.dataSource,1); |
| } else { |
| f_EPTF_str2int_HashMap_Erase(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_registerData.dataSource); |
| vl_counter := vl_counter +1; |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&pl_registerData.dataSource,vl_counter); |
| } |
| |
| //Create or adjust the variable of that contains the registered PTC names of the data source |
| var integer vl_varIdx := f_EPTF_Var_getId(c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_PTCs&"."&pl_registerData.dataSource); |
| if(vl_varIdx == -1) { |
| f_EPTF_Var_newCharstringlist(c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_PTCs&"."&pl_registerData.dataSource, {pl_registerData.ptcName}, vl_varIdx) |
| } else { |
| f_EPTF_Var_adjustContent(vl_varIdx, { charstringlistVal:= f_EPTF_Var_getCharstringlistValue(vl_varIdx)&{pl_registerData.ptcName} }) |
| } |
| |
| //Create or adjust the variable of that contains the registered Sources |
| vl_varIdx := f_EPTF_Var_getId(c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_Sources); |
| if(vl_varIdx == -1) { |
| // cannot be reached, var is created in init function |
| f_EPTF_Var_newCharstringlist(c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_Sources, {c_EPTF_DataSource_sourceId,pl_registerData.dataSource}, vl_varIdx) |
| } else { |
| // check if the source is already there: |
| var EPTF_CharstringList vl_currentSources := f_EPTF_Var_getCharstringlistValue(vl_varIdx); |
| var boolean vl_found := false; |
| for (var integer i:=0; i<sizeof(vl_currentSources);i:=i+1) { |
| if (vl_currentSources[i]==pl_registerData.dataSource) { |
| vl_found:=true; |
| break; |
| } |
| } |
| // if does not exit, add: |
| if(not vl_found) { |
| f_EPTF_Var_adjustContent(vl_varIdx, { charstringlistVal:= f_EPTF_Var_getCharstringlistValue(vl_varIdx)&{pl_registerData.dataSource} }) |
| } |
| } |
| } |
| |
| //deregisters all sources that belong to the given compRef |
| private function f_EPTF_DataSource_deregisterData( |
| in EPTF_DataSourceClient_CT pl_ownerCompRef |
| ) runs on EPTF_DataSource_CT { |
| |
| for(var integer i:=0; i<sizeof(v_EPTF_DataSource_DataHandler_List); i:=i+1) { |
| if (v_EPTF_DataSource_DataHandler_List[i].ownerCompRef!=pl_ownerCompRef) { |
| continue; |
| } |
| var charstring vl_dataSource := v_EPTF_DataSource_DataHandler_List[i].dataSource; |
| var charstring vl_ptcName := v_EPTF_DataSource_DataHandler_List[i].ptcName; |
| var charstring vl_handlerIdStr := vl_dataSource&"@"&vl_ptcName; |
| f_EPTF_str2int_HashMap_Erase(v_EPTF_DataSource_DataHandlerHash,vl_handlerIdStr); |
| v_EPTF_DataSource_DataHandler_List[i]:=c_EPTF_DataSource_DataHandler_invalid; |
| |
| var integer vl_counter; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&vl_dataSource,vl_counter)) { |
| f_EPTF_str2int_HashMap_Erase(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&vl_dataSource); |
| vl_counter := vl_counter -1; |
| if (vl_counter==0) { |
| f_EPTF_str2int_HashMap_Erase(v_EPTF_DataSource_DataHandlerHash_NoPTCName,vl_dataSource); |
| } else { |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_DataHandlerHash_NoPTCName,"Counter."&vl_dataSource,vl_counter); |
| if (vl_counter==1) { |
| // update the handler ID to the remaining one source: |
| var integer vl_handlerId := -1; |
| for(var integer j:=0; j<sizeof(v_EPTF_DataSource_DataHandler_List);j:=j+1) { |
| if (v_EPTF_DataSource_DataHandler_List[j].dataSource == vl_dataSource) { |
| vl_handlerId := j; |
| break; //found |
| } |
| } |
| f_EPTF_str2int_HashMap_Update(v_EPTF_DataSource_DataHandlerHash_NoPTCName,vl_dataSource,vl_handlerId); |
| } |
| } |
| } |
| |
| //Adjust the variable of that contains the registered PTC names of the data source |
| var integer vl_varIdx := f_EPTF_Var_getId(c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_PTCs&"."&vl_dataSource); |
| var EPTF_CharstringList vl_newValue := {}; |
| if(vl_varIdx != -1) { |
| var EPTF_CharstringList vl_currentValue := f_EPTF_Var_getCharstringlistValue(vl_varIdx); |
| |
| for(var integer j:=0; j<sizeof(vl_currentValue); j:=j+1) { |
| if (vl_currentValue[j] == vl_ptcName) { |
| continue; |
| } |
| vl_newValue[sizeof(vl_newValue)] := vl_currentValue[j]; |
| } |
| f_EPTF_Var_adjustContent(vl_varIdx, { charstringlistVal:= vl_newValue }) |
| } |
| |
| // if there are no more PTCs left to this source: |
| if (vl_varIdx!=-1 and vl_newValue == {}) { |
| |
| //Adjust the variable of that contains the registered Sources |
| vl_varIdx := f_EPTF_Var_getId(c_EPTF_DataSource_externalDataVar_prefix&"."&c_EPTF_DataSource_dataElement_Sources); |
| if(vl_varIdx != -1) { |
| var EPTF_CharstringList vl_currentSources := f_EPTF_Var_getCharstringlistValue(vl_varIdx); |
| var EPTF_CharstringList vl_newSources := {}; |
| for (var integer j:=0; j<sizeof(vl_currentSources);j:=j+1) { |
| if (vl_currentSources[j]==vl_dataSource) { |
| continue; |
| } |
| vl_newSources[sizeof(vl_newSources)] := vl_currentSources[j]; |
| } |
| f_EPTF_Var_adjustContent(vl_varIdx, { charstringlistVal:= vl_newSources }) |
| } |
| } |
| } |
| } |
| |
| private function f_EPTF_DataSource_handleGetData_sendResponse( |
| //request parameters: |
| in charstring pl_source, |
| in charstring pl_ptcName, // response may fill this if it was "" |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params, |
| // reponse parameters: |
| in integer pl_errorCode, // error code in the response |
| in charstring pl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| in EPTF_Var_CT/*EPTF_DataSourceClient_CT*/ pl_ownerCompRef,// reference to the remote component |
| in integer pl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| in EPTF_Var_DirectContent pl_dataValue, // the value of the data |
| // user data |
| in EPTF_IntegerList pl_userData // user specific data given at the request |
| ) runs on EPTF_DataSource_CT { |
| var integer vl_transactionId := pl_userData[0]; |
| var EPTF_DataSourceClient_CT vl_sourceCompRef := f_EPTF_DataSourceClient_downcast(pl_userData[1]) |
| |
| |
| // this is for compatibility: |
| if (pl_errorCode!=0) { |
| pl_remoteDataVarName := log2str(%definitionId&": Invalid iterator or externalData or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nElement Name : " ,pl_element, |
| "\nParams: " , pl_params)&"\n:"&pl_remoteDataVarName; |
| } |
| |
| // send response: |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{dataValue:={ |
| vl_transactionId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| pl_remoteDataVarName, |
| pl_dataValue, |
| pl_errorCode, |
| pl_ownerCompRef |
| }}, |
| vl_sourceCompRef |
| ); |
| } |
| |
| private function f_EPTF_DataSource_handleGetData( |
| in EPTF_DataSource_Msg_GetData pl_getData, |
| in EPTF_DataSourceClient_CT pl_sourceCompRef |
| ) runs on EPTF_DataSource_CT { |
| |
| f_EPTF_DataSource_getData_nonBlocking( |
| pl_source := pl_getData.dataSource, |
| pl_ptcName := pl_getData.ptcName, |
| pl_element := pl_getData.dataElement, |
| pl_params := pl_getData.params, |
| pl_getDataHandler := { |
| refers(f_EPTF_DataSource_handleGetData_sendResponse), |
| {pl_getData.transactionId,f_EPTF_Base_upcast(pl_sourceCompRef)} |
| } |
| ); |
| } |
| |
| // use non-blocking getDataValue: |
| private function f_EPTF_DataSource_handleGetDataValue( |
| in EPTF_DataSource_Msg_GetDataValue pl_getDataValue, |
| in EPTF_DataSourceClient_CT pl_sourceCompRef |
| ) runs on EPTF_DataSource_CT { |
| |
| var integer vl_errorCode := f_EPTF_DataSource_getDataValue_nonblocking( |
| pl_source := pl_getDataValue.dataSource, |
| pl_ptcName := pl_getDataValue.ptcName, |
| pl_element := pl_getDataValue.dataElement, |
| pl_params := pl_getDataValue.params, |
| pl_getDataValueHandler := { |
| refers(f_EPTF_DataSource_handleGetDataValue_sendResponse), |
| {pl_getDataValue.transactionId,f_EPTF_Base_upcast(pl_sourceCompRef)} |
| } |
| ); |
| } |
| |
| private function f_EPTF_DataSource_handleGetDataValue_sendResponse( |
| // reponse parameters: |
| in integer pl_errorCode, // error code in the response |
| in EPTF_Var_DirectContent pl_dataValue, // the value of the data |
| // user data |
| in EPTF_IntegerList pl_userData // user specific data given at the request |
| ) runs on EPTF_DataSource_CT { |
| |
| var integer vl_transactionId := pl_userData[0]; |
| var EPTF_DataSourceClient_CT vl_sourceCompRef := f_EPTF_DataSourceClient_downcast(pl_userData[1]) |
| |
| if (not isbound(pl_dataValue)) { |
| if (pl_errorCode==0) { |
| pl_errorCode := -1; |
| } |
| pl_dataValue := {charstringVal := "Unknown error"} |
| } |
| |
| // send response: |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{dataValueResponse:={ |
| vl_transactionId, |
| pl_dataValue, |
| pl_errorCode |
| }}, |
| vl_sourceCompRef |
| ); |
| } |
| |
| |
| private function f_EPTF_DataSource_handleSetDataValue( |
| in EPTF_DataSource_Msg_SetDataValue pl_setDataValue, |
| in EPTF_DataSourceClient_CT pl_sourceCompRef |
| ) runs on EPTF_DataSource_CT { |
| |
| var EPTF_Var_DirectContent vl_dataValue := pl_setDataValue.dataValue; |
| var integer vl_errorCode := f_EPTF_DataSource_setDataValue_nonblocking( |
| pl_dataValue := pl_setDataValue.dataValue, |
| pl_source := pl_setDataValue.dataSource, |
| pl_ptcName := pl_setDataValue.ptcName, |
| pl_element := pl_setDataValue.dataElement, |
| pl_params := pl_setDataValue.params, |
| pl_indexList := pl_setDataValue.indexList, |
| pl_setDataValueHandler := { |
| refers(f_EPTF_DataSource_handleSetDataValue_sendResponse), |
| {pl_setDataValue.transactionId,f_EPTF_Base_upcast(pl_sourceCompRef)} |
| } |
| ); |
| } |
| |
| private function f_EPTF_DataSource_handleSetDataValue_sendResponse( |
| // reponse parameters: |
| in integer pl_errorCode, // error code in the response |
| in EPTF_Var_DirectContent pl_dataValue, // the value of the data |
| // user data |
| in EPTF_IntegerList pl_userData // user specific data given at the request |
| ) runs on EPTF_DataSource_CT { |
| var integer vl_transactionId := pl_userData[0]; |
| var EPTF_DataSourceClient_CT vl_sourceCompRef := f_EPTF_DataSourceClient_downcast(pl_userData[1]) |
| |
| if (not isbound(pl_dataValue)) { |
| if (pl_errorCode==0) { |
| pl_errorCode := -1; |
| } |
| pl_dataValue := {charstringVal := "Unknown error"} |
| } |
| |
| // send response: |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{dataValueResponse:={ |
| vl_transactionId, |
| pl_dataValue, |
| pl_errorCode |
| }}, |
| vl_sourceCompRef |
| ); |
| } |
| |
| private function f_EPTF_DataSource_handleDataValue(in EPTF_DataSource_Msg_DataValue pl_dataValue) |
| runs on EPTF_DataSource_CT { |
| var integer vl_localDataVarId := -1; |
| |
| v_EPTF_DataSource_Msg_List[pl_dataValue.transactionId] := {dataValue := pl_dataValue}; |
| //decrease number of pending getData counter: |
| v_EPTF_DataSource_nofPendingGetData := v_EPTF_DataSource_nofPendingGetData - 1; |
| //if (v_EPTF_DataSource_nofPendingGetData==0) { |
| // action("*** NO MORE PENDING GetData LEFT!"); |
| //} |
| |
| var charstring vl_dataValueIdStr := pl_dataValue.dataSource&"@"&pl_dataValue.ptcName& |
| "."&pl_dataValue.dataElement&":"&log2str(pl_dataValue.params); |
| // store the returned varname in a hashmap (if varName is present, i.e. it is a response to getData. In the response to getDataValue varName is missing): |
| if(pl_dataValue.errorCode==0 and ispresent(pl_dataValue.dataVarName)) { |
| var charstring vl_dataValueIdStr_noPTCName := pl_dataValue.dataSource&"@."&pl_dataValue.dataElement&":"&log2str(pl_dataValue.params); |
| |
| var integer vl_dataValueId; |
| if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) { |
| |
| var charstring vl_remoteDataVarName := pl_dataValue.dataVarName; |
| var charstring vl_localVarName := "EPTF_DataSource_"&vl_remoteDataVarName&"."&vl_dataValueIdStr; |
| //create local variable with the value in the message: |
| vl_localDataVarId := f_EPTF_Var_newVar(vl_localVarName,pl_dataValue.dataValue); |
| |
| vl_dataValueId := sizeof(v_EPTF_DataSource_dataValue_List); |
| // store new datasource data: |
| v_EPTF_DataSource_dataValue_List[vl_dataValueId] := { |
| pl_dataValue.dataVarName, |
| pl_dataValue.ownerCompRef, |
| vl_localDataVarId |
| }; |
| // to be able to search by vl_dataValueIdStr: |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr,vl_dataValueId); |
| // to be able to search by vl_localVarName: |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_dataValueHash,vl_localVarName,vl_dataValueId); |
| // to be able to search by vl_dataValueIdStr_noPTCName: |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr_noPTCName,vl_dataValueId); |
| } else { |
| vl_localDataVarId := v_EPTF_DataSource_dataValue_List[vl_dataValueId].localDataVarId; |
| |
| // Update hashMap entry for NoPTCName: |
| // Only insert with noPTCName if it was not already added. |
| // Otherwise insert invalid data to sign that the PTC name should be specified |
| var integer vl_noPTCCheck := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr_noPTCName,vl_noPTCCheck)) { |
| // if valid entry found: |
| if (vl_noPTCCheck!=-1) { |
| //if it differs from the one with PTC name, then replace it with an invalid item (==more than one PTCName has the same source) |
| if (vl_noPTCCheck!=vl_dataValueId) { |
| f_EPTF_str2int_HashMap_Update(v_EPTF_DataSource_dataValueHash,vl_dataValueIdStr_noPTCName,-1); |
| } |
| } |
| }// else: not possible: entry with PTC name is always there |
| } |
| |
| } |
| // call handler if it was given: |
| if (isbound(v_EPTF_DataSource_GetDataHandler_DB[pl_dataValue.transactionId]) |
| and (0<sizeof(v_EPTF_DataSource_GetDataHandler_DB[pl_dataValue.transactionId]))) { |
| |
| for(var integer i:=0; i<sizeof(v_EPTF_DataSource_GetDataHandler_DB[pl_dataValue.transactionId]); i:=i+1) { |
| if (v_EPTF_DataSource_GetDataHandler_DB[pl_dataValue.transactionId][i].getDataHandler != null) { |
| if (not ispresent(pl_dataValue.dataVarName)) { |
| pl_dataValue.dataVarName := ""; |
| } |
| v_EPTF_DataSource_GetDataHandler_DB[pl_dataValue.transactionId][i].getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_dataValue.dataSource, |
| pl_ptcName := pl_dataValue.ptcName, // response may fill this if it was "" |
| pl_element := pl_dataValue.dataElement, |
| pl_params := pl_dataValue.params, |
| // reponse parameters: |
| pl_errorCode := pl_dataValue.errorCode, // error code in the response |
| pl_remoteDataVarName := pl_dataValue.dataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := pl_dataValue.ownerCompRef, // reference to the remote component |
| pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := pl_dataValue.dataValue, // the value of the data |
| // user data |
| pl_userData := v_EPTF_DataSource_GetDataHandler_DB[pl_dataValue.transactionId][i].userData // user specific data given at the request |
| ); |
| } |
| } |
| v_EPTF_DataSource_GetDataHandler_DB[pl_dataValue.transactionId] := {}; |
| f_EPTF_str2int_HashMap_Erase(v_EPTF_DataSource_pendingGetDataHash,vl_dataValueIdStr); |
| f_EPTF_Semaphore_delete(pl_dataValue.transactionId); |
| } else { |
| if (f_EPTF_Semaphore_isLocked(pl_dataValue.transactionId)) { |
| f_EPTF_Semaphore_unlock(pl_dataValue.transactionId); |
| } |
| } |
| } |
| |
| private function f_EPTF_DataSource_handleDataValueResponse(in EPTF_DataSource_Msg_DataValueResponse pl_dataValueResponse) |
| runs on EPTF_DataSource_CT { |
| |
| v_EPTF_DataSource_Msg_List[pl_dataValueResponse.transactionId] := {dataValueResponse := pl_dataValueResponse}; |
| //decrease number of pending getData counter: --in this case it is not needed, because it is not implemented for getDataValue and setDataValue |
| //v_EPTF_DataSource_nofPendingGetData := v_EPTF_DataSource_nofPendingGetData - 1; |
| |
| // call handler if it was given: |
| if (isbound(v_EPTF_DataSource_GetDataValueHandler_DB[pl_dataValueResponse.transactionId]) |
| and v_EPTF_DataSource_GetDataValueHandler_DB[pl_dataValueResponse.transactionId] != cg_EPTF_DataSource_GetDataValueHandler_null) { |
| |
| if (v_EPTF_DataSource_GetDataValueHandler_DB[pl_dataValueResponse.transactionId].getDataValueHandler != null) { |
| v_EPTF_DataSource_GetDataValueHandler_DB[pl_dataValueResponse.transactionId].getDataValueHandler.apply( |
| // reponse parameters: |
| pl_errorCode := pl_dataValueResponse.errorCode, // error code in the response |
| pl_dataValue := pl_dataValueResponse.dataValue, // the value of the data |
| // user data |
| pl_userData := v_EPTF_DataSource_GetDataValueHandler_DB[pl_dataValueResponse.transactionId].userData // user specific data given at the request |
| ); |
| } |
| |
| v_EPTF_DataSource_GetDataValueHandler_DB[pl_dataValueResponse.transactionId] := cg_EPTF_DataSource_GetDataValueHandler_null; |
| f_EPTF_Semaphore_delete(pl_dataValueResponse.transactionId); |
| } else { |
| if (f_EPTF_Semaphore_isLocked(pl_dataValueResponse.transactionId)) { |
| f_EPTF_Semaphore_unlock(pl_dataValueResponse.transactionId); |
| } |
| } |
| } |
| |
| private function f_EPTF_DataSource_handleValueList(in EPTF_DataSource_Msg_List pl_valueList) |
| runs on EPTF_DataSource_CT { |
| for(var integer i:=0; i<sizeof(pl_valueList); i:=i+1) { |
| if (ischosen(pl_valueList[i].dataValue)) { |
| f_EPTF_DataSource_handleDataValue(pl_valueList[i].dataValue); |
| } else if (ischosen(pl_valueList[i].conditionValue)) { |
| f_EPTF_DataSource_handleConditionValue(pl_valueList[i].conditionValue); |
| } |
| } |
| } |
| |
| private function f_EPTF_DataSource_handleGetCondition_sendResponse( |
| //request parameters: |
| in charstring pl_source, |
| in charstring pl_ptcName, // response may fill this if it was "" |
| in charstring pl_element, |
| in EPTF_DataSource_Params pl_params, |
| // reponse parameters: |
| in integer pl_errorCode, // error code in the response |
| in charstring pl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message |
| in EPTF_Var_CT/*EPTF_DataSourceClient_CT*/ pl_ownerCompRef,// reference to the remote component |
| in integer pl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!) |
| in EPTF_Var_DirectContent pl_dataValue, // the value of the data |
| // user data |
| in EPTF_IntegerList pl_userData // user specific data given at the request |
| ) runs on EPTF_DataSource_CT { |
| var integer vl_transactionId := pl_userData[0]; |
| var EPTF_DataSourceClient_CT vl_sourceCompRef := f_EPTF_DataSourceClient_downcast(pl_userData[1]) |
| |
| |
| // this is for compatibility: |
| if (pl_errorCode!=0) { |
| pl_remoteDataVarName := log2str(%definitionId&": Invalid condition or parameter: ", |
| "\nSource: ",pl_source, |
| "\nPTC : ",pl_ptcName , |
| "\nMethod Name : " ,pl_element, |
| "\nParams: " , pl_params)&"\n:"&pl_remoteDataVarName; |
| } |
| |
| // send response: |
| f_EPTF_DataSource_sendMsg(EPTF_DataSource_Msg:{conditionValue:={ |
| vl_transactionId, |
| pl_source, |
| pl_ptcName, |
| pl_element, |
| pl_params, |
| ischosen(pl_dataValue.boolVal) and pl_dataValue.boolVal == true, |
| pl_errorCode |
| }}, |
| vl_sourceCompRef |
| ); |
| } |
| |
| private function f_EPTF_DataSource_handleGetCondition( |
| in EPTF_DataSource_Msg_GetCondition pl_getCondition, |
| in EPTF_DataSourceClient_CT pl_sourceCompRef |
| ) runs on EPTF_DataSource_CT { |
| |
| f_EPTF_DataSource_getCondition_nonBlocking( |
| pl_source := pl_getCondition.dataSource, |
| pl_ptcName := pl_getCondition.ptcName, |
| pl_method := pl_getCondition.method, |
| pl_params := pl_getCondition.params, |
| pl_getConditionHandler := { |
| refers(f_EPTF_DataSource_handleGetCondition_sendResponse), |
| {pl_getCondition.transactionId,f_EPTF_Base_upcast(pl_sourceCompRef)} |
| } |
| ); |
| } |
| |
| private function f_EPTF_DataSource_handleConditionValue(in EPTF_DataSource_Msg_ConditionValue pl_conditionValue) |
| runs on EPTF_DataSource_CT { |
| v_EPTF_DataSource_Msg_List[pl_conditionValue.transactionId] := {conditionValue := pl_conditionValue}; |
| |
| //decrease number of pending getData counter: |
| v_EPTF_DataSource_nofPendingGetData := v_EPTF_DataSource_nofPendingGetData - 1; |
| //if (v_EPTF_DataSource_nofPendingGetData==0) { |
| // action("*** NO MORE PENDING GetData LEFT!"); |
| //} |
| |
| // call handler if it was given: |
| if (isbound(v_EPTF_DataSource_GetDataHandler_DB[pl_conditionValue.transactionId]) |
| and (0<sizeof(v_EPTF_DataSource_GetDataHandler_DB[pl_conditionValue.transactionId]))) { |
| |
| for(var integer i:=0; i<sizeof(v_EPTF_DataSource_GetDataHandler_DB[pl_conditionValue.transactionId]); i:=i+1) { |
| if(v_EPTF_DataSource_GetDataHandler_DB[pl_conditionValue.transactionId][i].getDataHandler != null) { |
| v_EPTF_DataSource_GetDataHandler_DB[pl_conditionValue.transactionId][i].getDataHandler.apply( |
| //request parameters: |
| pl_source := pl_conditionValue.dataSource, |
| pl_ptcName := pl_conditionValue.ptcName, // response may fill this if it was "" |
| pl_element := pl_conditionValue.method, |
| pl_params := pl_conditionValue.params, |
| // reponse parameters: |
| pl_errorCode := pl_conditionValue.errorCode, // error code in the response |
| pl_remoteDataVarName := "", // var name on the remote component. In case errorCode!=0: it contains the error message |
| pl_ownerCompRef := null, // reference to the remote component |
| pl_localDataVarId := -1, // var id on the local component (contains the current value, not subscribed to remote!) |
| pl_dataValue := {boolVal := pl_conditionValue.conditionValue}, // the value of the data |
| // user data |
| pl_userData := v_EPTF_DataSource_GetDataHandler_DB[pl_conditionValue.transactionId][i].userData // user specific data given at the request |
| ); |
| } |
| } |
| v_EPTF_DataSource_GetDataHandler_DB[pl_conditionValue.transactionId] := {}; |
| f_EPTF_Semaphore_delete(pl_conditionValue.transactionId); |
| } else { |
| if (f_EPTF_Semaphore_isLocked(pl_conditionValue.transactionId)) { |
| f_EPTF_Semaphore_unlock(pl_conditionValue.transactionId); |
| } |
| } |
| } |
| |
| private function f_EPTF_DataSource_handleReadyEvent(in EPTF_DataSource_Msg_ReadyEvent pl_readyEvent) |
| runs on EPTF_DataSource_CT { |
| for ( var integer i := 0; i < sizeof(v_EPTF_DataSource_ready_functions) ; i := i+1 ) |
| { |
| v_EPTF_DataSource_ready_functions[i].apply(pl_readyEvent.dataSource, pl_readyEvent.ptcName); |
| } |
| |
| } |
| |
| private function f_EPTF_DataSource_sendMsg(in EPTF_DataSource_Msg pl_msg, in EPTF_DataSourceClient_CT pl_to) runs on EPTF_DataSource_CT { |
| if (ischosen(pl_msg.getData) or ischosen(pl_msg.getCondition)) { |
| |
| var integer vl_bufferSize := sizeof(v_EPTF_DataSource_Msg_GetData_Buffer); |
| if (v_EPTF_DataSource_getDataMsgClusters_BufferEmpty) { |
| // if (vl_bufferSize==0) { |
| t_EPTF_DataSource_Msg_GetData_Buffer_timer.start; |
| v_EPTF_DataSource_getDataMsgClusters_BufferEmpty := false; |
| } |
| // v_EPTF_DataSource_Msg_GetData_Buffer[vl_bufferSize] := { pl_msg.getData, pl_to }; |
| |
| if(not isbound(v_EPTF_DataSource_getDataMsgClusters[f_EPTF_Base_upcast(pl_to)])) { |
| v_EPTF_DataSource_getDataMsgClusters[f_EPTF_Base_upcast(pl_to)] := {}; |
| v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[f_EPTF_Base_upcast(pl_to)] := 0; |
| } |
| v_EPTF_DataSource_getDataMsgClusters[f_EPTF_Base_upcast(pl_to)][sizeof(v_EPTF_DataSource_getDataMsgClusters[f_EPTF_Base_upcast(pl_to)])] := pl_msg; |
| |
| } else { |
| @try { |
| EPTF_DataSourceIf.send(pl_msg) to pl_to; |
| } @catch(dte_str) { |
| f_EPTF_DataSource_sendMsgErrorHandler(pl_msg,pl_to,dte_str); |
| } |
| } |
| } |
| |
| private function f_EPTF_DataSource_sendMsgErrorHandler(in EPTF_DataSource_Msg pl_msg, in EPTF_DataSourceClient_CT pl_to, in charstring pl_dte_str) runs on EPTF_DataSource_CT { |
| var charstring vl_errorMsg := log2str(%definitionId&": Cannot send the following message to component ",pl_to,": ",pl_msg,": ",pl_dte_str); |
| f_EPTF_DataSource_warning(vl_errorMsg); |
| |
| if (ischosen(pl_msg.getCondition)) { |
| // this is not reached, getCondition is handled separately |
| // //deregister sources that belong to this component: |
| // f_EPTF_DataSource_deregisterData(pl_to); |
| // |
| // // generate conditionValue locally with error code |
| // vl_msg := { conditionValue:= { |
| // transactionId := pl_msg.getCondition.transactionId, |
| // dataSource := pl_msg.getCondition.dataSource, |
| // ptcName := pl_msg.getCondition.ptcName, |
| // method := pl_msg.getCondition.method, |
| // params := pl_msg.getCondition.params, |
| // conditionValue := true, |
| // errorCode := 3 |
| // }} |
| // f_EPTF_DataSource_handleConditionValue(vl_msg.conditionValue); |
| } else if (ischosen(pl_msg.getData)) { |
| // this is not reached, getData is handled separately |
| } else if (ischosen(pl_msg.dataValue)) { |
| //ignore, message is not sent |
| //deregister sources that belong to this component: |
| f_EPTF_DataSource_deregisterData(pl_to); |
| } else if (ischosen(pl_msg.conditionValue)) { |
| //ignore, message is not sent |
| //deregister sources that belong to this component: |
| f_EPTF_DataSource_deregisterData(pl_to); |
| } else if (ischosen(pl_msg.getDataValue)) { |
| f_EPTF_DataSource_deregisterData(pl_to); |
| f_EPTF_DataSource_handleDataValueResponse({ |
| transactionId := pl_msg.getDataValue.transactionId, |
| dataValue := {charstringVal := vl_errorMsg}, |
| errorCode := -11 |
| }); |
| } else if (ischosen(pl_msg.setDataValue)) { |
| f_EPTF_DataSource_deregisterData(pl_to); |
| f_EPTF_DataSource_handleDataValueResponse({ |
| transactionId := pl_msg.setDataValue.transactionId, |
| dataValue := {charstringVal := vl_errorMsg}, |
| errorCode := -11 |
| }); |
| } |
| } |
| |
| private function f_EPTF_DataSource_calculateNofMsgsToSend() runs on EPTF_DataSource_CT return integer { |
| var integer vl_buffSize := sizeof(v_EPTF_DataSource_Msg_GetData_Buffer); |
| var integer vl_nofMsgsToSend := v_EPTF_DataSource_Msg_GetData_BufferBurstSize; |
| |
| if (vl_buffSize<vl_nofMsgsToSend + v_EPTF_DataSource_Msg_GetData_BufferStartIdx) { |
| vl_nofMsgsToSend := vl_buffSize - v_EPTF_DataSource_Msg_GetData_BufferStartIdx; |
| } //else { |
| //action("*** BUFFER SIZE: ", sizeof(v_EPTF_DataSource_Msg_Buffer)); |
| //action("*** msgs to send: ", vl_nofMsgsToSend-v_EPTF_DataSource_Msg_GetData_BufferStartIdx); |
| //action("*** msgs remain: ", vl_buffSize-vl_nofMsgsToSend); |
| //action("*** buffer content: ", v_EPTF_DataSource_Msg_Buffer); |
| //} |
| |
| // if pending messages would exceed limit, send less messages: |
| if (v_EPTF_DataSource_maxNofPendingGetData<v_EPTF_DataSource_nofPendingGetData+vl_nofMsgsToSend) { |
| vl_nofMsgsToSend := v_EPTF_DataSource_maxNofPendingGetData-v_EPTF_DataSource_nofPendingGetData; |
| //action("*** maxNofPendingMsgs reached!: ", v_EPTF_DataSource_nofPendingGetData, " msgs to send: ", vl_nofMsgsToSend); |
| } |
| //action("*** vl_nofMsgsToSend:", vl_nofMsgsToSend); |
| return vl_nofMsgsToSend; |
| } |
| |
| private function f_EPTF_DataSource_calculateNofMsgsToSendForCluster(in integer pl_compId) runs on EPTF_DataSource_CT return integer { |
| var integer vl_buffSize := sizeof(v_EPTF_DataSource_getDataMsgClusters[pl_compId]); |
| var integer vl_nofMsgsToSend := v_EPTF_DataSource_Msg_GetData_BufferBurstSize; |
| |
| if (vl_buffSize<vl_nofMsgsToSend + v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[pl_compId]) { |
| vl_nofMsgsToSend := vl_buffSize - v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[pl_compId]; |
| } |
| |
| // if pending getData messages would exceed limit, send less messages: |
| if (v_EPTF_DataSource_maxNofPendingGetData<v_EPTF_DataSource_nofPendingGetData+vl_nofMsgsToSend) { |
| vl_nofMsgsToSend := v_EPTF_DataSource_maxNofPendingGetData-v_EPTF_DataSource_nofPendingGetData; |
| //action("*** maxNofPendingGetData reached!: ", v_EPTF_DataSource_nofPendingGetData, " msgs to send: ", vl_nofMsgsToSend); |
| } |
| //action("*** vl_nofMsgsToSend:", vl_nofMsgsToSend); |
| return vl_nofMsgsToSend; |
| } |
| |
| private altstep as_EPTF_DataSource_Msg_GetData_Buffer_Handler() runs on EPTF_DataSource_CT { |
| // [sizeof(v_EPTF_DataSource_Msg_GetData_Buffer) != 0] t_EPTF_DataSource_Msg_GetData_Buffer_timer.timeout { |
| [not v_EPTF_DataSource_getDataMsgClusters_BufferEmpty] t_EPTF_DataSource_Msg_GetData_Buffer_timer.timeout { |
| //action("***Handling buffer"); |
| v_EPTF_DataSource_getDataMsgClusters_BufferEmpty := true; |
| for(var integer i:=0; i<sizeof(v_EPTF_DataSource_getDataMsgClusters);i:=i+1) { |
| if(not isbound(v_EPTF_DataSource_getDataMsgClusters[i]) or v_EPTF_DataSource_getDataMsgClusters[i] == {}) { |
| continue; |
| } |
| |
| var integer vl_buffSize := sizeof(v_EPTF_DataSource_getDataMsgClusters[i]); |
| var integer vl_lastIdx := v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[i] + f_EPTF_DataSource_calculateNofMsgsToSendForCluster(i); |
| |
| var EPTF_DataSource_Msg_List vl_msgListToSend := {}; |
| for(var integer j:=v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[i]; j<vl_lastIdx; j:=j+1) { |
| vl_msgListToSend[sizeof(vl_msgListToSend)] := v_EPTF_DataSource_getDataMsgClusters[i][j]; |
| } |
| @try{ |
| if (vl_lastIdx>v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[i]) { |
| EPTF_DataSourceIf.send({getList := vl_msgListToSend}) to f_EPTF_DataSourceClient_downcast(i); |
| } |
| } |
| @catch(dte_str) { |
| f_EPTF_DataSource_warning(log2str(%definitionId&": Cannot send the following getData requests ",v_EPTF_DataSource_getDataMsgClusters[i]," to component ",i,": ",dte_str)); |
| vl_lastIdx := vl_buffSize; |
| v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[i] := vl_buffSize; //this component terminated => all messages are removed |
| //deregister datasource sources that belong this compontent: |
| f_EPTF_DataSource_deregisterData(f_EPTF_DataSourceClient_downcast(i)); |
| //call handlers with error code: |
| for(var integer j:=0; j<sizeof(v_EPTF_DataSource_getDataMsgClusters[i]); j:=j+1) { |
| if (ischosen(v_EPTF_DataSource_getDataMsgClusters[i][j].getData)) { |
| f_EPTF_DataSource_handleDataValue({ |
| transactionId := v_EPTF_DataSource_getDataMsgClusters[i][j].getData.transactionId, |
| dataSource := v_EPTF_DataSource_getDataMsgClusters[i][j].getData.dataSource, |
| ptcName := v_EPTF_DataSource_getDataMsgClusters[i][j].getData.ptcName, |
| dataElement := v_EPTF_DataSource_getDataMsgClusters[i][j].getData.dataElement, |
| params := v_EPTF_DataSource_getDataMsgClusters[i][j].getData.params, |
| dataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",v_EPTF_DataSource_getDataMsgClusters[i][j].getData.dataSource, ": Source is not registered"), // the name of the EPTF_Var that stores the data on the data owner component (remote) |
| dataValue := {unknownVal:={omit}}, // the current value of the requested data (=value of the remote variable) |
| errorCode := 3, |
| ownerCompRef := null // used only between Server -> Client direction for forwarding subscription to the source component directly |
| }) |
| } else if (ischosen(v_EPTF_DataSource_getDataMsgClusters[i][j].getCondition)) { |
| f_EPTF_DataSource_handleConditionValue({ |
| transactionId := v_EPTF_DataSource_getDataMsgClusters[i][j].getCondition.transactionId, |
| dataSource := v_EPTF_DataSource_getDataMsgClusters[i][j].getCondition.dataSource, |
| ptcName := v_EPTF_DataSource_getDataMsgClusters[i][j].getCondition.ptcName, |
| method := v_EPTF_DataSource_getDataMsgClusters[i][j].getCondition.method, |
| params := v_EPTF_DataSource_getDataMsgClusters[i][j].getCondition.params, |
| conditionValue := true, // the current value of the requested condition |
| errorCode := 3 |
| }) |
| } |
| } |
| //remove messages from buffer towards this component: |
| v_EPTF_DataSource_getDataMsgClusters[i] := {}; |
| } |
| |
| v_EPTF_DataSource_nofPendingGetData := v_EPTF_DataSource_nofPendingGetData + vl_lastIdx - v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[i]; |
| //action("*** msg sent: ", sizeof(vl_msgListToSend)); |
| |
| v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[i] := vl_lastIdx; |
| if (v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[i]==vl_buffSize) { |
| v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[i] := 0; |
| v_EPTF_DataSource_getDataMsgClusters[i] := {}; |
| } else { |
| // there are still messages left in the buffer |
| v_EPTF_DataSource_getDataMsgClusters_BufferEmpty := false; |
| //t_EPTF_DataSource_Msg_GetData_Buffer_timer.start(0.001); |
| //v_EPTF_DataSource_startTime := f_EPTF_Base_getRelTimeInSecs(); |
| //action("**** msgs remain[",i,"]: ", vl_buffSize-v_EPTF_DataSource_getDataMsgClusters_BufferStartIdx[i]); |
| } |
| } |
| |
| if (not v_EPTF_DataSource_getDataMsgClusters_BufferEmpty) { |
| t_EPTF_DataSource_Msg_GetData_Buffer_timer.start(0.001); |
| //action("***restarting buffer timer"); |
| } |
| |
| repeat; |
| //------------------------------------------------------------------ |
| // alternate code without clustering: |
| // [sizeof(v_EPTF_DataSource_Msg_GetData_Buffer) != 0 and f_EPTF_DataSource_calculateNofMsgsToSend()>0] t_EPTF_DataSource_Msg_GetData_Buffer_timer.timeout { |
| // // TODO: send buffer with clustering |
| // |
| // |
| // var integer vl_buffSize := sizeof(v_EPTF_DataSource_Msg_GetData_Buffer); |
| // var integer vl_lastIdx := v_EPTF_DataSource_Msg_GetData_BufferStartIdx + f_EPTF_DataSource_calculateNofMsgsToSend(); |
| // |
| // for(var integer i:=v_EPTF_DataSource_Msg_GetData_BufferStartIdx; i<vl_lastIdx; i:=i+1) { |
| // EPTF_DataSourceIf.send({getData := v_EPTF_DataSource_Msg_GetData_Buffer[i].getDataMsg}) to v_EPTF_DataSource_Msg_GetData_Buffer[i].destinationCompRef; |
| // } |
| // |
| // //increase number of pending getData counter with the number of messages sent: |
| // v_EPTF_DataSource_nofPendingGetData := v_EPTF_DataSource_nofPendingGetData + vl_lastIdx - v_EPTF_DataSource_Msg_GetData_BufferStartIdx; |
| // |
| // v_EPTF_DataSource_Msg_GetData_BufferStartIdx := vl_lastIdx; |
| // if (v_EPTF_DataSource_Msg_GetData_BufferStartIdx==vl_buffSize) { |
| // v_EPTF_DataSource_Msg_GetData_BufferStartIdx := 0; |
| // v_EPTF_DataSource_Msg_GetData_Buffer := {}; |
| // } else { |
| // // there are still messages left in the buffer |
| // t_EPTF_DataSource_Msg_GetData_Buffer_timer.start(0.001); |
| // //action("**** msgs remain: ", vl_buffSize-v_EPTF_DataSource_Msg_GetData_BufferStartIdx); |
| // } |
| // repeat; |
| } |
| } |
| |
| private altstep as_EPTF_DataSource_EventHandler() runs on EPTF_DataSource_CT { |
| var EPTF_DataSource_Msg vl_msg; |
| var EPTF_DataSourceClient_CT vl_sender; |
| [] EPTF_DataSourceIf.receive(EPTF_DataSource_Msg:?) -> value vl_msg sender vl_sender { |
| if (ischosen(vl_msg.registerData)) { |
| f_EPTF_DataSource_handleRegisterData(vl_msg.registerData, vl_sender); |
| } else if (ischosen(vl_msg.dataValue)) { |
| f_EPTF_DataSource_handleDataValue(vl_msg.dataValue); |
| } else if (ischosen(vl_msg.dataValueResponse)) { |
| f_EPTF_DataSource_handleDataValueResponse(vl_msg.dataValueResponse); |
| } else if (ischosen(vl_msg.valueList)) { |
| f_EPTF_DataSource_handleValueList(vl_msg.valueList); |
| } else if (ischosen(vl_msg.conditionValue)) { |
| f_EPTF_DataSource_handleConditionValue(vl_msg.conditionValue); |
| } else if (ischosen(vl_msg.getData)) { |
| f_EPTF_DataSource_handleGetData(vl_msg.getData, vl_sender); |
| } else if (ischosen(vl_msg.getDataValue)) { |
| f_EPTF_DataSource_handleGetDataValue(vl_msg.getDataValue, vl_sender); |
| } else if (ischosen(vl_msg.setDataValue)) { |
| f_EPTF_DataSource_handleSetDataValue(vl_msg.setDataValue, vl_sender); |
| } else if (ischosen(vl_msg.getCondition)) { |
| f_EPTF_DataSource_handleGetCondition(vl_msg.getCondition, vl_sender); |
| } else if (ischosen(vl_msg.clientReady)) { |
| f_EPTF_DataSource_handleReadyEvent(vl_msg.clientReady); |
| } |
| repeat; |
| } |
| [] as_EPTF_DataSource_Msg_GetData_Buffer_Handler(); |
| } |
| |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_getParams |
| // |
| // Purpose: |
| // General function to extract the needed parameters from the pl_params list. |
| // Returns positive error code if params are not correct |
| // Returns -1 if params are wrong syntactically |
| // |
| // Parameters: |
| // *in* <EPTF_DataSource_Params> *pl_params* - the actual parameters |
| // *in* <EPTF_CharstringList> *pl_needed* - the parameters needed |
| // *in* <EPTF_CharstringList> *pl_result* - the value of the needed parameters |
| // *in* <f_EPTF_DataSource_DScheckParams_FT> *pl_checkParams* - function to check the parameters |
| // |
| // Returns: |
| // integer - 0 if OK, nonzero on error: number of params is not the same as pl_needed, |
| // or one or more params in pl_needed are not found |
| // |
| // Detailed Comments: |
| // Can to be called on <EPTF_DataSource_CT> and on <EPTF_DataSourceClient_CT> both. |
| // Typical usage is in the dataElement handler |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_getParams(in EPTF_DataSource_Params pl_params, |
| in EPTF_CharstringList pl_needed, |
| out EPTF_CharstringList pl_result, |
| in f_EPTF_DataSource_DScheckParams_FT pl_checkParams := null) |
| runs on EPTF_Logging_CT return integer { |
| pl_result := {}; |
| if(sizeof(pl_params) == sizeof(pl_needed)){ |
| for(var integer j := 0; j < sizeof(pl_needed); j := j + 1){ |
| for(var integer i := 0; i < sizeof(pl_params); i:= i + 1){ |
| if(pl_params[i].paramName == pl_needed[j]){ |
| pl_result[sizeof(pl_result)] := pl_params[i].paramValue; |
| } |
| } |
| } |
| if(sizeof(pl_result) != sizeof(pl_needed)){ |
| var EPTF_CharstringList vl_error := {}; |
| for(var integer i := 0; i < sizeof(pl_params); i:= i + 1){ |
| vl_error[i] := pl_params[i].paramName; |
| } |
| f_EPTF_Logging_warning(true,%definitionId& ": Invalid DataSource parameter: Parameters are not correct: "& |
| "\nReceived: "& log2str(vl_error)& |
| "\nNeeded : "& log2str(pl_needed) ); |
| return -1; |
| } |
| if (pl_checkParams!=null) { |
| return pl_checkParams.apply(pl_params); |
| } else { |
| return 0; |
| } |
| } else{ |
| var EPTF_CharstringList vl_error := {}; |
| for(var integer i := 0; i < sizeof(pl_params); i:= i + 1){ |
| vl_error[i] := pl_params[i].paramName; |
| } |
| if(sizeof(pl_params) < sizeof(pl_needed)){ |
| f_EPTF_Logging_warning(true,%definitionId& ": Invalid DataSource parameter: Too few parameters are given: "& |
| "\nReceived: "& log2str(vl_error)& |
| "\nNeeded : "& log2str(pl_needed)); |
| } else { |
| f_EPTF_Logging_warning(true,%definitionId& ": Invalid DataSource parameter: Too many parameters are given: "& |
| "\nReceived: "& log2str(vl_error)& |
| "\nNeeded : "& log2str(pl_needed)); |
| } |
| return -1; |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_extractParams |
| // |
| // Purpose: |
| // Extracts the needed parameters from the params. |
| // It returns "" for values of params that are not found. |
| // |
| // Parameters: |
| // *in* <EPTF_DataSource_Params> *pl_params* - the actual parameters |
| // *in* <EPTF_CharstringList> *pl_needed* - the parameters needed |
| // *in* <EPTF_CharstringList> *pl_result* - the value of the needed parameters |
| // |
| // Detailed Comments: |
| // Can be called in the dataElement handler or DScheckParams function |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_extractParams(in EPTF_DataSource_Params pl_params, |
| in EPTF_CharstringList pl_needed, |
| out EPTF_CharstringList pl_result) { |
| pl_result := {}; |
| for(var integer j := 0; j < sizeof(pl_needed); j := j + 1){ |
| pl_result[j] := ""; |
| for(var integer i := 0; i < sizeof(pl_params); i:= i + 1){ |
| if(pl_params[i].paramName == pl_needed[j]){ |
| pl_result[j] := pl_params[i].paramValue; |
| break; |
| } |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_replaceParams |
| // |
| // Purpose: |
| // Replaces the parameters from the params using the given param list. |
| // |
| // Parameters: |
| // *inout* <EPTF_DataSource_Params> *pl_params* - the actual parameters |
| // *in* <EPTF_CharstringList> *pl_paramsToReplace* - the parameters to replace and their new values |
| // |
| // Detailed Comments: |
| // Can be called in the dataElement handler or DScheckParams function |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_replaceParams(inout EPTF_DataSource_Params pl_params, |
| in EPTF_DataSource_Params pl_paramsToReplace) { |
| |
| for(var integer j := 0; j < sizeof(pl_paramsToReplace); j := j + 1){ |
| var boolean found := false; |
| var charstring pl_name := pl_paramsToReplace[j].paramName; |
| var charstring pl_value := pl_paramsToReplace[j].paramValue; |
| for(var integer i := 0; i < sizeof(pl_params); i:= i + 1){ |
| if(pl_params[i].paramName == pl_name){ |
| pl_params[i].paramValue := pl_value; |
| found := true; |
| break; |
| } |
| } |
| if (not found) { |
| pl_params := pl_params & {pl_paramsToReplace[j]}; |
| } |
| } |
| } |
| |
| // returns positive error code if params are not correct |
| // 0 if parameters are correct |
| private function f_EPTF_DataSource_DScheckParams( |
| in EPTF_DataSource_Params pl_params) |
| runs on EPTF_DataSource_CT return integer { |
| |
| return 0; |
| |
| } |
| |
| //Commandline Interface commands: |
| group DataSource_CLI { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_DataSource_CLI_init_CT |
| // |
| // Purpose: |
| // Init function for DataSource_CLI_CT |
| // |
| // Parameters: |
| // *in charstring pl_selfName* - the name of the component |
| // *in* <EPTF_CLI_CT> pl_CLI_compRef - the component reference of the CLI (default: null) |
| // |
| // Detailed Comments: |
| // Has to be called to initialize DataSource_CLI component. |
| // DataSource commands can be executed in the Command Line Interface |
| // after this function was called. |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_DataSource_CLI_init_CT(in charstring pl_selfName, in EPTF_CLI_CT pl_CLI_compRef := null) runs on EPTF_DataSource_CLI_CT { |
| |
| f_EPTF_DataSource_init_CT(pl_selfName); |
| |
| // initialize DataSource_CLI: |
| f_EPTF_CLI_Client_init_CT(pl_selfName, pl_CLI_compRef); |
| f_EPTF_CLI_Client_registerCommand( |
| c_EPTF_DataSource_CLI_commandName, |
| c_EPTF_DataSource_CLI_commandHelp, |
| refers(f_EPTF_DataSource_CLI_commandHandler) |
| ); |
| |
| } |
| |
| external function dec_datadescription (in octetstring pl_oct, out Datadescription pl_dataDescription) return integer |
| with {extension "prototype(backtrack) decode (XER:XER_EXTENDED) errorbehavior(ALL:WARNING)"} |
| |
| external function enc_datadescription (in Datadescription pl_dataDescription) return octetstring |
| with {extension "prototype(convert) encode (XER:XER_EXTENDED)"} |
| |
| external function dec_datadescriptionlist (in octetstring pl_oct, out Datadescriptionlist pl_dataDescriptionlist) return integer |
| with {extension "prototype(backtrack) decode (XER:XER_EXTENDED) errorbehavior(ALL:WARNING)"} |
| |
| external function enc_datadescriptionlist (in Datadescriptionlist pl_dataDescriptionlist) return octetstring |
| with {extension "prototype(convert) encode (XER:XER_EXTENDED)"} |
| |
| private function f_EPTF_DataSource_CLI_unichar2charstring(in universal charstring pl_uni) |
| return charstring{ |
| var charstring vl_char := ""; |
| for (var integer vl_i:= 0;vl_i<lengthof(pl_uni);vl_i:=vl_i+1) |
| { |
| vl_char := vl_char & int2char(unichar2int(pl_uni[vl_i])); |
| } |
| return vl_char |
| } |
| |
| private function f_EPTF_DataSource_CLI_result_from_Datadescription(in Datadescription pl_dataDescription, out charstring pl_result) |
| runs on EPTF_DataSource_CLI_CT return integer{ |
| // copy ptcName: |
| var charstring vl_ptcName := ""; |
| if (ispresent(pl_dataDescription.ptcname)) { |
| vl_ptcName := f_EPTF_DataSource_CLI_unichar2charstring(pl_dataDescription.ptcname); |
| } |
| |
| // convert params from vl_dataDescription to EPTF_DataSource_Params: |
| var EPTF_DataSource_Params vl_params := {}; |
| for(var integer i:=0; ispresent(pl_dataDescription.params) and i<sizeof(pl_dataDescription.params.dataparam_list); i:=i+1) { |
| vl_params[i] := { |
| f_EPTF_DataSource_CLI_unichar2charstring(pl_dataDescription.params.dataparam_list[i].name), |
| f_EPTF_DataSource_CLI_unichar2charstring(pl_dataDescription.params.dataparam_list[i].value_) |
| } |
| } |
| |
| var EPTF_Var_DirectContent vl_dataValue; |
| var integer vl_returnCode := f_EPTF_DataSource_getDataValue( |
| pl_dataValue := vl_dataValue, |
| pl_source := f_EPTF_DataSource_CLI_unichar2charstring(pl_dataDescription.source), |
| pl_ptcName := vl_ptcName, |
| pl_element := f_EPTF_DataSource_CLI_unichar2charstring(pl_dataDescription.element), |
| pl_params := vl_params |
| ); |
| if (vl_returnCode==0) { |
| // value of variable: |
| pl_result := f_EPTF_Var_directContent2str(vl_dataValue); |
| } else { |
| if (ischosen(vl_dataValue.charstringVal)) { |
| // error message: |
| pl_result := "Invalid data request for "&log2str(pl_dataDescription)&": "&vl_dataValue.charstringVal&": Requested data does not exist"; |
| } else { |
| pl_result := "Invalid datasource parameters "&log2str(pl_dataDescription)&": Requested data does not exist"; |
| } |
| } |
| return vl_returnCode; |
| } |
| |
| private function f_EPTF_DataSource_CLI_commandHandler(in charstring pl_commandArgs, inout charstring pl_result) |
| runs on EPTF_DataSource_CLI_CT return integer { |
| |
| if (pl_commandArgs=="help") { |
| pl_result := pl_result&" - executes DataSource commands\n"& |
| "Usage: "&pl_result&" <help|get|set|getCondition|getVarName> {parameters}\n"& |
| "\n"& |
| " help - print this help message\n"& |
| " get <xml format of Datadescription> - request the value of a dataElement\n"& |
| " getlist <xml format of DatadescriptionList> - request the value of a dataElementList\n"& |
| " set <xml format of Datadescription> <value> - set the value of a dataElement\n"& |
| " getCondition <xml format of Datadescription> - request the value of a condition\n"& |
| " getVarName <xml format of Datadescription> - request the variable name of a dataElement\n"& |
| " info [S=<sourceName>] [<E=<elementName>] [F=<TEXT|JSON>] - request information about dataElements\n"& |
| "\n"& |
| "Where\n"& |
| "Xml format of <Datadescription> is something like:\n"& |
| " <datadescription xmlns='http://ttcn.ericsson.se/protocolModules/xtdp/xtdl' element='Sources' source='DataSource'> </datadescription>\n"& |
| " or\n"& |
| " <datadescription xmlns='http://ttcn.ericsson.se/protocolModules/xtdp/xtdl' element='PTCs' source='DataSource'> <params> <dataparam name='Source' value='StatManager'/> </params> </datadescription>\n"& |
| " or\n"& |
| " <datadescription xmlns='http://ttcn.ericsson.se/protocolModules/xtdp/xtdl' element='PTCs' source='DataSource' ptcname='myPTC'> <params> <dataparam name='Source' value='StatManager'/> </params> </datadescription>\n"& |
| " Note, that the 'element' field in the Datadescription corresponds to the 'method' for Conditions.\n"& |
| " This format is similar to the one used in the custom GUI XML.\n"& |
| "Xml format of <Datadescriptionlist> (example): \n"& |
| " <datadescriptionlist xmlns='http://ttcn.ericsson.se/protocolModules/xtdp/xtdl'>\n"& |
| " <datadescription element='Sources' source='DataSource'> </datadescription>\n"& |
| " <datadescription element='PTCs' source='DataSource'> <params> <dataparam name='Source' value='StatManager'/> </params> </datadescription>\n"& |
| " </datadescriptionlist>\n"& |
| "<value>:\n"& |
| " should be in the same format as the value returned by the get command"; |
| return 0; // OK |
| } |
| |
| var charstring vl_firstArg := regexp(pl_commandArgs,c_EPTF_CLI_anyWord&c_EPTF_CLI_everything,0); |
| if (vl_firstArg=="get") { |
| var charstring vl_subCommandArgs := regexp(pl_commandArgs,c_EPTF_CLI_anyWord&c_EPTF_CLI_everything,1); |
| // decode subcommand: |
| var Datadescription vl_dataDescription; |
| if (0 != dec_datadescription(char2oct(vl_subCommandArgs),vl_dataDescription)) { |
| // error |
| pl_result := "Syntax error in argument "&vl_subCommandArgs&": Expecting XML format of the Datadescription"; |
| return 1; |
| }; |
| |
| var integer vl_returnCode; |
| vl_returnCode := f_EPTF_DataSource_CLI_result_from_Datadescription(vl_dataDescription, pl_result); |
| return vl_returnCode; |
| |
| } else if (vl_firstArg=="getlist") { |
| var charstring vl_subCommandArgs := regexp(pl_commandArgs,c_EPTF_CLI_anyWord&c_EPTF_CLI_everything,1); |
| // decode subcommand: |
| var Datadescriptionlist vl_dataDescriptionlist; |
| if (0 != dec_datadescriptionlist(char2oct(vl_subCommandArgs),vl_dataDescriptionlist)) { |
| // error |
| pl_result := "Syntax error in argument "&vl_subCommandArgs&": Expecting XML format of the Datadescriptionlist"; |
| return 1; |
| }; |
| |
| var integer vl_returnCode := 0, vl_dummy; |
| var integer vl_size := sizeof(vl_dataDescriptionlist.datadescription_list); |
| var charstring vl_result; |
| pl_result := ""; |
| for (var integer vl_i := 0; vl_i < vl_size; vl_i := vl_i + 1) { |
| if (vl_returnCode != 0) { |
| vl_dummy := f_EPTF_DataSource_CLI_result_from_Datadescription(vl_dataDescriptionlist.datadescription_list[vl_i], vl_result); |
| } else { |
| vl_returnCode := f_EPTF_DataSource_CLI_result_from_Datadescription(vl_dataDescriptionlist.datadescription_list[vl_i], vl_result); |
| } |
| pl_result := pl_result & vl_result & "\n"; |
| } |
| return vl_returnCode; |
| |
| } else if (vl_firstArg=="set") { |
| var charstring vl_subCommandArgs := regexp(pl_commandArgs,c_EPTF_CLI_anyWord&c_EPTF_CLI_everything&"</datadescription>"&c_EPTF_CLI_everything,1)&"</datadescription>"; |
| // decode subcommand: |
| var Datadescription vl_dataDescription := { |
| element := "elementName", |
| ptcname := "ptcName", |
| source := "sourceName", |
| params := {{ |
| {name:="param1Name", value_:="param1Value"}, |
| {name:="param2Name", value_:="param2Value"} |
| }} |
| }; |
| if (0 != dec_datadescription(char2oct(vl_subCommandArgs),vl_dataDescription)) { |
| // error |
| pl_result := "Syntax error in argument "&vl_subCommandArgs&": Expecting XML format of the Datadescription"; |
| return 1; |
| }; |
| |
| // copy ptcName: |
| var charstring vl_ptcName := ""; |
| if (ispresent(vl_dataDescription.ptcname)) { |
| vl_ptcName := f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.ptcname); |
| } |
| |
| // convert params from vl_dataDescription to EPTF_DataSource_Params: |
| var EPTF_DataSource_Params vl_params := {}; |
| for(var integer i:=0; ispresent(vl_dataDescription.params) and i<sizeof(vl_dataDescription.params.dataparam_list); i:=i+1) { |
| vl_params[i] := { |
| f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.params.dataparam_list[i].name), |
| f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.params.dataparam_list[i].value_) |
| } |
| } |
| |
| var charstring vl_dataVarName; |
| var integer vl_returnCode := f_EPTF_DataSource_getData( |
| pl_dataVarName := vl_dataVarName, |
| pl_source := f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.source), |
| pl_ptcName := vl_ptcName, |
| pl_element := f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.element), |
| pl_params := vl_params |
| ); |
| if (vl_returnCode==0) { |
| // value of variable: |
| var integer vl_idx := f_EPTF_Var_getId(vl_dataVarName); |
| if (vl_idx!=-1) { |
| if(not f_EPTF_Var_getSubsCanAdjust(vl_idx)) { |
| // variable is read only |
| pl_result := "Cannot change the value of the dataElement "&log2str(vl_dataDescription)&": DataElement is read-only!"; |
| return 2; // error: read-only var |
| }; |
| var charstring vl_variableValue := regexp(pl_commandArgs,c_EPTF_CLI_anyWord&c_EPTF_CLI_everything&"</datadescription>"&c_EPTF_CLI_everything,2); |
| vl_returnCode := f_EPTF_Var_str2content(vl_idx,vl_variableValue); |
| if (vl_returnCode == 0) { |
| pl_result := "Value set to data: "& vl_variableValue; |
| } else { |
| pl_result := "Syntax error in the value, or value is incompatible with the type of the data. Cannot set value: "&vl_variableValue; |
| } |
| } else { |
| pl_result := "Invalid datasource parameters "&log2str(vl_dataDescription)&": Variable with name "&vl_dataVarName&" for DataSource does not exist"; |
| } |
| } else { |
| pl_result := "Invalid datasource parameters "&log2str(vl_dataDescription)&": DataSource does not exist"; |
| } |
| return vl_returnCode; |
| |
| } else if (vl_firstArg=="getCondition") { |
| var charstring vl_subCommandArgs := regexp(pl_commandArgs,c_EPTF_CLI_anyWord&c_EPTF_CLI_everything,1); |
| // decode subcommand: |
| var Datadescription vl_dataDescription := { |
| element := "elementName", |
| ptcname := "ptcName", |
| source := "sourceName", |
| params := {{ |
| {name:="param1Name", value_:="param1Value"}, |
| {name:="param2Name", value_:="param2Value"} |
| }} |
| }; |
| if (0 != dec_datadescription(char2oct(vl_subCommandArgs),vl_dataDescription)) { |
| // error |
| pl_result := "Syntax error in argument "&vl_subCommandArgs&": Expecting XML format of the Datadescription"; |
| return 1; |
| }; |
| |
| // copy ptcName: |
| var charstring vl_ptcName := ""; |
| if (ispresent(vl_dataDescription.ptcname)) { |
| vl_ptcName := f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.ptcname); |
| } |
| |
| // convert params from vl_dataDescription to EPTF_DataSource_Params: |
| var EPTF_DataSource_Params vl_params := {}; |
| for(var integer i:=0; ispresent(vl_dataDescription.params) and i<sizeof(vl_dataDescription.params.dataparam_list); i:=i+1) { |
| vl_params[i] := { |
| f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.params.dataparam_list[i].name), |
| f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.params.dataparam_list[i].value_) |
| } |
| } |
| |
| var boolean vl_conditionValue; |
| var integer vl_returnCode := f_EPTF_DataSource_getCondition( |
| pl_conditionValue := vl_conditionValue, |
| pl_source := f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.source), |
| pl_ptcName := vl_ptcName, |
| pl_method := f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.element), |
| pl_params := vl_params |
| ); |
| if (vl_returnCode==0) { |
| // value of the condition: |
| pl_result := log2str(vl_conditionValue); |
| } else { |
| pl_result := "Invalid condition parameters "&log2str(vl_dataDescription)&": Condition does not exist"; |
| } |
| return vl_returnCode; |
| |
| } else if (vl_firstArg=="getVarName") { |
| var charstring vl_subCommandArgs := regexp(pl_commandArgs,c_EPTF_CLI_anyWord&c_EPTF_CLI_everything,1); |
| // decode subcommand: |
| var Datadescription vl_dataDescription := { |
| element := "elementName", |
| ptcname := "ptcName", |
| source := "sourceName", |
| params := {{ |
| {name:="param1Name", value_:="param1Value"}, |
| {name:="param2Name", value_:="param2Value"} |
| }} |
| }; |
| if (0 != dec_datadescription(char2oct(vl_subCommandArgs),vl_dataDescription)) { |
| // error |
| pl_result := "Syntax error in argument "&vl_subCommandArgs&": Expecting XML format of the Datadescription"; |
| return 1; |
| }; |
| |
| // copy ptcName: |
| var charstring vl_ptcName := ""; |
| if (ispresent(vl_dataDescription.ptcname)) { |
| vl_ptcName := f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.ptcname); |
| } |
| |
| // convert params from vl_dataDescription to EPTF_DataSource_Params: |
| var EPTF_DataSource_Params vl_params := {}; |
| for(var integer i:=0; ispresent(vl_dataDescription.params) and i<sizeof(vl_dataDescription.params.dataparam_list); i:=i+1) { |
| vl_params[i] := { |
| f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.params.dataparam_list[i].name), |
| f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.params.dataparam_list[i].value_) |
| } |
| } |
| |
| var charstring vl_dataVarName; |
| var integer vl_returnCode := f_EPTF_DataSource_getData( |
| pl_dataVarName := vl_dataVarName, |
| pl_source := f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.source), |
| pl_ptcName := vl_ptcName, |
| pl_element := f_EPTF_DataSource_CLI_unichar2charstring(vl_dataDescription.element), |
| pl_params := vl_params |
| ); |
| if (vl_returnCode==0) { |
| // name of variable: |
| pl_result := vl_dataVarName; |
| } else { |
| pl_result := "Invalid datasource parameters "&log2str(vl_dataDescription)&": Variable or the DataSource does not exist"; |
| } |
| return vl_returnCode; |
| |
| } else if (vl_firstArg=="info") { |
| var integer vl_returnCode := 0; |
| var charstring vl_subCommandArgs := regexp(pl_commandArgs,c_EPTF_CLI_anyWord&c_EPTF_CLI_everything,1); |
| var charstring vl_sourceName := regexp(vl_subCommandArgs,"([^S]#(0,)|[^S]#(0,)S[^=]#(0,))S="&"(([^'][^ \t]#(0,))|('[^']#(1,)'))"&c_EPTF_CLI_everything,1); |
| var charstring vl_elementName:= regexp(vl_subCommandArgs,"([^E]#(0,)|[^E]#(0,)E[^=]#(0,))E="&"(([^'][^ \t]#(0,))|('[^']#(1,)'))"&c_EPTF_CLI_everything,1); |
| var charstring vl_format:= regexp(vl_subCommandArgs,"([^F]#(0,)|[^F]#(0,)F[^=]#(0,))F="&"(([^'][^ \t]#(0,))|('[^']#(1,)'))"&c_EPTF_CLI_everything,1); |
| if (vl_format=="" or vl_format=="TEXT") { |
| pl_result := f_EPTF_DataSource_getHelpTEXT(regexp(vl_sourceName,"[']#(0,1)(([^']#(0,)|[^ \t]#(0,))#(1,))[']#(0,1)",0),regexp(vl_elementName,"[']#(0,1)(([^']#(0,)|[^ \t]#(0,))#(1,))[']#(0,1)",0)); |
| } else if (vl_format=="JSON") { |
| pl_result := oct2char(f_EPTF_DataSource_getHelpJSON(regexp(vl_sourceName,"[']#(0,1)(([^']#(0,)|[^ \t]#(0,))#(1,))[']#(0,1)",0),regexp(vl_elementName,"[']#(0,1)(([^']#(0,)|[^ \t]#(0,))#(1,))[']#(0,1)",0))); |
| } else { |
| pl_result := "Invalid format: "&vl_format&". Should be: TEXT or JSON"; |
| vl_returnCode := 1; |
| } |
| return vl_returnCode; |
| } |
| pl_result := "Syntax error in argument "&vl_firstArg&": Expecting <help|get|set|getCondition|getVarName|info>"; |
| return 1; // error; |
| } |
| |
| }// group DataSource_CLI |
| |
| private function f_EPTF_DataSource_error(in charstring pl_msg) runs on EPTF_DataSource_CT { |
| f_EPTF_Logging_error(true,"Error: "&pl_msg); |
| } |
| |
| private function f_EPTF_DataSource_warning(in charstring pl_msg) runs on EPTF_DataSource_CT { |
| f_EPTF_Logging_warning(true,"Warning: "&pl_msg); |
| } |
| |
| private function f_EPTF_DataSource_debug(in charstring pl_msg) runs on EPTF_DataSource_CT { |
| f_EPTF_Logging_debug(true,"Debug: "&pl_msg); |
| } |
| |
| } // module EPTF_CLL_DataSource_Functions |
| with { |
| extension "requiresTITAN CRL 113 200/3 R2A"; |
| } |