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

16Jan/0610

NotesSystem and DocumentExtended

Updated version of Domino Extended is now available.

Things are building. Simulating an abstract class in LotusScript started some discussion with Tim Triponcy, who combined the abstract classes with Julian's singleton concept. The result was a System class that would not have to be initialized but could be used by anything that included the script library. I like Tim's concept so much that I had to take it and run, with some minor changes and improvements (at lest from my perspective). I also wanted to take this same NotesSystem (new name) and port it to Java, since I have been doing most of my development in Java for Domino, using Domiclipse (awesome tool). Because Java can access the backend of Domino some of the UI methods have been commented out.  There is one other class that I created called NotesDocumentExtended (DocumentExtended in Java) to make my life easier and so I can be more lazy.

Enough said here are the class overviews

NotesSystem oveview

Private Class NotesSystem
	Public Sub New()
	Public Function hasWorkspace() As Boolean
	Public Function ThisWorkspace() As NotesUIWorkspace
	Public Function ThisDatabase() As NotesDatabase
	Public Function hasDocument() As Boolean
	Public Function ThisDocument() As NotesDocument
	Public Function hasUIDocument() As Boolean
	Public Function ThisUIDocument() As NotesUIDocument
	Public Function ThisSession() As NotesSession
	Public Function CurrentUser() As NotesName
	Public Function CurrentUserCommon() As String
	Public Function CurrentUserAbbreviated() As String
End Class

NotesDocumentExtended oveview

Public Class NotesDocumentExtended
	Public Function getFieldValues ( fieldName As String ) As Variant
	Public Function getFieldItem ( fieldName As String ) As NotesItem
	Public Sub replaceField ( fieldName As String , Var As Variant )
	Public Function getFieldText ( fieldName As String ) As String
	Public Function hasField ( fieldName As String ) As Boolean
	Public Function hasFieldText ( fieldName As String ) As Boolean
	Public Function hasDoc ( ) As Boolean
	Public Function hasDocument ( ) As Boolean
	Public Sub setDoc ( Doc As NotesDocument )
	Public Function Doc() As NotesDocument
	Public Sub setDocument ( Document As NotesDocument )
	Public Function Document As NotesDocument
End Class


Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
'Domino_Extended: 
 
Option Public
Option Declare
Dim System As Variant
 
'/**
' * A basic class to extend the NotesDocument class to reduce
' * code and improve error checking
' * 
' *	@author	Tim Tripcony				http://www.timtripcony.com
' *	@author	Chad Schelfhout		http://www.chadsmiley.com/
' * 	
' *	@version	1.0	Created by Tim
' *	@version	1.1	Split intialization, each object is initalized only when it is needed
' * @version	1.2	Converted NotesDocument to NotesDocumentExtended
' * @version	1.3	Converted properties to Function so it is easily ported to Java
' */
Private Class NotesSystem
	'Used to determine if each object has been initalized.
	Private boolSession As Boolean
	Private boolDatabase As Boolean
	Private boolWorkspace As Boolean
	Private boolUIDocument As Boolean
	Private boolDocumentExtended As Boolean
	Private boolName As Boolean
 
	'Possible objects that can be loaded
	Private sessionCurrent As NotesSession
	Private databaseCurrent As NotesDatabase
	Private workspaceCurrent As NotesUIWorkspace
	Private uiDocumentCurrent As NotesUIDocument
	Private documentExtendedCurrent As NotesDocumentExtended
	Private nameCurrent As NotesName	
 
	'/**
	' * Constructor, but nothing else is intialized until it is used.
	' */
	Public Sub New()
		Let boolSession = False
		Let boolDatabase = False
		Let boolWorkspace = False
		Let boolUIDocument = False
		Let boolDocumentExtended = False
		Let boolName = False
	End Sub
 
	'/**
	' * IntializeSession
	' */
	Private Sub intializeSession( )
		If Not boolSession Then
			Set SessionCurrent = New NotesSession()
			Let boolSession = True
		End If
	End Sub
	'/**
	' * Intialize Database
	' */
	Private Sub intializeDatabase( )
		If Not boolDatabase Then
			Call intializeSession()
			Set databaseCurrent = sessionCurrent.CurrentDatabase()
			Let boolDatabase = True
		End If
	End Sub
	'/**
	' * Intialize Document
	' */
	Private Sub intializeDocument( )
		If Not boolDocumentExtended Then
			Call intializeDatabase()
			Set documentExtendedCurrent = New NotesDocumentExtended()
			If isOnServer Then
				Call documentExtendedCurrent.setDocument ( sessionCurrent.DocumentContext() )
			Else
				Call intializeUIDocument()
				If hasUIDocument() Then
					Call documentExtendedCurrent.setDocument( uiDocumentCurrent.Document() )
				End If
			End If
			Let boolDocumentExtended = True
		End If
	End Sub
	'/**
	' * Determines if the object was loaded through the UI
	' */
	Private Function isOnServer () As Boolean
		Call intializeSession()
		isOnServer = sessionCurrent.IsOnServer()
	End Function
	'/**
	' * Intialize Workspace
	' */
	Private Sub intializeWorkspace( )
		If Not boolWorkspace Then
			If Not isOnServer Then
