Earlier this week I started work on my first project in which I need to specifically design a Notes application to support Blackberry Devices. To assist me with this I have started to extend the capabilities of the .Domino Framework.
The DominoWebSession class now has two additional properties DeviceType and DeviceModel. DeviceType will return "Blackberry" when the document is being loaded from a Blackberry Device (Later I expect to add other PDA devices such as iPhone). This property works by looking for the text "Blackberry" in the CGI variable HTTP_User_Agent. The DeviceModel property will pass back the specific Blackberry model. This property can potentially be used to identify the resolution and capabilities of the Blackberry device. I have also added a CGI\PDA subform that adds fields for these two properties to the standard CGI variables often passed with Web pages. I will also be adding general Blackberry specific development stuff to the knowledge base of the .Domino Framework wiki. This includes the following table of screen resolutions (I couldn't find a resource where this is documented).
| Model |
Name |
Resolution |
| 9500 |
Thunder |
360 x 480 |
| 9000 |
Bold |
480 x 320 |
| 8800 |
|
320 x 240 |
| 8700 |
|
320 x 240 |
| 8300 |
Curve |
320 x 240 |
| 8100 |
Pearl |
240 x 260 |
| 7200 |
|
240 x 160 |
| 7100 |
|
240 x 260 |
|
Ratings
0
|
Getting document locking to work has been one of my toughest assignment as a Notes developer. But I have finally gotten a solution that passed QA. So further to my previous FOUR blogs on this topic I can add the additional insight for others strugging to make document locking work (I know a few Notes developers that just gave up)
- Don't allow provisional locks. These are the locks that occur when the master lock server is down. When this server is down it is like not having document locking at all. Provisional locks can only be preveneted by coding EVERYTHING through LotusScript.
- Persistent temporary locks only work to a degree. These are the locks that occur when a document is placed in edit mode. With every application I have implemented document locking I have found documents popping up (usually 1-2 a week) that remain locked even after the document has bee closed. Users of these applications can become confused (and frustrated) about these locks and in some cases are unable to remove the locks themselves. If you can leave with this annoyance it is a LOT easier to implemen this model.
- The only reliable way to get document locking (and unlocking) to work is to allow persistent permanent locks only. These are the locks that are placed manually before the document is opened.
Implementing persistent permanent locking only is waaayyyy more challenging.
- The document locking event always occurs before any form event has a chance to respond. So you cannot intercept (and prevent) a document locking action. All you can do is detect and respond to a document locking operation.
- Users with Manager level access to a database can overide an existing lock. Unless care is taken these people can inadvertently destroy the integrity of the document locking process.
- After a document has been opened in edit mode it is not possible to differentiate between a permanent persistent lock and a permanent temporary lock.
In implementing a solution to the above I have now completely rewritten the logic for the DominoDocumentCollection.Lock and DominoDocumentCollection.UnLock methods. These methods now make use of a 2nd field that is added to documents when they are locked. This 2nd field helps to identify that a persistent permanent lock has been placed and who placed it. The form events must now be programmmed to check for the presence of a lock holder and 2nd field before allowing editing of a document. Additionally we can inspect the current usname against the lockholder and 2nd field to identify a Manager who has been able to lock the document without originally holding the permanent persisent lock. When this happens you can chose to refuse the edit request and restore the lock back to orginal lock holder. To the application users the process looks like this. They must first place a lock on one or more documents. This is done from relevant views via a view action and/or using an inviewedit process to toggle a lock icon by clicking on the relevant column in the view. An icon is added to the views to show documents that are locked. Locks do not work if the Master Lock Server is not available. Lock holders can then edit the locked document(s). When they are finished they must unlock the document. An Administrator with Manager level access can unlock documents locked by others (at their own peril!). A working example of this will be included as part of the next release of the .DominoFramework. Note: With Notes 6.0 it is not possible to edit attachments where a lock already exists. (This is not the case with Notes 8.0). To get around this issue I have devised a 2nd form that can be used to edit attachments. This form does not contain the event trapping to prevent a document being edited when locked. To reduce the risk of persistent temporary locks remaining, these are always removed when the document is closed (i.e lockholder is present but 2nd field is absent).
|
Ratings
0
|
|
For many years Microsoft have been trying to build a application capable to challenging Lotus Notes. For just as many years Microsoft have been falling short in that effort. Recently however I have began to notice that many of the organizations for whom I work Sharepoint is being considered as a solution for applications that would previously be the realm of Lotus Notes. Could it be that Lotus Notes now does have a viable competitor? It doesn't seem like it when you compare the products technically. But hey, to this day I still feel that Lotus 1-2-3 was a superior spreasheet application to Excel and I preferred Netscape Navigator over Internet Explorer. So who knows what the Microsoft marketing machine can convince senior IT executives. As I see it, Sharepoint has a number of distinct weaknesses. First, it still seems to have more hype than substance. It is not as much out of the box as Microsoft would like us all to believe. It is also not a single product, requiring the usual mismash of products such as Sharepoint Server, SQL Server, IIS, Visual Studio, Active Directory to work. And it is a Windows only solution aimed solely at selling even more MS software.... If I had the resources of a company like IBM this is how I would go about baking a killer product capable of resigning Sharepoint to the same fate as the last "great white hope" - IBM Workplace.
1) The base product would continue to be Lotus Notes. Nobody has ever come up with a product that can compete with Notes for the simplicity of building and deploying collaborative applications. Notes consists of a single NSF that contain all the data and code. By adding integrated security, replication, directory services, and mail services the task of building and deploying an application onto multiple servers has never been made easier. Add to that the new slick Notes 8.0 UI, composite applications and the as-yet untapped capabilities of X-Pages and you have a platform that is truly capable of rapidly delivering modern high quality SOA applications on both thick and thin client platforms. 2) One of the strength of Lotus Notes has always been the speed with which customized solutions can be developed. The programming base of Notes does however need an urgent overall to bring it into the 21st century. This includes completing the work already started to migrate Domino Designer to the Eclipse platform. Java and LotusScript editors need to delivered quickly along with native eclipse editors for all the other non-xpages design elements. The LotusScript language must be expanded to offer many of the capabilities found in Java (and VB.Net/C#). Likewise IBM need to find a way to make Java available in all the same places LotuScript can be used. We then have a HUGE army of Basic (LotusScript) and java programmers able to fully leverage the product. 3) Sharepoints' current strengths over Lotus Notes include Document Management and Workflow. I would turn this weakness into a strength by taking the Lotus Worklflow and Lotus Document Management products and integrating them into the standard Notes/Domino product. These products have been neglected and are unable to effectively compete as stand-alone products. It is often an impossible task to convince IT executives to approve the purchase of new products such as these. But then, if they were part of the core Notes product I wouldn't have to. I can't believe these products are huge contributors to the IBM bottom line. If they were, they would get an occasional mention at LotusSphere (outside of appearing on the annual LotusSphere Bingo cards). 4) The out-of-the-box capabilities of Notes would need to be expanded to take on Sharepoint. Enhanced document library and teamroom templates are needed that exploit the features of document management and workflow and build on some of the great ideas found in QUICKR (including the SNAPPS templates). Added to that we need a killer blog template - perhaps taking the existing IBM blog template and combining that with the OpenNTF Blogsphere template. A wiki template is needed - again the openNTF DominoWiki template is a great start. We would also need to add to the mix some of the social software capabilities found in Lotus Connections. An improved PAB that adds some of the profiling capabilities of Connections and even a little sex appeal with something like Lotus911's Carousel. For DogEars it would be hard to go past LinkJam - and why not throw in an idea/suggestion scheme template (IdeaJam). For good measure some form of Activity management template is needed. And while I am not a big twitter fan, a twitter template may not be a bad addition too. Also build out the RSS Feed manager to be comparable with products such as FeedDemon.
Take the above ingredients and mix in a large yellow bowl until the right consistency is achieved. Then add to a hot oven and allow to bake for 3-6 months. Don't cook for too long now or Sharepoint will be selling like hotcakes and the juggernaut may become uncatchable. Served to a large corporate audience I am sure this new Sharepoint Killer would soon get that yellow blood pumping through the veins of organizations around the globe.
|
Ratings
0
|
By default Notes only supports the dragging/dropping of documents into a folder.
The following is a technique developed for an application allowing the
simulation of dragging a collection of documents into a view:-
- For
each view to support drag/drop create a new (dummy) folder. The design
of the folder does not matter as it is never opened/used.
- Modify any outlines used to link to the dummy folder instead of the original view
- Place
the following code into the QueryOpen event of each dummy folder forcing the
associated view (or page with embedded single category view) to open
instead of the folder when selected from the outline.
Sub Queryopen(Source As Notesuiview, Continue As Variant) Dim UIW As New NotesUIWorkspace Continue = False Call UIW.SetTargetFrame("NotesView" ) Call UIW.CurrentDatabase.OpenView("Viewname" ) or Call UIW.OpenPage("Pagename" ) End Sub
- Modify the database's Postdragdrop event to evaluate continue = false, preventing documents being placed into these dummy folders.
- Finally,
add the code to the Postdragdrop event to perform the desired task for
a collection of documents being "dropped in the view".
|
Ratings
0
|
I common problem I encounter when maintaining Notes applications is that documents are being saved multiple times as the result of a single event/action. In some cases there may not have been any changes made to the actual data. Reducing the number of times a document is saved can generate a number of benefits to the application.
- Application Performance: The save operation is an expensive one. The fewer the number of saves, the faster the code runs.
- Server Performance: Each and every time a document is saved it creates the potential need for the server to update every view index to establish if the change has an effect on the view. The server may also need to update the full text index. If the data did not change this work results in no change (but the server doesn't know that!)
- Reduced Conflicts: A repeated number of saves can result in a save conflict being generated. It also increases the chances of replication conflicts if the document is being edited on another server.
- Accurate Edit History: The document history is updated each time the document is saved. The date/time of the last change and the identity of the author is somehwat invalid if the actual data did not change. The number of entries in the edit history can also become much larger than it needs to be if additional saves have been performed.
One of the main reasons for multiple saves is the difficulty of keeping track of when changes had been made. e.g. each section of code does a save just in case the next code block doesn't do a save. One of the way to minimize the number of changes is to keep track of whenever any item in a document has been changed and then only save the document if a change has been made (to one ore more items). The .Domino Framework provides one potential solution. Being Object Oriented, the document-based classes maintain an internal iHasChanged variable that is initially set to false. Each of the Property Set code blocks sets the iHasChanged variable to True. The .Domino Framework Property Generator Tool provides the option to include this logic as part of the p[roperty code it generates.
e.g. Property Get CompanyName As String If iDocument Is Nothing Then Exit Property If iDocument.HasItem("CompanyName" ) Then CompanyName$ = iDocument.GetItemValue("CompanyName" )(0) End Property Property Set CompanyName As String If iDocument Is Nothing Then Exit Property Call iDocument.ReplaceItemValue("CompanyName",CompanyName$) iHasChanged = True End Property
It is then possible at the very end of a code block (e.g. event or action) to test to see if any changes have been made and only invoke a save when the variable has been set. Note: The framework's DominoDocument class has a Save event which supports the above by only saving the document if a change has been made (iHasChanges = true). It also resets the flag after the save. To further reduce the number of changes it is also suggested that comparisons be made with the existing value before updating the object's property.
e.g. If Employee.CompanyName$ <> CompanyName$ Then Employee.CompanyName$ = CompanyName$ If Employee.Postcode$ <> Postcode$ Then Employee.Postcode$ = Postcode$
Using the above it is often possible to develop code that only needs to do a single save at the very end if, and only the values of at least one field have been changed.
|
Ratings
0
|
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
|
Ratings
0
|
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.
|
Ratings
0
|
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 |
|
Ratings
0
|
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.Co |