GetProgramFunctionInfo function
Syntax
GetProgramFunctionInfo(ProgramId)
Where ProgramId is the following for PeopleCode user-defined functions:
RECORD.RecordName.FIELD.FieldName.METHOD.MethodName
Where ProgramId is the following for Component Interface user-defined methods:
COMPONENTINTERFACE.CIName.METHODS.Methods
Description
Use the GetProgramFunctionInfo function to determine the full signature and return values of a PeopleCode user-defined function, or a Component Interface method.
Parameters
| Parameter | Description |
|---|---|
|
ProgramId |
Specify the full name of the function or the Component Interface method, as a string. |
Returns
An array of array of any.
There is one array for every function or method defined in the program. Each array contains the following information:
-
The name of the function.
-
The signature of the parameters as a comma-separated string (see additional information below.)
-
The signature of the result (see result list below.)
-
The annotation of the Doc tag.
-
A boolean indicator of whether this function is to be exported (as indicated by the noexp tag).
-
A boolean indicator of whether this function is permitted to be called by this user. This only makes sense for Functions defined as CI methods in Component Interface PeopleCode. The default value is True.
The parameters may be modified by the following values:
| Value | Description |
|---|---|
|
? |
An optional parameter. |
|
* |
A repeated parameter. |
|
& |
A parameter reference (PARM_NAME) |
The possibly values of the result are as follows. Note the use of both lower and upper case letters.
| Value | Description |
|---|---|
|
D |
Dec |
|
d |
Date |
|
S |
String |
|
A |
Any |
|
B |
Boolean |
|
V |
None |
|
t |
Time |
|
T |
DateTime |
|
I |
Image |
|
i |
Integer |
|
O |
Object |
|
f |
Float |
|
9 |
Number |
|
x |
Unknown |
|
[<value> |
Array A single bracket indicates a single array. Two brackets indicates a two-dimensional array, three brackets a three-dimensional array, and so on. The value following
the bracket indicates the type of array. For example, |
Example
In the following example, this code is associated with the record QE_ABSENCE_HIST, on the field QE_REASON, in the FieldChange event.
Function Update(&1 As string) Returns number NoExport
Doc "this is some attached annotation"
Return 1.23;
End-Function;
/* everything else . . */
The following PeopleCode program:
Local array of array of any &r;
&r = GetProgramFunctionInfo("RECORD.QE_ABSENCE_HIST.FIELD.QE_REASON.METHOD.Field
Change");
Returns a two-dimensional array with a single row that contains the following:
&r[1][1] – the name of the function “Update”
&r[1][2] – the signature of the parameter “S&”
&r[1][3] – the signature of the result “9”
&r[1][4] – the annotation of the doc tag “this is some attached annotation”
&r[1][5] – a boolean indicator of whether this function is to be exported. In this case it returns false.
The following example is used with a Component Interface program:
Function Update(&1 As string) Returns number NoExport
Doc "this is some attached annotation"
Return 1.23;
End-Function;
Function Updateagain(&1 As string) Returns number
Doc "this is some more attached annotation"
Return 1.23;
End-Function;
Local File &log;
Function LogText(&msg As string)
If &log = Null Then
Return
End-If;
&log.WriteLine(&msg);
End-Function;
Function CreateCI(&Name As string) Returns ApiObject
Local ApiObject &CI;
/** Get Component Interface **/
&CI = %Session.GetCompIntfc(@("CompIntfc." | &Name));
/* instantiate */
&CI.PROCESSNAME = "AEMINITEST";
&CI.PROCESSTYPE = "Application Engine";
&CI.RUNCONTROLID = 99;
&CI.Create();
Return &CI;
End-Function;
Function DisplayProgramFuncInfo(&r As array of array of any)
Local integer &i;
For &i = 1 To &r.Len
Local string &o;
&o = &r [&i][1] | "(" | &r [&i][2] | ";" | &r [&i][3] | ") doc '"
| &r [&i][4] | "'";
If &r [&i][5] = 0 Then
&o = &o | " noexport ";
Else
&o = &o | " export ";
End-If;
If &r [&i][6] = 0 Then
&o = &o | " no permission ";
Else
&o = &o | " permitted ";
End-If;
LogText(&o);
End-For;
End-Function;
Function SetupParameters(&Names As array of string, &Sigs As array of string)
Returns array of any
Local array of any &p = CreateArrayAny();
Local integer &i;
/* could use the parameter name to get values out of a dom?? */
/* Base types we could handle
// D = Dec
// S = String
// d = Date
// A = Any
// B = Boolean
// V = None
// t = Time
// T = DateTime
// I = Image
// O = Object
// i = Integer
// f = Float
// 9 = Number
// x = Unknown
*/
For &i = 1 To &Sigs.Len
Local string &parName = RTrim(LTrim(&Names [&i + 1]));
/* first name is create/get/?? */
/* Here is where you'd get the value for this particular parameter
and then push it properly onto the parameter array */
Evaluate Substring(&Sigs [&i], 1, 1)
When = "D"
&p.Push(1);
Break;
When = "S"
&p.Push("String for " | &parName);
Break;
When = "9"
When = "i"
&p.Push(&i);
Break;
When-Other
&p.Push("Unimplemented . . .");
End-Evaluate
End-For;
Return &p;
End-Function;
Function CallUDMMethod(&ci As ApiObject, &funcInfo As array of array of any,
&methodName As string) Returns any
/* an example of calling a user defined method on a ci */
/* 1. find it in the funcinfo */
Local integer &i = 1;
Local integer &nFuncs = &funcInfo.Len;
While &i <= &nFuncs
/* name should match and it should be exportable (the default)
and the doc tag should have something in it
and it should be permitted */
If &funcInfo [&i][1] = &methodName And
&funcInfo [&i][5] <> 0 And
Len(&funcInfo [&i][4]) > 0 And
&funcInfo [&i][6] <> 0 Then
Break;
End-If;
&i = &i + 1;
End-While;
If &i > &nFuncs Then
LogText("not found");
Return False;
End-If;
/* 2. Next get the info necessary to call the function based on the signature
info */
Local string &parSignatures = &funcInfo [&i][2];
Local boolean &bPars = False;
Local array of any &Pars;
If Len(&parSignatures) > 0 Then
&bPars = True;
Local array of string &parSignature = Split(&parSignatures, ",");
Local array of string &parNames = Split(&funcInfo [&i][4], ",");
/* first one should be Create/get/? */
/* number of parameters should match number of parameter names */
If &parSignature.Len <> &parNames.Len - 1 Then
LogText("length mismatch");
Return False;
End-If;
&Pars = SetupParameters(&parNames, &parSignature);
Else
&Pars = CreateArrayAny();
End-If;
/* 3. Call the udm method with our parameters */
Return &ci.InvokeMethodUDF(&methodName, &Pars);
End-Function;
QE_ABSENCE_HIST.QE_REASON.Value = ""; /* clean it up */
Local string &ciName = "PROCESSREQUEST";
Local ApiObject &CI = CreateCI(&ciName);
Local array of any &pars = CreateArrayAny("First parameter", 2);
/* check with variable for method name */
Local string &methodname = "FoxTest";
/* add in a bogus parameter - tested - works - fails with false return :-( as per⇒
usual in api objects*/
Local string &bogus = "bogus par";
&log = GetFile("C:\temp\junk\udflog.txt", "a", "UTF8", %FilePath_Absolute);
LogText("=====================================");
LogText("Result of direct call: " | &CI.InvokeMethodUDF(&methodname, &pars /* ,⇒
&bogus */));
rem LogText("&ci: " | &CI);
/* do this the new way - at least model how a webservices Peoplecode⇒
implementation could do it */
Local string &ciObjid = "COMPONENTINTERFACE." | &ciName | ".METHOD.Methods";
/* get the program information */
Local array of array of any &progInfo;
&progInfo = GetProgramFunctionInfo(&ciObjid);
/* returns a an array of arrays: an array for each function defined in the program.
Each row has the following ([i] = position i):
[1] = program name (string)
[2] = comma separated list of parameter signatures (string)
[3] = result signature (string)
[4] = text that was with the doc tag. Convention here is a comma separated list of⇒
values:
first item is one of either Create or Get, specifying what method has to be⇒
called first
second and subsequent items are the names of the parameters (this information⇒
is not obtainable from the
program information. These are the names to be exposed as the web service⇒
parameter names
e.g. the above function would have a doc like "Create, StringParameter,⇒
NumericParameter"
[5] = an integer setting: 0=no export and 1=export (the default)
[6] = an integer setting indicating the permission for user to call this (only⇒
applies to CI programs)
0=no permission and 1=permitted (the default)
*/
DisplayProgramFuncInfo(&progInfo);
If &CI = Null Then
&CI = CreateCI(&ciName);
End-If;
LogText("Result of indirect call: " | CallUDMMethod(&CI, &progInfo, &methodname));
Considerations Using Component Interfaces
Component Interfaces only support type conversion of primitive data types back and forth between PeopleCode values and those using inside Component Interface processing.
Component Interface processing traps all errors that occur inside the invocation of the Component Interface and on failure simply returns a false value.