Automation Script Function Named Parameters

December 24, 2021

Introduction

In Javascript, functions are defined by name and all function parameters are passed based on position. This means that any parameters not provided in a function call are passed as undefined and that if there are three parameters you must specify all three values even if you only want to pass the third parameter.

In this post we will look at a technique to provide parameters by name, which provides both flexibility for parameter definition and clarity for which parameters are passed to a function.

Named Parameters

The concept of named parameters is available in many languages and provides an expressive way to define the parameters passed to a function. Javascript ECMA5, as implemented by Nashorn, does not provide this capability natively, but thanks to the flexibility of JavaScript Objects and JavaScript Object Notation (JSON), we can implement a close imitation with many of the benefits.

A Typical Function

First, let's look at a typical function definition and call. Here we have a function with three parameters and a corresponding call with three values.

function example(param1, param2, param3) {
// do things with the parameters
}
// call the function
example(value1, value2, value3);

Considering this example, what if we do not want or need to pass the param2 value? Our example would now look like the following, where we still need to pass the second value, explicitly defined as undefined, in order to pass the third.

function example(param1, param2, param3) {
// do things with the parameters
// value1 has value of param1
var value1 = param1;
// value2 is now has a value of undefined
var value2 = param2;
// value3 has value of param3
var value3 = param3;
}
// call the function
example(value1, undefined, value3);

A Named Parameter Function

To transform this to a named parameter function all we need to do is change our function to accept a single parameter and then pass in a JavaScript Object as the value. The parameter values can then be accessed as member properties on the parameter object.

function example(param) {
// do things with the parameters
// value1 has value of param.value1
var value1 = param.param1;
// value2 is now has a value of undefined
var value2 = param.param2;
// value3 has value of param.value3
var value3 = param.param3;
}
// call the function
example({
"param1": value1,
"param3": value3
});

An Object Parameter Function

To take this one step further, you can define a new prototype and constructor for a parameter named ExampleParam and then define the default values within the constructor function. We can also validate that required parameters have been provided and because the param value is now an object, we can verify that the correct object has been passed in. As a bonus we have also defined a function of getParam4() on ExampleParam that returns a concatenation of the param1 and param2 values.

function example(param){
if (!param instanceof ExampleParam) {
throw new Error("Only ExampleParam objects are allowed as a parameter");
}
// value1 has value of param.value1
var value1 = param.value1;
// value2 is now has a string value of "default value"
var value2 = param.value2;
// value3 has value of param.value3
var value3 = param.value3;
// value3 is "value1 value3"
var value4 = param.getParam4();
}
example(new ExampleParam({"param1":"value1", "param3":"value3"}));
// define the prototype constructor function
function ExampleParam(params) {
this.param1 = params.param1 ? params.param1 : undefined;
// if params.param2 is not provided then set a default value.
this.param2 = params.param2 ? params.param2 : "default value";
this.param3 = params.param3 ? params.param3 : undefined;
if (!this.param3) {
throw new Error("param3 is required");
}
this.getParam4 = function () {
return this.param1 + " " + this.param3;
}
}
ExampleParam.prototype.constructor = ExampleParam;

Calendar Invite Revisited

In our calendar invite post, which can be found here, we created a function that had numerous parameters, with the last two being optional. Here we have reworked the function signature to take an InviteParameters object, which also provides validation of the inputs, ensuring that required parameters are provided, are the correct type and that the start time is before the end time. In the example below the invite is sent with an optional location value, without having to also provide the optional organizer value.

SimpleDateFormat = Java.type("java.text.SimpleDateFormat");
Date = Java.type("java.util.Date");
// call the main function of this script.
main()
function main() {
var f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
f.setTimeZone(userInfo.getTimeZone());
// this is a Date type, from an Mbo you can Mbo.getDate("DATEATTRIBUTE")
var startTime = f.parse("2022-01-01T13:00:00Z");
var endTime = f.parse("2022-01-01T14:00:00Z");
// test the sendInvite function with
sendInvite(new InviteParameters({
"userInfo": userInfo,
"from": "[email protected]",
"subject": "This is a meeting request",
"message": "Here are details about our meeting.",
"startTime": startTime,
"endTime": endTime,
"location": "Conference Room 4"
}));
}
function sendInvite(inviteParams) {
if (!inviteParams instanceof InviteParams) throw new Error("The inviteParams parameter must be an instance of InviteParameters");
//... send invite logic here
}
function InviteParameters(params) {
this.userInfo = params.userInfo ? params.UserInfo : undefined;
this.from = params.from ? params.from : undefined;
this.to = params.to ? params.to : undefined;
this.subject = params.subject ? params.from : "Invite from Maximo";
this.message = params.message ? params.message : "";
this.startTime = params.startTime ? params.startTime : undefined;
this.endTime = params.endTime ? params.endTime : undefined;
this.organizer = params.organizer ? params.organizer : undefined;
this.location = params.location ? params.location : undefined;
if (!userInfo) throw new Error("The userInfo parameter is required.");
if (!from) throw new Error("The from parameter is required.");
if (!to) throw new Error("The to parameter is required.");
if (!startTime) throw new Error("The startTime parameter is required.");
if (!endTime) throw new Error("The endTime parameter is required.");
if (!startTime instanceof Date) throw new Error("The startTime parameter must be an instance of the java.util.Date class.");
if (!endTime instanceof Date) throw new Error("The endTime parameter must be an instance of the java.util.Date class.");
if (startTime.after(endTime)) throw new Error("The startTime parameter must be before the endTime parameter");
}
InviteParameters.prototype.constructor = InviteParameters;

Conclusion

In this post we demonstrated using JSON objects to provide named function parameters. We then used an object prototype to define a new constructor that provided validation of the named parameters to provide consistent validation logic. Finally we revisited the sendInvite function and applied named parameters to provide validation and clarity to the function call.

Hopefully you have found this useful and if you have any questions or comments please reach out to us at [email protected]

In the time it took you to read this blog post...

You could have deployed Opqo, our game-changing mobile solution for Maximo.

Opqo is simple to acquire, simple to deploy and simple to use, with clear transparent monthly pricing that is flexible to your usage.