Multiple form aliases

Looking at the “Reply with History” form I saw that the form has multiple aliases. The form name is specified like the below:

Reply | wReply | Reply

A simple test reveals that you can use both the aliases (wReply and Reply) from commands such as @Command([Compose]). This is really nice for backwards compability if you need to rename a form.

LotusScript.doc (part 3)

I have based the layout on the layout of the javadoc documentation generated by the Sun tools. The main windows is separated into three main frames:

  • Top left – frame showing the different design elements with LotusScript (forms, views, agents and script libraries)
  • Bottom left – frame showing all found LotusScript classes in a sorted list
  • Right frame – main frame showing design elements with LotusScript

Below is a screenshot of the opening window (click on image for a larger version)…

…and a screenshot showing the documentation of a class (click on the screenshot for a larger version):

LotusScript.doc (part 2)

The code has been expanded so it now also supports:

  • Constants (incl. datatype)
  • Class properties
  • Methods and functions with global scope
  • Views
  • Forms

I have inserted some sample documentation generated below. As previously mentioned the next thing I am going to approach is formatting the output for easy navigation and cross-reference.

ScriptLibrary @ FooBar

Constant @ PRIVATE_STRING_CONST

[CONST] (PRIVATE) PRIVATE_STRING_CONST As String = “abc123”

Constant @ PUBLIC_INTEGER_CONST

[CONST] (PUBLIC) PUBLIC_INTEGER_CONST As Integer = 12345
This is a comment for my PUBLIC_INTEGER_CONST constant.

Constant @ FRIENDLY_STRING_CONST

[CONST] (PRIVATE) FRIENDLY_STRING_CONST As String = “should be ignored”

Class @ Bar

Parent class.

Class @ Foo (inherits from Bar)

This is a class comment and it may span multiple lines. The class the inherits from the Bar class.

Property @ Lekkim

[PROPERTY] (PRIVATE SETTER) Lekkim As String
Sets the lekkim.

Property @ Lekkim

[PROPERTY] (PRIVATE GETTER) Lekkim As String
Returns the lekkim.

Method @ New

[SUB] (PUBLIC) New
Constructor.

Function @ GlobalFunction

[FUNCTION] (PUBLIC) GlobalFunction(arg1 As String, arg2 As Long) returns NotesDocument
I have also documented my global function.

Method @ GlobalMethod

[SUB] (PUBLIC) GlobalMethod

Form @ _1. TestTest Document

Method @ Querysend

[SUB] (FRIENDLY) Querysend(Source As Notesuidocument, Continue As Variant)
Form Querysend event.

Method @ Queryclose

[SUB] (FRIENDLY) Queryclose(Source As Notesuidocument, Continue As Variant)
Queryclose event.

View @ Test documents|notesTestDocuments

Method @ Querypaste

[SUB] (FRIENDLY) Querypaste(Source As Notesuiview, Continue As Variant)
Querypaste view event.

LotusScript.doc (part 1)

LotusScript.doc is a series of script libraries that can generate HTML documentation for LotusScript libraries. It is mainly targeted at class delevelopment in script libraries but should be applicable to LotusScript in forms, views and agents.

I wrote the code last night and it looks promising. Below is a sample of some documentation I have generated. As you can see the documentation isn’t much to look at – layout will be the next issue I will address.

Sample documentation:

ScriptLibrary @ CLASS: DocumentationWriter

Class @ DocumentationWriter

A DocumentationWriter is used to write the documentation to an OutputStream.

Method @ New

[SUB] (PUBLIC) New(scripts As Vector)
Constructor.

Method @ Write

[SUB] (PUBLIC) Write(filename As String)
Writes the documentations.

The method signatures and comments are actually based on parses LotusScript code and shows that the library can parse classes with nested methods and functions. Comments are also included.

I have based the documentation format on the JavaDoc syntax:

'/**
' * Parent class.
' */
Public Class Bar

End Class