'Skip workspace initialization if the code is running on a server because NotesUIWorkspace would be unavailable
				Set workspaceCurrent = New NotesUIWorkspace()
			End If
			Let boolWorkspace = True
		End If
	End Sub
	'/**
	' * Intialize UI Document
	' */
	Private Sub intializeUIDocument( )
		If Not boolUIDocument Then
			If Not isOnServer Then
				Call intializeWorkspace()
				If hasWorkspace() Then
					Set uiDocumentCurrent = workspaceCurrent.CurrentDocument()
				End If
			End If
			Let boolUIDocument = True
		End If
	End Sub	
	'/**
	' * Intialize Name
	' */
	Private Sub intializeName()
		If Not boolName Then
			Call intializeSession()
			Set nameCurrent = New NotesName( sessionCurrent.EffectiveUserName ())
			Let boolName = True
		End If
	End Sub
 
	'/**
	' * Determines if a UI Workspace is available
	' */
	Public Function hasWorkspace() As Boolean
		Call intializeWorkspace()
		hasWorkspace = Not workspaceCurrent Is Nothing
	End Function
	'/**
	' * Returns the UI Workspace
	' * @return UI Workspace
	' */
	Public Function ThisWorkspace() As NotesUIWorkspace
		Call intializeWorkspace()
		Set ThisWorkspace = workspaceCurrent
	End Function
	'/**
	' * Returns the current database
	' * @return current database
	' */
	Public Function ThisDatabase() As NotesDatabase
		Call intializeDatabase()
		Set ThisDatabase = databaseCurrent
	End Function
	'/**
	' * determines if there is a current document
	' * @return True/False
	' */
	Public Function hasDocument() As Boolean
		Call intializeDocument()
		hasDocument = documentExtendedCurrent.hasDocument()
	End Function
	'/**
	' * Returns the current document
	' * @return current document
	' */
	Public Function ThisDocument() As NotesDocument
		Call intializeDocument()
		Set ThisDocument = documentExtendedCurrent.Document()
	End Function
	'/**
	' * Returns the current ui document
	' * @return current ui document
	' */
	Public Function ThisUIDocument() As NotesUIDocument
		Call intializeDocument()
		Set ThisUIDocument = uiDocumentCurrent
	End Function
	'/**
	' * Determines if a ui document is available
	' * @return True/False
	' */
	Public Function hasUIDocument() As Boolean
		Call intializeUIDocument()
		hasUIDocument = Not ( uiDocumentCurrent Is Nothing )
	End Function
	'/**
	' * Returns the current Session
	' * @return current Session
	' */
	Public Function ThisSession() As NotesSession
		Call intializeSession()
		Set ThisSession = sessionCurrent
	End Function
	'/**
	' * Returns the current Users Name object 
	' * @return current user Name object
	' */
	Public Function CurrentUser() As NotesName
		Call intializeName()
		Set CurrentUser = nameCurrent
	End Function
	'/**
	' * Returns the current users common name
	' * @return current users common name
	' */
	Public Function CurrentUserCommon() As String
		Call intializeName()
		CurrentUserCommon = nameCurrent.Common
	End Function
	'/**
	' * Returns the current users abbreviated name
	' * @return current users abbreviated name
	' */
	Public Function CurrentUserAbbreviated() As String
		Call intializeName()
		CurrentUserAbbreviated = nameCurrent.Abbreviated
	End Function
