ChadSmiley Blog Things about family, life, coding, and more

22Dec/057

Domino Document Locking Class 1.1

Updated version of Document Locking Class is now available.

Here is an update to the Document Locking Class:

Public Sub new(  inDoc As Variant )
Public Sub SetCurrentUser( user As String )
Public Function hasDocument()
Public Sub setDocument( inDoc As NotesDocument )
Public Sub setUIDocument( inUIDoc As NotesUIDocument )
Public Property Get toString As String
Public Property Get ShowPrompts As Boolean
Public Property Set ShowPrompts As Boolean
Public Function LockingEnabled() As Boolean
Public Function IsLockedByCurrentUser () As Boolean
Public Function IsDocumentLockedByCurrentUser (doc As NotesDocument ) As Boolean
Public Function IsUIDocumentLockedByCurrentUser ( uiDoc As NotesUIDocument ) As Boolean
Public Function LockedBy ( ) As String
Public Function IsLocked ( ) As Boolean
Public Function IsDocumentLocked ( doc As NotesDocument ) As Boolean
Public Function IsUIDocumentLocked (uiDoc As NotesUIDocument ) As Boolean
Public Function Lock() As Boolean
Public Function LockUIDocument (uiDoc As NotesUIDocument ) As Boolean
Public Function LockDocument (doc As NotesDocument ) As Boolean
Public Function UnLock () As Boolean
Public Function UnLockUIDocument (uiDoc As NotesUIDocument ) As Boolean
Public Function UnLockDocument (doc As NotesDocument ) As Boolean

Domino Document Locking

%INCLUDE "LSCONST.LSS"
 
