diff --git a/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java b/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java index e360682f30..55cb7bb718 100644 --- a/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java +++ b/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java @@ -828,16 +828,22 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli } /** - * This is the general search invitation method returning {@link Invitation}s + * {@inheritDoc} * - * @param criteria InvitationSearchCriteria - * @return the list of start tasks for invitations + * @deprecated */ public List searchInvitation(final InvitationSearchCriteria criteria) { - int limit = 200; + return searchInvitation(criteria, 200); + } + + /** + * {@inheritDoc} + */ + public List searchInvitation(InvitationSearchCriteria criteria, int limit) + { List invitationIds = searchInvitationsForIds(criteria, limit); - return invitationIds.isEmpty() ? Collections.emptyList() : searchInvitation(criteria, invitationIds); + return invitationIds.isEmpty() ? Collections. emptyList() : searchInvitation(criteria, invitationIds); } private List searchInvitation(final InvitationSearchCriteria criteria, List invitationIds) @@ -872,7 +878,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli if (toSearch == InvitationSearchCriteria.InvitationType.ALL || toSearch == InvitationSearchCriteria.InvitationType.NOMINATED) { - for (WorkflowTask task : searchNominatedInvitations(criteria)) + for (WorkflowTask task : searchNominatedInvitations(criteria, limit)) { String invitationId = task.getPath().getInstance().getId(); invitationIds.add(invitationId); @@ -886,7 +892,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli (toSearch == InvitationSearchCriteria.InvitationType.ALL || toSearch == InvitationSearchCriteria.InvitationType.MODERATED)) { - for (WorkflowTask task: searchModeratedInvitations(criteria)) + for (WorkflowTask task: searchModeratedInvitations(criteria, limit)) { String invitationId = task.getPath().getInstance().getId(); invitationIds.add(invitationId); @@ -937,14 +943,23 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli } return true; } - - private List searchModeratedInvitations(InvitationSearchCriteria criteria) + + /** + * + * @param criteria criteria to search by + * @param limit maximum number of IDs to return. If less than 1, there is no limit. + * @return list of WorkflowTask representing moderated invitations + */ + private List searchModeratedInvitations(InvitationSearchCriteria criteria, int limit) { long start = (logger.isDebugEnabled()) ? System.currentTimeMillis() : 0; WorkflowTaskQuery query = new WorkflowTaskQuery(); query.setTaskState(WorkflowTaskState.IN_PROGRESS); - + if (limit > 0) + { + query.setLimit(limit); + } Map properties = new HashMap(); String invitee = criteria.getInvitee(); if (invitee != null) @@ -998,13 +1013,22 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli return results; } - private List searchNominatedInvitations(InvitationSearchCriteria criteria) + /** + * + * @param criteria + * @param limit maximum number of IDs to return. If less than 1, there is no limit. + * @return list of WorkflowTask representing nominated invitations + */ + private List searchNominatedInvitations(InvitationSearchCriteria criteria, int limit) { long start = (logger.isDebugEnabled()) ? System.currentTimeMillis() : 0; WorkflowTaskQuery query = new WorkflowTaskQuery(); query.setTaskState(WorkflowTaskState.IN_PROGRESS); - + if (limit > 0) + { + query.setLimit(limit); + } String invitee = criteria.getInvitee(); if(invitee != null) { diff --git a/source/java/org/alfresco/repo/invitation/script/ScriptInvitationService.java b/source/java/org/alfresco/repo/invitation/script/ScriptInvitationService.java index f3e5fe92ec..ea05531afd 100644 --- a/source/java/org/alfresco/repo/invitation/script/ScriptInvitationService.java +++ b/source/java/org/alfresco/repo/invitation/script/ScriptInvitationService.java @@ -48,6 +48,8 @@ public class ScriptInvitationService extends BaseScopableProcessorExtension implements InitializingBean { + static final int DEFAULT_MAX_LIST_INVITATIONS_RETURN_SIZE = 200; + /** The invitation service */ private InvitationService invitationService; @@ -101,7 +103,13 @@ public class ScriptInvitationService extends BaseScopableProcessorExtension * List the open invitations. * props specifies optional properties to constrain the search. * - * @param props props + * By default, if no "resultsLimit" property is specified in the props argument, + * this method will return a maximum of DEFAULT_MAX_LIST_INVITATIONS_RETURN_SIZE (200) results + * + * @param props inviteeUserName + * @param props resourceName + * @param props resourceType + * @param props invitationType * * @return the invitations */ @@ -109,7 +117,9 @@ public class ScriptInvitationService extends BaseScopableProcessorExtension public ScriptInvitation[] listInvitations(Scriptable props) { InvitationSearchCriteriaImpl crit = new InvitationSearchCriteriaImpl(); - + + int resultsLimit = DEFAULT_MAX_LIST_INVITATIONS_RETURN_SIZE; + if (props.has("resourceName", props)) { crit.setResourceName((String)props.get("resourceName", props)); @@ -127,6 +137,21 @@ public class ScriptInvitationService extends BaseScopableProcessorExtension String invitationType = (String)props.get("invitationType", props); crit.setInvitationType(InvitationType.valueOf(invitationType)); } + if (props.has("resultsLimit", props)) + { + String resultsLimitStr = (String) props.get("resultsLimit", props); + try + { + if (resultsLimitStr != null && !resultsLimitStr.isEmpty()) + { + resultsLimit = Integer.parseInt(resultsLimitStr); + } + } + catch (Exception e) + { + // ignore any parse exceptions; no need to log them + } + } //MNT-9905 Pending Invites created by one site manager aren't visible to other site managers String currentUser = AuthenticationUtil.getRunAsUser(); @@ -136,12 +161,12 @@ public class ScriptInvitationService extends BaseScopableProcessorExtension if (siteShortName != null && (SiteModel.SITE_MANAGER).equals(siteService.getMembersRole(siteShortName, currentUser))) { final InvitationSearchCriteriaImpl criteria = crit; - + final int resultsLimitFinal = resultsLimit; RunAsWork> runAsSystem = new RunAsWork>() { public List doWork() throws Exception { - return invitationService.searchInvitation(criteria); + return invitationService.searchInvitation(criteria, resultsLimitFinal); } }; @@ -149,7 +174,7 @@ public class ScriptInvitationService extends BaseScopableProcessorExtension } else { - invitations = invitationService.searchInvitation(crit); + invitations = invitationService.searchInvitation(crit, resultsLimit); } ScriptInvitation[] ret = new ScriptInvitation[invitations.size()]; diff --git a/source/java/org/alfresco/repo/workflow/TaskComponent.java b/source/java/org/alfresco/repo/workflow/TaskComponent.java index f1ff21876a..def5971d0a 100644 --- a/source/java/org/alfresco/repo/workflow/TaskComponent.java +++ b/source/java/org/alfresco/repo/workflow/TaskComponent.java @@ -73,11 +73,16 @@ public interface TaskComponent /** * Query for tasks * - * @param query the filter by which tasks are queried - * @param sameSession indicates that the returned {@link WorkflowTask} elements will be used in - * the same session. If {@code true}, the returned List will be a lazy loaded list - * providing greater performance. - * @return the list of tasks matching the specified query + * Hint: use {@link WorkflowTaskQuery} setLimit() method to limit the number + * of processed items if you don't really need to go through all of them + * + * @param query + * the filter by which tasks are queried + * @param sameSession + * indicates that the returned {@link WorkflowTask} elements will + * be used in the same session. If {@code true}, the returned + * List will be a lazy loaded list providing greater performance. + * @return the list of tasks matching the specified query */ public List queryTasks(final WorkflowTaskQuery query, boolean sameSession); diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java index 29db948ff9..226844ac5c 100644 --- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java +++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java @@ -1238,8 +1238,15 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine } /** - * Converts the given list of {@link Task}s to a list of {@link WorkflowTask}s - * that have a valid domain. + * Converts the given list of {@link Task}s to a list of + * {@link WorkflowTask}s that have a valid domain. + * + * Note that this method is not very performant. It will do many DB queries + * for each of the Task item in the list of tasks as parameter. Make sure + * that you limit the size of the tasks list depending on your needs. Hint: + * use the WorkflowTaskQuery query parameter setLimit() method to limit the + * number of Tasks to process + * * @param tasks List */ private List getValidWorkflowTasks(List tasks) diff --git a/source/java/org/alfresco/service/cmr/invitation/InvitationService.java b/source/java/org/alfresco/service/cmr/invitation/InvitationService.java index 0dd362d68c..b8bc71a2c8 100644 --- a/source/java/org/alfresco/service/cmr/invitation/InvitationService.java +++ b/source/java/org/alfresco/service/cmr/invitation/InvitationService.java @@ -283,14 +283,36 @@ public interface InvitationService public List listPendingInvitationsForResource(Invitation.ResourceType resourceType, String resourceName); /** - * search invitation + * This is the general search invitation method returning {@link Invitation} + * This method has a hardcoded limit of 200 invitations to return. It has + * been deprecated and it is recommended to use the overloaded version for + * which you can specify an appropriate limit depending on the needs * * @param criteria InvitationSearchCriteria + * search criteria * @return the list of invitations + * + * @deprecated */ @NotAuditable public List searchInvitation(InvitationSearchCriteria criteria); + /** + * This is the general search invitation method returning {@link Invitation} + * This is the recommended method to use for searching invitations; Consider + * that the performance of the method will be greatly influenced by the + * limit specified + * + * @param criteria + * search criteria + * @param limit + * maximum number of IDs to return. If less than 1, there is no + * limit. + * @return the list of invitations + */ + @NotAuditable + public List searchInvitation(InvitationSearchCriteria criteria, int limit); + /** * @return true if emails are sent on invite. */ diff --git a/source/test-java/org/alfresco/repo/invitation/AbstractInvitationServiceImplTest.java b/source/test-java/org/alfresco/repo/invitation/AbstractInvitationServiceImplTest.java index 7f690b629d..6bf09c749a 100644 --- a/source/test-java/org/alfresco/repo/invitation/AbstractInvitationServiceImplTest.java +++ b/source/test-java/org/alfresco/repo/invitation/AbstractInvitationServiceImplTest.java @@ -1142,6 +1142,10 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri List resFive = invitationService.searchInvitation(crit1); assertEquals("user one does not have 2 nominated", 2, resFive.size()); + // now limit the search to 1 returned value + List limitRes = invitationService.searchInvitation(crit1, 1); + assertEquals("user one does not have 1 nominated", 1, limitRes.size()); + /** * Search with an empty criteria - should find all open invitations */ @@ -1149,6 +1153,10 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri invitationService.searchInvitation(crit2); assertTrue("search everything returned 0 elements", resFive.size() > 0); + // now search everything but limit the results to 3 + invitationService.searchInvitation(crit2, 3); + assertTrue("search everything returned 0 or more than 3 elements", resFive.size() > 0 && resFive.size() <=3); + InvitationSearchCriteriaImpl crit3 = new InvitationSearchCriteriaImpl(); crit3.setInviter(USER_MANAGER); crit3.setInvitationType(InvitationSearchCriteria.InvitationType.NOMINATED); @@ -1156,6 +1164,51 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri List res3 = invitationService.searchInvitation(crit3); assertEquals("user one does not have 2 nominated", 2, res3.size()); + //now limit the search to 1 result + res3 = invitationService.searchInvitation(crit3, 1); + assertEquals("user one does not have 1 nominated", 1, res3.size()); + } + + /** + * test that the search limiter works + */ + public void testSearchInvitationWithLimit() throws Exception + { + Invitation.ResourceType resourceType = Invitation.ResourceType.WEB_SITE; + String resourceName = SITE_SHORT_NAME_INVITE; + String inviteeRole = SiteModel.SITE_COLLABORATOR; + String serverPath = "wibble"; + String acceptUrl = "froob"; + String rejectUrl = "marshmallow"; + + authenticationComponent.setCurrentUser(USER_MANAGER); + + // Create 10 invites + for (int i = 0; i < 10; i++) + { + invitationService + .inviteNominated(USER_ONE, resourceType, resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + } + + // Invite USER_TWO + NominatedInvitation inviteForUserTwo = invitationService.inviteNominated(USER_TWO, resourceType, resourceName, + inviteeRole, serverPath, acceptUrl, rejectUrl); + + InvitationSearchCriteriaImpl query = new InvitationSearchCriteriaImpl(); + query.setInvitee(USER_TWO); + + // search all of them + List results = invitationService.searchInvitation(query, 0); + assertEquals(1, results.size()); + assertEquals(inviteForUserTwo.getInviteId(), results.get(0).getInviteId()); + + query = new InvitationSearchCriteriaImpl(); + query.setInvitee(USER_ONE); + + final int MAX_SEARCH = 3; + // only search for the first MAX_SEARCH + results = invitationService.searchInvitation(query, MAX_SEARCH); + assertEquals(MAX_SEARCH, results.size()); } public void disabled_test100Invites() throws Exception @@ -1175,7 +1228,7 @@ public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpri invitationService.inviteNominated(USER_ONE, resourceType, resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); } - // Invite USER_TWO + // Invite USER_TWO NominatedInvitation invite = invitationService.inviteNominated(USER_TWO, resourceType, resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); InvitationSearchCriteriaImpl query = new InvitationSearchCriteriaImpl();