Started efactoring InviatationServiceImpl so that it uses Activit workflow engine.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29990 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
N Smith
2011-08-23 13:24:42 +00:00
parent 24fa893ac3
commit fba09d9b2a
22 changed files with 602 additions and 682 deletions

View File

@@ -74,6 +74,7 @@
<bean id="baseJavaDelegate" class="org.alfresco.repo.workflow.activiti.BaseJavaDelegate" abstract="true">
<property name="serviceRegistry" ref="ServiceRegistry" />
<property name="beanRegistry" ref="activitiBeanRegistry" />
</bean>
<!-- Activiti Workflow Engine Factory -->

View File

@@ -5,6 +5,7 @@
<!-- Invitation Service Configuration File -->
<bean id="invitationService" class="org.alfresco.repo.invitation.InvitationServiceImpl" init-method="init">
<property name="workflowService" ref="WorkflowService"/>
<property name="workflowAdminService" ref="workflowAdminService"/>
<property name="personService" ref="PersonService"/>
<property name="permissionService" ref="PermissionService"/>
<property name="authenticationService" ref="AuthenticationService"/>
@@ -77,4 +78,28 @@
<property name="messageService" ref="messageService"/>
</bean>
<!-- Activiti Workflow Delegate beans -->
<bean id="baseInvitationDelegate" parent="baseJavaDelegate"
class="org.alfresco.repo.invitation.activiti.AbstractInvitationDelegate" abstract="true">
<property name="inviteHelper" ref="InviteHelper" />
</bean>
<bean id="AcceptNominatedInviteDelegate" parent="baseInvitationDelegate"
class="org.alfresco.repo.invitation.activiti.AcceptNominatedInviteDelegate" />
<bean id="ApproveModeratedInviteDelegate" parent="baseInvitationDelegate"
class="org.alfresco.repo.invitation.activiti.ApproveModeratedInviteDelegate" />
<bean id="CancelNominatedInviteDelegate" parent="baseInvitationDelegate"
class="org.alfresco.repo.invitation.activiti.CancelNominatedInviteDelegate" />
<bean id="RejectModeratedInviteDelegate" parent="baseInvitationDelegate"
class="org.alfresco.repo.invitation.activiti.RejectModeratedInviteDelegate" />
<bean id="RejectNominatedInviteDelegate" parent="baseInvitationDelegate"
class="org.alfresco.repo.invitation.activiti.RejectNominatedInviteDelegate" />
<bean id="SendNominatedInviteDelegate" parent="baseInvitationDelegate"
class="org.alfresco.repo.invitation.activiti.SendNominatedInviteDelegate" />
</beans>

View File