'/**
' * A rapper around the built-in document locking that is available in Notes/Domino 6.
' *	The purpose is to provide a better more consistant way of locking and unlocking documents.
' *	Will not lock a new document since it can not be locked.  Will only show warnings once.
' *
' *	@author	Chad Schelfhout		http://www.chadsmiley.com/
' *	@version	1.1
' */
Class DominoDocumentLocking
	Private pUser As String
	Private pDoc As NotesDocument
	Private pToString As String 
	Private pShowPrompts As Boolean
	Private pDatabase_Locking_Not_Enabled As String
	Private pDatabase_Locking_Not_Enabled_Title As String
	Private pDocument_Locked As String
	Private pDocument_Locked_Title As String
	Private pEnabled As Boolean
	Private pAlreadyLocked As Boolean
	'Flag used so user is only informed once that database locking is not enabled	
	Private pDatabasePrompted As Boolean
 
	'/**
	' * Constructor
	' */
	Public Sub new( inDoc As Variant )
		pDatabase_Locking_Not_Enabled = "Database locking has not been enabled."
		pDatabase_Locking_Not_Enabled_Title = "Locking Not Enabled"
		pDocument_Locked = "Unable to lock, currently locked by: "
		pDocument_Locked_Title = "Document Locked"
		pDatabasePrompted = False
		pAlreadyLocked = False
		pShowPrompts = True
		pToString = ""
		If Not inDoc Is Nothing Then
			If Typename( inDoc ) = "NOTESDOCUMENT" Then
				Set pDoc = inDoc
			Elseif Typename( inDoc ) = "NOTESUIDOCUMENT" Then
				Set pDoc = inDoc.Document
			End If
		End If
 
		Dim Session As New NotesSession
		pUser = Session.UserName 
		If Session.CurrentDatabase.IsDocumentLockingEnabled Then
			pEnabled = True
		Else
			pEnabled = False
		End If
	End Sub
 
	'/**
	' * Determines if the document is locked 
	' */
	Private Function HasLock ( ) As Boolean
		If pDoc Is Nothing Then
			HasLock = True
		Else
			'if there is no text then it is not locked
			HasLock = Len( pDoc.LockHolders(0) ) > 0
		End If
	End Function
 
	'/**
	' * Gets the current user
	' */
	Private Property Get CurrentUser As String
		CurrentUser = pUser
	End Property
	'/**
	' * Gets the current user
	' */
	Public Sub SetCurrentUser( user As String )
		pUser = user
	End Sub
	'/**
	' * Determines if the document is locked but the current user.
	' */
	Private Function CurrentUserHasLock( ) As Boolean
		CurrentUserHasLock = HasLock ()
		If CurrentUserHasLock Then
			If pDoc.LockHolders(0) = pUser Then
				CurrentUserHasLock = True
			Else	'Not the current user.
				CurrentUserHasLock = False
			End If
		End If
	End Function
 
	'/**
	' * Determines if a document exists
	' */
	Public Function hasDocument()
		hasDocument = Not pDoc Is Nothing
	End Function
	'/**
	' * Sets the Document
	' */
	Public Sub setDocument( inDoc As NotesDocument )
		Set pDoc = inDoc	
	End Sub
	'/**
	' * Sets the document base on the UI document
	' */
	Public Sub setUIDocument( inUIDoc As NotesUIDocument )
		If inUIDoc Is Nothing Then
			Call setDocument( inUIDoc.Document )
		End If
	End Sub
 
	'/**
	' * Returns string of any messages
	' */
	Public Property Get toString As String
		toString = pToString
	End Property
 
	'/**
	' * Returns wether prompts are displayed
	' */
	Public Property Get ShowPrompts As Boolean
		ShowPrompts = pShowPrompts
	End Property
	'/**
	' * Sets wether prompts are displayed
	' */
	Public Property Set ShowPrompts As Boolean
		pShowPrompts = ShowPrompts
	End Property
 
	'/**
	' * Determines if database locking is enabled.
	' */
	Public Function LockingEnabled() As Boolean
		If Not pEnabled Then
			If Not pDatabasePrompted Then
				pToString = pDatabase_Locking_Not_Enabled
				If showPrompts Then
					Msgbox pToString , MB_ICONSTOP , pDatabase_Locking_Not_Enabled_Title
				End If
				pDatabasePrompted = True
			End If
		End If
		LockingEnabled = pEnabled
	End Function
 
	'/**
	' * Determines if the current document is locked by the current user.
	' */
	Public Function IsLockedByCurrentUser () As Boolean
		IsLockedByCurrentUser = LockingEnabled()
		If IsLockedByCurrentUser Then
			IsLockedByCurrentUser = CurrentUserHasLock( )
		Else	'Locking not enabled
			IsLockedByCurrentUser = False
		End If
	End Function	
	'/**
	' * Determines if the document is locked but the current user.
	' */
	Public Function IsDocumentLockedByCurrentUser (doc As NotesDocument ) As Boolean
		Call SetDocument( doc )
		IsDocumentLockedByCurrentUser = IsLockedByCurrentUser
	End Function
 
	'/**
	' * Determines if the UI document is locked but the current user.
	' */
	Public Function IsUIDocumentLockedByCurrentUser ( uiDoc As NotesUIDocument ) As Boolean
		Call setUIDocument( uiDoc )
		IsUIDocumentLockedByCurrentUser = IsLockedByCurrentUser(  )
	End Function
 
	'/**
	' * Returns who the document is locked by 
	' */
	Public Function LockedBy ( ) As String
		If hasDocument() Then
			LockedBy = pDoc.LockHolders(0)
		Else
			LockedBy = ""
		End If
	End Function
	'/**
	' * Determines if the currnet document is locked 
	' */
	Public Function IsLocked ( ) As Boolean
		isLocked = LockingEnabled()
		If isLocked Then
			isLocked = HasLock( )
		Else	'Locking is not enabled
			isLocked = False
		End If
	End Function
	'/**
	' * Determines if the the document is locked 
	' */
	Public Function IsDocumentLocked ( doc As NotesDocument ) As Boolean
		Call setDocument( doc ) 
		isDocumentLocked = IsLocked()
	End Function
	'/**
	' * Determines if the UI document is locked 
	' */
	Public Function IsUIDocumentLocked (uiDoc As NotesUIDocument ) As Boolean
		'Check to make sure that there is a document, If there is none it is a new document
		If ( uiDoc.Document Is Nothing ) Then
			IsUIDocumentLocked = False
		Else
			IsUIDocumentLocked= IsDocumentLocked( uiDoc.Document )
		End If
	End Function
 
	'/**
	' * Locks the current document
	' */
	Public Function Lock() As Boolean
		Me.Lock = LockingEnabled()
		If Me.Lock Then	'Check to make locking is enabled.
			If Not pAlreadyLocked Then	'Make sure that the document is not allready locked.
				If HasLock( ) Then
					If CurrentUserHasLock( ) Then
						'Since the current user has the document locked then we don't need to.
						pAlreadyLocked = True
						Me.Lock = True
					Else
						'Document is locked by someone else.  Let's display the name
						pToString = pDocument_Locked + pDoc.LockHolders(0)
						If showPrompts Then
							Msgbox pToString , MB_ICONSTOP, pDocument_Locked_Title 
						End If
						Me.Lock = False
					End If
				Else
					'Make sure that there is a document to lock, New documents can not be locked.
					If Not pDoc.IsNewNote Then
						Call pdoc.Lock
					End If
					pAlreadyLocked = True
					Me.Lock = True
				End If
			End If
		End If
	End Function
	'/**
	' * Locks the UI document
	' */
	Public Function LockUIDocument (uiDoc As NotesUIDocument ) As Boolean
		Call setUIDocument( uiDoc )
		LockUIDocument = Me.Lock()
	End Function
 
	'/**
	' * Locks the document
	' */
	Public Function LockDocument (doc As NotesDocument ) As Boolean
		Call setDocument ( doc ) 
		LockDocument = Me.Lock()
	End Function
 
	'/**
	' *  Unlocks the current document
	' */
	Public Function UnLock () As Boolean
		Me.UnLock = False
		If Not pDoc Is Nothing Then
			If Not pDoc.IsNewNote Then
				If CurrentUserHasLock(  ) Then	'Only unlock if the current user has it locked.
					pDoc.UnLock
					Me.UnLock = True
				End If
			End If
		End If
	End Function
	'/**
	' *  Unlocks the UI document
	' */
	Public Function UnLockUIDocument (uiDoc As NotesUIDocument ) As Boolean
		Call setUIDocument( uiDoc )
		UnLockUIDocument = Me.UnLock()
	End Function
 
	'/**
	' * Unlocks the document
	' */
	Public Function UnLockDocument (doc As NotesDocument ) As Boolean
		Call setDocument( doc )
		UnLockDocument = Me.UnLock()
	End Function
 
