The SearchResult QueryOpen agent
This article is all about building fast executing and maintainable web agents. The agent retrieves the search parameters from the URL, does the FTsearch and returns the results in a field on a form.
Option Declare
Very frequently, this aspect of LotusScript programming is forgotten, even by many of the most notorious programmers. Personally, I think no agent should go without it... starting with:
Option Public
Option Declare
'Option Declare' protects against typing errors and stops any head over heels programmer spawning variables and thus making debugging a nightmare.
The StringBuffer class
Each time you add something to a string, a new memory location is reserved and the entire string is copied. This is a very costly operation. Instead of string concatenating, I use a Stringbuffer class, which uses an array to collect the strings. Since LotusScript only allows fixed length arrays, the Stringbuffer already allocates a number of entries. Only when the number of entries exceeds the allocated number, the array is redimmed with a fixed amount. Before joining the array to a string, the array is redimmed to its correct length. Using this Stringbuffer is a lot faster then using string concatenation.
Class StringBuffer
Private arr() As String
Private count As Integer
Private size As Integer
Private increment As Integer
Sub New(Byval a As Integer)
Redim arr(a)
increment=a
count=0
End Sub
Sub add(Byval a As String)
size=Ubound(arr())
If count>=size Then
Redim Preserve arr(size+increment)
End If
arr(count)=a
count=count+1
End Sub
Sub render(Byval a As String)
Dim i As Integer
For i=0 To count-1
Print arr(i) & a
Next
End Sub
Function collapse(Byval a As String) As String
Dim sTemp As String
Redim Preserve arr(count)
sTemp=Join(arr, a)
collapse=sTemp
End Function
End Class
Error trapping
I use a Stringbuffer object debug to collect debug information. You may notice a resemblance to Java or JavaScript here: it's the LotusScript equivalent of the try{} catch(e){} finally{} construct.
Sub Initialize
Dim debug As New StringBuffer(100)
debug.add "Agent started."
On Error Goto catch
' your code goes here
Goto finally
catch:
debug.add "Error " & Err & " in line " & Erl & ": " & Error$
Resume finally
finally:
debug.add "<br />Agent finished."
' render results and/or debug information
End Sub
The main function
This performs the search and builds the result including the page title. The HTML to use for each document entry was already available in the document itself, in the computed field IndexValue, so I just had to retrieve it. Again, I use a Stringbuffer object out to collect the results. Finally, the results are rendered in the 'SearchResults' field. To display debug information, I can add a 'SearchDebug' field on the form and render the debug information there.
Sub Initialize
On Error Goto catch
Dim ns As New NotesSession
Dim doc As NotesDocument
Dim out As New StringBuffer(100)
Dim debug As New StringBuffer(100)
Dim sQuery As String
Dim dc As notesDocumentCollection
Dim i As Integer
Set doc=ns.DocumentContext
debug.add "Agent started."
DbPath=doc.GetItemValue("DbPath")(0)
debug.add "DbPath: " + DbPath
sQuery=doc.GetItemValue("Query")(0)
out.add "<h1>Search results for '"+sQuery+"'</h1>"
Set dc=ns.CurrentDatabase.FTSearch(sQuery, 0)
out.add |<div id="viewbody">|
out.add "<p>" & dc.Count & " documents found.</p>"
For i=1 To dc.Count
out.add dc.GetNthDocument(i).GetItemValue("IndexValue")(0)
Next
out.add("</div>")
Goto finally
catch:
debug.add "Error " & Err & " in line " & Erl & ": " & Error$
out.add "Error " & Err & " in line " & Erl & ": " & Error$
Resume finally
finally:
debug.add "<br />Agent finished."
doc.replaceitemvalue "SearchResults", out.collapse("")
' doc.replaceitemvalue "SearchDebug", debug.collapse("<br />")
End Sub
Comments
To add a comment, log in or register as new user. It's free and safe.