diff --git a/config/alfresco/activiti-context.xml b/config/alfresco/activiti-context.xml index 78aea7b39c..e243ce6985 100644 --- a/config/alfresco/activiti-context.xml +++ b/config/alfresco/activiti-context.xml @@ -2,10 +2,10 @@ @@ -44,12 +44,12 @@ - + - - + + @@ -74,6 +74,7 @@ + @@ -187,7 +188,7 @@ factory-method="getManagementService" /> - + diff --git a/config/alfresco/invitation-service-context.xml b/config/alfresco/invitation-service-context.xml index 95f03e64f1..da6a976855 100644 --- a/config/alfresco/invitation-service-context.xml +++ b/config/alfresco/invitation-service-context.xml @@ -5,6 +5,7 @@ + @@ -77,4 +78,28 @@ + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/workflow/invitation-moderated-workflow-model.xml b/config/alfresco/workflow/invitation-moderated-workflow-model.xml index abdb1ba45e..2c24a50a89 100644 --- a/config/alfresco/workflow/invitation-moderated-workflow-model.xml +++ b/config/alfresco/workflow/invitation-moderated-workflow-model.xml @@ -1,70 +1,99 @@ - + - - - - - - + + + + + + - - - + + + - - - bpm:startTask - - bpm:assignee - bpm:groupAssignee - imwf:moderatedInvitationStats - - + + + bpm:startTask + + bpm:assignee + bpm:groupAssignee + imwf:moderatedInvitationStats + + - - bpm:workflowTask - - - d:text - - + + bpm:workflowTask + + bpm:groupAssignee + cm:ownable + imwf:moderatedInvitationStats + + - - bpm:groupAssignee - cm:ownable - imwf:moderatedInvitationStats - + + bpm:activitiOutcomeTask + + + d:text + Reject + + + + + Approve + Reject + + + + + + + + + {http://www.alfresco.org/model/workflow/invite/moderated/1.0}reviewOutcome + + + + + bpm:groupAssignee + cm:ownable + imwf:moderatedInvitationStats + + - + - - - - - - - d:text - - - d:text - WEB_SITE - - - d:text - - - d:text - - - d:text - - - - + + + + + d:text + + + d:text + WEB_SITE + + + d:text + + + d:text + + + d:text + + + d:text + + + + diff --git a/config/alfresco/workflow/invitation-moderated.bpmn20.xml b/config/alfresco/workflow/invitation-moderated.bpmn20.xml index 96434fde26..c92e37ae2d 100644 --- a/config/alfresco/workflow/invitation-moderated.bpmn20.xml +++ b/config/alfresco/workflow/invitation-moderated.bpmn20.xml @@ -27,8 +27,7 @@ - execution.setVariable('wf_reviewOutcome', task.getVariable('wf_reviewOutcome')); - execution.setVariable('imwf_reviewer'), person.properties.userName); + execution.setVariable('imwf_reviewOutcome', task.getVariable('imwf_reviewOutcome')); @@ -46,15 +45,15 @@ - ${wf_reviewOutcome == 'Approve'} + ${imwf_reviewOutcome == 'Approve'} - + - + diff --git a/config/alfresco/workflow/invitation-nominated-workflow-model.xml b/config/alfresco/workflow/invitation-nominated-workflow-model.xml index 136642cfc5..5e6d0734e3 100644 --- a/config/alfresco/workflow/invitation-nominated-workflow-model.xml +++ b/config/alfresco/workflow/invitation-nominated-workflow-model.xml @@ -42,20 +42,54 @@ - - bpm:workflowTask - + + bpm:workflowTask + cancel false - - - inwf:nominatedInvitationStats - - + + + inwf:nominatedInvitationStats + + + + + bpm:activitiOutcomeTask + + + d:text + Reject + + + + + accept + reject + reject + + + + + + + + + {http://www.alfresco.org/model/workflow/invite/moderated/1.0}reviewOutcome + + + + false + + + + inwf:nominatedInvitationStats + + bpm:workflowTask diff --git a/config/alfresco/workflow/invitation-nominated.bpmn20.xml b/config/alfresco/workflow/invitation-nominated.bpmn20.xml index 598962cfea..f58176ad3b 100644 --- a/config/alfresco/workflow/invitation-nominated.bpmn20.xml +++ b/config/alfresco/workflow/invitation-nominated.bpmn20.xml @@ -10,7 +10,7 @@ - + @@ -51,13 +51,13 @@ - + - + - + diff --git a/source/java/org/alfresco/repo/forms/processor/workflow/AbstractWorkflowFormProcessor.java b/source/java/org/alfresco/repo/forms/processor/workflow/AbstractWorkflowFormProcessor.java index 1fbcd0817b..73004ce6a1 100644 --- a/source/java/org/alfresco/repo/forms/processor/workflow/AbstractWorkflowFormProcessor.java +++ b/source/java/org/alfresco/repo/forms/processor/workflow/AbstractWorkflowFormProcessor.java @@ -21,13 +21,12 @@ package org.alfresco.repo.forms.processor.workflow; import java.util.ArrayList; import java.util.List; -import java.util.regex.Matcher; import org.alfresco.repo.forms.Form; import org.alfresco.repo.forms.FormData; +import org.alfresco.repo.forms.FormData.FieldData; import org.alfresco.repo.forms.FormNotFoundException; import org.alfresco.repo.forms.Item; -import org.alfresco.repo.forms.FormData.FieldData; import org.alfresco.repo.forms.processor.FormCreationData; import org.alfresco.repo.forms.processor.node.ContentModelFormProcessor; import org.alfresco.repo.forms.processor.node.ContentModelItemData; diff --git a/source/java/org/alfresco/repo/forms/processor/workflow/TaskFormPersister.java b/source/java/org/alfresco/repo/forms/processor/workflow/TaskFormPersister.java index f831d76107..2e60c509b5 100644 --- a/source/java/org/alfresco/repo/forms/processor/workflow/TaskFormPersister.java +++ b/source/java/org/alfresco/repo/forms/processor/workflow/TaskFormPersister.java @@ -65,7 +65,7 @@ public class TaskFormPersister extends ContentModelFormPersister throw new AccessDeniedException("Failed to update task with id '" + item.getId() + "'."); } - this.updater = new TaskUpdater(item.id, workflowService, nodeService, behaviourFilter); + this.updater = new TaskUpdater(item.getId(), workflowService, nodeService, behaviourFilter); } /** diff --git a/source/java/org/alfresco/repo/forms/processor/workflow/TaskFormProcessor.java b/source/java/org/alfresco/repo/forms/processor/workflow/TaskFormProcessor.java index 0040b75fd1..0f4ef7a6b9 100644 --- a/source/java/org/alfresco/repo/forms/processor/workflow/TaskFormProcessor.java +++ b/source/java/org/alfresco/repo/forms/processor/workflow/TaskFormProcessor.java @@ -99,8 +99,8 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor getPropertyValues(WorkflowTask task) { - return task.properties; + return task.getProperties(); } @Override protected Map getAssociationValues(WorkflowTask item) { - return item.properties; + return item.getProperties(); } @Override @@ -245,7 +241,7 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor props) + { + this.inviteId = props.get(ID_KEY); + this.inviteeUserName = props.get(INVITEE_KEY); + this.resourceName = props.get(RESOURCE_NAME_KEY); + this.roleName = props.get(ROLE_KEY); + String type = props.get(RESOURCE_TYPE_KEY); + this.resourceType = type==null ? ResourceType.WEB_SITE : ResourceType.valueOf(type); + } + /** * What sort of resource is it * @return the resource type @@ -58,26 +76,11 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType; return resourceType; } - public void setResourceType(ResourceType resourceType) - { - this.resourceType = resourceType; - } - - public void setInviteId(String inviteId) - { - this.inviteId = inviteId; - } - public String getInviteId() { return inviteId; } - public void setResourceName(String resourceName) - { - this.resourceName = resourceName; - } - public String getResourceName() { return resourceName; @@ -87,24 +90,11 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType; { return roleName; } - - /** - * @param roleName the roleName to set - */ - public void setRoleName(String roleName) - { - this.roleName = roleName; - } - - public abstract InvitationType getInvitationType(); - - public void setInviteeUserName(String inviteeUserName) - { - this.inviteeUserName = inviteeUserName; - } public String getInviteeUserName() { return inviteeUserName; } + + public abstract InvitationType getInvitationType(); } diff --git a/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java b/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java index 6052b36fb5..2e32042dbb 100644 --- a/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java +++ b/source/java/org/alfresco/repo/invitation/InvitationServiceImpl.java @@ -21,6 +21,7 @@ package org.alfresco.repo.invitation; import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -32,12 +33,12 @@ import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.PasswordGenerator; import org.alfresco.repo.security.authentication.UserNameGenerator; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.workflow.WorkflowConstants; import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.repo.workflow.activiti.ActivitiConstants; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.invitation.Invitation; import org.alfresco.service.cmr.invitation.InvitationException; @@ -56,9 +57,9 @@ import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; +import org.alfresco.service.cmr.workflow.WorkflowAdminService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; import org.alfresco.service.cmr.workflow.WorkflowException; -import org.alfresco.service.cmr.workflow.WorkflowInstance; import org.alfresco.service.cmr.workflow.WorkflowPath; import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.cmr.workflow.WorkflowTask; @@ -77,6 +78,7 @@ import org.springframework.extensions.surf.util.I18NUtil; * * @see org.alfresco.service.cmr.invitation.Invitation * @author mrogers + * @author Nick Smith */ public class InvitationServiceImpl implements InvitationService, NodeServicePolicies.BeforeDeleteNodePolicy { @@ -86,6 +88,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli * Services */ private WorkflowService workflowService; + private WorkflowAdminService workflowAdminService; private PersonService personService; private SiteService siteService; private MutableAuthenticationService authenticationService; @@ -148,7 +151,9 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli { List ret = new ArrayList(3); ret.add(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME); + ret.add(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI); ret.add(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME); + ret.add(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI); // old deprecated invitation workflow. ret.add("jbpm$wf:invite"); return ret; @@ -263,60 +268,46 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli */ public Invitation accept(String invitationId, String ticket) { - Invitation invitation = getInvitation(invitationId); - - if (invitation instanceof NominatedInvitation) + WorkflowTask startTask = getStartTask(invitationId); + NominatedInvitation invitation = getNominatedInvitation(startTask); + if(invitation == null) { - - // Check invitationId and ticket match - if (ticket == null || (!ticket.equals(((NominatedInvitation) invitation).getTicket()))) - { - throw new InvitationException("Response to invite has supplied an invalid ticket. The response to the " - + "invitation could thus not be processed"); - } - - /** - * Nominated invitation complete the wf:invitePendingTask along the - * 'accept' transition because the invitation has been accepted - */ - - // create workflow task query - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - // set the given invite ID as the workflow process ID in the - // workflow query - wfTaskQuery.setProcessId(invitationId); - - // find incomplete invite workflow tasks with given task name - wfTaskQuery.setActive(Boolean.TRUE); - wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); - - // set process name to "wf:invite" so that only - // invite workflow instances are considered by this query - wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); - - // query for invite workflow tasks with the constructed query - List wf_invite_tasks = workflowService.queryTasks(wfTaskQuery); - - if (wf_invite_tasks.size() == 0) - { - Object objs[] = { invitationId }; - throw new InvitationExceptionUserError("invitation.invite.already_finished", objs); - } - - // end all tasks found with this name - for (WorkflowTask workflowTask : wf_invite_tasks) - { - workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_ACCEPT); - } - - return invitation; + throw new InvitationException("State error, accept may only be called on a nominated invitation."); } - throw new InvitationException("State error, cannot call accept a moderated invitation"); - + // Check invitationId and ticket match + if(invitation.getTicket().equals(ticket)==false) + { + //TODO localise msg + String msg = "Response to invite has supplied an invalid ticket. The response to the invitation could thus not be processed"; + throw new InvitationException(msg); + } + endInvitation(startTask, + WorkflowModelNominatedInvitation.WF_TRANSITION_ACCEPT, null, + WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING, WorkflowModelNominatedInvitation.WF_TASK_ACTIVIT_INVITE_PENDING); + return invitation; } + private void endInvitation(WorkflowTask startTask, String transition, Map properties, QName... taskTypes ) + { + List tasks = workflowService.getTasksForWorkflowPath(startTask.getPath().getId()); + if(tasks.size()==1) + { + WorkflowTask task = tasks.get(0); + if(taskTypeMatches(task, taskTypes)) + { + if(properties != null) + { + workflowService.updateTask(task.getId(), properties, null, null); + } + workflowService.endTask(task.getId(), transition); + return; + } + } + // Throw exception if the task not found. + Object objs[] = { startTask.getPath().getInstance().getId() }; + throw new InvitationExceptionUserError("invitation.invite.already_finished", objs); + } + /** * Moderator approves this invitation * @@ -325,41 +316,25 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli */ public Invitation approve(String invitationId, String reason) { - Invitation invitation = getInvitation(invitationId); - if (invitation instanceof ModeratedInvitation) + WorkflowTask startTask = getStartTask(invitationId); + ModeratedInvitation invitation = getModeratedInvitation(startTask); + if(invitation == null) { - // Check approver is a site manager - String approverUserName = this.authenticationService.getCurrentUserName(); - checkManagerRole(approverUserName, invitation.getResourceType(), invitation.getResourceName()); - - WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); - - // 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); - wfModeratedTaskQuery.setProcessId(invitationId); - - // query for invite review tasks - List wf_moderated_tasks = this.workflowService.queryTasks(wfModeratedTaskQuery); - - for (WorkflowTask workflowTask : wf_moderated_tasks) - { - Map wfReviewProps = new HashMap(); - wfReviewProps.put(ContentModel.PROP_OWNER, approverUserName); - wfReviewProps.put(WorkflowModelModeratedInvitation.WF_PROP_REVIEW_COMMENTS, reason); - workflowService.updateTask(workflowTask.id, wfReviewProps, null, null); - workflowService.endTask(workflowTask.id, WorkflowModelModeratedInvitation.WF_TRANSITION_APPROVE); - } - } - else - { - throw new InvitationException("State error, cannot call approve on this type of invitation" - + invitation.getClass().getName()); + String msg = "State error, can only call approve on a Moderated invitation."; + throw new InvitationException(msg); } + + // Check approver is a site manager + String currentUser = this.authenticationService.getCurrentUserName(); + checkManagerRole(currentUser, invitation.getResourceType(), invitation.getResourceName()); + Map wfReviewProps = new HashMap(); + wfReviewProps.put(ContentModel.PROP_OWNER, currentUser); + wfReviewProps.put(WorkflowModelModeratedInvitation.WF_PROP_REVIEW_COMMENTS, reason); + endInvitation(startTask, + WorkflowModelModeratedInvitation.WF_TRANSITION_APPROVE, + wfReviewProps, + WorkflowModelModeratedInvitation.WF_ACTIVITI_REVIEW_TASK, WorkflowModelModeratedInvitation.WF_REVIEW_TASK); return invitation; - } /** @@ -370,135 +345,78 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli */ public Invitation reject(String invitationId, String reason) { - Invitation invitation = getInvitation(invitationId); - - if (invitation instanceof NominatedInvitation) + WorkflowTask startTask = getStartTask(invitationId); + if(taskTypeMatches(startTask, WorkflowModelModeratedInvitation.WF_START_TASK)) { - - /** - * Nominated invitation complete the wf:invitePendingTask along the - * 'reject' transition because the invitation has been rejected - */ - // create workflow task query - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - // set the given invite ID as the workflow process ID in the - // workflow query - wfTaskQuery.setProcessId(invitationId); - - // find incomplete invite workflow tasks with given task name - wfTaskQuery.setActive(Boolean.TRUE); - wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); - - // set process name to "wf:invite" so that only - // invite workflow instances are considered by this query - wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); - - // query for invite workflow tasks with the constructed query - List wf_invite_tasks = workflowService.queryTasks(wfTaskQuery); - - if (wf_invite_tasks.size() == 0) - { - Object objs[] = { invitationId }; - throw new InvitationExceptionUserError("invitation.invite.already_finished", objs); - } - - // end all tasks found with this name - for (WorkflowTask workflowTask : wf_invite_tasks) - { - workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_REJECT); - } - - return invitation; + return rejectModeratedInvitation(startTask, reason); } - - if (invitation instanceof ModeratedInvitation) + else { - WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); - - // Check rejecter is a site manager and throw and exception if not - String rejecterUserName = this.authenticationService.getCurrentUserName(); - checkManagerRole(rejecterUserName, invitation.getResourceType(), invitation.getResourceName()); - - // 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); - wfModeratedTaskQuery.setProcessId(invitationId); - - // query for invite review tasks - List wf_moderated_tasks = this.workflowService.queryTasks(wfModeratedTaskQuery); - - for (WorkflowTask workflowTask : wf_moderated_tasks) - { - Map wfReviewProps = new HashMap(); - wfReviewProps.put(ContentModel.PROP_OWNER, rejecterUserName); - wfReviewProps.put(WorkflowModelModeratedInvitation.WF_PROP_REVIEW_COMMENTS, reason); - workflowService.updateTask(workflowTask.id, wfReviewProps, null, null); - this.workflowService.endTask(workflowTask.id, WorkflowModelModeratedInvitation.WF_TRANSITION_REJECT); - } - - return invitation; + return rejectNominatedInvitation(startTask); } + } + private Invitation rejectModeratedInvitation(WorkflowTask startTask, String reason) + { + ModeratedInvitation invitation = getModeratedInvitation(startTask); + // Check rejecter is a site manager and throw and exception if not + String rejecterUserName = this.authenticationService.getCurrentUserName(); + checkManagerRole(rejecterUserName, invitation.getResourceType(), invitation.getResourceName()); + + Map properties = new HashMap(); + properties.put(ContentModel.PROP_OWNER, rejecterUserName); + properties.put(WorkflowModelModeratedInvitation.WF_PROP_REVIEW_COMMENTS, reason); + + endInvitation(startTask, + WorkflowModelModeratedInvitation.WF_TRANSITION_REJECT, + properties, + WorkflowModelModeratedInvitation.WF_ACTIVITI_REVIEW_TASK, WorkflowModelModeratedInvitation.WF_REVIEW_TASK); return invitation; } - /* - * cancel a pending request + private Invitation rejectNominatedInvitation(WorkflowTask startTask) + { + NominatedInvitation invitation = getNominatedInvitation(startTask); + endInvitation(startTask, + WorkflowModelNominatedInvitation.WF_TRANSITION_REJECT, null, + WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING, WorkflowModelNominatedInvitation.WF_TASK_ACTIVIT_INVITE_PENDING); + return invitation; + } + + /** + * {@inheritDoc} */ public Invitation cancel(String invitationId) { - Invitation invitation = getInvitation(invitationId); - - if (invitation instanceof NominatedInvitation) + WorkflowTask startTask = getStartTask(invitationId); + if(taskTypeMatches(startTask, WorkflowModelModeratedInvitation.WF_START_TASK)) { - - // Check canceller is a site manager - String approverUserName = this.authenticationService.getCurrentUserName(); - checkManagerRole(approverUserName, invitation.getResourceType(), invitation.getResourceName()); - - // create workflow task query - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - // set the given invite ID as the workflow process ID in the - // workflow query - wfTaskQuery.setProcessId(invitationId); - - // find incomplete invite workflow tasks with given task name - wfTaskQuery.setActive(Boolean.TRUE); - wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); - - // set process name to "wf:invite" so that only - // invite workflow instances are considered by this query - wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); - - // query for invite workflow tasks with the constructed query - List wf_invite_tasks = workflowService.queryTasks(wfTaskQuery); - - // end all tasks found with this name - for (WorkflowTask workflowTask : wf_invite_tasks) - { - workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_CANCEL); - } + return cancelModeratedInvitation(startTask); } - - if (invitation instanceof ModeratedInvitation) + else { - // Moderated invitation may be cancelled by either a site manager or - // the invitee. - String currentUserName = this.authenticationService.getCurrentUserName(); - - if (!currentUserName.equals(((ModeratedInvitation) invitation).getInviteeUserName())) - { - checkManagerRole(currentUserName, invitation.getResourceType(), invitation.getResourceName()); - } - workflowService.cancelWorkflow(invitationId); + return cancelNominatedInvitation(startTask); } + } + private Invitation cancelModeratedInvitation(WorkflowTask startTask) + { + ModeratedInvitation invitation = getModeratedInvitation(startTask); + String currentUserName = this.authenticationService.getCurrentUserName(); + if (false == currentUserName.equals(invitation.getInviteeUserName())) + { + checkManagerRole(currentUserName, invitation.getResourceType(), invitation.getResourceName()); + } + workflowService.cancelWorkflow(invitation.getInviteId()); + return invitation; + } + + private Invitation cancelNominatedInvitation(WorkflowTask startTask) + { + NominatedInvitation invitation = getNominatedInvitation(startTask); + endInvitation(startTask, + WorkflowModelNominatedInvitation.WF_TRANSITION_CANCEL, null, + WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING, WorkflowModelNominatedInvitation.WF_TASK_ACTIVIT_INVITE_PENDING); return invitation; } @@ -512,83 +430,67 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli */ public Invitation getInvitation(String invitationId) { + WorkflowTask startTask = getStartTask(invitationId); + return getInvitation(startTask); + } + private Invitation getInvitation(WorkflowTask startTask) + { + Invitation invitation = getNominatedInvitation(startTask); + if(invitation == null) + { + invitation = getModeratedInvitation(startTask); + } + return invitation; + } + + private ModeratedInvitation getModeratedInvitation(WorkflowTask startTask) + { + ModeratedInvitation invitation = null; + if (taskTypeMatches(startTask, WorkflowModelModeratedInvitation.WF_START_TASK)) + { + String invitationId = startTask.getPath().getInstance().getId(); + invitation = new ModeratedInvitationImpl(invitationId, startTask.getProperties()); + } + return invitation; + } + + private NominatedInvitation getNominatedInvitation(WorkflowTask startTask) + { + NominatedInvitation invitation = null; + if (taskTypeMatches(startTask, WorkflowModelNominatedInvitation.WF_TASK_INVITE_TO_SITE)) + { + Date inviteDate = startTask.getPath().getInstance().getStartDate(); + String invitationId = startTask.getPath().getInstance().getId(); + invitation = new NominatedInvitationImpl(invitationId, inviteDate, startTask.getProperties()); + } + return invitation; + } + + private boolean taskTypeMatches(WorkflowTask task, QName... types) + { + QName taskDefName = task.getDefinition().getMetadata().getName(); + return Arrays.asList(types).contains(taskDefName); + } + + private WorkflowTask getStartTask(String invitationId) + { validateInvitationId(invitationId); - - WorkflowInstance wi = null; + WorkflowTask startTask = null; try { - wi = workflowService.getWorkflowById(invitationId); + startTask = workflowService.getStartTask(invitationId); } catch (WorkflowException we) { // Do nothing } - - if (wi == null) + if (startTask == null) { Object objs[] = { invitationId }; throw new InvitationExceptionNotFound("invitation.error.not_found", objs); } - String workflowName = wi.getDefinition().getName(); - - if (workflowName.equals(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME)) - { - // This is a nominated invitation - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - wfTaskQuery.setProcessId(invitationId); - - // filter to find only the start task which contains the properties. - wfTaskQuery.setTaskState(WorkflowTaskState.COMPLETED); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE); - - // query for invite workflow task associate - List inviteStartTasks = workflowService.queryTasks(wfTaskQuery); - - // should also be 0 or 1 - if (inviteStartTasks.size() < 1) - { - throw new InvitationExceptionNotFound("invitation.error.not_found", invitationId); - } - else - { - WorkflowTask task = inviteStartTasks.get(0); - NominatedInvitationImpl result = new NominatedInvitationImpl(task.getProperties()); - result.setSentInviteDate(task.getPath().getInstance().getStartDate()); - result.setInviteId(invitationId); - return result; - } - } - if (workflowName.equals(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME)) - { - // This is a moderated invitation - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - wfTaskQuery.setProcessId(invitationId); - - // filter to find only the start task which contains the properties. - wfTaskQuery.setTaskState(WorkflowTaskState.COMPLETED); - wfTaskQuery.setTaskName(WorkflowModelModeratedInvitation.WF_START_TASK); - - List inviteStartTasks = workflowService.queryTasks(wfTaskQuery); - - // should also be 0 or 1 - if (inviteStartTasks.size() < 1) - { - // No start task - workflow may have been completed - Object objs[] = { invitationId }; - throw new InvitationExceptionNotFound("invitation.error.not_found", objs); - } - else - { - WorkflowTask task = inviteStartTasks.get(0); - ModeratedInvitationImpl result = new ModeratedInvitationImpl(task.properties); - result.setInviteId(invitationId); - return result; - } - } - - // Unknown workflow type here - return null; + return startTask; } /** @@ -627,7 +529,6 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli */ public List searchInvitation(InvitationSearchCriteria criteria) { - List ret = new ArrayList(); InvitationSearchCriteria.InvitationType toSearch = criteria.getInvitationType(); @@ -672,7 +573,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli // pick up the pending task wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); + wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING); wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); // query for invite workflow tasks @@ -787,8 +688,8 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli for (WorkflowTask workflowTask : wf_moderated_tasks) { // Add moderated invitations - String workflowId = workflowTask.path.instance.id; - ModeratedInvitationImpl result = new ModeratedInvitationImpl(workflowTask.properties); + 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 @@ -797,7 +698,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli for (QName key : keys) { Object val1 = wfQueryModeratedProps.get(key); - Object val2 = workflowTask.properties.get(key); + Object val2 = workflowTask.getProperties().get(key); if (!val1.equals(val2)) { // crap detected @@ -807,8 +708,6 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli } } // TODO END ALFCOM-2598 Work-around - - result.setInviteId(workflowId); if (!crap) { ret.add(result); @@ -833,6 +732,14 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli this.workflowService = workflowService; } + /** + * @param workflowAdminService the workflowAdminService to set + */ + public void setWorkflowAdminService(WorkflowAdminService workflowAdminService) + { + this.workflowAdminService = workflowAdminService; + } + /** * @return the workflow service */ @@ -1016,9 +923,8 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli private ModeratedInvitation startModeratedInvite(String inviteeComments, String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String inviteeRole) { - // Get invitee person NodeRef to add as assignee - NodeRef inviteeNodeRef = this.personService.getPerson(inviteeUserName); + NodeRef inviteeNodeRef = personService.getPerson(inviteeUserName); SiteInfo siteInfo = siteService.getSite(resourceName); @@ -1036,10 +942,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli // get the workflow description String workflowDescription = generateWorkflowDescription(siteInfo, "invitation.moderated.workflow.description"); - NodeRef wfPackage = this.workflowService.createPackage(null); - Map workflowProps = new HashMap(16); - workflowProps.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); workflowProps.put(WorkflowModel.ASSOC_ASSIGNEE, inviteeNodeRef); workflowProps.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, workflowDescription); workflowProps.put(WorkflowModelModeratedInvitation.ASSOC_GROUP_ASSIGNEE, roleGroup); @@ -1051,44 +954,8 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli // get the moderated workflow - WorkflowDefinition wfDefinition = this.workflowService - .getDefinitionByName(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME); - if (wfDefinition == null) - { - // handle workflow definition does not exist - Object objs[] = { WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME }; - throw new InvitationException("invitation.error.noworkflow", objs); - } - - // start the workflow - WorkflowPath wfPath = this.workflowService.startWorkflow(wfDefinition.getId(), workflowProps); - - String workflowId = wfPath.instance.id; - String wfPathId = wfPath.id; - List wfTasks = this.workflowService.getTasksForWorkflowPath(wfPathId); - - // throw an exception if no tasks where found on the workflow path - if (wfTasks.size() == 0) - { - Object objs[] = { WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME }; - throw new InvitationException("invitation.error.notasks", objs); - } - - try - { - WorkflowTask wfStartTask = wfTasks.get(0); - this.workflowService.endTask(wfStartTask.id, null); - } - catch (RuntimeException err) - { - if (logger.isDebugEnabled()) - logger.debug("Failed - caught error during Invite workflow transition: " + err.getMessage()); - throw err; - } - - ModeratedInvitationImpl result = new ModeratedInvitationImpl(workflowProps); - result.setInviteId(workflowId); - return result; + WorkflowDefinition wfDefinition = getWorkflowDefinition(false); + return (ModeratedInvitation) startWorkflow(wfDefinition, workflowProps); } /** @@ -1111,7 +978,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli // get the inviter user name (the name of user web script is executed // under) - String inviterUserName = this.authenticationService.getCurrentUserName(); + String inviterUserName = authenticationService.getCurrentUserName(); boolean created = false; checkManagerRole(inviterUserName, resourceType, siteShortName); @@ -1196,20 +1063,6 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli } } } - else - { - // TODO MER - Is the code block neccessary - seems to do nothing ? - // inviteeUserName was specified - NodeRef person = this.personService.getPerson(inviteeUserName); - - // TODO - Serializable firstNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_FIRSTNAME); - Serializable lastNameVal = this.getNodeService().getProperty(person, ContentModel.PROP_LASTNAME); - Serializable emailVal = this.getNodeService().getProperty(person, ContentModel.PROP_EMAIL); - firstNameVal = DefaultTypeConverter.INSTANCE.convert(String.class, firstNameVal); - lastNameVal = DefaultTypeConverter.INSTANCE.convert(String.class, lastNameVal); - emailVal = DefaultTypeConverter.INSTANCE.convert(String.class, emailVal); - } /** * throw exception if person is already a member of the given site @@ -1248,19 +1101,10 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli // Start the invite workflow with inviter, invitee and site properties // - WorkflowDefinition wfDefinition = this.workflowService - .getDefinitionByName(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME); - - if (wfDefinition == null) - { - // handle workflow definition does not exist - Object objs[] = { WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME }; - throw new InvitationException("invitation.error.noworkflow", objs); - } + WorkflowDefinition wfDefinition = getWorkflowDefinition(true); // Get invitee person NodeRef to add as assignee - NodeRef inviteeNodeRef = this.personService.getPerson(inviteeUserName); - + NodeRef inviteeNodeRef = personService.getPerson(inviteeUserName); SiteInfo siteInfo = this.siteService.getSite(siteShortName); String siteDescription = siteInfo.getDescription(); if (siteDescription == null) @@ -1295,6 +1139,14 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli workflowProps.put(WorkflowModelNominatedInvitation.WF_PROP_REJECT_URL, rejectUrl); workflowProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITE_TICKET, inviteTicket); + return (NominatedInvitation) startWorkflow(wfDefinition, workflowProps); + } + + private Invitation startWorkflow(WorkflowDefinition wfDefinition, Map workflowProps) + { + NodeRef wfPackage = workflowService.createPackage(null); + workflowProps.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); + // start the workflow WorkflowPath wfPath = this.workflowService.startWorkflow(wfDefinition.getId(), workflowProps); @@ -1303,54 +1155,19 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli // // get the workflow tasks - String workflowId = wfPath.instance.id; - String wfPathId = wfPath.id; - List wfTasks = this.workflowService.getTasksForWorkflowPath(wfPathId); - - // throw an exception if no tasks where found on the workflow path - if (wfTasks.size() == 0) - { - Object objs[] = { WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME }; - throw new InvitationException("invitation.error.notasks", objs); - } - - // - // first task in workflow task list (there should only be one) - // associated - // with the workflow path id (above) should be "wf:inviteToSiteTask", - // otherwise - // throw web script exception - // - String wfTaskName = wfTasks.get(0).name; - QName wfTaskNameQName = QName.createQName(wfTaskName, this.namespaceService); - QName inviteToSiteTaskQName = WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE; - if (!wfTaskNameQName.equals(inviteToSiteTaskQName)) - { - Object objs[] = { wfPathId, WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE }; - throw new InvitationException("invitation.error.wrong_first_task", objs); - } - - // get "inviteToSite" task - WorkflowTask wfStartTask = wfTasks.get(0); - + String workflowId = wfPath.getInstance().getId(); + WorkflowTask startTask = workflowService.getStartTask(workflowId); + // attach empty package to start task, end it and follow with transition // that sends out the invite if (logger.isDebugEnabled()) logger.debug("Starting Invite workflow task by attaching empty package..."); - NodeRef wfPackage = this.workflowService.createPackage(null); - Map wfTaskProps = new HashMap(1, 1.0f); - wfTaskProps.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); - wfTaskProps.put(WorkflowModel.PROP_WORKFLOW_INSTANCE_ID, workflowId); - - if (logger.isDebugEnabled()) - logger.debug("Updating Invite workflow task..."); - this.workflowService.updateTask(wfStartTask.id, wfTaskProps, null, null); if (logger.isDebugEnabled()) logger.debug("Transitioning Invite workflow task..."); try { - this.workflowService.endTask(wfStartTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_SEND_INVITE); + workflowService.endTask(startTask.getId(), null); } catch (RuntimeException err) { @@ -1358,12 +1175,44 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli logger.debug("Failed - caught error during Invite workflow transition: " + err.getMessage()); throw err; } + Invitation invitation = getInvitation(startTask); + return invitation; + } - NominatedInvitationImpl result = new NominatedInvitationImpl(workflowProps); - result.setTicket(inviteTicket); - result.setInviteId(workflowId); - result.setSentInviteDate(new Date()); - return result; + /** + * Return Activiti workflow definition unless Activiti engine is disabled. + * @param isNominated TODO + * @return + */ + private WorkflowDefinition getWorkflowDefinition(boolean isNominated) + { + String workflowName = isNominated ? getNominatedDefinitionName() : getModeratedDefinitionName(); + WorkflowDefinition definition = workflowService.getDefinitionByName(workflowName); + if (definition == null) + { + // handle workflow definition does not exist + Object objs[] = {workflowName}; + throw new InvitationException("invitation.error.noworkflow", objs); + } + return definition; + } + + private String getNominatedDefinitionName() + { +// if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) +// { +// return WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI; +// } + return WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME; + } + + private String getModeratedDefinitionName() + { +// if(workflowAdminService.isEngineEnabled(ActivitiConstants.ENGINE_ID)) +// { +// return WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI; +// } + return WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME; } /** diff --git a/source/java/org/alfresco/repo/invitation/InviteHelper.java b/source/java/org/alfresco/repo/invitation/InviteHelper.java index 6d3617d43d..799263dc71 100644 --- a/source/java/org/alfresco/repo/invitation/InviteHelper.java +++ b/source/java/org/alfresco/repo/invitation/InviteHelper.java @@ -28,6 +28,8 @@ import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVa import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarRole; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarServerPath; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarWorkflowInstanceId; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_TASK_ACTIVIT_INVITE_PENDING; import java.io.Serializable; import java.util.Arrays; @@ -66,6 +68,7 @@ import org.alfresco.service.cmr.workflow.WorkflowTaskState; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.util.collections.CollectionUtils; +import org.alfresco.util.collections.Filter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; @@ -153,32 +156,7 @@ public class InviteHelper implements InitializingBean */ public WorkflowTask findInviteStartTask(String inviteId) { - // create workflow task query - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - wfTaskQuery.setProcessId(inviteId); - - // set process name to "wf:invite" so that only tasks associated with - // invite workflow instances are returned by query - wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); - - // filter to find only the invite start task - wfTaskQuery.setTaskState(WorkflowTaskState.COMPLETED); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_TO_SITE); - - // query for invite workflow task associate - List inviteStartTasks = workflowService - .queryTasks(wfTaskQuery); - - // should also be 0 or 1 - if (inviteStartTasks.size() < 1) - { - return null; - } - else - { - return inviteStartTasks.get(0); - } + return workflowService.getStartTask(inviteId); } /** @@ -188,28 +166,16 @@ public class InviteHelper implements InitializingBean */ public List findInvitePendingTasks(String inviteeUserName) { - // create workflow task query - WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); - - // set process name to "wf:invite" so that only tasks associated with - // invite workflow instances are returned by query - wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); - - // set query to only pick up invite workflow instances - // associated with the given invitee user name - Map processCustomProps = new HashMap(1, 1.0f); - processCustomProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_USER_NAME, inviteeUserName); - wfTaskQuery.setProcessCustomProps(processCustomProps); - - // set query to only pick up in-progress invite pending tasks - wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); - wfTaskQuery.setTaskName(WorkflowModelNominatedInvitation.WF_INVITE_TASK_INVITE_PENDING); - - // query for invite workflow task associate - List inviteStartTasks = workflowService - .queryTasks(wfTaskQuery); - - return inviteStartTasks; + List tasks = workflowService.getAssignedTasks(inviteeUserName, WorkflowTaskState.IN_PROGRESS); + return CollectionUtils.filter(tasks, new Filter() + { + public Boolean apply(WorkflowTask value) + { + QName taskDefName = value.getDefinition().getMetadata().getName(); + return WF_TASK_INVITE_PENDING.equals(taskDefName) || + WF_TASK_ACTIVIT_INVITE_PENDING.equals(taskDefName); + } + }); } /** @@ -276,7 +242,7 @@ public class InviteHelper implements InitializingBean { if (overrideExisting || !siteService.isMember(siteName, invitee)) { - siteService.setMembership(siteName, invitee, role); + siteService.setMembership(siteName, invitee, role); } return null; } diff --git a/source/java/org/alfresco/repo/invitation/ModeratedInvitationImpl.java b/source/java/org/alfresco/repo/invitation/ModeratedInvitationImpl.java index 075b1b1b19..62c7db0395 100644 --- a/source/java/org/alfresco/repo/invitation/ModeratedInvitationImpl.java +++ b/source/java/org/alfresco/repo/invitation/ModeratedInvitationImpl.java @@ -18,7 +18,14 @@ */ package org.alfresco.repo.invitation; +import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_INVITEE_COMMENTS; +import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_INVITEE_ROLE; +import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_INVITEE_USER_NAME; +import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME; +import static org.alfresco.repo.invitation.WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE; + import java.io.Serializable; +import java.util.HashMap; import java.util.Map; import org.alfresco.service.cmr.invitation.ModeratedInvitation; @@ -32,29 +39,29 @@ import org.alfresco.service.namespace.QName; { private static final long serialVersionUID = -5557544865169876451L; - private String inviteeComments; + private final String inviteeComments; - public ModeratedInvitationImpl(Map workflowProps) + public ModeratedInvitationImpl(String inviteId, Map props) { - setInviteeUserName((String)workflowProps.get(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_USER_NAME)); - setRoleName((String)workflowProps.get(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_ROLE)); - setResourceName((String)workflowProps.get(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_NAME)); - if(workflowProps.containsKey(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE)) - { - setResourceType(ResourceType.valueOf((String)workflowProps.get(WorkflowModelModeratedInvitation.WF_PROP_RESOURCE_TYPE))); - } - inviteeComments = (String)workflowProps.get(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_COMMENTS); + super(getConstructorProps(inviteId, props)); + inviteeComments = (String)props.get(WF_PROP_INVITEE_COMMENTS); } + private static Map getConstructorProps(String inviteId, Map props) + { + Map parentProps = new HashMap(); + parentProps.put(ID_KEY, inviteId); + parentProps.put(INVITEE_KEY, (String) props.get(WF_PROP_INVITEE_USER_NAME)); + parentProps.put(ROLE_KEY,(String)props.get(WF_PROP_INVITEE_ROLE)); + parentProps.put(RESOURCE_NAME_KEY,(String)props.get(WF_PROP_RESOURCE_NAME)); + parentProps.put(RESOURCE_TYPE_KEY,(String)props.get(WF_PROP_RESOURCE_TYPE)); + return parentProps; + } + public String getInviteeComments() { return inviteeComments; } - - public void setInviteeComments(String inviteeComments) - { - this.inviteeComments = inviteeComments; - } @Override public InvitationType getInvitationType() { diff --git a/source/java/org/alfresco/repo/invitation/NominatedInvitationImpl.java b/source/java/org/alfresco/repo/invitation/NominatedInvitationImpl.java index 73b0aa7fe5..a5d7a320d6 100644 --- a/source/java/org/alfresco/repo/invitation/NominatedInvitationImpl.java +++ b/source/java/org/alfresco/repo/invitation/NominatedInvitationImpl.java @@ -18,8 +18,24 @@ */ package org.alfresco.repo.invitation; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_ACCEPT_URL; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_INVITEE_EMAIL; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_INVITEE_FIRSTNAME; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_INVITEE_LASTNAME; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_INVITEE_ROLE; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_INVITEE_USER_NAME; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_INVITER_USER_NAME; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_INVITE_TICKET; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_REJECT_URL; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_DESCRIPTION; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TITLE; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE; +import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.WF_PROP_SERVER_PATH; + import java.io.Serializable; import java.util.Date; +import java.util.HashMap; import java.util.Map; import org.alfresco.service.cmr.invitation.NominatedInvitation; @@ -35,43 +51,43 @@ import org.alfresco.service.namespace.QName; { private static final long serialVersionUID = -8800842866845149466L; - private String inviteeFirstName; - private String inviteeLastName; - private String inviteeEmail; - private String inviterUserName; - private String resourceDescription; - private String resourceTitle; - private String serverPath; - private String acceptUrl; - private String rejectUrl; - private Date sentInviteDate; - private String ticket; + private final String inviteeFirstName; + private final String inviteeLastName; + private final String inviteeEmail; + private final String inviterUserName; + private final String resourceDescription; + private final String resourceTitle; + private final String serverPath; + private final String acceptUrl; + private final String rejectUrl; + private final Date sentInviteDate; + private final String ticket; - public NominatedInvitationImpl(Map workflowProps) + public NominatedInvitationImpl(String inviteId, Date inviteDate, Map props) { - setInviteeUserName((String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_USER_NAME)); - setRoleName((String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_ROLE)); - inviteeFirstName = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_FIRSTNAME); - inviteeLastName = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_LASTNAME); - inviteeEmail = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_EMAIL); - inviterUserName = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITER_USER_NAME); - resourceTitle = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TITLE); - resourceDescription = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_DESCRIPTION); - setResourceName( (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME)); - - if (workflowProps.containsKey(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE)) - { - setResourceType(ResourceType.valueOf((String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE))); - } - serverPath = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_SERVER_PATH); - acceptUrl = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_ACCEPT_URL); - rejectUrl = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_REJECT_URL); - ticket = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITE_TICKET); + super(getConstructorProps(inviteId, props)); + inviteeFirstName = (String)props.get(WF_PROP_INVITEE_FIRSTNAME); + inviteeLastName = (String)props.get(WF_PROP_INVITEE_LASTNAME); + inviteeEmail = (String)props.get(WF_PROP_INVITEE_EMAIL); + inviterUserName = (String)props.get(WF_PROP_INVITER_USER_NAME); + resourceTitle = (String)props.get(WF_PROP_RESOURCE_TITLE); + resourceDescription = (String)props.get(WF_PROP_RESOURCE_DESCRIPTION); + serverPath = (String)props.get(WF_PROP_SERVER_PATH); + acceptUrl = (String)props.get(WF_PROP_ACCEPT_URL); + rejectUrl = (String)props.get(WF_PROP_REJECT_URL); + this.ticket = (String)props.get(WF_PROP_INVITE_TICKET); + this.sentInviteDate =inviteDate; } - public void setInviteeFirstName(String inviteeFirstName) + private static Map getConstructorProps(String inviteId, Map props) { - this.inviteeFirstName = inviteeFirstName; + Map parentProps = new HashMap(); + parentProps.put(ID_KEY, inviteId); + parentProps.put(INVITEE_KEY, (String) props.get(WF_PROP_INVITEE_USER_NAME)); + parentProps.put(ROLE_KEY,(String)props.get(WF_PROP_INVITEE_ROLE)); + parentProps.put(RESOURCE_NAME_KEY,(String)props.get(WF_PROP_RESOURCE_NAME)); + parentProps.put(RESOURCE_TYPE_KEY,(String)props.get(WF_PROP_RESOURCE_TYPE)); + return parentProps; } public String getInviteeFirstName() @@ -79,21 +95,11 @@ import org.alfresco.service.namespace.QName; return inviteeFirstName; } - public void setInviteeLastName(String inviteeLastName) - { - this.inviteeLastName = inviteeLastName; - } - public String getInviteeLastName() { return inviteeLastName; } - public void setInviteeEmail(String inviteeEmail) - { - this.inviteeEmail = inviteeEmail; - } - public String getInviteeEmail() { return inviteeEmail; @@ -109,51 +115,26 @@ import org.alfresco.service.namespace.QName; return resourceTitle; } - public void setServerPath(String serverPath) - { - this.serverPath = serverPath; - } - public String getServerPath() { return serverPath; } - public void setAcceptUrl(String acceptUrl) - { - this.acceptUrl = acceptUrl; - } - public String getAcceptUrl() { return acceptUrl; } - public void setRejectUrl(String rejectUrl) - { - this.rejectUrl = rejectUrl; - } - public String getRejectUrl() { return rejectUrl; } - public void setSentInviteDate(Date sentInviteDate) - { - this.sentInviteDate = sentInviteDate; - } - public Date getSentInviteDate() { return sentInviteDate; } - public void setTicket(String ticket) - { - this.ticket = ticket; - } - public String getTicket() { return ticket; @@ -164,11 +145,6 @@ import org.alfresco.service.namespace.QName; return inviterUserName; } - public void setInviterUserName(String inviterUserName) - { - this.inviterUserName= inviterUserName; - } - @Override public InvitationType getInvitationType() { diff --git a/source/java/org/alfresco/repo/invitation/WorkflowModelModeratedInvitation.java b/source/java/org/alfresco/repo/invitation/WorkflowModelModeratedInvitation.java index 5e016eab67..7ceac0aae6 100644 --- a/source/java/org/alfresco/repo/invitation/WorkflowModelModeratedInvitation.java +++ b/source/java/org/alfresco/repo/invitation/WorkflowModelModeratedInvitation.java @@ -41,6 +41,7 @@ public interface WorkflowModelModeratedInvitation // tasks public static final QName WF_START_TASK = QName.createQName(NAMESPACE_URI, "moderatedInvitationSubmitTask"); public static final QName WF_REVIEW_TASK = QName.createQName(NAMESPACE_URI,"moderatedInvitationReviewTask"); + public static final QName WF_ACTIVITI_REVIEW_TASK = QName.createQName(NAMESPACE_URI,"activitiModeratedInvitationReviewTask"); // associations static final QName ASSOC_GROUP_ASSIGNEE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "groupAssignee"); diff --git a/source/java/org/alfresco/repo/invitation/WorkflowModelNominatedInvitation.java b/source/java/org/alfresco/repo/invitation/WorkflowModelNominatedInvitation.java index 4534953012..6a737890e9 100644 --- a/source/java/org/alfresco/repo/invitation/WorkflowModelNominatedInvitation.java +++ b/source/java/org/alfresco/repo/invitation/WorkflowModelNominatedInvitation.java @@ -37,8 +37,9 @@ public interface WorkflowModelNominatedInvitation public static final String WORKFLOW_DEFINITION_NAME_ACTIVITI = "activiti$activitiInvitationNominated"; // tasks - public static final QName WF_INVITE_TASK_INVITE_TO_SITE = QName.createQName(NAMESPACE_URI, "inviteToSiteTask"); - public static final QName WF_INVITE_TASK_INVITE_PENDING = QName.createQName(NAMESPACE_URI, "invitePendingTask"); + public static final QName WF_TASK_INVITE_TO_SITE = QName.createQName(NAMESPACE_URI, "inviteToSiteTask"); + public static final QName WF_TASK_INVITE_PENDING = QName.createQName(NAMESPACE_URI, "invitePendingTask"); + public static final QName WF_TASK_ACTIVIT_INVITE_PENDING = QName.createQName(NAMESPACE_URI, "activitiInvitePendingTask"); public static final QName WF_TASK_ACCEPT_INVITE = QName.createQName(NAMESPACE_URI, "acceptInviteTask"); public static final QName WF_TASK_REJECT_INVITE = QName.createQName(NAMESPACE_URI, "rejectInviteTask"); diff --git a/source/java/org/alfresco/repo/invitation/activiti/RejectModeratedInviteDelegate.java b/source/java/org/alfresco/repo/invitation/activiti/RejectModeratedInviteDelegate.java index 882b4c8fdd..14e8d95ae4 100644 --- a/source/java/org/alfresco/repo/invitation/activiti/RejectModeratedInviteDelegate.java +++ b/source/java/org/alfresco/repo/invitation/activiti/RejectModeratedInviteDelegate.java @@ -44,7 +44,7 @@ import org.apache.commons.logging.LogFactory; * @author Frederik Heremans * @since 4.0 */ -public class RejectModeratedInviteDelegate extends BaseJavaDelegate +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); diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java index 1404f1091a..9630e9adb0 100644 --- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java +++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java @@ -1246,37 +1246,47 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine String msg = messageService.getMessage(ERR_END_UNEXISTING_TASK, taskId); throw new WorkflowException(msg); } - - // Signal the transition on the task - if (transition != null && - ActivitiConstants.DEFAULT_TRANSITION_NAME.equals(transition)==false) - { - // Only 'Next' is supported as transition. - String msg = messageService.getMessage(ERR_END_TASK_INVALID_TRANSITION, transition, taskId, ActivitiConstants.DEFAULT_TRANSITION_NAME); - throw new WorkflowException(msg); - } - setOutcome(task); + setOutcome(task, transition); taskService.complete(localTaskId); // The task should have a historicTaskInstance HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery().taskId(task.getId()).singleResult(); return typeConverter.convert(historicTask); } - private void setOutcome(Task task) + private void setOutcome(Task task, String transition) { + String outcomeValue = ActivitiConstants.DEFAULT_TRANSITION_NAME; + HashMap updates = new HashMap(); + Map properties = propertyConverter.getTaskProperties(task, false); QName outcomePropName = (QName) properties.get(WorkflowModel.PROP_OUTCOME_PROPERTY_NAME); if(outcomePropName !=null) { - Serializable rawOutcome = properties.get(outcomePropName); - String outcomeValue = ActivitiConstants.DEFAULT_TRANSITION_NAME; - if(rawOutcome != null) + if(transition != null) { - outcomeValue = DefaultTypeConverter.INSTANCE.convert(String.class, rawOutcome); + outcomeValue = transition; + Serializable transitionValue = propertyConverter.convertValueToPropertyType(task, transition, outcomePropName); + updates.put(outcomePropName, transitionValue); + } + else + { + Serializable rawOutcome = properties.get(outcomePropName); + if(rawOutcome != null) + { + outcomeValue = DefaultTypeConverter.INSTANCE.convert(String.class, rawOutcome); + } } - String outcomeName = factory.mapQNameToName(WorkflowModel.PROP_OUTCOME); - taskService.setVariableLocal(task.getId(), outcomeName, outcomeValue); } + else if (transition != null && + ActivitiConstants.DEFAULT_TRANSITION_NAME.equals(transition)==false) + { + // Only 'Next' is supported as transition. + String taskId = createGlobalId(task.getId()); + String msg = messageService.getMessage(ERR_END_TASK_INVALID_TRANSITION, transition, taskId, ActivitiConstants.DEFAULT_TRANSITION_NAME); + throw new WorkflowException(msg); + } + updates.put(WorkflowModel.PROP_OUTCOME, outcomeValue); + propertyConverter.updateTask(task, updates, null, null); } private WorkflowTask endStartTask(String taskId, String localTaskId, String transition) diff --git a/source/java/org/alfresco/repo/workflow/activiti/BaseJavaDelegate.java b/source/java/org/alfresco/repo/workflow/activiti/BaseJavaDelegate.java index 7f80935855..5ade778619 100644 --- a/source/java/org/alfresco/repo/workflow/activiti/BaseJavaDelegate.java +++ b/source/java/org/alfresco/repo/workflow/activiti/BaseJavaDelegate.java @@ -60,6 +60,6 @@ public abstract class BaseJavaDelegate implements JavaDelegate */ protected String getName() { - return getClass().getName(); + return getClass().getSimpleName(); } } diff --git a/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPropertyConverter.java b/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPropertyConverter.java index 4c60e684f8..f489896597 100644 --- a/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPropertyConverter.java +++ b/source/java/org/alfresco/repo/workflow/activiti/properties/ActivitiPropertyConverter.java @@ -61,6 +61,7 @@ import org.alfresco.service.cmr.dictionary.ClassAttributeDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.workflow.WorkflowException; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -600,6 +601,23 @@ public class ActivitiPropertyConverter throw new WorkflowException(msg); } + /** + * Converts a {@link Serializable} value to the type of the specified property. + * @param value + * @param definition + * @return + */ + public Serializable convertValueToPropertyType(Task task, Serializable value, QName propertyName) + { + TypeDefinition taskDef = typeManager.getFullTaskDefinition(task); + PropertyDefinition propDef = taskDef.getProperties().get(propertyName); + if(propDef != null) + { + return (Serializable) DefaultTypeConverter.INSTANCE.convert(propDef.getDataType(), value); + } + return value; + } + @SuppressWarnings("unchecked") private Map getNewTaskProperties(Task task, Map properties, Map> add, Map> remove) diff --git a/source/java/org/alfresco/service/cmr/workflow/WorkflowTaskQuery.java b/source/java/org/alfresco/service/cmr/workflow/WorkflowTaskQuery.java index 165ae6bf8b..f952bc749d 100644 --- a/source/java/org/alfresco/service/cmr/workflow/WorkflowTaskQuery.java +++ b/source/java/org/alfresco/service/cmr/workflow/WorkflowTaskQuery.java @@ -32,6 +32,9 @@ import org.alfresco.service.namespace.QName; */ public class WorkflowTaskQuery { + // Engine Id + private String engineId = null; + // task predicates private String taskId; private WorkflowTaskState taskState = WorkflowTaskState.IN_PROGRESS; @@ -45,7 +48,7 @@ public class WorkflowTaskQuery private String workflowDefinitionName; private Boolean active = Boolean.TRUE; private Map processCustomProps; - + // order by private OrderBy[] orderBy; @@ -263,4 +266,20 @@ public class WorkflowTaskQuery { this.limit = limit; } + + /** + * @param engineId the engineId to set + */ + public void setEngineId(String engineId) + { + this.engineId = engineId; + } + + /** + * @return the engineId + */ + public String getEngineId() + { + return engineId; + } }