'/**
' * This is a class comment
' * and it may span multiple lines. The class
' * the inherits from the Bar class.
' */
Public Class Foo As Bar
   '/**
   ' * Constructor.
   ' */
   Public Sub New()

   End Sub
End Class

The above code generates documentation that looks like this if the code is in a script library called “FooBarLib”:

ScriptLibrary @ Foo

Class @ Bar

Parent class.

Class @ Foo (inherits from Bar)

This is a class comment and it may span multiple lines. The class the inherits from the Bar class.

Method @ New

[SUB] (PUBLIC) New
Constructor.

I’ll post more once I have worked a little more on the presentation.

Using in JSTL under JBoss

The source of the problem could be found in the org.apache.taglibs.standard.tag.common.sql.DataSourceUtil class of the Jakarta implementation of JSTL. The problem is that the SQL function looks for the DataSource in the “java:comp/env” namespace where as my datasource was in the “java:” namespace.

The solution is to map the datasource to Tomcat using the web.xml and jboss-web.xml deployment descriptors:

web.xml

    <!-- JDBC DataSources (java:comp/env/jdbc) -->
    <resource-ref>
        <description>The used datasource</description>
        <res-ref-name>jdbc/DefaultDS</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>

jboss-web.xml

    <!-- make sure the web container can get jdbc connections -->
    <resource-ref>
        <res-ref-name>jdbc/DefaultDS</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <jndi-name>java:/pestikom2</jndi-name>
    </resource-ref>

The above makes the java:/pestikom2 datasource from JBoss available in the java:/comp/env namespace in Tomcat. The datasource can now be referenced from JSTL using:

<sql:query dataSource="jdbc/DefaultDS" var="some_var" scope="page" sql="select * from foo" />

2005 season finally here

Finally !! Some weather that resembles spring… Though not as warm as one could wish for (still only around 8 degress celsius) the weather turned sunny and it seemed as though everyone chose Easter as the time to start. The road along the coast northward from Copenhagen was “packed” with happy road bikers. Me and my big brother included.

For me it all started the night before because I still hadn’t changed back to my normal gearing (52/42/12) from my mountain gearing (52/39/13). I rode across the Pyrenees last summer and once I got back I never got around to changing the gearing back, but now I’m back and riding as never before.

For the last couple of months I have been training indoors (Spinning) riding steady at 75% -> 85% of my maximal heartrate and it seems to have worked for me. I feel stronger than normally starting out. Nice. The new Polar 725 watch I bought last year has been a real help since it allows me to monitor my training using procentages instead of the heartrate.

I also allows me to transfer the data to the computer where I keep a log of my training. Below is an example from my trip to the Pyrenees. The example shows three curves – one for heartrate, one for speed and a third for altitude.

Generic Lotus Notes export library

I finally got fed up writing ad-hoc export functions for applications so I have written a generic export library for Lotus Notes. The library is written in LotusScript and can be applied to any database.

Below I’ll discuss the concepts I have defined and show how the code is used.

The export library consists of four core concepts that translate into four core (abstract) classes:

  • OutputStream

    OutputStream models where the exported data is written to.
  • ExportSource

    ExportSource models a source of data for export.
  • ExportStrategy

    ExportStrategy models the way (e.g. CSV, XML) we write the exported data to the OutputStream.
  • ExportFormatter

    ExportFormatter models the way data from the NotesDocuments provided by the ExportSource is actually exported.

Below I’ll explain each concept in a little more detail.

OutputStream:

In the most simple form this is a thin wrapper around the built in NotesStream class. The class has been wrapped since it allows me to subclass OutputStream while keeping the classes that use OutputStream unaware of the differences. I have defined three sub-classes so far:

  • FileOutputStream (writes a a file on disk)
  • LineFileOutputStream (as above with each call to write() on a separate line – good for CSV exports)
  • RichTextOutputStream (writes to a NotesRichTextItem)

ExportSource:
At present I have two four implementations:

  • ViewExportSource (exports all the documents in a view)
  • CollectionExportSource (exports the documents in a NotesDocumentCollection)
  • SelectedExportSource (exports the documents the user has selected)
  • SearchExportSource (exports the documents found by the supplied @Formula query)

