Dim rtf As NotesRichTextItem 'Static hack
%REM ÷פߧ ___________________| Mb¤, 25.06.2005. |___________________ §ß¤×÷
---
--- Marko Bonaci, IBM PCLP Application developer
---
--- #### Multiway Tree ####
--- Also: n-ary tree, k-ary (k-way) tree
---
--- Script Library "libTree"
---
--- Script Library containing a n-ary tree implementation, which is used to represent a
--- hierarchy of NotesDocuments on the hierarchical view.
------------------------------------------------------------------------------------------------------------------
--- Definition: --- a multiway tree - is a tree with any number of children for each node.
--- --- a k-ary tree - is a tree with no more than k children for each node.
---
--- A k-ary tree may be thought of as a multiway tree limited to k children.
--- We can say our tree is a k-ary tree, cuz Lotus supports only 31 deep view level hierarchy.
---
--- Implementation is to have an array of child nodes at each node, rather than a fixed
--- number of children.
--- Class "Tree" represents tree structure whose every node is carrier of class "Container",
--- which is the data container and can be customized.
--- Class Container is pulled out from class TreeNode, although it could've been omitted
--- and data put directly in TreeNode. That was done to be able to customize data carrier
--- more easely (for a wide set of possibilities). I didn't want to restrict the fact that now any
--- data type can be represented potentialy, all considering what is the content of the
--- NotesDocument.
------------------------------------------------------------------------------------------------------------------
i.e.
O ( 1, 1 ) - this is the root - main tree node
| \
O O ( 2, 1 ), ( 2, 2 ) - two root's children
|
O____ ( 3, 1 ) - one grandchild
| \ \ \
O O O O ( 4, 1 ), ( 4, 2 ), ( 4, 3 ), ( 4, 4 ) - four grand-grandchildren
------------------------------------------------------------------------------------------------------------------
--- To succesfuly use this class you have to change only the following two lines of
--- private method processNode:
---
--- Call rtf.AppendText( Format$( iterator.n_data.doc.Created, "dd.mm.yyyy" ) & " " )
--- Call rtf.AppendText( iterator.n_data.doc.strDocType(0) )
---
--- Instead of "Created" place the name of the field that contains creation date
--- Instead of "strDocType" place the Form or other field that contains document type
--- Of course you're free to change this method to fit your specific needs.
%ENDREM ÷פߧ __________________________________________________________ §ß¤×÷
'-------------------------------------------------------------------------------------------------------------------------------------
Public Class Container
'-------------------------------------------------------------------------------------------------------------------------------------
Public doc As NotesDocument 'Document which the node represents
Public Sub New( doc As NotesDocument )
Set Me.doc = doc
End Sub
End Class
'-------------------------------------------------------------------------------------------------------------------------------------
Public Class TreeNode
'-------------------------------------------------------------------------------------------------------------------------------------
Public n_data As Container 'Structure - data carier
Public n_level As Integer 'Node's level in the tree
Public n_parent As TreeNode 'Pointer on parent node
Public n_children( ) As TreeNode 'Array of pointers on child nodes
Public Function isEqual( other As TreeNode ) As Integer
'We are establishing the rule that the nodes are equal if they point on the same NotesDocument
isEqual = ( Me.n_data.doc.UniversalID = other.n_data.doc.UniversalID )
End Function
End Class
'-------------------------------------------------------------------------------------------------------------------------------------
Public Class Tree
'-------------------------------------------------------------------------------------------------------------------------------------
Private t_db As NotesDatabase 'This db
Private t_root As TreeNode 'Reference on root - main tree node ( node at level 1 )
Private t_levelsCount As Integer 'Number of levels in the tree
Private t_nodesCount As Integer 'Number of nodes in the tree
Private t_nodesAtLevel( ) As Integer 'Number of nodes on every tree level
Declare Public Sub New( mainParent As NotesDocument )
Declare Public Sub printToRTItem( rt As NotesRichTextItem )
Declare Public Property Get nodesCount As Long
Declare Public Property Get nodesOnLevelCount( level As Integer ) As Long
Declare Private Sub initializeNode( curNode As TreeNode )
Declare Private Sub processNode( iterator As TreeNode )
Declare Private Sub sortLevel( level As Integer )
Declare Private Function isTheSameNode( tn1 As TreeNode, tn2 As TreeNode ) As Integer
'-------------------------------------------------------------------------------------------------------------------------------------
Public Sub New( mainParent As NotesDocument )
'Here we create tree and fill it with data
Dim i As Integer
Set t_db = mainParent.ParentDatabase
Set t_root = New TreeNode
Set t_root.n_data = New Container( mainParent ) '//// Root's Data
t_root.n_level = 1 'root's level is 1
t_nodesCount = 1
Dim c As NotesDocumentCollection
Dim tmpDoc As NotesDocument
Dim countChildren As Integer
'Children:
Set c = mainParent.Responses
If c Is Nothing Then Exit Sub
countChildren = c.Count
If countChildren = 0 Then Exit Sub
'Array-a initialization and data for root (level 1)
Redim t_nodesAtLevel( 1 To 2 )
t_nodesAtLevel( 1 ) = 1
t_nodesAtLevel( 2 ) = countChildren
Redim t_root.n_children( 1 To countChildren )
For i = 1 To countChildren
Set tmpDoc = c.GetNthDocument( i )
Dim tn As New TreeNode
Set tn.n_data = New Container( tmpDoc ) '//// Data of Root's Child
Set tn.n_parent = t_root '//// Parent of Root's Child's
tn.n_level = 2 '//// Level of Root's Child
Set t_root.n_children( i ) = tn '//// Root's Child
Call initializeNode( tn )
Next
End Sub
'-------------------------------------------------------------------------------------------------------------------------------------
Private Sub initializeNode( curNode As TreeNode )
%REM Recursively fill the tree nodes with elements ( all descendants )
For every node:
¤ Create temporary TreeNode in memory,
¤ Tell him who is his parent
¤ Tell him who is his document
¤ Tell him on which level he is
¤ Assign his children to him
%ENDREM
'current node has the level higher by 1 in relation to his parent
curNode.n_level = curNode.n_parent.n_level + 1
'number of levels is the current level (always max because of recursion)
t_levelsCount = curNode.n_level
'increment number of nodes
t_nodesCount = t_nodesCount + 1
Dim c As NotesDocumentCollection
Dim tmpDoc As NotesDocument
Dim countChildren As Integer, i As Integer
'Children:
Set tmpDoc = curNode.n_data.doc
Set c = tmpDoc.Responses
If c Is Nothing Then Exit Sub
countChildren = c.Count
If countChildren = 0 Then Exit Sub
'Levels:
If Ubound( t_nodesAtLevel ) <> curNode.n_level + 1 Then
Redim Preserve t_nodesAtLevel( 1 To curNode.n_level + 1 )
End If
t_nodesAtLevel( curNode.n_level + 1 ) = countChildren
Redim curNode.n_children( 1 To countChildren )
For i = 1 To countChildren
Set tmpDoc = c.GetNthDocument( i )
Dim tn As New TreeNode
Set tn.n_data = New Container( tmpDoc ) '//// Child's Data
Set tn.n_parent = curNode '//// Child's Parent
Set curNode.n_children( i ) = tn '//// Child's Child
Call initializeNode( tn )
Next
End Sub
'-------------------------------------------------------------------------------------------------------------------------------------
Private Function areNodesSame( tn1 As TreeNode, tn2 As TreeNode ) As Integer
'We are establishing the rule that the nodes are equal if they point on the same NotesDocument
areNodesSame = tn1.n_data.doc.UniversalID = tn2.n_data.doc.UniversalID
End Function
'-------------------------------------------------------------------------------------------------------------------------------------
Public Property Get nodesCount As Long
'Returns total number of nodes in the tree
nodesCount = t_nodesCount
End Property
'-------------------------------------------------------------------------------------------------------------------------------------
Public Property Get nodesOnLevelCount( level As Integer ) As Long
'Returns number of nodes on level
nodesOnLevelCount = t_nodesAtLevel( level )
End Property
'-------------------------------------------------------------------------------------------------------------------------------------
Public Sub printToRTItem( rt As NotesRichTextItem )
Dim iterator As TreeNode
Set rtf = rt
Set iterator = t_root
Call processNode( iterator )
End Sub
'-------------------------------------------------------------------------------------------------------------------------------------
Private Sub processNode( iterator As TreeNode )
Dim i As Integer
'Start writing to RTF **************************************************
Call rtf.AddNewline( 1 )
' Call rtf.AppendText( "|" )
' Call rtf.AddTab( iterator.n_level )
Call rtf.AppendText( Space$( 4 * ( iterator.n_level - 1 ) ) )
' Call rtf.AppendText( String$( 4 * ( iterator.n_level - 1 ), Asc( "-" ) ) )
Call rtf.AppendText( Format$( iterator.n_data.doc.Created, "dd.mm.yyyy" ) & " " )
Call rtf.AppendText( iterator.n_data.doc.strDocType(0) )
Call rtf.AppendText( " ----> " )
Call rtf.AppendDocLink( iterator.n_data.doc, "Link na dokument" )
'End writing to RTF **************************************************
If iterator.n_data.doc.Responses.Count = 0 Then Exit Sub
For i = 1 To Ubound( iterator.n_children )
Call processNode( iterator.n_children( i ) )
Next
End Sub
'-------------------------------------------------------------------------------------------------------------------------------------
End Class