End Class
 
 
 
'/**
' * A basic class to extend the NotesDocument class to reduce
' * code and improve error checking
' * 
' *	@author	Chad Schelfhout		http://www.chadsmiley.com/
' *	@version	1.1
' *
' * @history	1.0 Created
' * 					1.1 converted properties to function/subs and ported to Java
' */
Class NotesDocumentExtended
	Private pDoc As NotesDocument
 
	'/**
	' * Constructor
	' */
	Public Sub New()
	End Sub
	'/**
	' * Returns the Values ofthe field if it is availabe
	' * @param fieldName The name of the field on the document
	' * @return the values of the field, or nothing
	' */
	Public Function getFieldValues ( fieldName As String ) As Variant
		Set getFieldValues = Nothing
		If hasDocument() Then
			If pDoc.hasItem( fieldName ) Then
				getFieldValues = pDoc.getFirstItem( fieldName).Values
			End If
		End If
	End Function
	'/**
	' * Returns the Values ofthe field if it is availabe
	' * @param fieldName The name of the field on the document
	' * @return the notes item of the field, or nothing
	' */
	Public Function getFieldItem ( fieldName As String ) As NotesItem
		Set getFieldItem = Nothing
		If hasDocument() Then
			If pDoc.hasItem( fieldName ) Then
				Set getFieldItem = pDoc.getFirstItem( fieldName)
			End If
		End If
	End Function
	'/**
	' * Replaces the fields value with the new one supplied
	' * @param fieldName The name of the field on the document
	' * @param Item the new value for the field
	' */
	Public Sub replaceField ( fieldName As String , Var As Variant )
		If hasDocument() Then
			Call pDoc.ReplaceItemValue( fieldName , Var )
		End If
	End Sub
	'/**
	' * Returns the text representation of fields value
	' * @param fieldName The name of the field on the document
	' * @return the fields value as a string
	' */
	Public Function getFieldText ( fieldName As String ) As String
		getFieldText = ""
		If hasDocument() Then
			If pDoc.hasItem( fieldName ) Then
				getFieldText = pDoc.getFirstItem( fieldName).text
			End If
		End If
	End Function
	'/**
	' * Determines if the field exists on the document
	' * @param fieldName The name of the field on the document
	' * @return weather the field exists
	' */
	Public Function hasField ( fieldName As String ) As Boolean
		hasField = False
		If hasDocument() Then
			hasField = pDoc.hasItem( fieldName )
		End If
	End Function
	'/**
	' * Determines if the field has text. by converting all values to text and checking the length
	' * @param fieldName The name of the field on the document
	' * @return weather the text length is zero
	' */
	Public Function hasFieldText ( fieldName As String ) As Boolean
		hasFieldText = False
		If hasDocument() Then
			hasFieldText = ( Len( getFieldText( fieldName ) ) > 0 )
		End If
	End Function
	'/**
	' * Determines if a document exists
	' * @return weather there is a document
	' */
	Public Function hasDoc ( ) As Boolean
		hasDoc = Not ( pDoc Is Nothing )
	End Function
	'/**
	' * Determines if a document exists
	' * @return weather there is a document
	' */
	Public Function hasDocument ( ) As Boolean
		hasDocument = Not ( pDoc Is Nothing )
	End Function
	'/**
	' * Returns the true NotesDocument
	' * @return the NotesDocument
	' */
	Public Sub setDoc ( Doc As NotesDocument )
		Set pDoc = Doc
	End Sub
	'/**
	' * Returns the true NotesDocument
	' * @return the NotesDocument
	' */
	Public Function Doc() As NotesDocument
		Set Doc = pDoc
	End Function
	'/**
	' * Sets the true NotesDocument
	' * @param the NotesDocument
	' */
	Public Sub setDocument ( Document As NotesDocument )
		Set pDoc = Document 
	End Sub
	'/**
	' * Returns the true NotesDocument
	' * @return the NotesDocument
	' */
	Public Function Document As NotesDocument
		Set Document = pDoc
	End Function
