Appendix: Creating and Adding User-Defined Functions

This appendix discusses the use of user-defined functions.

User-defined functions allow model developers to extend the expression capabilities of PeopleSoft Advanced Configurator to meet specific needs not addressed by its pre-defined functions. This appendix provides instructions and information to help you add your own function.

In addition, a sample user-defined function called getQuantity is provided with the Configurator install. It consists of the compiled class file and Java source file, which are located in: \samples\Configurator\SampleSolutions\GetQuantity_UDF\classes Also included is a model and a readme file describing the sample function and how to add it to your system for demonstration. You can also modify the sample source file to create your own function.

Click to jump to parent topicAdding a User-Defined Function

To add a user-defined function:

  1. Stop the Configurator Server if it is running.

  2. Create a Java source file that implements the UserFunction and java.io.Serializable interfaces. To implement the UserFunction interface, add a method to the class that calculates the function’s return value. A number of functions are provided to access the arguments passed to the calculate method.

    See Implementing the UserFunction Interface.

  3. Compile this source file.

  4. Copy the newly compiled class file into the \classes directory of \\bea\weblogic81\
    config\CalicoDomain\applications\
    CalicoApp\Web-inf
    You may need to create the \classes directory.

  5. Locate UserFunctions.xml in \\bea\weblogic81\config\
    CalicoDomain\applications\CalicoApp\Web-inf\config

  6. Add the following lines between the <FUNCTION_LIST> tags:

    <FUNCTION NAME="getQuantity" CATEGORY="user" RETURN_TYPE="float"
    CLASS="Get⇒QuantityFunction" 1######DEFAULT_ARGUMENT_TYPE="integer" DEFAULT_ARGUMENT_NAME="getQuantity-var"

    1#######MIN_ARGUMENTS="2" MAX_ARGUMENTS="2"/>

    See Editing UserFunctions.xml.

    The Visual Modeler queries the server or other supported source for the contents of the UserFunctions.xml file to determine the names of the functions to be displayed in the expression editor.

    At compile time, the compiler employs the UserFunctions.xml file to detect the user-defined functions.

  7. Save the file and restart the Configuration Server.

  8. In the expression editor of the Visual Modeler, click the “Refresh Functions from Server” button. Visual Modeler queries the Configurator server for the contents of the UserFunctions.xml.

  9. Compile the model to complete the process. The Visual Modeler connects to the Configurator Server, reads the UserFunctions.xml file, and updates the editor’s list of user-defined functions available for modeling.

Click to jump to parent topicImplementing the UserFunction Interface

The primary method in the UserFunction interface is calculate() and must be defined by any class implementing the UserFunction interface.

The calculate() method is used to compute the result of the user-defined function, which is returned as an Object instance. Within the calculate() method, the function arguments can be retrieved from the UserFunctionsArgument instance using the methods provided by its class.

Click to jump to parent topicMethods

The UserFunction interface provides these methods:

numberOfArguments()

Returns the number of arguments that were passed into the user function. Each individual argument passed into the user function is actually a list of values. In the case of constants, return values from other functions, and single-select selection point attributes, the list will contain only one value. In the case of multiselect selection point attributes, the list can contain multiple values.

argumentContainsMultipleValues(int argumentPosition)

Returns true if an argument comprises multiple values, otherwise false is returned. As for Java arrays, references to the position of an argument begin at 0.

numberOfArgumentValues(int argumentPosition)

Returns the number of values associated with the specified argument position. If called for an argument for which argumentContainsMultipleValues() would return false, this method returns 1.

argumentIsInteger(int argumentPosition) argumentIsInteger(int argumentPosition, int valuePosition) argumentIsDouble(int argumentPosition) argumentIsDouble(int argumentPosition, int valuePosition) argumentIsNumber(int argumentPosition) argumentIsNumber(int argumentPosition, int valuePosition) argumentIsBoolean(int argumentPosition) argumentIsBoolean(int argumentPosition, int valuePosition) argumentIsString(int argumentPosition)argumentIsString (int argumentPosition, int valuePosition)

Used to determine the type of an argument value. These methods take either one argument, the argument position, or two arguments, the argument position and value position in the argument list. If only the argument position is specified, the value position is assumed to be 0. The return value of these methods is either true, if the value is of the specified type, or false, if the value is not of the specified type.