@@ -12,7 +12,8 @@
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/model/workflow/invite/moderated/1.0" prefix="imwf" />
<namespace
uri="http://www.alfresco.org/model/workflow/invite/moderated/1.0" prefix="imwf" />
</namespaces>
<types>
@@ -27,18 +28,43 @@
<type name="imwf:moderatedInvitationReviewTask">
<parent>bpm:workflowTask</parent>
<properties>
<property name="imwf:reviewComments">
<type>d:text</type>
</property>
</properties>
<mandatory-aspects>
<aspect>bpm:groupAssignee</aspect>
<aspect>cm:ownable</aspect>
<aspect>imwf:moderatedInvitationStats</aspect>
</mandatory-aspects>
</type>
<type name="imwf:activitiModeratedInvitationReviewTask">
<parent>bpm:activitiOutcomeTask</parent>
<properties>
<property name="imwf:reviewOutcome">
<type>d:text</type>
<default>Reject</default>
<constraints>
<constraint name="imwf:reviewOutcomeOptions"
type="LIST">
<parameter name="allowedValues">
<list>
<value>Approve</value>
<value>Reject</value>
</list>
</parameter>
</constraint>
</constraints>
</property>
</properties>
<overrides>
<property name="bpm:outcomePropertyName">
<default>{http://www.alfresco.org/model/workflow/invite/moderated/1.0}reviewOutcome
</default>
</property>
</overrides>
<mandatory-aspects>
<aspect>bpm:groupAssignee</aspect>
<aspect>cm:ownable</aspect>
<aspect>imwf:moderatedInvitationStats</aspect>
</mandatory-aspects>
</type>
</types>
@@ -62,6 +88,9 @@
<property name="imwf:inviteeComments">
<type>d:text</type>
</property>
<property name="imwf:reviewComments">
<type>d:text</type>
</property>
</properties>
</aspect>
</aspects>

View File

@@ -27,8 +27,7 @@
<activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
<activiti:field name="script">
<activiti:string>
execution.setVariable('wf_reviewOutcome', task.getVariable('wf_reviewOutcome'));
execution.setVariable('imwf_reviewer'), person.properties.userName);
execution.setVariable('imwf_reviewOutcome', task.getVariable('imwf_reviewOutcome'));
</activiti:string>
</activiti:field>
</activiti:taskListener>
@@ -46,15 +45,15 @@
<exclusiveGateway id="reviewDecision" name="Review Decision" />
<sequenceFlow id="flow3" sourceRef="reviewDecision" targetRef="approved">
<conditionExpression xsi:type="tFormalExpression">${wf_reviewOutcome == 'Approve'}</conditionExpression>
<conditionExpression xsi:type="tFormalExpression">${imwf_reviewOutcome == 'Approve'}</conditionExpression>
</sequenceFlow>
<serviceTask id="approved" name="Approved" activiti:class="org.alfresco.repo.invitation.ModerationApproveDelegate" />
<serviceTask id="approved" name="Approved" activiti:class="ApproveModeratedInviteDelegate" />
<sequenceFlow id="flow5" sourceRef="approved" targetRef="end" />
<sequenceFlow id="flow4" sourceRef="reviewDecision" targetRef="rejected" />
<serviceTask id="rejected" name="Rejected" activiti:class="org.alfresco.repo.invitation.ModerationRejectDelegate" />
<serviceTask id="rejected" name="Rejected" activiti:class="RejectModeratedInviteDelegate" />
<sequenceFlow id='flow6' sourceRef='rejected' targetRef='end' />
<endEvent id="end" />

View File