End Class
 
 
Sub Initialize
	Set System = New NotesSystem()
End Sub
</textarea>
<h3>Java NotesSystem</h3>
<a href="javascript:highlight(2)"> Select All</a><BR><BR>
<textarea rows="20" cols=60" wrap="virtual" class="codebox200" id="FormulaCodeBlock2" onFocus="javascript:highlight(2)" title="Use the Select All link above to select all the text.">
package com.ChadSmiley.domino.Extended;
 
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.Name;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.Session;
 
/**
 * A basic class to extend the NotesDocument class to reduce
 * code and improve error checking
 * 
 * @author	Tim Tripcony				http://www.timtripcony.com
 * @author	Chad Schelfhout		http://www.chadsmiley.com/
 * 	
 * @version	1.0	Created by Tim
 * @version	1.1	Split intialization, each object is initalized only when it is needed
 * @version	1.2	Converted NotesDocument to NotesDocumentExtended
 * @version	1.3	Converted properties to Function so it is easily ported to Java
 */
 
public class NotesSystem {
//	Used to determine if( each object has been initalized.
	private boolean boolSession;
	private boolean boolDatabase;
//	private boolean boolWorkspace;
//	private boolean boolUIDocument;
	private boolean boolDocumentExtended;
	private boolean boolName;
 
//	Possible objects that can be loaded
	private Session sessionCurrent;
	private Database databaseCurrent;
//	private UIWorkspace workspaceCurrent;
//	private UIDocument uiDocumentCurrent;
	private DocumentExtended documentExtendedCurrent;
	private Name nameCurrent;
 
	/**
	 * Constructor, but nothing else is intialized until it is used.
	 */
	public NotesSystem(){
		 boolSession = false;
		 boolDatabase = false;
//		 boolWorkspace = false;
//		 boolUIDocument = false;
		 boolDocumentExtended = false;
		 boolName = false;
	}
 
	/**
	 * IntializeSession
	 */
	private void intializeSession( ){
		if( ! boolSession) {
			try {
				sessionCurrent = NotesFactory.createSession();
			} catch (NotesException e) {
				sessionCurrent = null;
			};
			boolSession = true;
		}
	}
	/**
	 * Intialize Database
	 */
	private void intializeDatabase( ){
		if( ! boolDatabase) {
			intializeSession();
			try {
				databaseCurrent = sessionCurrent.getAgentContext().getCurrentDatabase();
			} catch (NotesException e) {
				databaseCurrent = null;
			}
			boolDatabase = true;
		}
	}
	/**
	 * Intialize Document
	 */
	private void intializeDocument( ){
		if( ! boolDocumentExtended ) {
			intializeDatabase();
			documentExtendedCurrent = new DocumentExtended();
			if( isOnServer()) {
				try {
					documentExtendedCurrent.setDocument( sessionCurrent.getAgentContext().getDocumentContext() );
				} catch (NotesException e) {
				}
			}else{
//				intializeUIDocument();
//				if( hasUIDocument()) {
//					documentExtendedCurrent.Document = uiDocumentCurrent.getDocument();
//				}
			}
			boolDocumentExtended = true;
		}
	}
	/**
	 * Determines if( the object was loaded through the UI
	 */
	private boolean isOnServer (){
		intializeSession();
		try {
			return sessionCurrent.isOnServer();
		} catch (NotesException e) {
			return false;
		}
	}
//	/**
//	 * Intialize Workspace
//	 */
//	private void intializeWorkspace( ){
//		if( ! boolWorkspace) {
//			if( ! isOnServer) {
////Skip workspace initialization if( the code is running on a server because NotesUIWorkspace would be unavailable
//				workspaceCurrent = new UIWorkspace();
//			}
//			 boolWorkspace = true;
//		}
//	}
//	/**
//	 * Intialize UI Document
//	 */
//	private void intializeUIDocument( )
//		if( ! boolUIDocument) {
//			if( ! isOnServer) {
//				intializeWorkspace();
//				if( hasWorkspace()) {
//					uiDocumentCurrent = workspaceCurrent.getCurrentDocument();
//				}
//			}
//			boolUIDocument = true;
//		}
//	}	
	/**
	 * Intialize Name
	 */
	private void intializeName(){
		if( ! boolName) {
			intializeSession();
			try {
				nameCurrent = sessionCurrent.getUserNameObject();
			} catch (NotesException e) {
			}
			boolName = true;
		}
	}
 
//	/**
//	 * Determines if( a UI Workspace is available
//	 */
//	public boolean hasWorkspace() {
//		intializeWorkspace();
//		hasWorkspace = workspaceCurrent != null;
//	}
	/**
	 * Returns the current database
	 * @return current database
	 */
	public Database thisDatabase() {
		intializeDatabase();
		return databaseCurrent;
	}
	/**
	 * determines if( there is a current document
	 * @return true/false
	 */
	public boolean hasDocument(){
		intializeDocument();
		return documentExtendedCurrent.hasDocument();
	}
 
