Blogs

Blog Tags Help

Enter a tag to filter the current view
Combined feed for site

.Domino Framework

.Domino Framework

Main  | Next

Optimizing Database Lookups

Peter Presnell  

It is a common feature of an application to perform lookups into a view to locate a document based upon one or more keys.  The following are some tips for optimizing the LotusScript code when there may be a large number of lookups being performed (e.g. running against all selected documents in a view or all documents in a database).

 

1) Code the view name as a constant so that it is easier to maintain (and read) the code

2) Make the view static.  For OOP define a private variable in the class for the view.  For procedural code define a static function.

3) Fetch the view from that database once only by checking to see if the view is "Nothing"

4) To locate documents that have been created after the view was last refreshed it is usually more efficient to do a search first and then refresh the view (and research) only if the initial search failed than to refresh the view first every time.

 

Procedural Code:-

 

Static Function getByKeys(Source As variant) As NotesDocument

Dim iView as NotesView

If iView Is Nothing Then Set iView = DB.getView(MY_VIEW_NAME)
  If iView Is Nothing Then Exit Function
  Set getByKeys = iView.GetDocumentByKey(Source)
  If getByKeys Is Nothing Then
   Call iView.Refresh
   Set getByKeys = iView.GetDocumentByKey(Source)
  End If

End Function

 

OOP Code:

 

Class MyClass

Private iView As NotesView

Function getByKeys(Source As variant) As NotesDocument

If iView Is Nothing Then Set iView = DB.getView(MY_VIEW_NAME)
  If iView Is Nothing Then Exit Function
  Set getByKeys = iView.GetDocumentByKey(Source)
  If getByKeys Is Nothing Then
   Call iView.Refresh
   Set getByKeys = iView.GetDocumentByKey(Source)
  End If

End Function

End Class

History Of LotusScript - Part 3

Peter Presnell  

LotusScript is a dialect of the BASIC programming language.  Version 1.0  of LotusScript was released in 1993 as part of a new spreadsheet product called Lotus Improv.  LotusScript 2.0 added the ability to work with Notes applications and formed part of Lotus Visual Programmer (ViP).  ViP was designed as a competitor for Visual Basic, which had been released by Microsoft in 1991.   ViP was eventually discontinued as a stand-alone product and we saw LotusScript 3.0 added to Notes 4.0 in January 1996.  At this time LotusScript required the use of the "C API" to access Notes data.  In October 1996 Microsoft launched VB4,adding the ability to define custom classes, effectively making BASIC an Object Oriented Programming language.  In December 1996 Notes 4.5 was released adding the ability to create LotusScript libraries and providing 26 product classes that allowed direct access to Notes data.  At this time both Visual Basic and LotusScript were comparable products.  As discussed  last week in Part 1 Lotus/IBM continued to provide significant enhancements to the LotusScript language as part of Notes R5 (1999) and Notes 6.0  (2002).

In April 2003 the landscape of BASIC programming changed when Microsoft introduced VB.Net as part of its .Net Framework.  A new programming language (C#) was also developed as part of the .Net framework, but Microsoft also updated its VB language to allow devoted BASIC programmers an easy way to migrate to its new development platform.  This stragey seemed to work.  In Part 2 I contrasted the approach being taken by IBM who seemed to focus its effort post 6.0 on building a competing product for Lotus Notes called IBM Workplace.  Notes 8.0 provided some extensions but Notes 8.5 now looks like being the first release of Notes in which no extensions of the LotusScript language are provided and the promised Eclipse LotusScript Editor is also missing.  This is all comes despite the fact that LotusScript remains the core programming language for most Notes development.  Java has now been added as an alternative but it is still not implemented fully and does not have the same following as LotusScript.

I blogged last month about some of the things I would like to see added to the LotusScript language.  Many of these have been posted by me and others on IdeaJam.  But whilst there is little that can be done to extend the LotusScript language, the good news is that we as Notes developers can use the LotusScript language that we already have to fill in many of the gaps that exist in the product classes such as NotesDatabase and NotesDocument.  This uses the Object Oreinted Programming capabilities of Lotuscript to extend the existing product classes allowing us to add new properties/methods and even create new classes.  The following techniques will work for Notes 4.5+.

1) LotusScript Library
Create one (or more) LotusScript Libraries to hold your code.  Options include having one LotusScript library for all the new classes, or having a separate LotusScript library for each class.  The new classes can then be introduced to your Notes application via the Use statement.
Examples:
Use "BleedYellow" or Use "BleedYellow.BleedYellowDocumentCollection"

2) Create New Classes
Create one or more new classes.  It is suggested you chose names for your new classes that are derived from the product class being "extended" (e.g. DominoDocument, NotesDocument2, SuperNotesDocument).  Because LotusScript presently does not allow us to extend product classes directly we need to create new classes from scratch that include rather than extend the base class.

Example:
The NotesDocumentCollection class could be extended as follows:-

Class BleedYellowDocument Collection

  Public Documents As NotesDocumentCollection

  Sub New(Source As NotesDocumentCollection)
    Set Documents = Source
  End Sub

End Class


Note: If LotusScript supported direct extensions of product classes the above code could effectively be replaced with:-
Class BleedYellowDocumentCollection As NotesDocumentCollection
End Class