@@ -57,6 +57,40 @@
</mandatory-aspects>
</type>
<type name="inwf:activitiInvitePendingTask">
<parent>bpm:activitiOutcomeTask</parent>
<properties>
<property name="inwf:inviteOutcome">
<type>d:text</type>
<default>Reject</default>
<constraints>
<constraint name="inwf:inviteOutcomeOptions"
type="LIST">
<parameter name="allowedValues">
<list>
<value>accept</value>
<value>reject</value>
<value>reject</value>
</list>
</parameter>
</constraint>
</constraints>
</property>
</properties>
<overrides>
<property name="bpm:outcomePropertyName">
<default>{http://www.alfresco.org/model/workflow/invite/moderated/1.0}reviewOutcome
</default>
</property>
<property name="bpm:reassignable">
<default>false</default>
</property>
</overrides>
<mandatory-aspects>
<aspect>inwf:nominatedInvitationStats</aspect>
</mandatory-aspects>
</type>
<type name="inwf:acceptInviteTask">
<parent>bpm:workflowTask</parent>
<overrides>

View File

@@ -10,7 +10,7 @@
<sequenceFlow id="flow1" sourceRef="start" targetRef="sendInvite" />
<serviceTask id="sendInvite" name="Send Invite" activiti:class="org.alfresco.repo.invitation.SendInvitationDelegate" />
<serviceTask id="sendInvite" name="Send Invite" activiti:delegateExpression="${SendNominatedInviteDelegate}" />
<sequenceFlow id="flow2" sourceRef="sendInvite" targetRef="invitePending" />
@@ -51,13 +51,13 @@
<sequenceFlow id="flow7" sourceRef="inviteGateway" targetRef="cancelled" />
<serviceTask id="accepted" name="Accepted" activiti:class="org.alfresco.repo.invitation.AcceptInviteDelegate" />
<serviceTask id="accepted" name="Accepted" activiti:delegateExpression="${AcceptNominatedInviteDelegate}" />
<sequenceFlow id="flow6" sourceRef="accepted" targetRef="end" />
<serviceTask id="rejected" name="Rejected" activiti:class="org.alfresco.repo.invitation.RejectInviteDelegate" />
<serviceTask id="rejected" name="Rejected" activiti:delegateExpression="${RejectNominatedInviteDelegate}" />
<sequenceFlow id="flow8" sourceRef="rejected" targetRef="end" />
<serviceTask id="cancelled" name="Cancelled" activiti:class="org.alfresco.repo.invitation.CancelInviteDelegate" />
<serviceTask id="cancelled" name="Cancelled" activiti:delegateExpression="${CancelNominatedInviteDelegate}" />
<sequenceFlow id="flow9" sourceRef="cancelled" targetRef="end" />
<endEvent id="end" />

View File

@@ -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;

View File

@@ -65,7 +65,7 @@ public class TaskFormPersister extends ContentModelFormPersister<WorkflowTask>
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);
}
/**

View File

@@ -99,8 +99,8 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor<WorkflowTas
this.personService = personService;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.workflow.AbstractWorkflowFormProcessor#getTypedItemForDecodedId(java.lang.String)
/**
* {@inheritDoc}
*/
@Override
protected WorkflowTask getTypedItemForDecodedId(String itemId)
@@ -108,31 +108,27 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor<WorkflowTas
return workflowService.getTaskById(itemId);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemType(java.lang.Object)
/**
* {@inheritDoc}
*/
@Override
protected String getItemType(WorkflowTask item)
{
TypeDefinition typeDef = item.definition.metadata;
TypeDefinition typeDef = item.getDefinition().getMetadata();
return typeDef.getName().toPrefixString(namespaceService);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemURI(java.lang.Object)
/**
* {@inheritDoc}
*/
@Override
protected String getItemURI(WorkflowTask item)
{
return "api/task-instances/" + item.id;
return "api/task-instances/" + item.getId();
}
/*
* @see org.alfresco.repo.forms.processor.task.ContentModelFormProcessor#getLogger()
/**
* {@inheritDoc}
*/
@Override
protected Log getLogger()
@@ -143,19 +139,19 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor<WorkflowTas
@Override
protected TypeDefinition getBaseType(WorkflowTask task)
{
return task.definition.metadata;
return task.getDefinition().getMetadata();
}
@Override
protected Map<QName, Serializable> getPropertyValues(WorkflowTask task)
{
return task.properties;
return task.getProperties();
}
@Override
protected Map<QName, Serializable> getAssociationValues(WorkflowTask item)
{
return item.properties;
return item.getProperties();
}
@Override
@@ -245,7 +241,7 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor<WorkflowTas
private String getTransitionValues(WorkflowTask item)
{
WorkflowTransition[] transitions = item.definition.node.transitions;
WorkflowTransition[] transitions = item.getDefinition().getNode().getTransitions();
if (transitions == null || transitions.length == 0)
{

View File

@@ -90,7 +90,7 @@ public class WorkflowFormProcessor extends AbstractWorkflowFormProcessor<Workflo
@Override
protected String getItemType(WorkflowDefinition item)
{
return item.name;
return item.getName();
}
/* (non-Javadoc)
@@ -99,7 +99,7 @@ public class WorkflowFormProcessor extends AbstractWorkflowFormProcessor<Workflo
@Override
protected String getItemURI(WorkflowDefinition item)
{
return "api/workflow-definitions/"+item.id;
return "api/workflow-definitions/"+item.getId();
}
/* (non-Javadoc)

View File

@@ -18,36 +18,54 @@
*/
package org.alfresco.repo.invitation;
import java.util.Map;
import org.alfresco.service.cmr.invitation.Invitation;
import org.alfresco.service.cmr.invitation.Invitation.InvitationType;
import org.alfresco.service.cmr.invitation.Invitation.ResourceType;
/* package scope */ abstract class InvitationImpl
{
public static final String ID_KEY = "id";
public static final String INVITEE_KEY = "invitee";
public static final String RESOURCE_NAME_KEY = "resourceName";
public static final String RESOURCE_TYPE_KEY = "resourceType";
public static final String ROLE_KEY = "role";
/**
* Unique reference for this invitation
*/
private String inviteId;
private final String inviteId;
/**
* Which resource is this invitation for ?
*/
private String resourceName;
private final String resourceName;
/**
* What sort of invitation is this invitation for e.g. WEB_SITE or WEB_PROJECT
*/
private Invitation.ResourceType resourceType;
private final Invitation.ResourceType resourceType;
/**
* What role is the invitation for.
*/
private String roleName;
private final String roleName;
/**
* Who is this invitation for
*/
private String inviteeUserName;
private final String inviteeUserName;
public InvitationImpl(Map<String, String> 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
@@ -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;
@@ -88,23 +91,10 @@ 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();
}

View File

@@ -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<String> ret = new ArrayList<String>(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,58 +268,44 @@ 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)
{
throw new InvitationException("State error, accept may only be called on a nominated invitation.");
}
// Check invitationId and ticket match
if (ticket == null || (!ticket.equals(((NominatedInvitation) invitation).getTicket())))
if(invitation.getTicket().equals(ticket)==false)
{
throw new InvitationException("Response to invite has supplied an invalid ticket. The response to the "
+ "invitation could thus not be processed");
//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);
}
/**
* 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<WorkflowTask> 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);
}
endInvitation(startTask,
WorkflowModelNominatedInvitation.WF_TRANSITION_ACCEPT, null,
WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING, WorkflowModelNominatedInvitation.WF_TASK_ACTIVIT_INVITE_PENDING);
return invitation;
}
throw new InvitationException("State error, cannot call accept a moderated invitation");
private void endInvitation(WorkflowTask startTask, String transition, Map<QName, Serializable> properties, QName... taskTypes )
{
List<WorkflowTask> 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);
}
/**
@@ -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)
{
String msg = "State error, can only call approve on a Moderated invitation.";
throw new InvitationException(msg);
}
// 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<WorkflowTask> wf_moderated_tasks = this.workflowService.queryTasks(wfModeratedTaskQuery);
for (WorkflowTask workflowTask : wf_moderated_tasks)
{
String currentUser = this.authenticationService.getCurrentUserName();
checkManagerRole(currentUser, invitation.getResourceType(), invitation.getResourceName());
Map<QName, Serializable> wfReviewProps = new HashMap<QName, Serializable>();
wfReviewProps.put(ContentModel.PROP_OWNER, approverUserName);
wfReviewProps.put(ContentModel.PROP_OWNER, currentUser);
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());
}
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<WorkflowTask> wf_invite_tasks = workflowService.queryTasks(wfTaskQuery);
if (wf_invite_tasks.size() == 0)
return rejectModeratedInvitation(startTask, reason);
}
else
{
Object objs[] = { invitationId };
throw new InvitationExceptionUserError("invitation.invite.already_finished", objs);
return rejectNominatedInvitation(startTask);
}
}
// end all tasks found with this name
for (WorkflowTask workflowTask : wf_invite_tasks)
private Invitation rejectModeratedInvitation(WorkflowTask startTask, String reason)
{
workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_REJECT);
}
return invitation;
}
if (invitation instanceof ModeratedInvitation)
{
WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery();
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());
// 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);
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
properties.put(ContentModel.PROP_OWNER, rejecterUserName);
properties.put(WorkflowModelModeratedInvitation.WF_PROP_REVIEW_COMMENTS, reason);
// query for invite review tasks
List<WorkflowTask> wf_moderated_tasks = this.workflowService.queryTasks(wfModeratedTaskQuery);
endInvitation(startTask,
WorkflowModelModeratedInvitation.WF_TRANSITION_REJECT,
properties,
WorkflowModelModeratedInvitation.WF_ACTIVITI_REVIEW_TASK, WorkflowModelModeratedInvitation.WF_REVIEW_TASK);
return invitation;
}
for (WorkflowTask workflowTask : wf_moderated_tasks)
private Invitation rejectNominatedInvitation(WorkflowTask startTask)
{
Map<QName, Serializable> wfReviewProps = new HashMap<QName, Serializable>();
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);
}
NominatedInvitation invitation = getNominatedInvitation(startTask);
endInvitation(startTask,
WorkflowModelNominatedInvitation.WF_TRANSITION_REJECT, null,
WorkflowModelNominatedInvitation.WF_TASK_INVITE_PENDING, WorkflowModelNominatedInvitation.WF_TASK_ACTIVIT_INVITE_PENDING);
return invitation;
}
return invitation;
}
/*
* cancel a pending request
/**
* {@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<WorkflowTask> wf_invite_tasks = workflowService.queryTasks(wfTaskQuery);
// end all tasks found with this name
for (WorkflowTask workflowTask : wf_invite_tasks)
return cancelModeratedInvitation(startTask);
}
else
{
workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_CANCEL);
return cancelNominatedInvitation(startTask);
}
}
if (invitation instanceof ModeratedInvitation)
private Invitation cancelModeratedInvitation(WorkflowTask startTask)
{
// Moderated invitation may be cancelled by either a site manager or
// the invitee.
ModeratedInvitation invitation = getModeratedInvitation(startTask);
String currentUserName = this.authenticationService.getCurrentUserName();
if (!currentUserName.equals(((ModeratedInvitation) invitation).getInviteeUserName()))
if (false == currentUserName.equals(invitation.getInviteeUserName()))
{
checkManagerRole(currentUserName, invitation.getResourceType(), invitation.getResourceName());
}
workflowService.cancelWorkflow(invitationId);
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<WorkflowTask> 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<WorkflowTask> 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<Invitation> searchInvitation(InvitationSearchCriteria criteria)
{
List<Invitation> ret = new ArrayList<Invitation>();
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<QName, Serializable> workflowProps = new HashMap<QName, Serializable>(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<WorkflowTask> 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<QName, Serializable> 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<WorkflowTask> 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<QName, Serializable> wfTaskProps = new HashMap<QName, Serializable>(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;
}
/**

View File

@@ -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<WorkflowTask> 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<WorkflowTask> 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<QName, Object> processCustomProps = new HashMap<QName, Object>(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<WorkflowTask> inviteStartTasks = workflowService
.queryTasks(wfTaskQuery);
return inviteStartTasks;
List<WorkflowTask> tasks = workflowService.getAssignedTasks(inviteeUserName, WorkflowTaskState.IN_PROGRESS);
return CollectionUtils.filter(tasks, new Filter<WorkflowTask>()
{
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);
}
});
}
/**

View File

@@ -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,18 +39,23 @@ import org.alfresco.service.namespace.QName;
{
private static final long serialVersionUID = -5557544865169876451L;
private String inviteeComments;
private final String inviteeComments;
public ModeratedInvitationImpl(Map<QName, Serializable> workflowProps)
public ModeratedInvitationImpl(String inviteId, Map<QName, Serializable> 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)));
super(getConstructorProps(inviteId, props));
inviteeComments = (String)props.get(WF_PROP_INVITEE_COMMENTS);
}
inviteeComments = (String)workflowProps.get(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_COMMENTS);
private static Map<String, String> getConstructorProps(String inviteId, Map<QName, Serializable> props)
{
Map<String, String> parentProps = new HashMap<String, String>();
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()
@@ -51,11 +63,6 @@ import org.alfresco.service.namespace.QName;
return inviteeComments;
}
public void setInviteeComments(String inviteeComments)
{
this.inviteeComments = inviteeComments;
}
@Override
public InvitationType getInvitationType() {
return InvitationType.MODERATED;

View File

@@ -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<QName, Serializable> workflowProps)
public NominatedInvitationImpl(String inviteId, Date inviteDate, Map<QName, Serializable> 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<String, String> getConstructorProps(String inviteId, Map<QName, Serializable> props)
{
this.inviteeFirstName = inviteeFirstName;
Map<String, String> parentProps = new HashMap<String, String>();
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()
{

View File

@@ -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");

View File

@@ -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");

View File

@@ -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);

View File

@@ -1246,38 +1246,48 @@ 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<QName, Serializable> updates = new HashMap<QName, Serializable>();
Map<QName, Serializable> properties = propertyConverter.getTaskProperties(task, false);
QName outcomePropName = (QName) properties.get(WorkflowModel.PROP_OUTCOME_PROPERTY_NAME);
if(outcomePropName !=null)
{
if(transition != null)
{
outcomeValue = transition;
Serializable transitionValue = propertyConverter.convertValueToPropertyType(task, transition, outcomePropName);
updates.put(outcomePropName, transitionValue);
}
else
{
Serializable rawOutcome = properties.get(outcomePropName);
String outcomeValue = ActivitiConstants.DEFAULT_TRANSITION_NAME;
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)
{

View File

@@ -60,6 +60,6 @@ public abstract class BaseJavaDelegate implements JavaDelegate
*/
protected String getName()
{
return getClass().getName();
return getClass().getSimpleName();
}
}

View File

@@ -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<QName, Serializable> getNewTaskProperties(Task task, Map<QName, Serializable> properties, Map<QName, List<NodeRef>> add,
Map<QName, List<NodeRef>> remove)

View File

@@ -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;
@@ -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;
}
}