	/**
	 * Returns the current document
	 * @return current document
	 */
	public Document thisDocument() {
		intializeDocument();
		return documentExtendedCurrent.getDocument();
	}
//	/**
//	 * Returns the current ui document
//	 * @return current ui document
//	 */
//	public UIDocument ThisUIDocument(){
//		intializeDocument();
//		return uiDocumentCurrent;
//	}
//	/**
//	 * Determines if a ui document is available
//	 * @return true/false
//	 */
//	public boolean hasUIDocument(){
//		intializeUIDocument();
//		hasUIDocument = uiDocumentCurrent != null;
//	}
	/**
	 * Returns the current Session
	 * @return current Session
	 */
	public Session thisSession() {
		intializeSession();
		return sessionCurrent;
	}
	/**
	 * Returns the current Users Name object 
	 * @return current user Name object
	 */
	public Name currentUser(){
		intializeName();
		return nameCurrent;
	}
	/**
	 * Returns the current users common name
	 * @return current users common name
	 */
	public String currentUserCommon(){
		intializeName();
		try {
			return nameCurrent.getCommon();
		} catch (NotesException e) {
			return "";
		}
	}
	/**
	 * Returns the current users abbreviated name
	 * @return current users abbreviated name
	 */
	public String currentUserAbbreviated(){
		intializeName();
		try {
			return nameCurrent.getAbbreviated();
		} catch (NotesException e) {
			return "";
		}
	}
}
</textarea>
<h3>Java DocumentExtended</h3>
<a href="javascript:highlight(3)"> Select All</a><BR><BR>
<textarea rows="20" cols=60" wrap="virtual" class="codebox200" id="FormulaCodeBlock3" onFocus="javascript:highlight(3)" title="Use the Select All link above to select all the text.">
package com.ChadSmiley.domino.Extended; 
 
import java.util.Vector;
 
import lotus.domino.Document;
import lotus.domino.NotesException;
 
/**
 * A basic class to extend the NotesDocument class to reduce
 * code and improve error checking
 * 
 * @author Chad Schelfhout http://www.chadsmiley.com
 * @version 1.1
 * 
 * @history	1.0 Created in LotusScript
 * 			1.1 Created in Java
 */
public class DocumentExtended {
	private Document pDoc = null;
 
	/**
	 * Determines if the Notes Document has been Set
	 * @return boolean
	 */
	public boolean hasDoc() {
		return pDoc != null;
	}
	/**
	 * Determines if the Notes Document has been Set
	 * @return boolean
	 */
	public boolean hasDocument() {
		return pDoc != null;
	}
 