3) Make Base Object A Property
While the example above works, OOP principals require that Properties be used instead of exposing public variables directly.  This allows you the ability to wrap additional logic around the object at any time, such as validation, without exposing any changes in the interface to consumers of the class.

Class BleedYellowDocument Collection
  Private iDocuments As NotesDocumentCollection
  Sub New(Source As NotesDocumentCollection)
    Set iDocuments = Source
  End Sub
  Property Get Documents As NotesDocumentCollection
    Set Documents = iDOcuments
  End Property
 
Property Get Documents As NotesDocumentCollection
    Set iDocuments = Documents
  End Property
End Class

4) Extend The Constructor
One of the first extensions that can be applied to a class is the options for the constructor.  By always making the single parameter to a the constructor a Variant it becomes possible to pass a wide range of objects to the constructor, including arrays and lists.  In a way this overcomes one of the weaknesses of LotusScript, the inability to overload a method.  The TypeName statement can be used identify the type of object being passed.

  Sub New(Source As Variant)

    Dim Doc As NotesDocument
    Select Case TypeName(Source)
      Case "NOTESDOCUMENTCOLLECTION"
        Set iDocuments = Source
      Case "NOTESDATABASE"

        Set iDocuments = Source.GetProfileDocCollection("passingkeythatdoesnotalreadyexist" )
      Case "NOTESVIEW"

        Set iDocuments = Source.Parent.GetProfileDocCollection("passingkeythatdoesnotalreadyexist" )

        Set Doc =  Source.GetFirstDocument
        While Not Doc Is Nothing
         Call iDocumentCollection.AddDocument(Doc)
         Set Doc = Source.GetNextDocument(Doc)
       Wend
      Case "NOTESDOCUMENT"

        Set iDocuments = Source.GetProfileDocCollection("passingkeythatdoesnotalreadyexist" )
        Call iDocuments.Add(Source)
      Case "OBJECT"

        Set iDocuments = Session.CurrentDatabase.GetProfileDocCollection("passingkeythatdoesnotalreadyexist" )
    End Select
  End Sub

 

Applying the above code....

Set Collection = New BleedyellowDocumentCollection(Nothing)            ' Create empty document collection in current database

Set Collection = New BleedyellowDocumentCollection(DB)                     ' Create empty document collection in DB

Set Collection = New BleedyellowDocumentCollection(Doc)                    ' Create document collection with single document Doc

Set Collection = New BleedyellowDocumentCollection(DB.Document) ' Create document collection with all documents in database DB

Set Collection = New BleedyellowDocumentCollection(View)                  ' Create document collection with all documents in view View

 

5) Add New Properties/Methods
Build out your new class by adding additional properties/methods (Note: The OOP term Method = Sub/Function in LotusScript).  You can also rewrite the logic of the product class by adding code to the new extended class.

Example: A new Add method could be developed that provides a much wider range of options for what is added to the collection.  Passing a NotesView could add all document in that view to the collection.

Sub Add(Source As Variant)
  Select Case TypeName(Source)
    Case "NOTESVIEW"
.. code to add documents in view
  End Select
End Sub


6) Using The New Class
The properties/methods of the base class can be accessedd via the base object.  The new properties/ethods are accessed via the new class.

e.g.

Dim UIW As New NotesUIWorkspace
Dim Collection As BleedYellowDocumentCollection
Dim Favorites As NotesView

Set Collection = New BleedYellowDocumentCollection(UIW.CurrentView) ' Create collection with document selected in view
Call Collection.Document.Add(Doc) ' Adds document to collection using existing NotesDocumentCollection method
Call Collection.Add(Favourites) ' Adds all the document in the Favourites folder the the collection using the new enhanced Add method


.Domino Framework
The .Domino Framework provides a large number of examples of the above in practice.  A lot of the code is found in a LotusScript library base.Domino.Application.  This library provides 100s of new properties/methods for classes such as DominoDatabase, DominoView, DominoDocumentCollection, and DominoDocument.  You can use these classes directly or take parts of the code to build your own custom classes.  So don't just wait for IBM to take the lead, If you are not already doing so, start building your own custom classes to fill in the gaps needed by your applications.

History Of LotusScript - Part 2

Peter Presnell  

Yesterday I documented the changes introduced to LotusScript with Notes 6.0 and the momentum the language had at that time. 

Today I wish to jump forward to the next release of Notes - Notes 8.5.  The release notes suggest that Notes 8.5 has two new LotusScript statements and 4 new methods/properties being added to existing classes.  This blog entry is going to be shorter than I originally thought, because on checking further, it turns out that all of these LotusScript extensions are in fact documented as being part of the 8.0 release.   So as it stands, Notes 8.5 will be the first release of Notes in which not a single extension of the language is provided.  Even in the dark days of Notes 7.0/IBM Workplace we were still able to get something.

Note: A more complete history of LotuScript since Note 4.0 is included in the .Domino Framework wiki.  The following is a summary from the wiki showing the number of extensions made to the LotusScript language since Notes 4.0:-

Release LS Extensions New Classes New Methods/Properties
Notes 4.0     ? n/a n/a
Notes 4.5 ? 26 n/a
Notes 4.6 ? 1 6
Notes 5.0 13 8 107
Notes 6.0 9 40 181
Notes 6.5 0 0 35
Notes 7.0 0 0 17
Notes 8.0 2 4 45
Notes 8.5 0 0 0

