Extending The LotusScript Wrapper Classes
The wrapper classes I blogged about in February went down a lot better than I thought they might.
So, taking it further. Let's extend the DocumentWrapper class some more. Since first writing about them on here I've been busy using and extending them as I go. Here are a few examples of some of the properties I've added
Simple Helper Properties
Some very simple properties: WebLink, UNID and IsNew.
Property Get WebLink As String WebLink = "/" + Replace(web.database.Filepath, "\", "/") + "/0/" + UNID + "?OpenDocument" End Property Property Get UNID As String UNID = Document.Universalid End Property Property Get IsNew As Boolean IsNew = document.Isnewnote End Property
These don't do anything that can't already be done. They just make it simpler and quicker to code.
Logging Document Actions
Properties are all well and good. But they're just borne of laziness really. Let's add a method or two, to make it really useful. How about adding a new method to the base class called LogAction() which you might use like this:
invoice.LogAction("Invoice Approved")
And the method might look like this (it assumes all your Forms have a standard field called "ActionLog"):
Sub LogAction( Action As String ) Dim item as NotesItem Set item = document.GetFirstItem( "ActionLog" ) Call item.AppendToTextList( Action + " on " + Format(Now, "dd mmm yy") +_ " at " + Format(Now, "hh:nn:ss") + " by " + web.User.Abbreviated ) End Sub
The web.user part assumes you're already using my WebSession Class.
Deleting Documents
If you never actually delete documents, but merely flag them as deleted then you can give all objects based on the DocumentWrapper class a Delete() method, like so:
Sub MarkDeleted() Call SetFieldValue("Delete", "1") Call LogAction("Document Deleted") End Sub
You can then add an IsDeleted property to the DocumentWrapper class, like so:
Property IsDeleted As Boolean IsDeleted = (GetFieldValue("Deleted")="1") End If
At this point you might consider moving some of the field name and their values to "static strings" at the top of the class, then changes the corresponding methods, like this:
Const DELETED_FIELD_NAME = "Deleted" Const DELETED_FIELD_VALUE = "1" Sub MarkDeleted() Call SetFieldValue(DELETED_FIELD_NAME, DELETED_FIELD_VALUE) End Sub Property IsDeleted As Boolean IsDeleted = (GetFieldValue(DELETED_FIELD_NAME) = DELETED_FIELD_VALUE) End If
Naturally you might want to add an UnDelete() method too...
Extending Derived Classes
So far I've talked about extending the base DocumentWrapper class. Everything we add there is available to all classes derived from it. But, obviously, you can also add properties and methods to the derived classes. For example, the Invoice class might want an Approve() method. This could either simply flag it as approved or perform some more complex workflow logic, passing it between approvers.
Class Invoice As DocumentWrapper Sub Approve() 'Do whatever LogAction("Approved") End Sub Sub AddItem(Description as String, Value as Currency) 'Add to the relevant fields End Sub End Class
Notice I added a call to LogAction() inside the Approve() method. That way you never forget to log the approval no matter where you call the Approve() method from.
The possibilities are almost endless.
Summary
These wrapper classes have completely changed the way I code my Domino web apps! My dream has always been to be a "proper coder". I'd love to be able to work completely in Visual Studio writing C#. Unless you've done that you won't appreciate what a pleasure it can be. I get a buzz from writing my own classes and then using them. This is a buzz I've never really had while coding for Domino. Until now. These wrapper classes will have to do for the time being.
Next week I'll talk even more about them and show how to handle collections of documents that belong to other documents. While I go, I'm working on a demo app that brings it all together.
Jake, keep up the good work - am loving it :o)
Reply
Isn't the "Delete" subroutine used as a destructor in LotusScript?
So you'll probably mark every document as deleted when the object gets out of scope :-)
Reply
Terminate is called when the document goes out of scope but I believe Delete has to be invoked just like Sub New()
Reply
Show the rest of this thread
I should have learnt by now not to post LotusScript code that I wrote "off the top of my head" in a text editto. I've done this in the past and been shouted down for it. Should only ever post code I've "compiled" and tested...
Interesting that the Delete() sub is reserved. Didn't know that. Probably could have guessed though. Doh.
I've updated the code in the post above.
Reply
Why assume the ActionLog field is on a form? Just add it to the document conditionally so you don't have a runtime error when you forgot to add the field.
if document.hasitem("ActionLog") then
Set item = document.GetFirstItem( "ActionLog" )
else
Set item = document.appenditemvalue ("ActionLog","")
end if
Reply
Not sure that you would want to use appendItemValue.
From the help file:
"If the document already has an item called name, appendItemValue does not replace it. Instead, it creates another item of the same name and gives it the value you specify."
Reply
Show the rest of this thread
I didn't know that this "Property" statement even existed in LotusScript!
Searching Help gives no relevant results.
FWIW, I ended up searching Help for "Property Get" to find it.
Reply
Now, that's a refreshing change. Nice to hear from somebody down at my level who is learning from what I write. Rather than only getting feedback from the know-it-alls who want to point the errors of my ways (I openly welcome any corrections to what I write but can't help sensing a smugness about it sometimes).
It's always been a bone on contention for me that learning to code in Notes properly comes with very little decent help. I guess the way to have done it would have been to read some good books on (Visual) Basic and imply from them. Oh, how I wish I'd done that ten years ago....
Reply
Show the rest of this thread
Personally, I usually avoided the use of Properties. Trouble is, I seem to always forget why. Once in a while I try to use them again and then obviously stumble across some annoyance ...
But that was back in the days of Domino 7 (in my case: more than 5 months ago :-P).
Apart from some sort of implicit documentation, using getter and setter methods (read: standard functions) should serve the same purpose just as well.
Reply