diff --git a/config/alfresco/workflow/invitation-moderated-workflow-model.xml b/config/alfresco/workflow/invitation-moderated-workflow-model.xml index d31b18ea1c..e4a32b3a94 100644 --- a/config/alfresco/workflow/invitation-moderated-workflow-model.xml +++ b/config/alfresco/workflow/invitation-moderated-workflow-model.xml @@ -20,7 +20,6 @@ bpm:startTask - bpm:assignee bpm:groupAssignee imwf:moderatedInvitationStats @@ -40,7 +39,6 @@ d:text - reject @@ -56,8 +54,7 @@ - {http://www.alfresco.org/model/workflow/invite/moderated/1.0}reviewOutcome - + {http://www.alfresco.org/model/workflow/invite/moderated/1.0}reviewOutcome diff --git a/config/alfresco/workflow/invitation-moderated.bpmn20.xml b/config/alfresco/workflow/invitation-moderated.bpmn20.xml index c1ee8264fd..a1f75b44fc 100644 --- a/config/alfresco/workflow/invitation-moderated.bpmn20.xml +++ b/config/alfresco/workflow/invitation-moderated.bpmn20.xml @@ -28,6 +28,7 @@ execution.setVariable('imwf_reviewOutcome', task.getVariable('imwf_reviewOutcome')); + execution.setVariable('imwf_reviewer', person.properties.userName); @@ -44,7 +45,7 @@ - ${imwf_reviewOutcome == 'Approve'} + ${imwf_reviewOutcome=='approve'} diff --git a/config/alfresco/workflow/invitation-nominated.bpmn20.xml b/config/alfresco/workflow/invitation-nominated.bpmn20.xml index 32f43cfa10..523bc2ecfc 100644 --- a/config/alfresco/workflow/invitation-nominated.bpmn20.xml +++ b/config/alfresco/workflow/invitation-nominated.bpmn20.xml @@ -57,16 +57,55 @@ - - + - + + + + + + + if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority; + + + + + + + ${initiator.properties.userName} + + + + + + + + + + + + if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority; + + + + + + + ${initiator.properties.userName} + + + + + + diff --git a/source/java/org/alfresco/repo/invitation/InvitationServiceImplTest.java b/source/java/org/alfresco/repo/invitation/AbstractInvitationServiceImplTest.java similarity index 94% rename from source/java/org/alfresco/repo/invitation/InvitationServiceImplTest.java rename to source/java/org/alfresco/repo/invitation/AbstractInvitationServiceImplTest.java index 62ed25de82..d838939adc 100644 --- a/source/java/org/alfresco/repo/invitation/InvitationServiceImplTest.java +++ b/source/java/org/alfresco/repo/invitation/AbstractInvitationServiceImplTest.java @@ -20,6 +20,7 @@ package org.alfresco.repo.invitation; import java.lang.reflect.Field; +import java.util.Calendar; import java.util.Date; import java.util.List; @@ -31,12 +32,15 @@ import org.alfresco.repo.management.subsystems.ApplicationContextFactory; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.site.SiteModel; +import org.alfresco.repo.workflow.WorkflowAdminServiceImpl; +import org.alfresco.repo.workflow.activiti.ActivitiConstants; +import org.alfresco.repo.workflow.jbpm.JBPMEngine; import org.alfresco.service.cmr.invitation.Invitation; +import org.alfresco.service.cmr.invitation.Invitation.ResourceType; import org.alfresco.service.cmr.invitation.InvitationSearchCriteria; import org.alfresco.service.cmr.invitation.InvitationService; import org.alfresco.service.cmr.invitation.ModeratedInvitation; import org.alfresco.service.cmr.invitation.NominatedInvitation; -import org.alfresco.service.cmr.invitation.Invitation.ResourceType; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; @@ -48,19 +52,20 @@ import org.springframework.util.ReflectionUtils; /** * Unit tests of Invitation Service */ -public class InvitationServiceImplTest extends BaseAlfrescoSpringTest +public abstract class AbstractInvitationServiceImplTest extends BaseAlfrescoSpringTest { private SiteService siteService; - private AuthenticationComponent authenticationComponent; + protected AuthenticationComponent authenticationComponent; private PersonService personService; - private InvitationService invitationService; + protected InvitationService invitationService; private MailActionExecuter mailService; private boolean startSendEmails; - private InvitationServiceImpl invitationServiceImpl; + protected InvitationServiceImpl invitationServiceImpl; + protected WorkflowAdminServiceImpl workflowAdminService; - private final static String SITE_SHORT_NAME_INVITE = "InvitationTest"; - private final static String SITE_SHORT_NAME_RED = "InvitationTestRed"; - private final static String SITE_SHORT_NAME_BLUE = "InvitationTestBlue"; + protected final static String SITE_SHORT_NAME_INVITE = "InvitationTest"; + protected final static String SITE_SHORT_NAME_RED = "InvitationTestRed"; + protected final static String SITE_SHORT_NAME_BLUE = "InvitationTestBlue"; public final static String PERSON_FIRSTNAME = "InvitationFirstName123"; public final static String PERSON_FIRSTNAME_SPACES = "Invitation First\tName\n1\r2\r\n3"; public final static String PERSON_LASTNAME = "InvitationLastName123"; @@ -91,9 +96,15 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest this.personService = (PersonService) this.applicationContext.getBean("PersonService"); this.authenticationComponent = (AuthenticationComponent) this.applicationContext .getBean("authenticationComponent"); - this.invitationServiceImpl = (InvitationServiceImpl) this.applicationContext.getBean("invitationService"); + this.invitationServiceImpl = (InvitationServiceImpl) applicationContext.getBean("invitationService"); + this.workflowAdminService = (WorkflowAdminServiceImpl)applicationContext.getBean(WorkflowAdminServiceImpl.NAME); this.startSendEmails = invitationServiceImpl.isSendEmails(); + + // Check both workflow engines are active. + assertTrue(workflowAdminService.isEngineEnabled(JBPMEngine.ENGINE_ID)); + assertTrue(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)); + invitationServiceImpl.setSendEmails(true); // TODO MER 20/11/2009 Bodge - turn off email sending to prevent errors @@ -139,6 +150,10 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest @Override protected void onTearDownInTransaction() throws Exception { + // Make sure both workflow engines are enabled. + workflowAdminService.setActivitiEngineEnabled(true); + workflowAdminService.setJbpmEngineEnabled(true); + this.authenticationComponent.setSystemUserAsCurrentUser(); invitationServiceImpl.setSendEmails(startSendEmails); siteService.deleteSite(SITE_SHORT_NAME_INVITE); @@ -170,7 +185,9 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest */ public void testNominatedInvitationNewUser() throws Exception { - Date startDate = new java.util.Date(); + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, -1); + Date startDate = calendar.getTime(); String inviteeFirstName = PERSON_FIRSTNAME; String inviteeLastName = PERSON_LASTNAME; @@ -200,8 +217,8 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest // sentInviteDate should be set to today { Date sentDate = nominatedInvitation.getSentInviteDate(); - assertTrue("sentDate wrong - too early", sentDate.after(startDate)); - assertTrue("sentDate wrong - too late", sentDate.before(new Date(new Date().getTime() + 1))); + assertTrue("sentDate wrong - too early. Start Date: " +startDate +"\nSent Date: "+sentDate, sentDate.after(startDate)); + assertTrue("sentDate wrong - too lateStart Date: " +startDate +"\nSent Date: "+sentDate, sentDate.before(new Date(new Date().getTime() + 1))); } assertEquals("resource type name wrong", resourceType, nominatedInvitation.getResourceType()); @@ -336,7 +353,9 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest */ public void testNominatedInvitationNewUserReject() throws Exception { - Date startDate = new java.util.Date(); + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, -1); + Date startDate = calendar.getTime(); String inviteeFirstName = PERSON_FIRSTNAME; String inviteeLastName = PERSON_LASTNAME; @@ -365,8 +384,8 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest // sentInviteDate should be set to today { Date sentDate = nominatedInvitation.getSentInviteDate(); - assertTrue("sentDate wrong - too early", sentDate.after(startDate)); - assertTrue("sentDate wrong - too late", sentDate.before(new Date(new Date().getTime() + 1))); + assertTrue("sentDate wrong - too earlyStart Date: " +startDate +"\nSent Date: "+sentDate, sentDate.after(startDate)); + assertTrue("sentDate wrong - too lateStart Date: " +startDate +"\nSent Date: "+sentDate, sentDate.before(new Date(new Date().getTime() + 1))); } /** @@ -555,7 +574,7 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest String acceptUrl = "froob"; String rejectUrl = "marshmallow"; - this.authenticationComponent.setCurrentUser(USER_MANAGER); + authenticationComponent.setCurrentUser(USER_MANAGER); NominatedInvitation nominatedInvitation = invitationService.inviteNominated(inviteeUserName, resourceType, resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); @@ -657,7 +676,7 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest * Now verify access control list */ String roleName = siteService.getMembersRole(resourceName, inviteeUserName); - assertEquals("role name wrong", roleName, inviteeRole); + assertEquals("role name wrong", inviteeRole, roleName); siteService.removeMembership(resourceName, inviteeUserName); } @@ -748,7 +767,7 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest * Now verify access control list */ String roleName = siteService.getMembersRole(resourceName, inviteeUserName); - assertEquals("role name wrong", roleName, inviteeRole); + assertEquals("role name wrong", inviteeRole, roleName); siteService.removeMembership(resourceName, inviteeUserName); } diff --git a/source/java/org/alfresco/repo/invitation/ActivitiInvitationServiceImplTests.java b/source/java/org/alfresco/repo/invitation/ActivitiInvitationServiceImplTests.java new file mode 100644 index 0000000000..f3bb58c279 --- /dev/null +++ b/source/java/org/alfresco/repo/invitation/ActivitiInvitationServiceImplTests.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.invitation; + +import org.alfresco.repo.site.SiteModel; +import org.alfresco.service.cmr.invitation.Invitation; +import org.alfresco.service.cmr.invitation.NominatedInvitation; + +/** + * @author Nick Smith + * @since 4.0 + * + */ +public class ActivitiInvitationServiceImplTests extends AbstractInvitationServiceImplTest +{ + /** + * {@inheritDoc} + */ + @Override + protected void onSetUpInTransaction() throws Exception + { + super.onSetUpInTransaction(); + + // Add a few Jbpm invitations to check they dont' interfere with Activiti invitations. + workflowAdminService.setActivitiEngineEnabled(false); + + String invitee = USER_ONE; + 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); + + // Start Nominated Invitation + invitationService.inviteNominated(invitee, resourceType, + resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + + // Start Moderated Invitation + invitationService.inviteModerated("", invitee, + resourceType, resourceName, inviteeRole); + + // Disable Jbpm and enable Activiti + workflowAdminService.setJbpmEngineEnabled(false); + workflowAdminService.setActivitiEngineEnabled(true); + + } +} diff --git a/source/java/org/alfresco/repo/invitation/FullInvitationServiceImplTests.java b/source/java/org/alfresco/repo/invitation/FullInvitationServiceImplTests.java new file mode 100644 index 0000000000..e889ba1ece --- /dev/null +++ b/source/java/org/alfresco/repo/invitation/FullInvitationServiceImplTests.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.invitation; + + +/** + * Test InvitationService with both engines enabled. + * @author Nick Smith + * @since 4.0 + * + */ +public class FullInvitationServiceImplTests extends AbstractInvitationServiceImplTest +{ + // See inheited tests. +} diff --git a/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java b/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java index 860af5bfb0..dfe3dcfae9 100644 --- a/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java +++ b/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java @@ -38,8 +38,11 @@ import org.alfresco.repo.security.authentication.PasswordGenerator; import org.alfresco.repo.security.authentication.UserNameGenerator; import org.alfresco.repo.site.SiteModel; import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.repo.workflow.activiti.ActivitiConstants; +import org.alfresco.repo.workflow.jbpm.JBPMEngine; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.invitation.Invitation; +import org.alfresco.service.cmr.invitation.Invitation.ResourceType; import org.alfresco.service.cmr.invitation.InvitationException; import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden; import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound; @@ -68,6 +71,8 @@ import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.util.GUID; import org.alfresco.util.PropertyCheck; +import org.alfresco.util.collections.CollectionUtils; +import org.alfresco.util.collections.Function; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.extensions.surf.util.I18NUtil; @@ -531,197 +536,174 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli * @param criteria * @return the list of invitations */ - public List searchInvitation(InvitationSearchCriteria criteria) + public List searchInvitation(final InvitationSearchCriteria criteria) { - List ret = new ArrayList(); - + List searchResults = new ArrayList(); InvitationSearchCriteria.InvitationType toSearch = criteria.getInvitationType(); - - /** - * Nominated search below - */ if (toSearch == InvitationSearchCriteria.InvitationType.ALL || toSearch == InvitationSearchCriteria.InvitationType.NOMINATED) { - // query for nominated workflow tasks by given parameters - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - HashMap wfNominatedQueryProps = new HashMap(10, 1.0f); - - if (criteria.getInviter() != null) - { - wfNominatedQueryProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITER_USER_NAME, criteria - .getInviter()); - } - if (criteria.getInvitee() != null) - { - wfNominatedQueryProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_USER_NAME, criteria - .getInvitee()); - } - if (criteria.getResourceType() != null) - { - wfNominatedQueryProps.put(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE, criteria - .getResourceType().toString()); - } - if (criteria.getResourceName() != null) - { - wfNominatedQueryProps.put(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME, criteria - .getResourceName()); - } - - // set workflow task query parameters - wfTaskQuery.setProcessCustomProps(wfNominatedQueryProps); - - // query only active workflows - wfTaskQuery.setActive(Boolean.TRUE); - - // pick up the pending task - wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING); - wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); - - // query for invite workflow tasks - List wf_invite_tasks = this.workflowService.queryTasks(wfTaskQuery); - - for (WorkflowTask workflowTask : wf_invite_tasks) - { - // get workflow instance (ID) that pendingInvite task (in query - // result set) - - String workflowId = workflowTask.getPath().getInstance().getId(); - // TODO ALFCOM-2597 workflowTask.properties does not contain - // custom process values - // NominatedInvitationImpl result = new - // NominatedInvitationImpl(workflowTask.properties); - // result.setInviteId(workflowId); - // ret.add(result); - - Invitation result = getInvitation(workflowId); - - // TODO ALFCOM-2598 records are being returned that do not match - // properties - Set keys = wfNominatedQueryProps.keySet(); - boolean crap = false; - for (QName key : keys) - { - if (key.equals(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_USER_NAME)) - { - Object val1 = wfNominatedQueryProps.get(key); - Object val2 = ((NominatedInvitation) result).getInviteeUserName(); - if (!val1.equals(val2)) - { - // Uh oh ... crap detected - crap = true; - logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); - break; - } - } - if (key.equals(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME)) - { - Object val1 = wfNominatedQueryProps.get(key); - Object val2 = result.getResourceName(); - if (!val1.equals(val2)) - { - // Uh oh ... crap detected - crap = true; - logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); - break; - } - } - if (key.equals(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE)) - { - Object val1 = wfNominatedQueryProps.get(key); - Object val2 = result.getResourceType().toString(); - if (!val1.equals(val2)) - { - - // Uh oh ... crap detected - crap = true; - logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); - break; - } - } - } - - if (!crap) - { - ret.add(result); - } - } + searchResults.addAll(searchNominatedInvitations(criteria)); } - - /** - * Moderated search below - */ if (toSearch == InvitationSearchCriteria.InvitationType.ALL || toSearch == InvitationSearchCriteria.InvitationType.MODERATED) { - // This is a moderated search - WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); - // workflow query properties - HashMap wfQueryModeratedProps = new HashMap(3, 1.0f); - - if (criteria.getInvitee() != null) + searchResults.addAll(searchModeratedInvitations(criteria)); + } + + return CollectionUtils.transform(searchResults, new Function() + { + public Invitation apply(WorkflowTask task) { - wfQueryModeratedProps.put(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_USER_NAME, criteria - .getInvitee()); - } - if (criteria.getResourceType() != null) - { - wfQueryModeratedProps.put(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE, criteria - .getResourceType().toString()); - } - if (criteria.getResourceName() != null) - { - wfQueryModeratedProps.put(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME, criteria - .getResourceName()); + String invitationId = task.getPath().getInstance().getId(); + Invitation invitation = getInvitation(invitationId); + return invitationMatches(invitation, criteria) ? invitation : null; } - // set workflow task query parameters - wfModeratedTaskQuery.setProcessCustomProps(wfQueryModeratedProps); + }); + } - // Current Review Moderated Tasks - wfModeratedTaskQuery.setActive(Boolean.TRUE); - wfModeratedTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfModeratedTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_REVIEW_TASK); - wfModeratedTaskQuery.setProcessName(WorkflowModelModeratedInvitation.WF_PROCESS_INVITATION_MODERATED); - - // query for invite workflow tasks - List wf_moderated_tasks = this.workflowService.queryTasks(wfModeratedTaskQuery); - - for (WorkflowTask workflowTask : wf_moderated_tasks) + /** + * Fix for ALF-2598 + * @param invitation + * @param criteria + * @return + */ + private boolean invitationMatches(Invitation invitation, InvitationSearchCriteria criteria) + { + String invitee = criteria.getInvitee(); + if(invitee!= null && + false == invitee.equals(invitation.getInviteeUserName())) + { + return false; + } + String inviter = criteria.getInviter(); + if(inviter!= null) + { + if (invitation instanceof NominatedInvitation) { - // Add moderated invitations - String workflowId = workflowTask.getPath().getInstance().getId(); - ModeratedInvitationImpl result = new ModeratedInvitationImpl(workflowId, workflowTask.getProperties()); - - // TODO ALFCOM-2598 records are being returned that do not match - // properties - Set keys = wfQueryModeratedProps.keySet(); - boolean crap = false; - for (QName key : keys) + NominatedInvitation modInvite = (NominatedInvitation) invitation; + if(inviter.equals(modInvite.getInviterUserName())) { - Object val1 = wfQueryModeratedProps.get(key); - Object val2 = workflowTask.getProperties().get(key); - if (!val1.equals(val2)) - { - // crap detected - crap = true; - logger.debug("ALFCOM-2598 key:" + key + "query:" + val1 + "task:" + val2); - break; - } - } - // TODO END ALFCOM-2598 Work-around - if (!crap) - { - ret.add(result); + return false; } } + else + { + return false; + } } + String resourceName= criteria.getResourceName(); + if(resourceName!= null && + false == resourceName.equals(invitation.getResourceName())) + { + return false; + } + return true; + } + + private List searchModeratedInvitations(InvitationSearchCriteria criteria) + { + WorkflowTaskQuery query = new WorkflowTaskQuery(); + query.setTaskState(WorkflowTaskState.IN_PROGRESS); + + Map properties = new HashMap(); + String invitee = criteria.getInvitee(); + if (invitee != null) + { + properties.put(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_USER_NAME, invitee); + } + //TODO Uncomment if more than one ResourceType added. +// ResourceType resourceType = criteria.getResourceType(); +// if (resourceType != null) +// { +// properties.put(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE, resourceType.toString()); +// } + String resourceName = criteria.getResourceName(); + if (resourceName != null) + { + properties.put(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME, resourceName); + } + query.setProcessCustomProps(properties); - // End moderated invitation + query.setTaskName(WorkflowModelModeratedInvitation.WF_REVIEW_TASK); - return ret; + // query for invite workflow tasks + List results = new ArrayList(); + if(workflowAdminService.isEngineEnabled(JBPMEngine.ENGINE_ID)) + { + query.setTaskName(WorkflowModelModeratedInvitation.WF_REVIEW_TASK); + List jbpmTasks = this.workflowService.queryTasks(query); + if(jbpmTasks !=null) + { + results.addAll(jbpmTasks); + } + } + if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) + { + query.setTaskName(WorkflowModelModeratedInvitation.WF_ACTIVITI_REVIEW_TASK); + List jbpmTasks = this.workflowService.queryTasks(query); + if(jbpmTasks !=null) + { + results.addAll(jbpmTasks); + } + } + return results; + } + + private List searchNominatedInvitations(InvitationSearchCriteria criteria) + { + WorkflowTaskQuery query = new WorkflowTaskQuery(); + query.setTaskState(WorkflowTaskState.IN_PROGRESS); + + String invitee = criteria.getInvitee(); + if(invitee != null) + { + query.setActorId(invitee); + } + + Map queryProps = new HashMap(); + String inviter = criteria.getInviter(); + if (inviter != null) + { + queryProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITER_USER_NAME, inviter); + } + String resourceName = criteria.getResourceName(); + if (resourceName != null) + { + queryProps.put(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME, resourceName); + } + + //TODO uncomment if more ResourceTypes are created. +// ResourceType resourceType = criteria.getResourceType(); +// if (resourceType != null) +// { +// wfNominatedQueryProps.put(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE, +// resourceType.name()); +// } + // set workflow task query parameters + query.setProcessCustomProps(queryProps); + + List results = new ArrayList(); + if(workflowAdminService.isEngineEnabled(JBPMEngine.ENGINE_ID)) + { + query.setTaskName(WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING); + List jbpmTasks = this.workflowService.queryTasks(query); + if(jbpmTasks !=null) + { + results.addAll(jbpmTasks); + } + } + if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) + { + query.setTaskName(WorkflowModelNominatedInvitation.WF_TASK_ACTIVIT_INVITE_PENDING); + List jbpmTasks = this.workflowService.queryTasks(query); + if(jbpmTasks !=null) + { + results.addAll(jbpmTasks); + } + } + return results; } // Implementation methods below @@ -947,7 +929,6 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli String workflowDescription = generateWorkflowDescription(siteInfo, "invitation.moderated.workflow.description"); Map workflowProps = new HashMap(16); - workflowProps.put(WorkflowModel.ASSOC_ASSIGNEE, inviteeNodeRef); workflowProps.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, workflowDescription); workflowProps.put(WorkflowModelModeratedInvitation.ASSOC_GROUP_ASSIGNEE, roleGroup); workflowProps.put(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_COMMENTS, inviteeComments); @@ -1202,20 +1183,28 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli private String getNominatedDefinitionName() { -// if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) -// { -// return WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI; -// } - return WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME; + if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) + { + return WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI; + } + else if(workflowAdminService.isEngineEnabled(JBPMEngine.ENGINE_ID)) + { + return WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME; + } + throw new IllegalStateException("None of the Workflow engines supported by teh InvitationService are currently enabled!"); } private String getModeratedDefinitionName() { -// if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) -// { -// return WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI; -// } - return WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME; + if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) + { + return WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI; + } + else if(workflowAdminService.isEngineEnabled(JBPMEngine.ENGINE_ID)) + { + return WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME; + } + throw new IllegalStateException("None of the Workflow engines supported by teh InvitationService are currently enabled!"); } /** diff --git a/source/java/org/alfresco/repo/invitation/InviteHelper.java b/source/java/org/alfresco/repo/invitation/InviteHelper.java index 0422b1294b..18a6c4c34b 100644 --- a/source/java/org/alfresco/repo/invitation/InviteHelper.java +++ b/source/java/org/alfresco/repo/invitation/InviteHelper.java @@ -53,6 +53,7 @@ import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.invitation.Invitation; import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden; import org.alfresco.service.cmr.invitation.InvitationService; import org.alfresco.service.cmr.repository.NodeRef; @@ -255,11 +256,12 @@ public class InviteHelper implements InitializingBean * is still disabled and there are no outstanding pending invites for that invitee. * * @param inviteeUserName + * @param currentInviteId TODO * @param authenticationservice * @param personService * @param workflowService */ - public void deleteAuthenticationIfUnused(final String inviteeUserName) + public void deleteAuthenticationIfUnused(final String inviteeUserName, final String currentInviteId) { AuthenticationUtil.runAs(new RunAsWork() { @@ -267,8 +269,16 @@ public class InviteHelper implements InitializingBean { // see if there are any pending invites (invite workflow instances with invitePending task in-progress) // outstanding for given invitee user name - List pendingTasks = findInvitePendingTasks(inviteeUserName); - boolean invitesPending = (pendingTasks != null) && (pendingTasks.size() > 0); + List pendingInvites = invitationService.listPendingInvitationsForInvitee(inviteeUserName); + boolean invitesPending = CollectionUtils.isEmpty(pendingInvites)==false; + if(invitesPending && pendingInvites.size()==1) + { + Invitation pendingInvite = pendingInvites.get(0); + if(pendingInvite.getInviteId().equals(currentInviteId)) + { + invitesPending = false; + } + } // if invitee's user account is still disabled and there are no pending invites outstanding // for the invitee, then remove the account and delete the invitee's person node @@ -293,7 +303,7 @@ public class InviteHelper implements InitializingBean /** * @param executionVariables */ - public void cancelInvitation(Map executionVariables) + public void cancelInvitation(Map executionVariables, String currentInviteId) { // Get the invitee user name and site short name variables off the execution context String inviteeUserName = (String) executionVariables.get(wfVarInviteeUserName); @@ -312,7 +322,7 @@ public class InviteHelper implements InitializingBean // Clean up invitee's user account and person node if they are not in use i.e. // account is still disabled and there are no pending invites outstanding for the // invitee - deleteAuthenticationIfUnused(inviteeUserName); + deleteAuthenticationIfUnused(inviteeUserName, currentInviteId); } public void sendNominatedInvitation(Map executionVariables) diff --git a/source/java/org/alfresco/repo/invitation/JbpmInvitationServiceImplTests.java b/source/java/org/alfresco/repo/invitation/JbpmInvitationServiceImplTests.java new file mode 100644 index 0000000000..b16ec8d227 --- /dev/null +++ b/source/java/org/alfresco/repo/invitation/JbpmInvitationServiceImplTests.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.invitation; + +import org.alfresco.repo.site.SiteModel; +import org.alfresco.service.cmr.invitation.Invitation; + +/** + * @author Nick Smith + * @since 4.0 + * + */ +public class JbpmInvitationServiceImplTests extends AbstractInvitationServiceImplTest +{ + /** + * {@inheritDoc} + */ + @Override + protected void onSetUpInTransaction() throws Exception + { + super.onSetUpInTransaction(); + + // Add a few Jbpm invitations to check they dont' interfere with Activiti invitations. + workflowAdminService.setJbpmEngineEnabled(false); + + String invitee = USER_ONE; + 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); + + // Start Nominated Invitation + invitationService.inviteNominated(invitee, resourceType, + resourceName, inviteeRole, serverPath, acceptUrl, rejectUrl); + + // Start Moderated Invitation + invitationService.inviteModerated("", invitee, + resourceType, resourceName, inviteeRole); + + // Disable Jbpm and enable Activiti + workflowAdminService.setActivitiEngineEnabled(false); + workflowAdminService.setJbpmEngineEnabled(true); + + } +} diff --git a/source/java/org/alfresco/repo/invitation/activiti/CancelNominatedInviteDelegate.java b/source/java/org/alfresco/repo/invitation/activiti/CancelNominatedInviteDelegate.java index 3defe6d2a2..63599348b7 100644 --- a/source/java/org/alfresco/repo/invitation/activiti/CancelNominatedInviteDelegate.java +++ b/source/java/org/alfresco/repo/invitation/activiti/CancelNominatedInviteDelegate.java @@ -21,6 +21,7 @@ package org.alfresco.repo.invitation.activiti; import java.util.Map; import org.activiti.engine.delegate.DelegateExecution; +import org.alfresco.repo.workflow.activiti.ActivitiConstants; /** * Activiti delegate that is executed when a invitation request has @@ -36,6 +37,7 @@ public class CancelNominatedInviteDelegate extends AbstractInvitationDelegate public void execute(DelegateExecution execution) throws Exception { Map executionVariables = execution.getVariables(); - inviteHelper.cancelInvitation(executionVariables); + String invitationId = ActivitiConstants.ENGINE_ID + "$" + execution.getProcessInstanceId(); + inviteHelper.cancelInvitation(executionVariables, invitationId); } } diff --git a/source/java/org/alfresco/repo/invitation/activiti/RejectModeratedInviteDelegate.java b/source/java/org/alfresco/repo/invitation/activiti/RejectModeratedInviteDelegate.java index 14e8d95ae4..862e086566 100644 --- a/source/java/org/alfresco/repo/invitation/activiti/RejectModeratedInviteDelegate.java +++ b/source/java/org/alfresco/repo/invitation/activiti/RejectModeratedInviteDelegate.java @@ -18,21 +18,8 @@ */ package org.alfresco.repo.invitation.activiti; -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - import org.activiti.engine.delegate.DelegateExecution; -import org.alfresco.repo.action.executer.MailActionExecuter; import org.alfresco.repo.invitation.ModeratedActionReject; -import org.alfresco.repo.invitation.WorkflowModelModeratedInvitation; -import org.alfresco.repo.workflow.activiti.BaseJavaDelegate; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.action.Action; -import org.alfresco.service.cmr.action.ActionService; -import org.alfresco.service.cmr.repository.TemplateService; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * Activiti delegate that is executed when a invitation-moderated process is reviewed @@ -46,61 +33,10 @@ import org.apache.commons.logging.LogFactory; */ public class RejectModeratedInviteDelegate extends AbstractInvitationDelegate { - private static final String REJECT_TEMPLATE = "/alfresco/bootstrap/invite/moderated-reject-email.ftl"; - private static final Log logger = LogFactory.getLog(RejectModeratedInviteDelegate.class); - @Override public void execute(DelegateExecution execution) throws Exception { - final ServiceRegistry serviceRegistry = getServiceRegistry(); - - // Do nothing if emails disabled. - if(!serviceRegistry.getInvitationService().isSendEmails()) - { - return; - } - - final String resourceType = (String) execution.getVariable(WorkflowModelModeratedInvitation.wfVarResourceType); - final String resourceName = (String) execution.getVariable(WorkflowModelModeratedInvitation.wfVarResourceName); - final String inviteeUserName = (String) execution.getVariable(WorkflowModelModeratedInvitation.wfVarInviteeUserName); - final String inviteeRole = (String) execution.getVariable(WorkflowModelModeratedInvitation.wfVarInviteeRole); - final String reviewer = (String) execution.getVariable(WorkflowModelModeratedInvitation.wfVarReviewer); - final String reviewComments = (String) execution.getVariable(WorkflowModelModeratedInvitation.wfVarReviewComments); - - final TemplateService templateService = serviceRegistry.getTemplateService(); - final ActionService actionService = serviceRegistry.getActionService(); - - // send email to the invitee if possible - but don't fail the rejection if email cannot be sent - try - { - // Build our model - Map model = new HashMap(8, 1.0f); - model.put("resourceName", resourceName); - model.put("resourceType", resourceType); - model.put("inviteeRole", inviteeRole); - model.put("reviewComments", reviewComments); - model.put("reviewer", reviewer); - model.put("inviteeUserName", inviteeUserName); - - // Process the template - // Note - because we use a classpath template, rather than a Data Dictionary - // one, we can't have the MailActionExecutor do the template for us - String emailMsg = templateService.processTemplate("freemarker", REJECT_TEMPLATE, model); - - // Send - Action emailAction = actionService.createAction("mail"); - emailAction.setParameterValue(MailActionExecuter.PARAM_TO, inviteeUserName); - emailAction.setParameterValue(MailActionExecuter.PARAM_FROM, reviewer); - emailAction.setParameterValue(MailActionExecuter.PARAM_SUBJECT, "Rejected invitation to web site:" + resourceName); - emailAction.setParameterValue(MailActionExecuter.PARAM_TEXT, emailMsg); - emailAction.setExecuteAsynchronously(true); - actionService.executeAction(emailAction, null); - } - catch(Exception e) - { - // Swallow exception - logger.error("unable to send reject email", e); - } + inviteHelper.rejectModeratedInvitation(execution.getVariables()); } } diff --git a/source/java/org/alfresco/repo/invitation/activiti/RejectNominatedInviteDelegate.java b/source/java/org/alfresco/repo/invitation/activiti/RejectNominatedInviteDelegate.java index 0f72bcd3b7..2e38b79bae 100644 --- a/source/java/org/alfresco/repo/invitation/activiti/RejectNominatedInviteDelegate.java +++ b/source/java/org/alfresco/repo/invitation/activiti/RejectNominatedInviteDelegate.java @@ -20,6 +20,7 @@ package org.alfresco.repo.invitation.activiti; import org.activiti.engine.delegate.DelegateExecution; import org.alfresco.repo.invitation.WorkflowModelNominatedInvitation; +import org.alfresco.repo.workflow.activiti.ActivitiConstants; /** * Activiti delegate that is executed when a invitation request has @@ -36,6 +37,7 @@ public class RejectNominatedInviteDelegate extends AbstractInvitationDelegate { // Get the invitee user name String inviteeUserName = (String) execution.getVariable(WorkflowModelNominatedInvitation.wfVarInviteeUserName); - inviteHelper.deleteAuthenticationIfUnused(inviteeUserName); + String invitationId = ActivitiConstants.ENGINE_ID + "$" + execution.getProcessInstanceId(); + inviteHelper.deleteAuthenticationIfUnused(inviteeUserName, invitationId); } } diff --git a/source/java/org/alfresco/repo/invitation/site/CancelInviteAction.java b/source/java/org/alfresco/repo/invitation/site/CancelInviteAction.java index bd55cbb3d2..d0c9e83db0 100644 --- a/source/java/org/alfresco/repo/invitation/site/CancelInviteAction.java +++ b/source/java/org/alfresco/repo/invitation/site/CancelInviteAction.java @@ -18,22 +18,10 @@ */ package org.alfresco.repo.invitation.site; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarInviteeUserName; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarResourceName; -import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarWorkflowInstanceId; - import java.util.Map; -import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.repo.workflow.jbpm.JBPMEngine; import org.jbpm.graph.exe.ExecutionContext; -import org.springframework.beans.factory.BeanFactory; /** * This class contains logic that gets executed when @@ -53,6 +41,7 @@ public class CancelInviteAction extends AbstractInvitationAction public void execute(ExecutionContext executionContext) throws Exception { Map executionVariables = executionContext.getContextInstance().getVariables(); - inviteHelper.cancelInvitation(executionVariables); + String invitationId = JBPMEngine.ENGINE_ID + "$" + executionContext.getContextInstance().getProcessInstance().getId(); + inviteHelper.cancelInvitation(executionVariables, invitationId); } } diff --git a/source/java/org/alfresco/repo/invitation/site/RejectInviteAction.java b/source/java/org/alfresco/repo/invitation/site/RejectInviteAction.java index 7d4034d705..a1545a4bd0 100644 --- a/source/java/org/alfresco/repo/invitation/site/RejectInviteAction.java +++ b/source/java/org/alfresco/repo/invitation/site/RejectInviteAction.java @@ -19,13 +19,8 @@ package org.alfresco.repo.invitation.site; import org.alfresco.repo.invitation.WorkflowModelNominatedInvitation; -import org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.security.MutableAuthenticationService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.repo.workflow.jbpm.JBPMEngine; import org.jbpm.graph.exe.ExecutionContext; -import org.springframework.beans.factory.BeanFactory; /** * This class contains logic that gets executed when @@ -45,6 +40,7 @@ public class RejectInviteAction extends AbstractInvitationAction { // get the invitee user name String inviteeUserName = (String) executionContext.getVariable(WorkflowModelNominatedInvitation.wfVarInviteeUserName); - inviteHelper.deleteAuthenticationIfUnused(inviteeUserName); + String invitationId = JBPMEngine.ENGINE_ID + "$" + executionContext.getContextInstance().getProcessInstance().getId(); + inviteHelper.deleteAuthenticationIfUnused(inviteeUserName, invitationId); } } diff --git a/source/java/org/alfresco/repo/workflow/WorkflowAdminServiceImpl.java b/source/java/org/alfresco/repo/workflow/WorkflowAdminServiceImpl.java index 408e9eba6c..7a95df5766 100644 --- a/source/java/org/alfresco/repo/workflow/WorkflowAdminServiceImpl.java +++ b/source/java/org/alfresco/repo/workflow/WorkflowAdminServiceImpl.java @@ -30,6 +30,8 @@ import org.alfresco.service.cmr.workflow.WorkflowAdminService; */ public class WorkflowAdminServiceImpl implements WorkflowAdminService { + public static final String NAME = "workflowAdminService"; + private boolean jbpmEngineEnabled = true; private boolean activitiEngineEnabled = true;