blob: 40436a54cdcff51356ef60cf02baae64bef3b308 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// //
// 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";
}