End Class
Filed under: Domino Leave a comment
Comments (7) Trackbacks (0)
  1. Chad, this class is excellent! I just incorporated it into a web app I’m currently working on.

    I did find one thing that may be useful to add. For dbs where I use doc locking, I add a scheduled agent that removes the locks from documents that have been locked for more than a specified # of hours. The agent would be running with an ID defined as Manager in the ACL. However, your code only unlocks a doc if the current user is listed as a lock owner.

    What I’m thinking is that it would be useful to have a “manager override” flag, where a document could be unlocked even if the current user isn’t listed as a lock owner. This special flag would also work if the database owner needed to unlock a document on an emergency basis, and isn’t a lock owner. What do you think?

  2. I can see where other people would have the same need.

    I would like to see it implemented using a role. If the current user is apart of ‘[Unlock Document]‘ then continue into edit mode after the document is unlocked. This role should be set by the application, so in another application it could be ‘[admin]‘ or ‘[developer]‘. I could see having a default role of something like ‘[Unlock Document]‘.

    Have you done any coding for this?

  3. Not yet, but I’ll need to do something relatively soon.

    My idea was to query the current user’s access level for the current db (using notesDatabase.CurrentAccessLevel). Based on the way doc locking works, anyone designated as a Manager in the ACL would be able to unlock any document. So, I’m not sure if adding a role would add any value, since a person could be included in the role but not able to unlock documents they haven’t locked, if they weren’t defined as a Manager.

    I’ll probably look into modifying your code next week. I can send you what I come up with when I’m done, if you like.

  4. Chad

    Sorry for one more question

    I used the class in the webquery open like
    flag = DocLock.IsDocumentLocked (wdoc)

    it is giving “False” if the document is opened in web by user and is not locked
    I am locking it by “Call DocLock.LockDocument(wdoc)” in the same webqueryopen agent

    if is save i can unlock it like “call DocLock.UnLockDocument(wdoc) in webquerysave but how can i unlock if i just close the document without saving

    Please help

  5. Great to see that it will be used.

    Yes the 4 digit validation is easier, thanks.

  6. Has anybody experienced the replication conflict issue when using document locking in combination with server and local based replicas?

    I finally turned off document locking to avoid this issue which appears to be a bug within Domino. It occured whenever a record was updated on the server using document locking in a clustered environment when there were also replicas existing on workstations.

    Even though the documents were not updated on the workstations, whenever they replicated to the cluster it generates a series of replication conflicts….
    With messages like
    Changes made to database ‘database title goes here’ have not been incorporated into the database. There was a conflict detected. Your changes may be found in body of this message……

    I finally removed all code (bypassed actually) that performed locking and turned off the document locking for the database.

    Just curious if you ever experienced this error…

  7. Mark, I have not experienced those messages. I ran into some problems with clustering and documented it here:http://www.chadsmiley.com/chadsmiley/home.nsf/d6plinks/Documents_Stay_Locked

    Since we have been in contact with Lotus and they have produced a hotfix for us.

    Sorry I could not be of more help.


Leave a comment


No trackbacks yet.