Bitwyse1
Bitwyse1

Reputation: 339

Javascript vs. Lotusscript

I am hoping someone can put me out of my misery here. I rewrote a LotusScript function in JavaScript and it is not working as it should be. I can't look at this thing anymore. I"m hoping someone can help me figure this out.

The function takes a name of a group and an address book db object. It fetches and returns all the members of that group including nested groups. It works great in the Lotusscript version but not in the Javascript version. It's something to do with the recursive function and the index into the array's.

If you create two groups. Put 10 names in the first group and 5 names in the second group. Note, Name the second group with a leading # to make it sort to the top of the first group

group-A 1group-A bla bla2 bla3 bla4 bla5 bla6 bla7 bla8 bla9 bla10

1group-A other1 other2 other3 other4 other5

In the Javascript version when you pass the function group-A it returns 10 names. Five from the second group and the second five from the first group.

Here is the code for the lotusscript version

Function LibGetGroupMembers( groupName As String, addressBook As NotesDatabase ) As Variant

'  This Function takes a passed in group name and gets all the members of that group.
'  Not a big whoop until you consider nested group names.  This is a recursive routine.
'
 '   Inputs  :  Name of the group to fetch the members of.
'
'  Uses     :  Global objects
 '
 '  Outputs : Returns an array of members
 '
 '  History:
 '  02.19.2001  - Steven Rieger           :  Created Function.

Dim groupView As NotesView
Dim groupMainDoc As NotesDocument
Dim groupMembers As Variant
Dim nestedGroupMembers As Variant
Dim arrayOfMembers() As String
Dim mainIndex As Integer
Dim nestedIndex As Integer
Dim resultIndex As Integer


On Error Goto ErrorHandling

gLibObjectName = CStr( GetThreadInfo(1) ) & " - " & gLibDatabaseNamePath
gLibErrorMessage = "Begin " & gLibObjectName
Call LibLogErrorPushCallingPgm ( gLibErrorMessage  )
Print( gLibErrorMessage )

gLibAdditionalErrorMessage = "Fetching Group View From NAB"
Set groupView = addressBook.GetView( "($VIMGroups)" )
If( groupView Is Nothing ) Then
    Call LibLogError( "Error: Un-able to get view from address book", gLibErrorMessage )
    Exit Function
End If

gLibAdditionalErrorMessage = "Fetching Group Main Document " & groupName    
Set groupMainDoc = groupView.GetDocumentByKey( groupName, True )

resultIndex = 0
Redim arrayOfMembers( 0 )

'  Did we find a matching group document?
If Not( groupMainDoc Is Nothing ) Then
    If Not( Iselement ( gListOfGroupNames( Lcase( groupName ) ) ) ) Then
'           Print( "Processing Group: " & groupName )
        gListOfGroupNames( Lcase( groupName ) ) = " "
        groupMembers=groupMainDoc.GetItemValue( "Members" )
        For mainIndex = Lbound( groupMembers ) To Ubound( groupMembers)
            nestedGroupMembers= LibGetGroupMembers( groupMembers( mainIndex ), addressBook )
            If( nestedGroupMembers(0) = "" ) Then
                If( groupMembers( mainIndex ) <> "" ) Then
                    Redim Preserve arrayOfMembers( Ubound( arrayOfMembers ) + 1) 
                    arrayOfMembers( resultIndex ) = groupMembers( mainIndex )
                    resultIndex = resultIndex + 1
                End If
            Else
                Redim Preserve arrayOfMembers( Ubound( nestedGroupMembers ) + resultIndex ) 
                For nestedIndex = Lbound( nestedGroupMembers ) To Ubound( nestedGroupMembers )
                    arrayOfMembers( resultIndex ) = nestedGroupMembers( nestedIndex )
                    resultIndex = resultIndex + 1
                Next
            End If
        Next
        If( arrayOfMembers( Ubound( arrayOfMembers ) ) = "" And Ubound( arrayOfMembers ) > 0 ) Then
            Redim Preserve arrayOfMembers( Ubound( arrayOfMembers ) - 1 ) 
        End If
    Else
        groupName = "*** Circular Group: " & groupName & " ***"
    End If
End If

LibGetGroupMembers = arrayOfMembers

Goto Bye

ErrorHandling :
Call LibLogError( "Error: " & Err( ) & ": " & Error( ) & Chr( 13 ) & Chr( 13 ) & "Occured in Module " & CStr( GetThreadInfo(1) ) & " at Line Number: " & Erl(), CStr( GetThreadInfo(1) & " - " & gLibDatabaseNamePath ) )
Resume Bye     

Bye: 

gLibAdditionalErrorMessage = "End " & CStr( GetThreadInfo(1) & " - " & gLibDatabaseNamePath ) 
' This will pop the last entry of the stack!
Call libLogErrorPopCallingPgm()
Print( gLibAdditionalErrorMessage )

End Function

HERE IS THE CODE FOR THE JAVASCRIPT FUNCTION