History Of LotusScript - Part 1

Peter Presnell  

A large part of the .DominoFramework involves extending the base LotusScript classes provided by Notes such as NotesDatabase, NotesDocumentCollection, and NotesDocument.  Extensions that I would hope one day may be included as part of that next great release of Notes.  You know the one, the one where IBM show their renewed support for Notes client development and the LotusScript programming language!

 

To keep track of all the features already available within LotuScript I have started compiling a history of the LotusScript language.  It is proving to be an interesting exercise.  The last Notes release I got excited about (as a Notes client developer) was 6.0.  And now I can see why... That release contained 9 new LotusScript statements, 40 new LotusScript classes, and 181 new properties/methods for existing classes.  Pretty impressive really, and shows the priority, focus, and direction IRIS (RIP) was providing for LotusScript at the time.  Note: Much of the work started with the 6.0 release (DXL, InViewEdit, NotesRichText, CSS for forms/pages, Document Locking) has still never been finished off 6 years later.  For those of you that may be interested, I have listed these language extensions below.  (Hence this will is a lengthy blog, but tomorrow's blog should be much smaller when I list the new LotusScript features coming in Notes 8.5).

 

 New LotusScript Statements (9)
* Boolean datatype
* CBool function
* Byte datatype
* CByte fundtion
* Implode function
* Join function
* Replace function
* Split function
* StrToken function

 

New Classes (40)
* NotesAdministrationProcess
* NotesColorObject
* NotesDOMAttributeNode
* NotesDOMCDATASectionNode
* NotesDOMCharacterDataNode
* NotesDOMCommentNode
* NotesDOMDocumentFragmentNode
* NotesDOMDocumentNode
* NotesDOMDocumentTypeNode
* NotesDOMElementNode
* NotesDOMEntityNode
* NotesDOMEntityReferenceNode
* NotesDOMNamedNodeMap
* NotesDOMNode
* NotesDOMNodeList
* NotesDOMNotationNode
* NotesDOMParser
* NotesDOMProcessingInstructionNode
* NotesDOMTextNode
* NotesDOMXMLDeclNode
* NotesDXLExporter
* NotesDXLImporter
* NotesMIMEHeader
* NotesNoteCollection
* NotesReplicationEntry
* NotesRichTextDocLink
* NotesRichTextNavigator
* NotesRichTextRange
* NotesRichTextSection
* NotesRichTextTable
* NotesSAXAttributeList
* NotesSAXException
* NotesSAXParser
* NotesStream
* NotesUIScheduler
* NotesXMLProcessor
* NotesXSLTransformer

 

New Methods/Properties (181)
* NotesACL.AdministrationServer
* NotesACL.iSadminNames
* NotesACL.IsAdminReaderAuthor
* NotesACL.IsExtendedAccess
* NotesACLEnry.CanReplicateOrCopyDocuments
* NotesAgent.IsActivatable
* NotesAgent.HttpURL
* NotesAgent.Lock
* NotesAgent.LockProvisional
* NotesAgent.LockHolders
* NotesAgent.NotesURL
* NotesAgent.OnBehalfOf
* NotesAgent.Unlock
* NotesDatabase.ACLActivityLog
* NotesDatabase.FileFormat
* NotesDatabase.FTIndexFrequency
* NotesDatabase.IsClusterReplication
* NotesDatabase.IsConfigurationDirectory
* NotesDatabase.IsCurrentAccessPublicReader
* NotesDatabase.IsCurrentAccessPublicWriter
* NotesDatabase.IsDesignLockingEnabled
* NotesDatabase.IsDocumentLockingEnabled
* NotesDatabase.IsInMultiDbIndexing
* NotesDatabase.IsInService
* NotesDatabase.IsLink
* NotesDatabase.IsPendingDelete
* NotesDatabase.LastFixup
* NotesDatabase.LimitRevisions
* NotesDatabase.LimitUpdatedBy
* NotesDatabase.ListInDbCatalog
* NotesDatabase.SizeWarning
* NotesDatabase.Type
* NotesDatabase.UndeleteExpireTime
* NotesDatabase.CompactWithOptions
* NotesDatabase.CreateFTIndex
* NotesDatabase.CreateNoteCollection
* NotesDatabase.CreateView
* NotesDatabase.Fixup
* NotesDatabase.FTSearchRange
* NotesDatabase.GetOption
* NotesDatabase.MarkForDelete
* NotesDatabase.QueryAccessRoles
* NotesDatabase.RemoveFTIndex
* NotesDatabase.SetOption
* NotesDatabase.Sign
* NotesDatabase.UnprocessedFTSearchRange
* NotesDatabase.HttpURL
* NotesDatabase.NotesURL
* NotesDocument.HttpURL
* NotesDocument.NotesURL
* NotesDocument.IsEncrypted
* NotesDocument.LockHolders
* NotesDocument.CloseMIMEEntities
* NotesDocument.CreateMIMEEntity
* NotesDocument.GetItemValueDateTimeArray
* NotesDocument.GetMIMEEntity
* NotesDocument.GetReceivedItemText
* NotesDocument.Lock
* NotesDocument.LockProvisional
* NotesDocument.RemovePermanently
* NotesDocument.Unlock
* NotesForm.HttpURL
* NotesForm.NotesURL
* NotesForm.LockHolders
* NotesForm.GetFieldType
* NotesForm.Lock
* NotesForm.LockProvisional
* NotesForm.Unlock
* NotesItem.GetValueDateTimeArray
* NotesMIMEEntity.BoundaryEnd
* NotesMIMEEntity.BoundaryStart
* NotesMIMEEntity.Charset
* NotesMIMEEntity.Encoding
* NotesMIMEEntity.HeaderObjects
* NotesMIMEEntity.Preamble
* NotesMIMEEntity.CreateChildEntity
* NotesMIMEEntity.CreateHeader
* NotesMIMEEntity.CreateParentEntity
* NotesMIMEEntity.DecodeContent
* NotesMIMEEntity.EncodeContent
* NotesMIMEEntity.GetContentAsBytes
* NotesMIMEEntity.GetContentAsText
* NotesMIMEEntity.GetEntityAsText
* NotesMIMEEntity.GetNextEntity
* NotesMIMEEntity.GetNthHeader
* NotesMIMEEntity.GetPrevEntity
* NotesMIMEEntity.GetPrevSibling
* NotesMIMEEntity.GetSomeHeaders
* NotesMIMEEntity.Remove
* NotesMIMEEntity.SetContentFromBytes
* NotesMIMEEntity.SetContentFromText s
* NotesSession.HttpURL
* NotesSession.URLDatabase
* NotesSession.Resolve
* NotesView.HttpURL
* NotesView.NotesURL
* NotesViewColumn.Parent
* NotesReplication.DontSendLocalSecurityUpdates
* NotesReplication.GetEntry
* NotesRichTextItem.AppendTable
* NotesRichTextItem.BeginInsert
* NotesRichTextItem.BeginSection
* NotesRichTextItem.Compact
* NotesRichTextItem.CreateNavigator
* NotesRichTextItem.CreateRange
* NotesRichTextItem.EndInsert
* NotesRichTextItem.EndSection
* NotesRichTextItem.GetNotesFont
* NotesRichTextItem.GetUnformattedText
* NotesRichTextItem.Update
* NotesRichTextStyle.IsDefault
* NotesSession.OrgDirectoryPath
* NotesSession.UserGroupNameList
* NotesSession.CreatAdministrationProcess
* NotesSession.CreateColorObject
* NotesSession.CreateDOMParser
* NotesSession.CreateDXLExporter
* NotesSession.CreateDXLImporter
* NotesSession.CreateSAXParser
* NotesSession.CreateStream
* NotesSession.CreateXSLTransformer
* NotesSession.GetUserPolicySettings
* NotesSession.HashPassword
* NotesSession.SendConsoleCommand
* NotesSession.VerifyPassword
* NotesUIDatabase.Close
* NotesUIDatabase.PostDropToArchive
* NotesUIDatabase.QueryDropToArchive
* NotesUIDocument.GetSchedulerObject
* NotesUIDocument.OnHelp
* NotesUIDocument.OnLoad
* NotesUIDocument.OnSubmit
* NotesUIDocument.OnUnload
* NotesUIDocument.PostSend
* NotesUIDocument.QueryRecalc
* NotesUIDocument.QuerySend
* NotesUIView.CalendarDateTimeEnd
* NotesUIView.CaretNoteID
* NotesUIView.ViewInheritedFrom
* NotesUIView.Close
* NotesUIView.DeselectAll
* NotesUIView.InViewEdit
* NotesUIView.PostEntryResize
* NotesUIView.QueryEntryResize
* NotesUIWorkspace.GetCurrentDatabase
* NotesUIWorkspace.ViewRebuild
* NotesUIWorkspace.ComposeDocument
* NotesUIWorkspace.DialogBox
* NotesView.EntryCount
* NotesView.IsProhibitDesignRefresh
* NotesView.LockHolders
* NotesView.SelectionFormula
* NotesView.ViewInheritedName
* NotesView.CopyColumn
* NotesView.CreateColumn
* NotesView.Lock
* NotesView.LockProvisional
* NotesView.RemoveColumn
* NotesView.SetAliases
* NotesView.Unlock
* NotesViewColumn.HeaderFontColor
* NotesViewColumn.HeaderFontFace
* NotesViewColumn.HeaderFontPointSize
* NotesViewColumn.HeaderFontStyle
* NotesViewColumn.IsFontBold
* NotesViewColumn.IsFontItalic
* NotesViewColumn.IsFontStrikethrough
* NotesViewColumn.IsFontUnderline
* NotesViewColumn.IsHeaderFontBold
* NotesViewColumn.IsHeaderFontItalic
* NotesViewColumn.IsHeaderFontStrikethrough
* NotesViewColumn.IsHeaderFontUnderline
* NotesViewColumn.IsNumberAttribParens
* NotesViewColumn.IsNumberAttribPercent
* NotesViewColumn.IsNumberAttribPunctuated
* NotesViewColumn.ResortToViewName
* NotesViewColumn.SecondaryResortColumnIndex
* NotesViewNavigator.Count
* ODBCConnection.ThreadSafeDriver
* ODBCResultSet.Connection

Document Locking

Peter Presnell  

Document Locking continues to be a frustration for me to implement.  Despite all my best endeavours I have simply not been able to implement Persistent Temporary document locking with Notes 6.0 so that it works reliably.  I have in which it is important to ensure that (1) only one person can edit a document at any one time, (2) documents do not remain in a state where they remain locked by a person who is unable to remove the lock, and (3) no replication/save conflicts occur .  Unless soemone has a brilliant solution it seems the simplest way to achieve this is to supp[ort Persistant locks only in which the user must first lock the document manually, then edit the document, before releasing the lock.

 

In providing the above solution I have now extended the .DominoFramework and provide an example inside the framework of how to impliment persistant document locking.  This involves adding an icon to a view to display an icon next to documents that have been locked.  Clicking on the icon toggles the lock of/on using InViewEdit.  View actions are also provided to support the locking/unlocking of documents.  To prevent persistant temporary locks (the lock you get by default when you attempt to edit an unlocked document) I have wired the onQueryModeChange event to call a method that validates that a persistant lock already exists.  This code will all be abvailable as part of the next beta release of the .Domino Framework.

I have also added to the .Domino Framework Wiki with content about what I have learnt and suggest when working with Notes document locking:-

 

Document Locking allows Notes application to control edit access to a single document by more than one user. The standard Notes Document Locking feature will only work where an Administration Server (aka master lock server) has been nominated in the ACL of the database and the Allow Document Locking property set for the database.

Lock Types

The following are the different lock types that can occur on a document:-

Type Description
Persistent This occurs when the user (or code) places a lock on the document directly.
Persistent Temporary This occurs when the user attempts to edit a document and the master lock server is available and permits the lock. The lock is supposed to be removed when the user finishes editing the document, but this is not always the case.
Provisional This occurs when the user (or code) places a lock on the document directly and the master lock server is not available. The provisional lock may be promoted to a persistent lock when the master lock server becomes available.
Provisional Temporary This occurs when the user attempts to edit a document and the master lock server is not available. The lock is supposed to be removed when the user finishes editing the document, but this may not always be the case.

Fields

The following is a list of fields used in supporting document locking:-

Field Description
$PTWriters Names of the people/groups holding a provisional temporary lock on a document
$PWriters Names of the people/groups holding a provisional lock on a document
$Writers Names of the people/group holding a lock on a document
$WritersDate? Date/time document was locked

Errors

The following are some of the errors associated with document locking:-

Error Description
4000 User is not authorized to lock/unlock the document. This can occur if the user does not have edit authority for the document or they are attempting to unlock a document locked by somebody else without manager access.
4595 Document has been locked by somebody else
4597 Master lock server not available

Best Practices

  • The only reliable way to implement document locking seems to be to support persistent locking only (not persistant temporary locking). This requires that a lock be placed on a document when the master lock server is available. The document can then be safely edited before the lock then released.
  • To prevent a persistent temporary lock being created it is necessary to prevent the document being placed in edit mode when first opened. This is best handled in the PostOpen? event by setting Source.EditMode? = False. It is also necessary to prevent a document being placed in edit mode unless the document already has a persistent lock. This is best handled as part of the QueryModeChange? event.
  • If the form has an Edit action then hide the Edit action if the name in the $Writers field is not the current user.

Notes

  • A person with Manager access can unlock/edit a document locked by somebody else. If you wish to prevent this happening from inside LotusScript code, check the contents of the $Writers field first before invoking the Unlock method.
  • There seem to be a number of scenarios when can result in a temporary lock remaining after the user closes a document or switches from edit mode. These locks must be removed manually or via an agent (lock decay).
  • When edit locking is implemented, it appears that if another person attempts to edit the same document on another server then the updated copy of the document is used even if replication has not yet taken place. I accnot find any documentation on this, but it seems to be a BONUS.
  • If a document is opened in read mode and somebody subsequently edits the document, the original user will receive a warning if they then try to edit the document they have open. They are warned that they should close the document and re-open it (to get an updated copy). If they ignore this warning and try to edit the document a second time no warning is displayed and the old version of the document becomes editable. this will almost always result in a replication conflict and/or an e-mail being generated that warns about the potential loss of data.
  • If locks are placed on a local replica of the database, details about the lock may not replicate to the other servers. In this case the master lock server is still aware of the lock even though the server documents do not contain the $Writers and $WritersDate? fields.

Related Information

.Domino Framework Roadmap

Peter Presnell  

For those of you that have found the code contained within the .Domino Framework usefull, the following is a brief roadmap for the project.

 

July 2008: Beta 0.6 is planned as the last public beta for the framework.   No major enhancements are planned.  The focus will be on testing and documenting the existing content as well as filling in some of the gaps.

August 2008Version 1.0 should be released.  As stated previously, this first release will support Notes 6.0+ client application development on a Windows platform.

September 2008-December 2008: Version 1.1 is planned as the first release in which development feature found in versions of Notes 6.5,  7.0, 8.0, 8.0.1, and 8.0.2 are implemented. 

 

Note: There are no plans at this time to develop functionality for Notes 8.5 into the framework because the .Domino Framework is largely Notes client based using LotusScript code and there is very little in Notes 8.5 for Notes client development (outside of being able to set the system date/time!).  I do hope to extend the framework in 2009 to include Web development components and possibly some Java components.

 

I encourage anyone who has any feedback or ideas on the framework to contact me directly or via the OpenNTF project.  I am especially interested in ways in which the framework can be adapted to make your life as a Notes developer easier.

Working with Holidays

Peter Presnell  

I have been working on a couple of applications recently which manage milestones.  In setting the milestones it is necessary to adjust them so that they do not fall on weekends or official government holidays.  To achieve this I have utilized some of the existing components of the .Domino Framework as well as extending the framework to provide a more complete solution.

  1. The .Domino Framework provides a ($Calendar) view that can be added to any application that needs to support business holidays.  This view displays the existing holidays and provides actions for importing holidays from a NAB or creating entries manually.
  2. A Domino.Applications.Holidays namespace (aka LotsScript Library) provides the business logic necessary to support the importing of holidays into the application.  The DominoDatabaseWithHolidays class is used to extend the NotesDatabase class and includes an ImportHolidays method.  This method makes use of the undocumented NotesCSEventOwnerDocument class to calculate dates for repeating holidays in a similar way to importing holidays into your PAB.
  3. Because I was unable to get the official government holidays added to the company's Domain Directory (NAB) it was necessary for me to create a separate database to define these holiday groups.  The Import Holidays method has therefore been defined to look for an External Dependency document defining the location of the "Holidays" database.  If this is not defined then the official NAB is used.
  4. The framework also contains the (ListResource) subform that is used by the Mail database to prompt the user to elect holiday categories to be imported.
  5. The DominoDatabaseWithHolidays class also has a BusinessHolidays function that returns a list of all the holidays found in the database.
  6. The Domino.@Functions namespace contains an atfBusinessDay function.  This accepts a date (or array of dates), a list of holidays and adjusts the date(s) so that they do not fall on a weekend or one of the listed holidays.  A boolean flag is used to indicate if a day should be moved forwards or backwards to avoid falling on a non-business day.

So... to adjust milestones so they do not fall on a non-business day:-

  1. Import relevant holidays from the NAB into the application
  2. Use the atfbusiness holiday function passing a list of holidays obtained using the DominoDatabaseWithHolidays.BusinessHolidays method.

The code for all these classes/methods will be available as part of the 0.6 beta release of the .Domino Framework (expected towards the end of this month).  Some of the code is already present in the 0.5 Beta release available at OpenNTF.org.

Maintaining Document UNIDS

Peter Presnell  

Some connected posts from Nathan Freeman, Andrew Pollak, and  Andrei Kouvchinnikov talk about the ability to set the Universal ID of a document.  This is pretty cool stuff.  So I thought it would be a worthwhile extension of the .Domino Framework to support this capability.  As is my way, I have stolen some of the code and ideas to support the updating of the Document UNID.

 

The Document UIND in the new Inspector tool is now read/write.  Simply type in a new UNID over the top of the existing value displayed, click save and the document will be assigned a new UNID.  Note: Because the save creates a new document, the original document is deleted (for which you need delete rights to the database).

 

I have also extended the DominoDocumentCollection class to implement some of Nathan's ideas:-

A new MakeResponse method has been added. This acts similar to the NotesDocument.MakeResponse method, except that it makes all documents in a collection the response documents for a nominated parent odcument.

A new CreateNewDocumentKey method has been added.  This takes as an argument a field name to be used as the key.  A new UNID is calculated based upon the value of the provided field (1st item for lists).  To minimize issues with response documents the MakeResponse method is called so that all reponse documents are now linked to the new UNID.

 

 '/**
 ' *  Creates new UNIDs based upon a key value.  This supports faster lookup of documents by key (as per Nathan Freeman)
 ' */  
 Sub CreateNewDocumentKey(KeyField As String)
  Dim NewUNID    As String
  Dim UNID     As String
  Dim CommandString As String
  Dim Result     As Variant
  Dim NextDoc    As NotesDocument
  Dim Children    As baseDominoDocumentCollection
  Dim OriginalDoc   As NotesDocument
  
  On Error 4091 Resume Next
  Set Doc = iDocumentCollection.GetFirstDocument
  While Not Doc Is Nothing
   Set NextDoc = iDocumentCollection.GetNextDocument(Doc)  
   If Doc.HasItem(KeyField$) Then
    UNID$ = Doc.UniversalID$
    CommandString$ =
@Password">|@Password("| + Cstr(Doc.GetItemValue(KeyField)(0)) + |" )|
    Result = Evaluate(CommandString$)
    NewUNID$ = Mid$(Result(0),2,32)
    If NewUNID$ <> UNID$ Then    ' Document already keyed on this value
     Doc.UniversalID = NewUNID$
     Call Doc.Save(True,False)
     If Err = 0 Then        ' Indicates document UNID already exists
      Set OriginalDoc = Doc.ParentDatabase.GetDocumentByUNID(UNID$)
      If OriginalDoc.Responses.Count > 0 Then
       Set Children = New baseDominoDocumentCollection(OriginalDoc.Responses)
       Call Children.MakeResponse(Doc)
      End If
      Call OriginalDoc.Remove(True)
     End If
    End If
   End If
   Set Doc = NextDoc
  Wend
 End Sub

Why Notes?

Peter Presnell  

During my time as a Notes developer (mostly as an independent contractor/consultant) I have had the chance to work  with a large number of companies on four separate continents.  In all that time I cannot remember a single client in which the Notes development was ever considered "strategic".  In fact, in many, the attitude towards Notes was (and often still is) decidedly hostile.  So if Notes is often seen (unfairly?) as the ugly duckling in the programming world, why is there so many Notes databases out there and so many Notes developers still being employed?

One of the reasons for this seems to be that fact that unlike many other development platforms, Notes has always extended down to reach many people who would not be typically classified as programmers.  People can start out with a Notes template such as TeamRoom or Discussion Library and get a small application up and running pretty quickly.  These same people then find that with little or no formal programming experience they can add a few fields to a form, add another column to a view or even create a whole new view from scratch.  Then using nothing more than a few simple forms, views, and  little bit of @functions and @commands a whole new application can be built to automate a task that may have outgrown an Excel spreadsheet or fits some new process.  A few of the more adventurous "non-programmers" even find some basic LotusScript within their capabilities.  To a seasoned Notes programmer many of these applications look decidely ugly and badly written but they are highly effective.  They provide the basic functionality that is needed by the business and because they have usually flown underneath the radar screen nobody has bothered to question whether Notes is the right tool to use.

It is usually only when the application breaks, the creator leaves/transfers, or there is a need to enhance the application that it suddenly appears on the radar screen of a Notes development group.  As a developer I often get assigned to work on applications that were orginally developed this way.  Whilst I may be tempted to curse the bad design, inefficient code, and the fact a production application is running on a development server, I can also be thankful that another business process has found a home in the Notes development arena giving me work and the chance to show what Notes can really do!  I have worked for some companies with as many as 80,000 non-mail databases of which less than 20% were ever supported by a Notes development group!

This feeder base of applications is an important part of the Notes development food chain.  Without these applications many companies may have been able to contemplate a life without Notes (and Notes programmers).

I am not sure if the role of this type of development is fully recognized when the future of Notes is being mapped out.  Few of these "non-programmers" are represented on the various forums such as IdeaJam, Planet Lotus, and IBM's Notes discussion forums. And they probably are not heavily represented at events like LotusSphere.  And they almost ceratinly do not get to be design partners evaluating the latest release of Notes.

With the Notes 8.5 beta having been released I have started to wonder what impact the new development tools and environment may have on Notes "non-programmers".  A full-time developer (especially one who has developed with Java), probably loves the move of Designer to eclipse.  Notes developers who have long struggled with design issues such as joining views or developing Notes/Web client or Web only applications probably love the new capabilities of X-Pages and the extended JavaScript language.  The Notes development world is beginning to look a lot more like Java and ASP.Net development environments.  But are these capabilities going to attract more "non-programmers" or less?  IBM have not yet made public too much about what the Notes development environment will look like post Notes 8.5 but it does seem like eclipse will at least be part of that.  My hope is that in acquiring some of the tools that Java and .Net developers take for granted we do not take the Notes development environment out of reach of the "non-Notes" programmers.  At least not until more companies understand that Notes truly is a strategic platform and it is OK to make it the #1 choice for developing many applications.

Does LotusScript Have a Future?

Peter Presnell  

One thing that has struck me about  the Notes 8.5 beta is that X-Pages implements JavaScript as the only option for both client-sided and server-sided scripting.  Neither @Language nor LotusScript appear to be supported directly but the "JavaScript" language has been expanded to provide @Formula emulation.  The new server-sided JavaScript now also seems to be able to do some of the things only done in the past using LotusScript...  When X-Pages is made available for the Notes client I am expecting to see support for JavaScript only.  We already have LotusScript able to run on the Notes client and Domino servers, so why is IBM going to so much trouble to extended JavaScript for server-sided scripting?  Could it be that  LotusScript is not part of the long term vision IBM has for Notes development?   As a devoted LotusScript programmer (biggot) I am hoping I am wrong...

 

The next version of Notes (post 8.5) promises to be a very interesting one for Notes developers.  Consider a scenario in which:-

  1. X-Pages provides an alternative to Forms, Views, Pages, and Subforms with the added advantages of running on both a Web client and a Notes client, plus the ability to link to non-Notes data sources;
  2. X-Pages supports "JavaScript" directly but not LotusScript or @Formula
  3. There is little or no future extension of LotusScript language to make it a more modern OOP language;
  4. There are few (if any) enhancement made to "old-style "design elements such as Forms, Views, Pages, Subforms, Framesets, Outlines;
  5. The Eclipse IDE does not provide native support for these older style design elements  - although we do get the LotusScript editor almost everyone has been waiting for.

It sounds to me like a completely new Notes II programming environment has been created. An environment in which many of the Notes development paradigms of the past have been replaced, including either the death (or significant downsizing) of the role of LotusScript.   Will we have the choice of staying with what we know (e.g. LotusScript & @Formulas) or will we have to move to a new way of doing things (most likely JavaScript based0)?  And where does Java fit with this?  Hopefully IBM will soon provide a clearer picture to the public of its plans for Notes development post Notes 8.0.

 

Perhaps those more in the know than I can comment about where I am completely wrong....  "Whenever you have eliminated the impossible, whatever remains, however improbable, must be true".

.Domino Framework 0.5 Beta Released

Peter Presnell  

The latest beta of the .Domino Framework has been released at OpenNTF.  This release inclorporates the new Inspector tool and adds an application template that can be used to build a new application from scratch that includes the generic application components of the .Domino Framework.

 

Wordle of .Domino Framework

A new Notes data management tool (Inspector)

Peter Presnell  

I am just putting the finishing touches on what I believe will the most useful tool to be provided as part of the .Domino Frramework yet.  The tool is called Inspector and the following provides a brief summary of what its capabilities will include in its initial release:-

  1. View and change database properties

  2. Select another database

  3. Perform actions against the database (e.g. Open, Sign)

  4. View data documents, profile documents, design documents, and deletion stubs
  5. Build a document collection using any combination of search, FT search, view, or manual selection
  6. Enter a Notes URL, NoteID, or Document UNID to select a specific document
  7. Display the documents contained in the document collection.
  8. Navigate through document collection
  9. Perform actions against the document collection (e.g Setting field values, removing template inheritance)
  10. Display details about any one document in collection
  11. Display a list of items in the document
  12. Perform actions against the document (e.g. Delete, Sign)
  13. Display and edit information about any item in a document (type, value, flags)
  14. For LotusScript Libraries show details of the classes, methods, & properties contained in the design document.

This functionality can invoked from ANY Notes database regardless of whether or not it implements the .Domino Framework.  This is done via a Toolbar "Magic Button" that passes information about the current database/document to the .Domino Framework database.

 

I see a LOT of potential for expanding the tool further to expose even more of the functionality built into the .Domino Framework.  E.g. Providing the ability to apply XSLT to transform data and design documents using styles sheets that reside in the .Domino Framework database.

 

The 0.5 Beta of the .Domino Framework onm OpenNTF is planned for later this week.

Domino.Reflection Namespace Extended

Peter Presnell  

I have just finished expanding the Domino.Reflection namespace to allow the new Inspector tool to browse the contents of LotusScript libraries. 

Inspector will be able to display information about data documents, profile documents, design documents, and deletion stubs found in ANY database. Inspector will be able to provide a list of all (or selected) design documents found in a database (Domino Designer is not required).

As part of the display information for Design documents I have decided to provide information about any classes found in a selected LotusScript library.  Using the extended DominoScriptLibrary class (part of the Domino.Reflection namespace), I can now return a list of properties and methods for a nominated class.  I can also get the code used  for any one of the properties/methods.  Combining these features together Inspector becomes (amongst other things) a basic class browser for LotusScript libraries.

Both the extended Domino.Reflection namespace and the new Inspector tool will be released as part of the 0.5 beta of the .Domino Framework planned for the end of this week.

Editing Design Properties Via DXL In Designer 8.5

Peter Presnell  

Whilst a native eclipse editor is not yet available in Designer 8.5 for Forms and View it seems that option is provided to edit the DXL for these design elements.  This provides both raw DXL/XML code and a node/property tree for these design elements.  There are times when this can be a distinct advantage over the traditional Domino Designer tool to find and set values (e.g. search and replace".  Not all Design elements are supported (e.g. LotusScript Libraries).

External Dependencies

Peter Presnell  

I started work today on building out the documentation for External Dependencies. 

 

External Dependencies are used within the .Domino framework as a way of documentin g links to external applications via meta-data.  This brings a number of advantags to the application.

  1. Documentation of external dependencies allows an analyst/developer to make a quick assessment of the extent to which an application is linked to others. This is an important part of application documentation that is often forgotten or left outdated.
  2. Storing the details of dependencies in the form of meta-data allows changes to be made to the location of external dependencies without the need for programming changes.
  3. Storing the details of dependencies in the form of meta-data allows a change to be effected with a single change.
  4. Storing the details of dependencies in the form of meta-data makes it possible for development, QA, and production instances of an application to maintain links to different external sources.

One of the technques I developed for working with external dependencies was to create a Static Property for the database to avoid the need for locating the database each and every time.  The first time Application A has need to refer to Application B it searches for an external dependency document that defines the location of the database and then opens the database.  On subsequent attempts it refers to the chached copy of the database object.

 

Example:

 

'/**
' * Provide static link to Subpoena database
' */

Static Property Get FACTSubpoenaDatabase As FACTSubpoenaDatabase
  Static This As FACTSubpoenaDatabase ' Static reference to Subpoena database
  Dim ExternalDependency As DominoExternalDependency ' External dependency defining location of Subpoena database
  Dim SubpoenaDB As NotesDatabase ' Subpoena Database

  If This Is Nothing Then
    Set ExternalDependency = New DominoExternalDependency(EXTERNAL_DEP_SUBPOENA_DATABASE)
    If Not ExternalDependency.Document Is Nothing Then Set SubpoenaDB = ExternalDependency.GetDB
    If SubpoenaDB Is Nothing Then Set SubpoenaDB = Session.CurrentDatabase
    Set This = New FACTSubpoenaDatabase(SubpoenaDB,"" )
  End If
  Set FACTSubpoenaDatabase = This

End Property

Main  | Next