This is an automated email from the ASF dual-hosted git repository.

pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new d2fcfb0cc3 NIFI-14350: Adding filters for roles and statuses on Get 
Box File Collaborators processor
d2fcfb0cc3 is described below

commit d2fcfb0cc35ed95b2f7b5e121b0516455390c590
Author: Noah Cover <[email protected]>
AuthorDate: Mon Mar 10 10:59:09 2025 -0700

    NIFI-14350: Adding filters for roles and statuses on Get Box File 
Collaborators processor
    
    Signed-off-by: Pierre Villard <[email protected]>
    
    This closes #9792.
---
 .../processors/box/GetBoxFileCollaborators.java    | 174 +++++++++++++++++----
 .../box/GetBoxFileCollaboratorsTest.java           | 154 ++++++++++++++++--
 2 files changed, 285 insertions(+), 43 deletions(-)

diff --git 
a/nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/main/java/org/apache/nifi/processors/box/GetBoxFileCollaborators.java
 
b/nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/main/java/org/apache/nifi/processors/box/GetBoxFileCollaborators.java
index 26211d334a..25a8682a26 100644
--- 
a/nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/main/java/org/apache/nifi/processors/box/GetBoxFileCollaborators.java
+++ 
b/nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/main/java/org/apache/nifi/processors/box/GetBoxFileCollaborators.java
@@ -41,6 +41,7 @@ import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.processor.util.StandardValidators;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -60,10 +61,20 @@ import static 
org.apache.nifi.processors.box.BoxFileAttributes.ID_DESC;
 @SeeAlso({FetchBoxFile.class, ListBoxFile.class})
 @WritesAttributes({
         @WritesAttribute(attribute = ID, description = ID_DESC),
+        // Always present (backward compatibility attributes)
         @WritesAttribute(attribute = "box.collaborations.<status>.users.ids", 
description = "Comma-separated list of user collaborator IDs by status"),
         @WritesAttribute(attribute = "box.collaborations.<status>.groups.ids", 
description = "Comma-separated list of group collaborator IDs by status"),
         @WritesAttribute(attribute = 
"box.collaborations.<status>.users.emails", description = "Comma-separated list 
of user collaborator emails by status"),
         @WritesAttribute(attribute = 
"box.collaborations.<status>.groups.emails", description = "Comma-separated 
list of group collaborator emails by status"),
+        // New attributes (only present when both Roles and Statuses 
properties are set)
+        @WritesAttribute(attribute = 
"box.collaborations.<status>.<role>.users.ids", description = "Comma-separated 
list of user collaborator IDs by status and role. " +
+                "Only present when both Roles and Statuses properties are 
set."),
+        @WritesAttribute(attribute = 
"box.collaborations.<status>.<role>.users.logins", description = 
"Comma-separated list of user collaborator logins by status and role. " +
+                "Only present when both Roles and Statuses properties are 
set."),
+        @WritesAttribute(attribute = 
"box.collaborations.<status>.<role>.groups.ids", description = "Comma-separated 
list of group collaborator IDs by status and role. " +
+                "Only present when both Roles and Statuses properties are 
set."),
+        @WritesAttribute(attribute = 
"box.collaborations.<status>.<role>.groups.emails", description = 
"Comma-separated list of group collaborator emails by status and role. " +
+                "Only present when both Roles and Statuses properties are 
set."),
         @WritesAttribute(attribute = "box.collaborations.count", description = 
"Total number of collaborations on the file"),
         @WritesAttribute(attribute = ERROR_CODE, description = 
ERROR_CODE_DESC),
         @WritesAttribute(attribute = ERROR_MESSAGE, description = 
ERROR_MESSAGE_DESC)
@@ -79,6 +90,24 @@ public class GetBoxFileCollaborators extends 
AbstractProcessor {
             .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
             .build();
 
+    public static final PropertyDescriptor ROLES = new 
PropertyDescriptor.Builder()
+            .name("Roles")
+            .description("A comma-separated list of collaboration roles to 
retrieve. Available roles: editor, viewer, previewer, " +
+                    "uploader, previewer uploader, viewer uploader, co-owner, 
owner. If not specified, no filtering by role will be applied.")
+            .required(false)
+            
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
+    public static final PropertyDescriptor STATUSES = new 
PropertyDescriptor.Builder()
+            .name("Statuses")
+            .description("A comma-separated list of collaboration statuses to 
retrieve. Available statuses: accepted, pending, rejected. " +
+                    "If not specified, no filtering by status will be 
applied.")
+            .required(false)
+            
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
     public static final Relationship REL_SUCCESS = new Relationship.Builder()
             .name("success")
             .description("FlowFiles that have been successfully processed will 
be routed to this relationship")
@@ -102,7 +131,9 @@ public class GetBoxFileCollaborators extends 
AbstractProcessor {
 
     private static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = 
List.of(
             BoxClientService.BOX_CLIENT_SERVICE,
-            FILE_ID
+            FILE_ID,
+            ROLES,
+            STATUSES
     );
 
     private volatile BoxAPIConnection boxAPIConnection;
@@ -131,8 +162,20 @@ public class GetBoxFileCollaborators extends 
AbstractProcessor {
         }
 
         final String fileId = 
context.getProperty(FILE_ID).evaluateAttributeExpressions(flowFile).getValue();
+
+        // Get optional properties
+        String roles = null;
+        if (context.getProperty(ROLES).isSet()) {
+            roles = 
context.getProperty(ROLES).evaluateAttributeExpressions(flowFile).getValue();
+        }
+
+        String statuses = null;
+        if (context.getProperty(STATUSES).isSet()) {
+            statuses = 
context.getProperty(STATUSES).evaluateAttributeExpressions(flowFile).getValue();
+        }
+
         try {
-            flowFile = fetchCollaborations(fileId, session, flowFile);
+            flowFile = fetchCollaborations(fileId, roles, statuses, session, 
flowFile);
             session.transfer(flowFile, REL_SUCCESS);
         } catch (final BoxAPIResponseException e) {
             flowFile = session.putAttribute(flowFile, ERROR_MESSAGE, 
e.getMessage());
@@ -164,52 +207,123 @@ public class GetBoxFileCollaborators extends 
AbstractProcessor {
     }
 
     private FlowFile fetchCollaborations(final String fileId,
+                                         final String roleFilter,
+                                         final String statusFilter,
                                          final ProcessSession session,
                                          final FlowFile flowFile) {
+
         final BoxFile boxFile = getBoxFile(fileId);
         final Iterable<BoxCollaboration.Info> collaborations = 
boxFile.getAllFileCollaborations();
 
-        final List<String> statusTypes = List.of(
-                "accepted.users", "accepted.groups",
-                "pending.users", "pending.groups",
-                "rejected.users", "rejected.groups"
-        );
+        final Set<String> allowedRoles = parseFilter(roleFilter);
+        final Set<String> allowedStatuses = parseFilter(statusFilter);
+
+        final Map<String, List<String>> attributeValues = new HashMap<>();
+        int count = processCollaborations(collaborations, allowedRoles, 
allowedStatuses, attributeValues);
+
+        final Map<String, String> attributes = new HashMap<>();
+        attributes.put(ID, fileId);
+        attributes.put("box.collaborations.count", String.valueOf(count));
+
+        // Add all collected attributes with prefix
+        attributeValues.forEach((key, values) ->
+                addAttributeIfNotEmpty(attributes, "box.collaborations." + 
key, values));
 
-        final Map<String, List<String>> collabIdMap = statusTypes.stream()
-                .collect(Collectors.toMap(key -> key, key -> new 
ArrayList<>()));
+        return session.putAllAttributes(flowFile, attributes);
+    }
 
-        final Map<String, List<String>> collabEmailMap = statusTypes.stream()
-                .collect(Collectors.toMap(key -> key, key -> new 
ArrayList<>()));
+    /**
+     * Parses a comma-separated string filter into a set of trimmed, lowercase 
values.
+     *
+     * @param filter the comma-separated filter string
+     * @return a Set of filter values, or null if the input was null
+     */
+    private Set<String> parseFilter(final String filter) {
+        if (filter == null) {
+            return null;
+        }
+        return Arrays.stream(filter.toLowerCase().split(","))
+                .map(String::trim)
+                .collect(Collectors.toSet());
+    }
 
+    /**
+     * Processes a list of collaborations, applying role and status filters,
+     * and populates the attributeValues map with collaboration attributes.
+     *
+     * @param collaborations  the collaborations to process
+     * @param allowedRoles    the set of allowed roles, or null for no 
filtering
+     * @param allowedStatuses the set of allowed statuses, or null for no 
filtering
+     * @param attributeValues the map to populate with collaboration attributes
+     * @return the total count of collaborations processed (before filtering)
+     */
+    private int processCollaborations(final Iterable<BoxCollaboration.Info> 
collaborations,
+                                      final Set<String> allowedRoles,
+                                      final Set<String> allowedStatuses,
+                                      final Map<String, List<String>> 
attributeValues) {
         int count = 0;
-        for (final BoxCollaboration.Info collabInfo : collaborations) {
-            count++;
 
-            boolean isUser = 
collabInfo.getAccessibleBy().getType().equals(BoxCollaborator.CollaboratorType.USER);
-            final String collabId = collabInfo.getAccessibleBy().getID();
-            final String status = 
collabInfo.getStatus().toString().toLowerCase();
-            final String type = isUser ? "users" : "groups";
-            final String key = status + "." + type;
+        for (final BoxCollaboration.Info collab : collaborations) {
+            count++;
 
-            collabIdMap.get(key).add(collabId);
+            final String status = collab.getStatus().toString().toLowerCase();
+            final String role = collab.getRole().toString().toLowerCase();
 
-            final String email = collabInfo.getAccessibleBy().getLogin();
-            if (email != null) {
-                collabEmailMap.get(key).add(email);
+            // Skip if not in allowed roles or statuses
+            if ((allowedRoles != null && !allowedRoles.contains(role))
+                    || (allowedStatuses != null && 
!allowedStatuses.contains(status))) {
+                continue;
             }
+
+            // Process this collaboration's attributes
+            processCollaboration(collab, status, role, allowedRoles != null && 
allowedStatuses != null, attributeValues);
         }
 
-        final Map<String, String> attributes = new HashMap<>();
-        attributes.put(ID, fileId);
-        attributes.put("box.collaborations.count", String.valueOf(count));
+        return count;
+    }
 
-        collabIdMap.forEach((key, value) ->
-                addAttributeIfNotEmpty(attributes, "box.collaborations." + key 
+ ".ids", value));
+    /**
+     * Processes a single collaboration and adds its attributes to the 
attributeValues map.
+     *
+     * @param collab          the collaboration to process
+     * @param status          the lowercase status of the collaboration
+     * @param role            the lowercase role of the collaboration
+     * @param useNewFormat    whether to include new format attributes (with 
role)
+     * @param attributeValues the map to populate with collaboration attributes
+     */
+    private void processCollaboration(final BoxCollaboration.Info collab,
+                                      final String status,
+                                      final String role,
+                                      final boolean useNewFormat,
+                                      final Map<String, List<String>> 
attributeValues) {
+        final boolean isUser = 
collab.getAccessibleBy().getType().equals(BoxCollaborator.CollaboratorType.USER);
+        final String entityType = isUser ? "users" : "groups";
+        final String collabId = collab.getAccessibleBy().getID();
+        final String login = collab.getAccessibleBy().getLogin();
 
-        collabEmailMap.forEach((key, value) ->
-                addAttributeIfNotEmpty(attributes, "box.collaborations." + key 
+ ".emails", value));
+        // Add backward compatibility attributes
+        addToMap(attributeValues, status + "." + entityType + ".ids", 
collabId);
 
-        return session.putAllAttributes(flowFile, attributes);
+        if (login != null) {
+            final String loginKey = isUser ? status + ".users.emails" : status 
+ ".groups.emails";
+            addToMap(attributeValues, loginKey, login);
+        }
+
+        // Add new format attributes if filters were provided
+        if (useNewFormat) {
+            addToMap(attributeValues, status + "." + role + "." + entityType + 
".ids", collabId);
+
+            if (login != null) {
+                final String loginKey = isUser
+                        ? status + "." + role + ".users.logins" :
+                        status + "." + role + ".groups.emails";
+                addToMap(attributeValues, loginKey, login);
+            }
+        }
+    }
+
+    private void addToMap(final Map<String, List<String>> map, final String 
key, final String value) {
+        map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
     }
 
     private void addAttributeIfNotEmpty(final Map<String, String> attributes,
diff --git 
a/nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/test/java/org/apache/nifi/processors/box/GetBoxFileCollaboratorsTest.java
 
b/nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/test/java/org/apache/nifi/processors/box/GetBoxFileCollaboratorsTest.java
index 0e374ca33d..b07e4e6af6 100644
--- 
a/nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/test/java/org/apache/nifi/processors/box/GetBoxFileCollaboratorsTest.java
+++ 
b/nifi-extension-bundles/nifi-box-bundle/nifi-box-processors/src/test/java/org/apache/nifi/processors/box/GetBoxFileCollaboratorsTest.java
@@ -36,6 +36,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
@@ -104,6 +106,9 @@ public class GetBoxFileCollaboratorsTest extends 
AbstractBoxFileTest {
     @Test
     void testGetCollaborationsFromFlowFileAttribute() {
         testRunner.setProperty(GetBoxFileCollaborators.FILE_ID, "${box.id}");
+        testRunner.setProperty(GetBoxFileCollaborators.ROLES, "editor");
+        testRunner.setProperty(GetBoxFileCollaborators.STATUSES, 
"accepted,pending");
+
         final MockFlowFile inputFlowFile = new MockFlowFile(0);
         final Map<String, String> attributes = new HashMap<>();
         attributes.put(BoxFileAttributes.ID, TEST_FILE_ID);
@@ -119,19 +124,49 @@ public class GetBoxFileCollaboratorsTest extends 
AbstractBoxFileTest {
         final MockFlowFile flowFilesFirst = flowFiles.getFirst();
 
         flowFilesFirst.assertAttributeEquals("box.collaborations.count", "5");
-        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.users.ids", 
TEST_USER_ID_1 + "," + TEST_USER_ID_2);
-        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.groups.ids", 
TEST_GROUP_ID_1);
-        
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.users.ids", 
TEST_USER_ID_3);
-        
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.groups.ids", 
TEST_GROUP_ID_2);
-        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.users.emails",
 TEST_USER_EMAIL_1 + "," + TEST_USER_EMAIL_2);
-        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.groups.emails",
 TEST_GROUP_EMAIL_1);
-        
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.users.emails", 
TEST_USER_EMAIL_3);
-        
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.groups.emails",
 TEST_GROUP_EMAIL_2);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.users.ids",
 TEST_USER_ID_1 + "," + TEST_USER_ID_2);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.groups.ids",
 TEST_GROUP_ID_1);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.editor.users.ids",
 TEST_USER_ID_3);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.editor.groups.ids",
 TEST_GROUP_ID_2);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.users.logins",
 TEST_USER_EMAIL_1 + "," + TEST_USER_EMAIL_2);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.groups.emails",
 TEST_GROUP_EMAIL_1);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.editor.users.logins",
 TEST_USER_EMAIL_3);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.editor.groups.emails",
 TEST_GROUP_EMAIL_2);
     }
 
     @Test
     void testGetCollaborationsFromProperty() {
         testRunner.setProperty(GetBoxFileCollaborators.FILE_ID, TEST_FILE_ID);
+        testRunner.setProperty(GetBoxFileCollaborators.ROLES, "editor");
+        testRunner.setProperty(GetBoxFileCollaborators.STATUSES, "accepted");
+
+        setupMockCollaborations();
+
+        final MockFlowFile inputFlowFile = new MockFlowFile(0);
+        testRunner.enqueue(inputFlowFile);
+        testRunner.run();
+
+        
testRunner.assertAllFlowFilesTransferred(GetBoxFileCollaborators.REL_SUCCESS, 
1);
+        final List<MockFlowFile> flowFiles = 
testRunner.getFlowFilesForRelationship(GetBoxFileCollaborators.REL_SUCCESS);
+        final MockFlowFile flowFilesFirst = flowFiles.getFirst();
+
+        flowFilesFirst.assertAttributeEquals("box.collaborations.count", "5");
+        // New format attributes
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.users.ids",
 TEST_USER_ID_1 + "," + TEST_USER_ID_2);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.groups.ids",
 TEST_GROUP_ID_1);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.users.logins",
 TEST_USER_EMAIL_1 + "," + TEST_USER_EMAIL_2);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.groups.emails",
 TEST_GROUP_EMAIL_1);