	/**
	 * Returns the a Notes Document.
	 * @return Document
	 */
	public Document getDoc() {
		return pDoc;
	}
	/**
	 * Returns the a Notes Document.
	 * @return Document
	 */
	public Document getDocument() {
		return pDoc;
	}
 
	/**
	 * Sets the Notes Document.
	 * @param Doc The Notes Document to set
	 */
	public void setDoc(Document Doc) {
		this.pDoc = Doc;
	}
 
	/**
	 * Sets the Notes Document.
	 * @param Doc The Notes Document to set
	 */
	public void setDocument(Document Doc) {
		this.pDoc = Doc;
	}
 
	public String getFieldText( String fieldName ){
		try {
			if ( hasField( fieldName ) ){
				return pDoc.getFirstItem( fieldName ).getText();
			}else{
				return "";
			}
		} catch (Exception e) {
			return "";
		}
	}
 
	public void recycle(){
		try {
			if ( pDoc != null ){
				pDoc.recycle();
				pDoc = null;
			}
		} catch (Exception e) {
		}
	}
	public void finalize(){
		recycle();
	}
	/**
	 * Method hasField.
	 * @param FromURLField
	 * @return boolean
	 */
	public boolean hasField(String fieldName) {
		try {
			if( hasDocument() ){
					if ( pDoc.hasItem( fieldName ) ){
						return true;
					}
			}
			return false;
		} catch (NotesException e) {
			return false;
		}
	}
 