ExportStrategy:
The class is modelled on the Strategy pattern and I have defined three implementations so far:

  • CsvExportStrategy (exports the data in CSV format)
  • XmlExportStrategy (exports the data in XML format)
  • RssExportStrategy (exports the data in RSS format)

ExportFormatter:
I am a little unsure whether ExportFormatter is the correct name but here goes. I have defined two implementations so far:

  • ViewExportFormatter (exports the data as defined by a view in a database, that is reusing the @Formula for the columns)
  • ConfigurationExportFormatter (exports the data as defined by a set of configuration documents thus allowing the user to define his own export)

You combine the above concepts to export data. If you need to export the selected documents to a CSV-file using the format of the current view you would combine:

  • LineFileOutputStream pointing to a file on disk
  • SelectedExportSource to export the documents the use as selected
  • CsvExportStrategy to write the exported data as CSV
  • ViewExportFormatter to format the data as the current view

Example 1:
Export selected documents based on a view to a CSV-file on disk.

Option Public
Option Explicit
Use "CLASS: ExportSource"
Use "CLASS: OutputStream"
Use "CLASS: ExportFormatter"
Use "CLASS: ExportStrategy"

Sub Initialize
   'declarations
   Dim session As New NotesSession
   Dim db As NotesDatabase
   Dim view As NotesView
   Set db = session.GetDatabase("", "export_db.nsf")
   Set view = db.GetView("ExportDocuments")

   'we want to export selected documents only
   Dim es As New SelectedExportSource()

   'we want to format the documents as the current view (notesTestDocuments)
   Dim formatter As New ViewExportFormatter(Nothing, "notesTestDocuments", Nothing)

   'the documents should be written to a file replacing any existing file
   Dim out As New LineFileOutputStream("d:\export.csv", True)
   Call out.Open()

   'export the data as CSV to the created OutputStream and the ExportSource
   Dim strategy As New CsvExportStrategy(out, es)
   Call strategy.Export(formatter, True)

   'close the OutputStream
   Call out.Close()

End Sub

Example 2:
Export all documents in a view to a richtext item on a document as XML.

Option Public
Option Explicit
Use "CLASS: ExportSource"
Use "CLASS: OutputStream"
Use "CLASS: ExportFormatter"
Use "CLASS: ExportStrategy"

Sub Initialize
   'declarations
   Dim ws As New NotesUIWorkspace
   Dim session As New NotesSession
   Dim db As NotesDatabase
   Dim view As NotesView
   Dim doc As NotesDocument
   Dim rt As NotesRichTextItem

   'get current database and view
   Set db = session.CurrentDatabase
   Set view = ws.CurrentView.View

   'we want to export all documents in the current view
   Dim es As New ViewExportSource(view)

   'we want to format the documents as the current view (notesTestDocuments)
   Dim formatter As New ViewExportFormatter(view, "", Nothing)

   'the documents should be written to a rich text item
   Set doc = db.CreateDocument
   Call doc.ReplaceItemValue("Form", "TestDocument")
   Call doc.ReplaceItemValue("Title", "XML Export " + Now)
   Set rt = New NotesRichTextItem(doc, "Body")
   Dim out As New RichTextOutputStream(rt)
   Call out.Open()

   'export the data as XML to the created OutputStream and the ExportSource
   Dim strategy As New XmlExportStrategy(out, es)
   Call strategy.Export(formatter, True)

   'close the OutputStream
   Call out.Close()

   'save document
   Call doc.Save(True, False)

End Sub

Since some exports (i.e. selected documents as CSV to a file) are done quite frequently I have defined some helper classes (really based on the Facade pattern). These helper classes are called Exporters and wrap the above example 1 on one line of code:

Option Public
Option Explicit
Use "CLASS: Exporter"

Sub Initialize
   Dim exporter As New CsvExporter("d:\export.csv", "notesTestDocuments", True)
End Sub