Prototype in Siebel eScript
Tucked away in a remote corner in the eScript reference of the Siebel Bookshelf is a single paragraph referring to prototypes. Common to javascript developers, prototype in Siebel eScript is not something that we bother about too often. Prototypes provide a highly reusable way of extending out of the box objects, with an optimal memory usage as a bonus.
How do we use Prototypes? #
As always, the best way to understand will be through an example. Let us consider a problem where we need to add x days to the given date and get the next working day (to keep things simple, assume it is any day other than Saturday or Sunday).
We go about this problem by extending the ‘Date’ object to support new functionality - “to add x days and retrieve the next working day”. For now we keep the definition of prototype and the actual call together, however they may be located in different objects as well.
To demo the prototype define custom business service ‘COG Get Working Day’ in Siebel Tools or Client. Paste the following code in relevant sections:
(declarations)
Date.prototype.AddDaysToGetWrkDay = AddDaysToGetWrkDay;
AddDaysToGetWrkDay: A Custom Function
function AddDaysToGetWrkDay(iDays, Outputs)
{
var iDateNew; var iOneDay = 24 _ 60 _ 60 _ 1000; // day in milliseconds - (hrs/day _ min _ sec _ ms)
this.setMilliseconds(iDays \* iOneDay);
if(this.getDay() == 0 this.getDay() == 6) { // if sunday or saturday
// add one more day and check whether that falls on working day
this.AddDaysToGetWrkDay(1);
}
return this;
}
Service_PreInvokeMethod
function Service_PreInvokeMethod(MethodName, Inputs, Outputs) {
try {
var dSomeDate = new Date("1/28/2011");
dSomeDate.AddDaysToGetWrkDay(1);
Outputs.SetProperty("New Date", dSomeDate);
return CancelOperation;
} catch (e) {
throw e;
} finally {
dSomeDate = null;
}
}
When executed through simulator (or a call from placed from another service), the service returns the next working day - in the above example 31-Jan-2011. Read on to find out how.
Explanation #
- ‘Date.prototype.AddDaysToGetWrkDay = AddDaysToGetWrkDay’ is the statement that tells the execution engine that there is a new prototype for Date object, and the extended functionality is provided by the function (or object) called ‘AddDaysToGetWrkDay’. This is not synonymous with calling a function since there is no actual execution at this point. It is equivalent to a declaration.
- Next, define the function ‘AddDaysToGetWrkDay’. This will act on the provided date object, which is referenced using ’this’. All it does is to add the given number of days to the date, check whether the new date falls on a Saturday or Sunday, continue adding more days if that is the case, and return the final date. Recursion is used to keep on adding days until it is not required.
- ‘Service_PreInvokeMethod’ just calls the extended function ‘AddDaysToGetWrkDay’ against the date object. When the actual call is made, the scripting engine looks at the Date object itself to check whether such a method is present, and then consults the prototype. Since such a prototype exists and points to a function, the function is executed to return the result.
Note that the prototype itself may be defined only once, and the functionality is available thereon. Though this example is simple at its best, it does demonstrate how prototypes can be used to extend the objects.
Do keep in mind that:
- Prototypes share the same memory space. Multiple invocations do not mean multiple copies of the same prototype in memory
- Prototypes can also be added later. Dynamic invocation can mean that you don’t need to do everything in one place and at once
- A prototype can also be extended further. For example, I can very well define another which says ‘AddDaysToGetWrkDay.prototype.ExcludeDay’ to selectively exclude certain days. For example, myDate.AddDaysToGetWrkDay(21).ExcludeDay(“Tuesday”) can return the working day 21 days from the given date, but which is not a Tuesday
- From the above point you can observe that the methods can be executed in a ‘chained’ manner, which gives us a scalable solution that is easy to maintain (remember my OO reference in another article?)
- Use prototypes for reusable functions - that is when they provide the maximum value