+        // For pending status items, they shouldn't appear since we're only 
checking accepted status
+        
flowFilesFirst.assertAttributeNotExists("box.collaborations.pending.editor.users.ids");
+        
flowFilesFirst.assertAttributeNotExists("box.collaborations.pending.editor.groups.ids");
+        
flowFilesFirst.assertAttributeNotExists("box.collaborations.pending.editor.users.logins");
+        
flowFilesFirst.assertAttributeNotExists("box.collaborations.pending.editor.groups.emails");
+    }
+
+    @Test
+    void testGetCollaborationsBackwardCompatibility() {
+        testRunner.setProperty(GetBoxFileCollaborators.FILE_ID, TEST_FILE_ID);
+        // Don't set ROLES or STATUSES properties to test backward 
compatibility mode
 
         setupMockCollaborations();
 
@@ -144,6 +179,7 @@ public class GetBoxFileCollaboratorsTest extends 
AbstractBoxFileTest {
         final MockFlowFile flowFilesFirst = flowFiles.getFirst();
 
         flowFilesFirst.assertAttributeEquals("box.collaborations.count", "5");
+        // Backward compatibility attributes should exist
         
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.users.ids", 
TEST_USER_ID_1 + "," + TEST_USER_ID_2);
         
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.groups.ids", 
TEST_GROUP_ID_1);
         
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.users.ids", 
TEST_USER_ID_3);
@@ -152,6 +188,12 @@ public class GetBoxFileCollaboratorsTest extends 
AbstractBoxFileTest {
         
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.groups.emails",
 TEST_GROUP_EMAIL_1);
         
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.users.emails", 
TEST_USER_EMAIL_3);
         