argumentIntegerValue(int argumentPosition) argumentIntegerValue(int argumentPosition, int valuePosition) argumentDoubleValue(int argumentPosition) argumentDoubleValue(int argumentPosition, int valuePosition) argumentBooleanValue(int argumentPosition) argumentBooleanValue(int argumentPosition, int valuePosition) argumentStringValue(int argumentPosition) argumentStringValue(int argumentPosition, int valuePosition)

Used to retrieve an argument value. These methods take either one argument, the argument position, or two arguments, the argument position and value position in the argument list. If only the argument position is specified, the value position is assumed to be 0. The return value of these methods is the specified value from the argument list. The method argumentIntegerValue() will coerce a float value to an integer value and argumentDoubleValue() will coerce an integer value to a float value.

argumentQuantity(int argumentPosition);argumentQuantity(int argumentPosition, int valuePosition);

Used to retrieve the quantity associated with argument values. In the case of constants and return values from other functions, the quantity returned is always 1. In the case of selection point attributes, the quantity returned is the quantity associated with the selected domain member that is associated with the attribute value.

argumentLongValue( int argumentPosition, int valuePosition)argumentLongValue( int argumentPosition);

These methods allow a user-defined function to request arguments as long integer values rather than integer values. These methods behave the same as the existing argumentIntegerValue methods except that they return a Java long rather than a Java int. Call these methods if you expect to retrieve numbers larger than 2,096,000,000 ( a Java-imposed limit to the int type).

If you don't, and such a huge number gets entered into your UDF, it will get truncated (and might become negative or some other funny effect)

Click to jump to parent topicExceptions

If the argument or value positions are invalid or if an invalid type is requested, the UserFunctionException exception will be thrown by the argument access methods.

Click to jump to parent topicEditing UserFunctions.xml

Entries in UserFunctions.xml must contain either:

Or,

You can specify:

Tag definitions are:

RETURN_TYPE

Legal values are integer, float, double, number, string, date, boolean, long, and object. If this tag is unspecified, it is assumed to be object. Using number as the return type signifies that the return value will be either a double or integer. Using float as the return type is identical to using double as the return type. Using object as the return type signifies that the return value will be either integer, double, string, date, or boolean.

MIN_ARGUMENTS and MAX_ARGUMENTS

Should be integers or the symbol “variable”. If unspecified, these tags are assumed to be variable.

DEFAULT_ARGUMENT_TYPE

Has the same allowed types as the RETURN_TYPE tag.

DEFAULT_ARGUMENT_AGGREGATION

Should be a Boolean value. By default it is assumed to be false.

DEFAULT_ARGUMENT_NAMED

Is a description of the function’s arguments.

Specify information for each argument using the ARGUMENT tag.

For each argument, specify the NAME tag needs to be specified for each argument and is a description of the argument.

The type can be specified for each argument using the TYPE tag and aggregation can be specified using the AGGREGATOR tag. The TYPE tag has the same allowed types as the RETURN_TYPE tag. By default, the type is object.

The AGGREGATOR tag should be a boolean value and by default is false. If an argument is specified to be an aggregator, then the compiler enforces the restriction that only selection point/attribute references, function calls, and numeric variables can be specified for this argument in an expression.

Examples

The content portion of an example UserFunctions.xml file illustrates the use of the second method above:

public class TripleFunction implements UserFunction, java.io.Serializable { public Object calculate( UserFunctionArguments args) { try { if (args.argumentIsInteger(0)) { return new Integer(3 * args.argumentIntegerValue(0)); } else if (args.argumentIsDouble(0)) { return new Double(3.0 * args.argumentDoubleValue(0)); } return(new Integer(0)); } catch (UserFunctionException e) { return(new Integer(0)); } } }

The following example is of a user function called tripleWithQty, which takes 1 or more numeric arguments. Each argument value is multiplied by 3 and its associated quantity and the resulting values are summed and returned as a Double value.

import com.calico.engine.config.lightning.compiler.UserFunction; import com.calico.engine.config.lightning.compiler.UserFunctionArguments; import com.calico.engine.config.lightning.compiler.UserFunctionException; public class TripleWithQtyFunction implements UserFunction, java.io.Serializable { public Object calculate( UserFunctionArguments args) { try { int i, j; double sum = 0.0; for (i = 0; i < args.numberOfArguments(); i++) { for (j = 0; j < args.numberOfArgumentValues(i); j++) { if (args.argumentIsNumber(i,j)) { sum += 3.0 * args.argumentDoubleValue(i,j) * args.argumentQuantity(i,j); } } } return(new Double (sum)); } catch (UserFunctionException e) { return(new Double(0.0)); } } }

