Email Me
my first name at my last name dot com
Archives
Past Blog Entries
Links
Andy Wrenbeck
ApplePhoneShow
Ben Abler
Ben Poole
Bob Lutz
Bob Obringer
Bruce Elgort
Carpeaqua
Codestore
Cult of Mac
Daring Fireball
Detroit News
Domino Unplugged
Ed Brill
Guidebook
I, Cringely
Joe Litton
Jonvon
NSFTools
NSLog
Ned Batchelder
Old Blog
Raymond Chen
Scobleizer Weblog
Techdirt
Unsanity
Weblogs Apple Log
bonj
I recently had a need to implement a factory style
pattern in LotusScript and I thought it might make an interesting topic
for an article.
Here is the scenario:
This company wants to make a change to the standard
Lotus Notes mail template. Of course, this change has to be as
lightweight as possible, since playing with the mail template at all is
asking for trouble. To make the scenario even more interesting, the
Notes mail template is controlled by the parent company of this Notes
shop. Getting a change made to the mail template becomes a very big
deal. Finally, word comes down from high up that unless we can get this
change in place, heads will role.
So, how do you update the mail template with the
absolute least amount of impact on the template itself? The solution was
to implement a factory pattern, slightly modified, in LotusScript. The
change that we needed to make was to alter the processing of a calendar
event entry when that event came from a customer of this company.
Keeping in mind that this is a shared template and we only want to alter
the processing when the document comes from one specific company and is
received by a member of this company and not the parent company or any
other affiliate which also happens to be using the common template.
The solution I came up with only requires a single
line of code to be changed in the base template. The rest of the code
will exist in a stand alone script library, which can be maintained
outside the base template. So, before digging into the script libary, I
will discuss the template change.
The change was on the "Notice" form. In the QueryOpen
event for the form, this line of code was used to create an instance of
the CSEventNotes class, which is used within the code throughout the
rest of the form:
Set csEventObj= New CSEventNotes( 1,
source.document, source )
Rather than using this line of code, I replaced it
with a call to my factory function:
Set csEventObj = ABCEventClassFactory( 1,
source.document, source )
Technically, there is a second line of code which is
also needed, which tells the form to use my new script library with the
factory function and the overridden class:
Use "ABCCSEventNotes"
That is the extent of the changes that were required
to be made to the base design of the template. It should be noted that
the custom class must be a subclass of the CSEventNotes class. A new
script library was created with the above name. The library contains two
things. One, a new class which extends the CSEventNotes class to
override the functionality. Second, the factory function is defined.
Here is the function:
Function ABCEventClassFactory(nEventType As
Integer, note As notesdocument, source As notesuidocument) As
CSEventNotes
Dim abccheck As Boolean
On Error Goto returnstandard
abccheck =
False
Dim fromstring As
Stringfromstring = Ucase(note.GetItemValue("From")(0))
If ( Instr(fromstring, "@XYZ.COM") > 0 ) Then
abccheck = True
End If
If (abccheck = True) Then
Set
ABCEventClassFactory = New ABCCSEventNotes( 1, source.document, source )
Else
Set ABCEventClassFactory = New
CSEventNotes( 1, source.document, source )
End If
theend:
Exit Function
returnstandard:
Set ABCEventClassFactory = New CSEventNotes( 1, source.document, source )
Resume theend
End Function
There are a couple of notes about this function that
I wanted to make. If some sort of error happens trying to figure out
what to do, then I want to play it safe and return an instance of the
CSEventNotes class. Second, the more hardcore coders out there will be
wondering why I have two if statements when appears that it could be
simply done in a single if. Its really a simple answer. The real code
has more complex logic to determine which class should be returned. Most
of the business logic code was stripped out for this example.
In a nutshell, what this function does is make some
decisions about which class the user needs based on some sort of
business logic. This could be easily extended to return a wide variety
of different classes to meet different needs. I have effectivity
isolated the specific implementation of the business logic from the
calling object, which is the Notice form in this case. This is really
the essence of the factory pattern.
To finish the story, lets look at a sample
implementation of the ABCCSEventNotes class. What I want is to change
the standard CSEventNotes class to change the behavior of the
SubProcessAction method. This sample code demonstrates how the
customization would look.
Class ABCCSEventNotes As CSEventNotes
Sub
New (nEventType As Integer, note As notesdocument, source As
notesuidocument), CSEventNotes( nEventType, note, source)
'nothing
required, let the CSEventNotes constructor handle everything
End Sub
'This is the override of the CSEvent ProcessAction method
Sub
ProcessAction(vArgs As Variant)
...
...End Sub
End Class
The class needs to have a constructor (New) method,
although it is not doing to do anything specific in this case. The
constructor simply calls the parent (CSEventNotes) constructor and then
does nothing. There is only one method from the parent class which needs
to be overridden. That is the ProcessAction sub.
I hope this article provides a good example of using Object Orientated concepts in LotusScript to solve problems in a low impact, low risk way.