	/**
	 * Method getFieldValues.
	 * @param DynamicFormFIELD
	 * @return Vector
	 */
	public Vector getFieldValues(String fieldName) {
		try {
			if ( hasField( fieldName ) ){
				return pDoc.getFirstItem( fieldName ).getValues();
			}else{
				return new Vector();
			}
		} catch (NotesException e) {
			return new Vector();
		}
	}
}
Comments (10) Trackbacks (0)
  1. You did exactly what I’d been planning to do next: put in a dependency hierarchy to ensure that only the objects that are needed get initialized, based on which object is being accessed. Keeps the abstract class absolutely as lean as possible. I also agree that the properties are better as functions. Good work!

    I also like the idea of the NotesDocumentExtended class… there seems to be some duplication in the functions, though, i.e. setDoc() looks identical to setDocument(), same for hasDoc() and hasDocument(), Doc() and Document(), etc.

  2. I am glad you like it. The doc and document classes were purposely done just to accommodate everyone.

  3. Nice, but why are you using Let in your code?

  4. On the java stuff; some constructive criticism, honest

    1: You should only override finalize() when you really need to. see:
    http://www-128.ibm.com/developerworks/java/library/j-jtctips/j-jtc0319a.html

    If you use it for every doc you access then you are going to cause your GC to have to do a lot mroe work.

    2. If you want to have a recyle() method, you should drop your ref to the doc. You can’t do anything with it anyway. Just explicity set it to null.

    3. Urgh, methods with leading uppercase letters.

    Personaly I’d refactor the lazy init into the accessors and just call them. But that’s probably a style thang.

  5. Let provides additional readability: you can see at a glance that a statement is an assignment, not an evaluation, and that the assignment impacts a variable that is not an object reference (as opposed to Set). It takes less than a second to include each time, has no impact on performance, and saves time later when troubleshooting or modifying code. In other words, the benefits are the same as those gained by using intelligent naming for variables instead of one or two characters.

  6. @3 The let is the formal way of writting it. Most of the time you will not see it.

    @4 Thanks Kerr, The suggestions make sense, and I will make the changes. With regards to #2, Here is what Domino Designer Help says

    Java has no knowlege of the heavyweight back-end Domino Objects, only the lightweight Java objects representing them. Garbage collection has no effect on Domino Objects unless you first explicitly recycle them.
    If you appear to have memory problems, try recycle but adhere to the following guidelines:
    - Recycle an object only if it is no longer needed.
    - Recycle an object in the same thread in which it is created.
    - Recycling a parent recycles all the children.
    - In Session, call recycle() only after all other threads exit.
    - Where NotesThread.sinitThread() and NotesThread.stermThread() are used, call recycle() before stermThread.

  7. @6
    You missed the point I was making. After you have recycled the doc by calling doc.recycle() there is no reason to hold onto reference to the doc object. Once it’s been recycled you can’t use it for anything. therefore you may as well set you’re reference to null and allow the java object to availible for garbage collection.

    I was having a think about these classes and I’m not sure where I’d see using them would be that helpfull. Are you just trying to avoid writing the classic start to an agent’s NotesMain method? What are your real drivers? What would a simple agent look like with these classes and what would it look like without?

    You just eat the NotesExceptions, don’t even spit them out to a log, System.out or System.err. So how do you know what went wrong when something does go wrong?

    The accessor methods can return null so when you use them you can’t blindly assume that the value is not null, requiring you to check (before hand using the hasFoo() methods if you want).

    You really don’t need to worry about recycling docs unless you are dealing with a large number of them, say looping through a view where you get a handle to each doc. I’d be more conserned about accidentaly loosing reference to the DocumetnExtended object, having it gc’d and then finding the doc I have still got a handle to doesn’t work cause it’s been recycled. Remember session will recycle all its child objects when it’s recycled, which happens automaticaly in an agent.

    I really don’t want to come across as being negative, hopefully you will take these comments in the constructive manor in which they are meant. Again this is just my person opinion, so I’ll be checking back to see the counter comments

  8. @7 I fixed the recycle method, no I did not understand what you meant. I understand your point about the usage of NotesSystem in Java, because Session is available through the agent and if I would write something outside of Notes then the current database would not be applicable. So the NotesSystem needs a little more work

    Are you saying that you would never write an NotesDocumentExtended type class? Let’s just say that you would, could you post what it would look like or send me an e-mail. I would like see your implementation.

    Please keep the comments coming, that is why I take the time to have a blog is to learn from other people.

  9. I’d be very careful about what it was I was trying to achieve. I’ve certainly wanted to extend the NotesDocument class, and it’s sometimes a real pain that you can’t, but I can’t think of a good way to do it without writing a whole new wrapper to the entire API. If in an agent I was using a generic DocumentExtended object, I would still have to get the Document object and pass it in. What I’d want is a view extended that would give me DocumentExtended back, etc, etc. That’s a pretty big overhead. And you also need to ask yourself, why didn’t Lotus just make the java api that way. There must be something about what they’ve exposed that fits with Domino. Be careful of covering that up or you may find you need it at some point.

    What I have wanted to do in the past is extend the document so that it also has business methods, representing a particular type of document in my application, say UserProfile, Article, etc. So since I can’t extend the domino document I have to be able to pass in the document, either in the constructor or at some other point. I could then make all of my business objects extend that. In this way my DocumentExtended class would take a Document in the constructor, probably storing it in a final variable, just for good measure, and then implement lotus.domino.Document and pass all the calls through to the stored doc. My business classes would then extend the wrapper class and override and overload the methods as appropriate. Obviously I could organise this into farther hierarchies of business object.

    What I tend to do now is one of the following:

    Create the business objects and have them take a document in the constructor and have the business object know how to deal with the doc.

    or

    Have the business objects know nothing about domino and have data access objects that load and save them.

    What is the best way to do it? It all depends on how complex the application needs to be. For most little agents you can just access the doc. When you start having to create business objects, you will start to abstract the doc automatically, and in a way that is suitable for the app in question.

    A DocumentExtended class I used automatically on every agent? No.

  10. @9 These are some of the same thoughts that went through my mind when I was creating these classes. The question why Lotus did not add some of these methods is a good question. I can not answer why they did not, and I am not saying that they should, but they would be a ‘nice to have’.

    I would agree with you and from a web agent perspective I would typically access the document directly. On a scheduled agent running over all or some of the documents in a database a DocumentExtended and/or a ViewExtended could make the code cleaner and simpler. The only reason I say that is because they typically access more fields and more documents.

    I have not ventured out into the buisness object yet but I can see where you are going with them.


Leave a comment


No trackbacks yet.