flowFilesFirst.assertAttributeEquals("box.collaborations.pending.groups.emails",
 TEST_GROUP_EMAIL_2);
+
+        // New format attributes should not exist
+        
flowFilesFirst.assertAttributeNotExists("box.collaborations.accepted.editor.users.ids");
+        
flowFilesFirst.assertAttributeNotExists("box.collaborations.accepted.editor.groups.ids");
+        
flowFilesFirst.assertAttributeNotExists("box.collaborations.accepted.editor.users.logins");
+        
flowFilesFirst.assertAttributeNotExists("box.collaborations.accepted.editor.groups.emails");
     }
 
     @Test
@@ -172,6 +214,31 @@ public class GetBoxFileCollaboratorsTest extends 
AbstractBoxFileTest {
         flowFilesFirst.assertAttributeEquals(BoxFileAttributes.ERROR_MESSAGE, 
"API Error [404]");
     }
 
+    @Test
+    void testGetCollaborationsWithMultipleRoles() {
+        testRunner.setProperty(GetBoxFileCollaborators.FILE_ID, TEST_FILE_ID);
+        testRunner.setProperty(GetBoxFileCollaborators.ROLES, "editor,viewer");
+        testRunner.setProperty(GetBoxFileCollaborators.STATUSES, "accepted");
+
+        setupMockCollaborationsWithMultipleRoles();
+
+        final MockFlowFile inputFlowFile = new MockFlowFile(0);
+        testRunner.enqueue(inputFlowFile);
+        testRunner.run();
+
+        
testRunner.assertAllFlowFilesTransferred(GetBoxFileCollaborators.REL_SUCCESS, 
1);
+        final List<MockFlowFile> flowFiles = 
testRunner.getFlowFilesForRelationship(GetBoxFileCollaborators.REL_SUCCESS);
+        final MockFlowFile flowFilesFirst = flowFiles.getFirst();
+
+        flowFilesFirst.assertAttributeEquals("box.collaborations.count", "5");
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.users.ids",
 TEST_USER_ID_1 + "," + TEST_USER_ID_2);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.groups.ids",
 TEST_GROUP_ID_1);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.viewer.users.ids",
 TEST_USER_ID_3);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.users.logins",
 TEST_USER_EMAIL_1 + "," + TEST_USER_EMAIL_2);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.editor.groups.emails",
 TEST_GROUP_EMAIL_1);
