Tuesday, January 16, 2007

Using List in Simple Form Validation

In LotusScript, List is a very useful collection data type. I've spoken to quite a few developer and not many of them is taking advantage of List data type. Below is a simple validation example using List.

First example, is a typical simple validation I found in a form
Function ValidateSubmit As Boolean
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = ws.CurrentDocument

If uidoc.FieldGetText("FirstName") = "" Then
Msgbox "Please enter your first name"
ValidateSubmit = False
Exit Function
Elseif uidoc.FieldGetText("LastName") = "" Then
Msgbox "Please enter your last name"
ValidateSubmit = False
Exit Function
Elseif uidoc.FieldGetText("Gender") = "" Then
Msgbox "Please select your gender"
ValidateSubmit = False
Exit Function
'........ other validation
End If
ValidateSubmit = True
End Function
Second example, fields and messages stored in a List for validation
Function ValidateSubmit As Boolean
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = ws.CurrentDocument

Dim fieldList List As String
fieldList("FirstName") = "Please enter your first name"
fieldList("LastName") = "Please enter your last name"
fieldList("Gender") = "Please select your gender"
'...fieldList("OtherFields") = "return message"

Forall f In fieldList
If uidoc.FieldGetText(Listtag(f)) = "" Then
Msgbox f
ValidateSubmit = False
Exit Function
End If
End Forall
ValidateSubmit = True
End Function
As the number of fields to be validated grows, maintaining the List in the second example is much simple than the first example. This is just a very simple example to showcase the use of List. You can even store objects in the List. Try using List if you haven't done so.

5 comments:

Chris said...

Good tip, Thanks!

Thomas Bahn said...

I absolutely agree, that lists should be in every LotusScript developer's toolbox.

But your example isn't one of the best to show that, since you could use a function with two arguments.

One thing, what I find really cool about lists is that are not limited (except by memory), and have a super fast lookup algorithm. This can come in very handy, if you have to compare two (or more) very big sets of documents (idea from Bill Buchan).

Thomas

William Beh said...

@thomas,
The example is just a simple one to get an easy understanding of how List can be used. Like stated, List can even stored objects, own created or Lotus (notesdocument, notesitem, etc). How do you used it to compare 2 big set of document?

Thomas Bahn said...

Bill showed, how he synchronized two big (hundreds of thousands of documents) Domino Directories:

He cycled through all person documents in one directory and created a list with the NotesName as key and the UNID as value. Then he iterated over the second one, doing the same.

Then he created three empty lists: persons only in first directory, persons only in the second directory and persons with different entries in both directories.

After that, he iterated through the first list, looking up each NotesName from the first list in the second one. This is a very, very efficient lookup. If he found the NotesName there, too, he got the two document get db.GetDocumentByUNID, which is again very fast, and compared the person's documents. If they were different, he put the NotesName - UNID pair into the "different" list. If there were no entry in the second list with the NotesName, he added the pair to the "only in first" list.

Done that, he cycled through the second list, looking up the NotesName in the first list. If the person document were missing there, he added the NotesName and UNID to the "only in second" list.

At the end, he had three list: One with persons only in the first address book, one with the persons only in the second, one in both, but with differences.

Because, the lookups in list are very fast, as the db.GetDocumentByUNID, this solution is much faster then the "simple" one with view.GetDocumentByKey.

One could store the NotesDocument objects instead of the UNID, but then there would be as many objects as person documents as in both databases, which could be more then Notes could handle well.


We use the same approach with a (smaller) organizational directory and a phone book, but we have created a class with all items of interest. We store objects of this class with the data from the documents instead of the UNID. This way, we can compare the entries without loading the documents a second time.

Thomas

Andrei Kouvchinnikov said...

For 2-3 years ago I wrote an agent to compare 2 Address Books and show documewnts that differ. It is easy to change and I applied it in many different situations. Here is the code:
LotusScript to compare documents in 2 replicas
To compare whether particular fields in the documents are different is more time consuming and I in a couple of cases I used hash value (32 characters) of fields to store the hash value of combined fields. You can get hashed value using either @Password function or MD5 libraries. Then I compared the hashes in the same way as I compare UNIDs in the example agent.
Something like this:
Dim MyDocList List as String
ev=evaluate(|@Password(FirstName+LastName+OfficePhoneNumber)|, doc)
hash=ev(0)
MyDocList(hash)=hash
......

But if you have a big collection of documents where you want to make just 5-10 searches/comparisions, it's in most cases faster to make FTSearch or db.search.
You can also save the computed hash value in the document so next time you make a comparision you do not need to compute it again and get it directly from the view column, this will greatly improve the performance of field comparisions.