Click to jump to parent topicUsing the Sample User-Defined Function getQuantity( )

This section describes the sample user-defined function called getQuantity( ) that is provided with the Visual Modeler.

Click to jump to top of pageClick to jump to parent topicUnderstanding the getQuantity( ) Sample Function

getQuantity( ) is a sample user-defined function that returns the selected quantity of a specific domain member within a multi-select selection point. The associated files and a sample model implementing this function are included on the Configurator CD. You can use this sample in your own modeling or simply to understand how to define and implement your own expression functions.

Suppose you want to know the quantity of the selected domain member in a single-selection point. You could use the pre-defined function countWithQty( ) to retrieve that value. However, this function cannot recognize more than one selected domain member, so you must use the getQuantity( ) sample function for multi-select selection points.

The sample getQuantity( ) user-defined function requires two files and a sample model to demonstrate its use:

The compiled class file and Java source file are located on the PeopleSoft Advanced Configurator CD at:

\samples\Configurator\SampleSolutions\GetQuantity_UDF\classes

The getQuantity() function has two arguments:

Note. Set the return type for getQuantity( ) to Numeric. The expression in the figure below, named GQ2 in the sample model, will return the quantity selected on the A2 domain member.

Click to jump to top of pageClick to jump to parent topicSetting Up getQuantity( )

To demonstrate getQuantity(), you must first place it and the model files in the appropriate directories.

To install the function:

  1. Stop the PeopleSoft Advanced Configurator Server if it is running.

  2. Create a \classes folder that resides within the \Web-inf folder of your PeopleSoft Advanced Configurator installation. For example:

    C:\bea\weblogic81\config\CalicoDomain\applications\CalicoApp\Web-Inf

  3. Copy the getQuantityFunction.class file to the \classes folder just created.

  4. Locate UserFunctions.xml on the Configurator CD:

    \samples\Configurator\SampleSolutions\GetQuantity_UDF\WEB-INF\config

  5. Do one of the following:

    If no user-defined functions have been installed in your PeopleSoft Advanced Configurator environment, you can copy the entire UserFunctions.xml file into the config folder, located typically in:

    C:\bea\weblogic81\config\CalicoDomain\applications\CalicoApp\
    Web-inf\config

    If user-defined functions are already installed in your PeopleSoft Advanced Configurator environment, open the UserFunctions.xml file from the CD and copy and paste the following text to your existing UserFunctions.xml file between the <FUNCTION_LIST> tags:

    <FUNCTION NAME="getQuantity" CATEGORY="user" RETURN_TYPE="float" CLASS="GetQuantityFunction" DEFAULT_ARGUMENT_TYPE="integer" DEFAULT_ARGUMENT_NAME="getQuantity-var" MIN_ARGUMENTS="2" MAX_ARGUMENTS="2"/>

  6. Locate the getQuantity sample model on the Configurator CD in:

    \samples\Configurator\SampleSolutions\GetQuantity_UDF\model

  7. Copy the getQuantity folder and its contents to:

    C:\bea\weblogic81\config\CalicoDomain\applications\CalicoApp\
    Web-inf\classes

    Note. Do not place the getQuantity folder and its contents in a subfolder.

  8. Start the PeopleSoft Advanced Configurator Server.

  9. Start the Visual Modeler and open the getQuantity sample model you just copied.

  10. Select Project, Settings to verify that the model is pointing at the correct hostname for your Configurator Server.

  11. Open any expression (for example, GQ2) by double-clicking on one in the Components windows.

  12. Click on the Refresh Functions From Server button. The Visual Modeler will connect to the Configurator Server , read the UserFunctions.xml file, and update the list of user-defined functions available for modeling.

  13. Click on the compile icon in the toolbar of the Visual Modeler. Verify that the model was compiled successfully by viewing its name in the Visual Modeler message window, as shown:

Click to jump to top of pageClick to jump to parent topicViewing getQuantity( ) Behavior

This section discusses how to run the GetQuantity model so as to observe results from the getQuantity( ) function.

To see the runtime behavior of getQuantity( ), compile and run the getQuantity( ) sample model by clicking the Compile and run the model icon in the toolbar of the Visual Modeler. Enter quantity values for each domain member on the selection point and click the Submit button. Note that the G1-G5 expressions return the quantity values entered. Also note that the GQ2 expression returns the quantity value of A2, as it was used in the examples above.