+        
flowFilesFirst.assertAttributeEquals("box.collaborations.accepted.viewer.users.logins",
 TEST_USER_EMAIL_3);
+    }
+
     @Test
     void testBoxApiExceptionHandling() {
         testRunner.setProperty(GetBoxFileCollaborators.FILE_ID, TEST_FILE_ID);
@@ -205,15 +272,76 @@ public class GetBoxFileCollaboratorsTest extends 
AbstractBoxFileTest {
         
when(mockBoxFile.getAllFileCollaborations()).thenReturn(mockCollabIterable);
     }
 
+    private void setupMockCollaborationsWithMultipleRoles() {
+        BoxCollaboration.Role editorRole = mock(BoxCollaboration.Role.class);
+        lenient().when(editorRole.toString()).thenReturn("editor");
+        BoxCollaboration.Role viewerRole = mock(BoxCollaboration.Role.class);
+        lenient().when(viewerRole.toString()).thenReturn("viewer");
+        BoxCollaboration.Status acceptedStatus = 
BoxCollaboration.Status.ACCEPTED;
+        BoxCollaboration.Status pendingStatus = 
BoxCollaboration.Status.PENDING;
+        // Editor role collaborators
+        
lenient().when(mockCollabInfo1.getAccessibleBy()).thenReturn(mockUserInfo1);
+        
lenient().when(mockUserInfo1.getType()).thenReturn(BoxCollaborator.CollaboratorType.USER);
+        lenient().when(mockUserInfo1.getID()).thenReturn(TEST_USER_ID_1);
+        lenient().when(mockCollabInfo1.getStatus()).thenReturn(acceptedStatus);
+        lenient().when(mockCollabInfo1.getRole()).thenReturn(editorRole);
+        lenient().when(mockUserInfo1.getLogin()).thenReturn(TEST_USER_EMAIL_1);
+        // Editor role collaborator
+        
lenient().when(mockCollabInfo2.getAccessibleBy()).thenReturn(mockUserInfo2);
+        
lenient().when(mockUserInfo2.getType()).thenReturn(BoxCollaborator.CollaboratorType.USER);
+        lenient().when(mockUserInfo2.getID()).thenReturn(TEST_USER_ID_2);
+        lenient().when(mockCollabInfo2.getStatus()).thenReturn(acceptedStatus);
+        lenient().when(mockCollabInfo2.getRole()).thenReturn(editorRole);
+        lenient().when(mockUserInfo2.getLogin()).thenReturn(TEST_USER_EMAIL_2);
+        // Editor role collaborator
+        
lenient().when(mockCollabInfo3.getAccessibleBy()).thenReturn(mockGroupInfo1);
+        
lenient().when(mockGroupInfo1.getType()).thenReturn(BoxCollaborator.CollaboratorType.GROUP);
+        lenient().when(mockGroupInfo1.getID()).thenReturn(TEST_GROUP_ID_1);
+        lenient().when(mockCollabInfo3.getStatus()).thenReturn(acceptedStatus);
+        lenient().when(mockCollabInfo3.getRole()).thenReturn(editorRole);
+        
lenient().when(mockGroupInfo1.getLogin()).thenReturn(TEST_GROUP_EMAIL_1);
+        // Viewer role collaborator
+        
lenient().when(mockCollabInfo4.getAccessibleBy()).thenReturn(mockUserInfo3);
+        
lenient().when(mockUserInfo3.getType()).thenReturn(BoxCollaborator.CollaboratorType.USER);
+        lenient().when(mockUserInfo3.getID()).thenReturn(TEST_USER_ID_3);
+        lenient().when(mockCollabInfo4.getStatus()).thenReturn(acceptedStatus);
+        lenient().when(mockCollabInfo4.getRole()).thenReturn(viewerRole);
+        lenient().when(mockUserInfo3.getLogin()).thenReturn(TEST_USER_EMAIL_3);
+        // Pending collaborators - should be filtered out by status filter
+        
lenient().when(mockCollabInfo5.getAccessibleBy()).thenReturn(mockGroupInfo2);
+        
lenient().when(mockGroupInfo2.getType()).thenReturn(BoxCollaborator.CollaboratorType.GROUP);
+        lenient().when(mockGroupInfo2.getID()).thenReturn(TEST_GROUP_ID_2);
+        lenient().when(mockCollabInfo5.getStatus()).thenReturn(pendingStatus);
+        lenient().when(mockCollabInfo5.getRole()).thenReturn(editorRole);
+        
lenient().when(mockGroupInfo2.getLogin()).thenReturn(TEST_GROUP_EMAIL_2);
+        lenient().when(mockCollabIterable.iterator()).thenReturn(
+                List.of(mockCollabInfo1, mockCollabInfo2, mockCollabInfo3, 
mockCollabInfo4, mockCollabInfo5).iterator()
+        );
+
+        
lenient().when(mockBoxFile.getAllFileCollaborations()).thenReturn(mockCollabIterable);
+    }
+
     private void setupCollaborator(final BoxCollaboration.Info collabInfo,
                                    final BoxCollaborator.Info collaboratorInfo,
                                    final BoxCollaborator.CollaboratorType type,
                                    final String id,
                                    final BoxCollaboration.Status status) {
-        when(collabInfo.getAccessibleBy()).thenReturn(collaboratorInfo);
-        when(collaboratorInfo.getType()).thenReturn(type);
-        when(collaboratorInfo.getID()).thenReturn(id);
-        when(collabInfo.getStatus()).thenReturn(status);
+        setupCollaborator(collabInfo, collaboratorInfo, type, id, status, 
BoxCollaboration.Role.EDITOR);
+    }
+
+    private void setupCollaborator(final BoxCollaboration.Info collabInfo,
+                                   final BoxCollaborator.Info collaboratorInfo,
+                                   final BoxCollaborator.CollaboratorType type,
+                                   final String id,
+                                   final BoxCollaboration.Status status,
+                                   final BoxCollaboration.Role role) {
+        BoxCollaboration.Role editorRole = mock(BoxCollaboration.Role.class);
+        lenient().when(editorRole.toString()).thenReturn("editor");
+        
lenient().when(collabInfo.getAccessibleBy()).thenReturn(collaboratorInfo);
+        lenient().when(collaboratorInfo.getType()).thenReturn(type);
+        lenient().when(collaboratorInfo.getID()).thenReturn(id);
+        lenient().when(collabInfo.getStatus()).thenReturn(status);
+        lenient().when(collabInfo.getRole()).thenReturn(editorRole);
 
         final Map<String, String> userEmails = Map.of(
                 TEST_USER_ID_1, TEST_USER_EMAIL_1,
@@ -232,6 +360,6 @@ public class GetBoxFileCollaboratorsTest extends 
AbstractBoxFileTest {
             email = groupEmails.getOrDefault(id, null);
         }
 
-        when(collaboratorInfo.getLogin()).thenReturn(email);
+        lenient().when(collaboratorInfo.getLogin()).thenReturn(email);
     }
 }
\ No newline at end of file

Reply via email to