function jsLibGetGroupMembers( groupName:string, addressBook:NotesDatabase )
{
//  This Function takes a passed in group name and gets all the members of that group.
//  Not a big whoop until you consider nested group names.  This is a recursive routine.
//
//   Inputs  :  Name of the group to fetch the members of.
//
//  Uses     :  Global objects
//
//  Outputs : Returns an array of members
//
//  History:
//  02.19.2001  - Steven Rieger           :  Created Function.

var groupView:NotesView;
var groupMainDoc:NotesDocument;
var groupMembers:java.util.Vector;
var nestedGroupMembers = new Array();
var arrayOfMembers = new Array();
var mainIndex:Integer;
var nestedIndex:Integer;
var resultIndex:Integer;

print( "Begin jsLibGetGroupMembers - Passed in Name: " + groupName  );
groupView = addressBook.getView( "($VIMGroups)" )
if( groupView == null ) 
{
    print( "group document not found!" );
    return nestedGroupMembers;
}

//  gLibAdditionalErrorMessage = "Fetching Group Main Document " & groupName    
groupMainDoc = groupView.getDocumentByKey( groupName, true )

resultIndex = 0

//  Did we find a matching group document?
if( groupMainDoc != null ) 
{   //  is the group name already in the global list of groups?
    if( !(groupName.toLowerCase() in gListOfGroupNames ) )  
    {
        //  Add the group name to the globla list of groups to prevent processing duplicate groups
        gListOfGroupNames[ groupName.toLowerCase() ] = " "
        groupMembers = groupMainDoc.getItemValue( "Members" );
        for( groupMemberIndex = 0; groupMemberIndex < groupMembers.length; groupMemberIndex++ )
        {
            //  Fetch any nested group members if the current member is a group name
            nestedGroupMembers = jsLibGetGroupMembers( groupMembers[groupMemberIndex], addressBook );
            if ( typeof nestedGroupMembers[0] === 'undefined' || nestedGroupMembers[0] === null )
            {
                //  If no group was found and we have an actual member name add it to the list.
                if( groupMembers[groupMemberIndex].length > 0 ) 
                {
                    print( "adding user to array: " + groupMembers[groupMemberIndex] + " resultIndex = " + resultIndex );
                    arrayOfMembers[resultIndex] = groupMembers[groupMemberIndex];
                    resultIndex += 1;
                }
                else
                {
                    print( "No User to Add!");
                }
            }
            else
            {
                //  If this was a nested group we found add the members of that group to the list
                for( nestedGroupMemberIndex = 0; nestedGroupMemberIndex < nestedGroupMembers.length; nestedGroupMemberIndex++ )
                {
                    print( "adding nested user to array: " + nestedGroupMembers[nestedGroupMemberIndex] + " resultIndex = " + resultIndex );
                    arrayOfMembers[ resultIndex ] = nestedGroupMembers[nestedGroupMemberIndex];
                    resultIndex += 1;
                }
            } 
        }
    }
    else
        print( "Duplicate Group!");
}
else
{
    print( "no group doc found!" );
}
print( "exiting jsLibGetGroupMembers: " + "\n" + arrayOfMembers );
return arrayOfMembers;

}

Upvotes: 1

Views: 1435

Answers (1)

Tim Tripcony
Tim Tripcony

Reputation: 8086

This answer will no doubt seem ironic given my recent blog post, but here's an SSJS implementation that will return a sorted list of all members of a group hierarchy:

var AtFunctions = (function() {

    function getGroupNames (groupRecord, serverName) {
        var result = new java.util.TreeSet();
        if (groupRecord) {
            for (var eachMember in groupRecord.getItemValue("Members")) {
                var nestedGroupRecord = getGroupRecord(eachMember, serverName);
                if (nestedGroupRecord) {
                    result.addAll(getGroupNames(nestedGroupRecord, serverName));
                    nestedGroupRecord.recycle();
                } else {
                    result.add(eachMember);
                }
            }
        }
        return result;
    }

    function getGroupRecord (groupName, serverName) {
        var result = null;
        try {
            serverName = (serverName || session.getServerName());
            var NAB = session.getDatabase(serverName, "names.nsf");
            var groupView = NAB.getView("($VIMGroups)");
            result = groupView.getDocumentByKey(groupName, true);
        } catch (e) {
            print("Error getting group record: " + e.toString());
        }
        return result;
    }

    var API = {
        expandNameList: function(groupName, serverName) {
            var result = new java.util.TreeSet();
            if (groupName) {
                var groupRecord = getGroupRecord(groupName, serverName);
                if (groupRecord) {
                    result.addAll(getGroupNames(groupRecord, serverName));
                    groupRecord.recycle();
                }
            }
            return result;
        }
    };

    return API;

})();

var @ExpandNameList = AtFunctions.expandNameList;

The variable alias at the end will allow you to treat this as a custom @Function, if desired, so you can call this one of two ways:

var groupMembers = @ExpandNameList("All Employees");
var groupMembers = AtFunctions.expandNameList("All Employees");
// in either syntax, you can optionally pass a server name as a second argument

NOTE: it's using the Java TreeSet class instead of JavaScript arrays, which has the following benefits:

  1. It's automatically sorted. You might not want this, but for this type of operation, it's often useful.
  2. It automatically ignores duplicates, so you should only get one instance of each name even if the same member exists in multiple subgroups.
  3. Syntactically, it's just so much easier to manipulate than an array.

Enjoy. :)

Upvotes: 8

Related Questions