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

@@ -2,10 +2,10 @@
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
@@ -48,8 +48,8 @@
<!-- Job-executor will be enabled once the SchemaAvailableEvent has been fired --> <!-- Job-executor will be enabled once the SchemaAvailableEvent has been fired -->
<property name="jobExecutorActivate" value="false" /> <property name="jobExecutorActivate" value="false" />
<!-- Limit the visible beans in expressions --> <!-- Limit the visible beans in expressions -->
<property name="beans" ref="activitiBeanRegistry" /> <property name="beans" ref="activitiBeanRegistry" />
<property name="customTypes"> <property name="customTypes">
<list> <list>
@@ -74,6 +74,7 @@
<bean id="baseJavaDelegate" class="org.alfresco.repo.workflow.activiti.BaseJavaDelegate" abstract="true"> <bean id="baseJavaDelegate" class="org.alfresco.repo.workflow.activiti.BaseJavaDelegate" abstract="true">
<property name="serviceRegistry" ref="ServiceRegistry" /> <property name="serviceRegistry" ref="ServiceRegistry" />
<property name="beanRegistry" ref="activitiBeanRegistry" />
</bean> </bean>
<!-- Activiti Workflow Engine Factory --> <!-- Activiti Workflow Engine Factory -->

View File

@@ -5,6 +5,7 @@
<!-- Invitation Service Configuration File --> <!-- Invitation Service Configuration File -->
<bean id="invitationService" class="org.alfresco.repo.invitation.InvitationServiceImpl" init-method="init"> <bean id="invitationService" class="org.alfresco.repo.invitation.InvitationServiceImpl" init-method="init">
<property name="workflowService" ref="WorkflowService"/> <property name="workflowService" ref="WorkflowService"/>
<property name="workflowAdminService" ref="workflowAdminService"/>
<property name="personService" ref="PersonService"/> <property name="personService" ref="PersonService"/>
<property name="permissionService" ref="PermissionService"/> <property name="permissionService" ref="PermissionService"/>
<property name="authenticationService" ref="AuthenticationService"/> <property name="authenticationService" ref="AuthenticationService"/>
@@ -77,4 +78,28 @@
<property name="messageService" ref="messageService"/> <property name="messageService" ref="messageService"/>
</bean> </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> </beans>

View File

@@ -1,70 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Moderated invitation workflow --> <!-- Moderated invitation workflow -->
<model name="imwf:invitation-moderated-workflow-model" xmlns="http://www.alfresco.org/model/dictionary/1.0"> <model name="imwf:invitation-moderated-workflow-model" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<imports> <imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" /> <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
<import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm" /> <import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm" />
<import uri="http://www.alfresco.org/model/workflow/1.0" prefix="wf" /> <import uri="http://www.alfresco.org/model/workflow/1.0" prefix="wf" />
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" /> <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
</imports> </imports>
<namespaces> <namespaces>
<namespace uri="http://www.alfresco.org/model/workflow/invite/moderated/1.0" prefix="imwf" /> <namespace
</namespaces> uri="http://www.alfresco.org/model/workflow/invite/moderated/1.0" prefix="imwf" />
</namespaces>
<types> <types>
<type name="imwf:moderatedInvitationSubmitTask"> <type name="imwf:moderatedInvitationSubmitTask">
<parent>bpm:startTask</parent> <parent>bpm:startTask</parent>
<mandatory-aspects> <mandatory-aspects>
<aspect>bpm:assignee</aspect> <aspect>bpm:assignee</aspect>
<aspect>bpm:groupAssignee</aspect> <aspect>bpm:groupAssignee</aspect>
<aspect>imwf:moderatedInvitationStats</aspect> <aspect>imwf:moderatedInvitationStats</aspect>
</mandatory-aspects> </mandatory-aspects>
</type> </type>
<type name="imwf:moderatedInvitationReviewTask"> <type name="imwf:moderatedInvitationReviewTask">
<parent>bpm:workflowTask</parent> <parent>bpm:workflowTask</parent>
<properties> <mandatory-aspects>
<property name="imwf:reviewComments"> <aspect>bpm:groupAssignee</aspect>
<type>d:text</type> <aspect>cm:ownable</aspect>
</property> <aspect>imwf:moderatedInvitationStats</aspect>
</properties> </mandatory-aspects>
</type>
<mandatory-aspects> <type name="imwf:activitiModeratedInvitationReviewTask">
<aspect>bpm:groupAssignee</aspect> <parent>bpm:activitiOutcomeTask</parent>
<aspect>cm:ownable</aspect> <properties>
<aspect>imwf:moderatedInvitationStats</aspect> <property name="imwf:reviewOutcome">
</mandatory-aspects> <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>
</type> </types>
</types> <aspects>
<aspect name="imwf:moderatedInvitationStats">
<aspects> <properties>
<aspect name="imwf:moderatedInvitationStats"> <property name="imwf:inviteeUserName">
<properties> <type>d:text</type>
<property name="imwf:inviteeUserName"> </property>
<type>d:text</type> <property name="imwf:resourceType">
</property> <type>d:text</type>
<property name="imwf:resourceType"> <default>WEB_SITE</default>
<type>d:text</type> </property>
<default>WEB_SITE</default> <property name="imwf:resourceName">
</property> <type>d:text</type>
<property name="imwf:resourceName"> </property>
<type>d:text</type> <property name="imwf:inviteeRole">
</property> <type>d:text</type>
<property name="imwf:inviteeRole"> </property>
<type>d:text</type> <property name="imwf:inviteeComments">
</property> <type>d:text</type>
<property name="imwf:inviteeComments"> </property>
<type>d:text</type> <property name="imwf:reviewComments">
</property> <type>d:text</type>
</properties> </property>
</aspect> </properties>
</aspects> </aspect>
</aspects>
</model> </model>

View File

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

View File

@@ -42,20 +42,54 @@
</mandatory-aspects> </mandatory-aspects>
</type> </type>
<type name="inwf:invitePendingTask"> <type name="inwf:invitePendingTask">
<parent>bpm:workflowTask</parent> <parent>bpm:workflowTask</parent>
<overrides> <overrides>
<property name="bpm:hiddenTransitions"> <property name="bpm:hiddenTransitions">
<default>cancel</default> <default>cancel</default>
</property> </property>
<property name="bpm:reassignable"> <property name="bpm:reassignable">
<default>false</default> <default>false</default>
</property> </property>
</overrides> </overrides>
<mandatory-aspects> <mandatory-aspects>
<aspect>inwf:nominatedInvitationStats</aspect> <aspect>inwf:nominatedInvitationStats</aspect>
</mandatory-aspects> </mandatory-aspects>
</type> </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"> <type name="inwf:acceptInviteTask">
<parent>bpm:workflowTask</parent> <parent>bpm:workflowTask</parent>

View File

@@ -10,7 +10,7 @@
<sequenceFlow id="flow1" sourceRef="start" targetRef="sendInvite" /> <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" /> <sequenceFlow id="flow2" sourceRef="sendInvite" targetRef="invitePending" />
@@ -51,13 +51,13 @@
<sequenceFlow id="flow7" sourceRef="inviteGateway" targetRef="cancelled" /> <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" /> <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" /> <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" /> <sequenceFlow id="flow9" sourceRef="cancelled" targetRef="end" />
<endEvent id="end" /> <endEvent id="end" />

View File

@@ -21,13 +21,12 @@ package org.alfresco.repo.forms.processor.workflow;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Matcher;
import org.alfresco.repo.forms.Form; import org.alfresco.repo.forms.Form;
import org.alfresco.repo.forms.FormData; import org.alfresco.repo.forms.FormData;
import org.alfresco.repo.forms.FormData.FieldData;
import org.alfresco.repo.forms.FormNotFoundException; import org.alfresco.repo.forms.FormNotFoundException;
import org.alfresco.repo.forms.Item; 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.FormCreationData;
import org.alfresco.repo.forms.processor.node.ContentModelFormProcessor; import org.alfresco.repo.forms.processor.node.ContentModelFormProcessor;
import org.alfresco.repo.forms.processor.node.ContentModelItemData; 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() + "'."); 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; this.personService = personService;
} }
/* (non-Javadoc) /**
* @see org.alfresco.repo.forms.processor.workflow.AbstractWorkflowFormProcessor#getTypedItemForDecodedId(java.lang.String) * {@inheritDoc}
*/ */
@Override @Override
protected WorkflowTask getTypedItemForDecodedId(String itemId) protected WorkflowTask getTypedItemForDecodedId(String itemId)
@@ -108,32 +108,28 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor<WorkflowTas
return workflowService.getTaskById(itemId); return workflowService.getTaskById(itemId);
} }
/* /**
* (non-Javadoc) * {@inheritDoc}
* */
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemType(java.lang.Object)
*/
@Override @Override
protected String getItemType(WorkflowTask item) protected String getItemType(WorkflowTask item)
{ {
TypeDefinition typeDef = item.definition.metadata; TypeDefinition typeDef = item.getDefinition().getMetadata();
return typeDef.getName().toPrefixString(namespaceService); return typeDef.getName().toPrefixString(namespaceService);
} }
/* /**
* (non-Javadoc) * {@inheritDoc}
* */
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemURI(java.lang.Object)
*/
@Override @Override
protected String getItemURI(WorkflowTask item) 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 @Override
protected Log getLogger() protected Log getLogger()
{ {
@@ -143,19 +139,19 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor<WorkflowTas
@Override @Override
protected TypeDefinition getBaseType(WorkflowTask task) protected TypeDefinition getBaseType(WorkflowTask task)
{ {
return task.definition.metadata; return task.getDefinition().getMetadata();
} }
@Override @Override
protected Map<QName, Serializable> getPropertyValues(WorkflowTask task) protected Map<QName, Serializable> getPropertyValues(WorkflowTask task)
{ {
return task.properties; return task.getProperties();
} }
@Override @Override
protected Map<QName, Serializable> getAssociationValues(WorkflowTask item) protected Map<QName, Serializable> getAssociationValues(WorkflowTask item)
{ {
return item.properties; return item.getProperties();
} }
@Override @Override
@@ -245,7 +241,7 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor<WorkflowTas
private String getTransitionValues(WorkflowTask item) private String getTransitionValues(WorkflowTask item)
{ {
WorkflowTransition[] transitions = item.definition.node.transitions; WorkflowTransition[] transitions = item.getDefinition().getNode().getTransitions();
if (transitions == null || transitions.length == 0) if (transitions == null || transitions.length == 0)
{ {

View File

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

View File

@@ -18,36 +18,54 @@
*/ */
package org.alfresco.repo.invitation; package org.alfresco.repo.invitation;
import java.util.Map;
import org.alfresco.service.cmr.invitation.Invitation; import org.alfresco.service.cmr.invitation.Invitation;
import org.alfresco.service.cmr.invitation.Invitation.InvitationType; import org.alfresco.service.cmr.invitation.Invitation.InvitationType;
import org.alfresco.service.cmr.invitation.Invitation.ResourceType; import org.alfresco.service.cmr.invitation.Invitation.ResourceType;
/* package scope */ abstract class InvitationImpl /* 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 * Unique reference for this invitation
*/ */
private String inviteId; private final String inviteId;
/** /**
* Which resource is this invitation for ? * 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 * 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. * What role is the invitation for.
*/ */
private String roleName; private final String roleName;
/** /**
* Who is this invitation for * 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 * What sort of resource is it
@@ -58,26 +76,11 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType;
return resourceType; return resourceType;
} }
public void setResourceType(ResourceType resourceType)
{
this.resourceType = resourceType;
}
public void setInviteId(String inviteId)
{
this.inviteId = inviteId;
}
public String getInviteId() public String getInviteId()
{ {
return inviteId; return inviteId;
} }
public void setResourceName(String resourceName)
{
this.resourceName = resourceName;
}
public String getResourceName() public String getResourceName()
{ {
return resourceName; return resourceName;
@@ -88,23 +91,10 @@ import org.alfresco.service.cmr.invitation.Invitation.ResourceType;
return roleName; 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() public String getInviteeUserName()
{ {
return inviteeUserName; return inviteeUserName;
} }
public abstract InvitationType getInvitationType();
} }

View File

@@ -21,6 +21,7 @@ package org.alfresco.repo.invitation;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; 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.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil; 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.PasswordGenerator;
import org.alfresco.repo.security.authentication.UserNameGenerator; 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.site.SiteModel;
import org.alfresco.repo.workflow.WorkflowConstants;
import org.alfresco.repo.workflow.WorkflowModel; 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.dictionary.DictionaryService;
import org.alfresco.service.cmr.invitation.Invitation; import org.alfresco.service.cmr.invitation.Invitation;
import org.alfresco.service.cmr.invitation.InvitationException; 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.security.PersonService;
import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService; 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.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowException; 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.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask; 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 * @see org.alfresco.service.cmr.invitation.Invitation
* @author mrogers * @author mrogers
* @author Nick Smith
*/ */
public class InvitationServiceImpl implements InvitationService, NodeServicePolicies.BeforeDeleteNodePolicy public class InvitationServiceImpl implements InvitationService, NodeServicePolicies.BeforeDeleteNodePolicy
{ {
@@ -86,6 +88,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
* Services * Services
*/ */
private WorkflowService workflowService; private WorkflowService workflowService;
private WorkflowAdminService workflowAdminService;
private PersonService personService; private PersonService personService;
private SiteService siteService; private SiteService siteService;
private MutableAuthenticationService authenticationService; private MutableAuthenticationService authenticationService;
@@ -148,7 +151,9 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
{ {
List<String> ret = new ArrayList<String>(3); List<String> ret = new ArrayList<String>(3);
ret.add(WorkflowModelNominatedInvitation.WORKFLOW_DEFINITION_NAME); 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);
ret.add(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME_ACTIVITI);
// old deprecated invitation workflow. // old deprecated invitation workflow.
ret.add("jbpm$wf:invite"); ret.add("jbpm$wf:invite");
return ret; return ret;
@@ -263,58 +268,44 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
*/ */
public Invitation accept(String invitationId, String ticket) public Invitation accept(String invitationId, String ticket)
{ {
Invitation invitation = getInvitation(invitationId); WorkflowTask startTask = getStartTask(invitationId);
NominatedInvitation invitation = getNominatedInvitation(startTask);
if (invitation instanceof NominatedInvitation) 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())))
{
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<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);
}
return 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<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) public Invitation approve(String invitationId, String reason)
{ {
Invitation invitation = getInvitation(invitationId); WorkflowTask startTask = getStartTask(invitationId);
if (invitation instanceof ModeratedInvitation) ModeratedInvitation invitation = getModeratedInvitation(startTask);
if(invitation == null)
{ {
// Check approver is a site manager String msg = "State error, can only call approve on a Moderated invitation.";
String approverUserName = this.authenticationService.getCurrentUserName(); throw new InvitationException(msg);
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)
{
Map<QName, Serializable> wfReviewProps = new HashMap<QName, Serializable>();
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());
} }
// Check approver is a site manager
String currentUser = this.authenticationService.getCurrentUserName();
checkManagerRole(currentUser, invitation.getResourceType(), invitation.getResourceName());
Map<QName, Serializable> wfReviewProps = new HashMap<QName, Serializable>();
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; return invitation;
} }
/** /**
@@ -370,135 +345,78 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
*/ */
public Invitation reject(String invitationId, String reason) public Invitation reject(String invitationId, String reason)
{ {
Invitation invitation = getInvitation(invitationId); WorkflowTask startTask = getStartTask(invitationId);
if(taskTypeMatches(startTask, WorkflowModelModeratedInvitation.WF_START_TASK))
if (invitation instanceof NominatedInvitation)
{ {
return rejectModeratedInvitation(startTask, reason);
/**
* 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)
{
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;
} }
else
if (invitation instanceof ModeratedInvitation)
{ {
WorkflowTaskQuery wfModeratedTaskQuery = new WorkflowTaskQuery(); return rejectNominatedInvitation(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);
// query for invite review tasks
List<WorkflowTask> wf_moderated_tasks = this.workflowService.queryTasks(wfModeratedTaskQuery);
for (WorkflowTask workflowTask : wf_moderated_tasks)
{
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);
}
return invitation;
} }
}
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<QName, Serializable> properties = new HashMap<QName, Serializable>();
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; return invitation;
} }
/* private Invitation rejectNominatedInvitation(WorkflowTask startTask)
* cancel a pending request {
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) public Invitation cancel(String invitationId)
{ {
Invitation invitation = getInvitation(invitationId); WorkflowTask startTask = getStartTask(invitationId);
if(taskTypeMatches(startTask, WorkflowModelModeratedInvitation.WF_START_TASK))
if (invitation instanceof NominatedInvitation)
{ {
return cancelModeratedInvitation(startTask);
// 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)
{
workflowService.endTask(workflowTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_CANCEL);
}
} }
else
if (invitation instanceof ModeratedInvitation)
{ {
// Moderated invitation may be cancelled by either a site manager or return cancelNominatedInvitation(startTask);
// the invitee.
String currentUserName = this.authenticationService.getCurrentUserName();
if (!currentUserName.equals(((ModeratedInvitation) invitation).getInviteeUserName()))
{
checkManagerRole(currentUserName, invitation.getResourceType(), invitation.getResourceName());
}
workflowService.cancelWorkflow(invitationId);
} }
}
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; return invitation;
} }
@@ -512,83 +430,67 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
*/ */
public Invitation getInvitation(String invitationId) 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); validateInvitationId(invitationId);
WorkflowTask startTask = null;
WorkflowInstance wi = null;
try try
{ {
wi = workflowService.getWorkflowById(invitationId); startTask = workflowService.getStartTask(invitationId);
} }
catch (WorkflowException we) catch (WorkflowException we)
{ {
// Do nothing // Do nothing
} }
if (startTask == null)
if (wi == null)
{ {
Object objs[] = { invitationId }; Object objs[] = { invitationId };
throw new InvitationExceptionNotFound("invitation.error.not_found", objs); throw new InvitationExceptionNotFound("invitation.error.not_found", objs);
} }
String workflowName = wi.getDefinition().getName(); return startTask;
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;
} }
/** /**
@@ -627,7 +529,6 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
*/ */
public List<Invitation> searchInvitation(InvitationSearchCriteria criteria) public List<Invitation> searchInvitation(InvitationSearchCriteria criteria)
{ {
List<Invitation> ret = new ArrayList<Invitation>(); List<Invitation> ret = new ArrayList<Invitation>();
InvitationSearchCriteria.InvitationType toSearch = criteria.getInvitationType(); InvitationSearchCriteria.InvitationType toSearch = criteria.getInvitationType();
@@ -672,7 +573,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
// pick up the pending task // pick up the pending task
wfTaskQuery.setTaskState(WorkflowTaskState.IN_PROGRESS); 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); wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE);
// query for invite workflow tasks // query for invite workflow tasks
@@ -787,8 +688,8 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
for (WorkflowTask workflowTask : wf_moderated_tasks) for (WorkflowTask workflowTask : wf_moderated_tasks)
{ {
// Add moderated invitations // Add moderated invitations
String workflowId = workflowTask.path.instance.id; String workflowId = workflowTask.getPath().getInstance().getId();
ModeratedInvitationImpl result = new ModeratedInvitationImpl(workflowTask.properties); ModeratedInvitationImpl result = new ModeratedInvitationImpl(workflowId, workflowTask.getProperties());
// TODO ALFCOM-2598 records are being returned that do not match // TODO ALFCOM-2598 records are being returned that do not match
// properties // properties
@@ -797,7 +698,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
for (QName key : keys) for (QName key : keys)
{ {
Object val1 = wfQueryModeratedProps.get(key); Object val1 = wfQueryModeratedProps.get(key);
Object val2 = workflowTask.properties.get(key); Object val2 = workflowTask.getProperties().get(key);
if (!val1.equals(val2)) if (!val1.equals(val2))
{ {
// crap detected // crap detected
@@ -807,8 +708,6 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
} }
} }
// TODO END ALFCOM-2598 Work-around // TODO END ALFCOM-2598 Work-around
result.setInviteId(workflowId);
if (!crap) if (!crap)
{ {
ret.add(result); ret.add(result);
@@ -833,6 +732,14 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
this.workflowService = workflowService; this.workflowService = workflowService;
} }
/**
* @param workflowAdminService the workflowAdminService to set
*/
public void setWorkflowAdminService(WorkflowAdminService workflowAdminService)
{
this.workflowAdminService = workflowAdminService;
}
/** /**
* @return the workflow service * @return the workflow service
*/ */
@@ -1016,9 +923,8 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
private ModeratedInvitation startModeratedInvite(String inviteeComments, String inviteeUserName, private ModeratedInvitation startModeratedInvite(String inviteeComments, String inviteeUserName,
Invitation.ResourceType resourceType, String resourceName, String inviteeRole) Invitation.ResourceType resourceType, String resourceName, String inviteeRole)
{ {
// Get invitee person NodeRef to add as assignee // Get invitee person NodeRef to add as assignee
NodeRef inviteeNodeRef = this.personService.getPerson(inviteeUserName); NodeRef inviteeNodeRef = personService.getPerson(inviteeUserName);
SiteInfo siteInfo = siteService.getSite(resourceName); SiteInfo siteInfo = siteService.getSite(resourceName);
@@ -1036,10 +942,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
// get the workflow description // get the workflow description
String workflowDescription = generateWorkflowDescription(siteInfo, "invitation.moderated.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); Map<QName, Serializable> workflowProps = new HashMap<QName, Serializable>(16);
workflowProps.put(WorkflowModel.ASSOC_PACKAGE, wfPackage);
workflowProps.put(WorkflowModel.ASSOC_ASSIGNEE, inviteeNodeRef); workflowProps.put(WorkflowModel.ASSOC_ASSIGNEE, inviteeNodeRef);
workflowProps.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, workflowDescription); workflowProps.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, workflowDescription);
workflowProps.put(WorkflowModelModeratedInvitation.ASSOC_GROUP_ASSIGNEE, roleGroup); workflowProps.put(WorkflowModelModeratedInvitation.ASSOC_GROUP_ASSIGNEE, roleGroup);
@@ -1051,44 +954,8 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
// get the moderated workflow // get the moderated workflow
WorkflowDefinition wfDefinition = this.workflowService WorkflowDefinition wfDefinition = getWorkflowDefinition(false);
.getDefinitionByName(WorkflowModelModeratedInvitation.WORKFLOW_DEFINITION_NAME); return (ModeratedInvitation) startWorkflow(wfDefinition, workflowProps);
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;
} }
/** /**
@@ -1111,7 +978,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
// get the inviter user name (the name of user web script is executed // get the inviter user name (the name of user web script is executed
// under) // under)
String inviterUserName = this.authenticationService.getCurrentUserName(); String inviterUserName = authenticationService.getCurrentUserName();
boolean created = false; boolean created = false;
checkManagerRole(inviterUserName, resourceType, siteShortName); 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 * 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 // Start the invite workflow with inviter, invitee and site properties
// //
WorkflowDefinition wfDefinition = this.workflowService WorkflowDefinition wfDefinition = getWorkflowDefinition(true);
.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);
}
// Get invitee person NodeRef to add as assignee // 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); SiteInfo siteInfo = this.siteService.getSite(siteShortName);
String siteDescription = siteInfo.getDescription(); String siteDescription = siteInfo.getDescription();
if (siteDescription == null) 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_REJECT_URL, rejectUrl);
workflowProps.put(WorkflowModelNominatedInvitation.WF_PROP_INVITE_TICKET, inviteTicket); 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 // start the workflow
WorkflowPath wfPath = this.workflowService.startWorkflow(wfDefinition.getId(), workflowProps); WorkflowPath wfPath = this.workflowService.startWorkflow(wfDefinition.getId(), workflowProps);
@@ -1303,54 +1155,19 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
// //
// get the workflow tasks // get the workflow tasks
String workflowId = wfPath.instance.id; String workflowId = wfPath.getInstance().getId();
String wfPathId = wfPath.id; WorkflowTask startTask = workflowService.getStartTask(workflowId);
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);
// attach empty package to start task, end it and follow with transition // attach empty package to start task, end it and follow with transition
// that sends out the invite // that sends out the invite
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Starting Invite workflow task by attaching empty package..."); 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()) if (logger.isDebugEnabled())
logger.debug("Transitioning Invite workflow task..."); logger.debug("Transitioning Invite workflow task...");
try try
{ {
this.workflowService.endTask(wfStartTask.id, WorkflowModelNominatedInvitation.WF_TRANSITION_SEND_INVITE); workflowService.endTask(startTask.getId(), null);
} }
catch (RuntimeException err) catch (RuntimeException err)
{ {
@@ -1358,12 +1175,44 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
logger.debug("Failed - caught error during Invite workflow transition: " + err.getMessage()); logger.debug("Failed - caught error during Invite workflow transition: " + err.getMessage());
throw err; throw err;
} }
Invitation invitation = getInvitation(startTask);
return invitation;
}
NominatedInvitationImpl result = new NominatedInvitationImpl(workflowProps); /**
result.setTicket(inviteTicket); * Return Activiti workflow definition unless Activiti engine is disabled.
result.setInviteId(workflowId); * @param isNominated TODO
result.setSentInviteDate(new Date()); * @return
return result; */
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.wfVarRole;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarServerPath; import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarServerPath;
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarWorkflowInstanceId; 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.io.Serializable;
import java.util.Arrays; 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.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.collections.CollectionUtils; import org.alfresco.util.collections.CollectionUtils;
import org.alfresco.util.collections.Filter;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
@@ -153,32 +156,7 @@ public class InviteHelper implements InitializingBean
*/ */
public WorkflowTask findInviteStartTask(String inviteId) public WorkflowTask findInviteStartTask(String inviteId)
{ {
// create workflow task query return workflowService.getStartTask(inviteId);
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);
}
} }
/** /**
@@ -188,28 +166,16 @@ public class InviteHelper implements InitializingBean
*/ */
public List<WorkflowTask> findInvitePendingTasks(String inviteeUserName) public List<WorkflowTask> findInvitePendingTasks(String inviteeUserName)
{ {
// create workflow task query List<WorkflowTask> tasks = workflowService.getAssignedTasks(inviteeUserName, WorkflowTaskState.IN_PROGRESS);
WorkflowTaskQuery wfTaskQuery = new WorkflowTaskQuery(); return CollectionUtils.filter(tasks, new Filter<WorkflowTask>()
{
// set process name to "wf:invite" so that only tasks associated with public Boolean apply(WorkflowTask value)
// invite workflow instances are returned by query {
wfTaskQuery.setProcessName(WorkflowModelNominatedInvitation.WF_PROCESS_INVITE); QName taskDefName = value.getDefinition().getMetadata().getName();
return WF_TASK_INVITE_PENDING.equals(taskDefName) ||
// set query to only pick up invite workflow instances WF_TASK_ACTIVIT_INVITE_PENDING.equals(taskDefName);
// 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;
} }
/** /**
@@ -276,7 +242,7 @@ public class InviteHelper implements InitializingBean
{ {
if (overrideExisting || !siteService.isMember(siteName, invitee)) if (overrideExisting || !siteService.isMember(siteName, invitee))
{ {
siteService.setMembership(siteName, invitee, role); siteService.setMembership(siteName, invitee, role);
} }
return null; return null;
} }

View File

@@ -18,7 +18,14 @@
*/ */
package org.alfresco.repo.invitation; 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.io.Serializable;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.alfresco.service.cmr.invitation.ModeratedInvitation; import org.alfresco.service.cmr.invitation.ModeratedInvitation;
@@ -32,30 +39,30 @@ import org.alfresco.service.namespace.QName;
{ {
private static final long serialVersionUID = -5557544865169876451L; 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)); super(getConstructorProps(inviteId, props));
setRoleName((String)workflowProps.get(WorkflowModelModeratedInvitation.WF_PROP_INVITEE_ROLE)); inviteeComments = (String)props.get(WF_PROP_INVITEE_COMMENTS);
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);
} }
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() public String getInviteeComments()
{ {
return inviteeComments; return inviteeComments;
} }
public void setInviteeComments(String inviteeComments)
{
this.inviteeComments = inviteeComments;
}
@Override @Override
public InvitationType getInvitationType() { public InvitationType getInvitationType() {
return InvitationType.MODERATED; return InvitationType.MODERATED;

View File

@@ -18,8 +18,24 @@
*/ */
package org.alfresco.repo.invitation; 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.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.alfresco.service.cmr.invitation.NominatedInvitation; import org.alfresco.service.cmr.invitation.NominatedInvitation;
@@ -35,43 +51,43 @@ import org.alfresco.service.namespace.QName;
{ {
private static final long serialVersionUID = -8800842866845149466L; private static final long serialVersionUID = -8800842866845149466L;
private String inviteeFirstName; private final String inviteeFirstName;
private String inviteeLastName; private final String inviteeLastName;
private String inviteeEmail; private final String inviteeEmail;
private String inviterUserName; private final String inviterUserName;
private String resourceDescription; private final String resourceDescription;
private String resourceTitle; private final String resourceTitle;
private String serverPath; private final String serverPath;
private String acceptUrl; private final String acceptUrl;
private String rejectUrl; private final String rejectUrl;
private Date sentInviteDate; private final Date sentInviteDate;
private String ticket; 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)); super(getConstructorProps(inviteId, props));
setRoleName((String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_ROLE)); inviteeFirstName = (String)props.get(WF_PROP_INVITEE_FIRSTNAME);
inviteeFirstName = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_FIRSTNAME); inviteeLastName = (String)props.get(WF_PROP_INVITEE_LASTNAME);
inviteeLastName = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_LASTNAME); inviteeEmail = (String)props.get(WF_PROP_INVITEE_EMAIL);
inviteeEmail = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITEE_EMAIL); inviterUserName = (String)props.get(WF_PROP_INVITER_USER_NAME);
inviterUserName = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_INVITER_USER_NAME); resourceTitle = (String)props.get(WF_PROP_RESOURCE_TITLE);
resourceTitle = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TITLE); resourceDescription = (String)props.get(WF_PROP_RESOURCE_DESCRIPTION);
resourceDescription = (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_DESCRIPTION); serverPath = (String)props.get(WF_PROP_SERVER_PATH);
setResourceName( (String)workflowProps.get(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_NAME)); acceptUrl = (String)props.get(WF_PROP_ACCEPT_URL);
rejectUrl = (String)props.get(WF_PROP_REJECT_URL);
if (workflowProps.containsKey(WorkflowModelNominatedInvitation.WF_PROP_RESOURCE_TYPE)) this.ticket = (String)props.get(WF_PROP_INVITE_TICKET);
{ this.sentInviteDate =inviteDate;
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);
} }
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() public String getInviteeFirstName()
@@ -79,21 +95,11 @@ import org.alfresco.service.namespace.QName;
return inviteeFirstName; return inviteeFirstName;
} }
public void setInviteeLastName(String inviteeLastName)
{
this.inviteeLastName = inviteeLastName;
}
public String getInviteeLastName() public String getInviteeLastName()
{ {
return inviteeLastName; return inviteeLastName;
} }
public void setInviteeEmail(String inviteeEmail)
{
this.inviteeEmail = inviteeEmail;
}
public String getInviteeEmail() public String getInviteeEmail()
{ {
return inviteeEmail; return inviteeEmail;
@@ -109,51 +115,26 @@ import org.alfresco.service.namespace.QName;
return resourceTitle; return resourceTitle;
} }
public void setServerPath(String serverPath)
{
this.serverPath = serverPath;
}
public String getServerPath() public String getServerPath()
{ {
return serverPath; return serverPath;
} }
public void setAcceptUrl(String acceptUrl)
{
this.acceptUrl = acceptUrl;
}
public String getAcceptUrl() public String getAcceptUrl()
{ {
return acceptUrl; return acceptUrl;
} }
public void setRejectUrl(String rejectUrl)
{
this.rejectUrl = rejectUrl;
}
public String getRejectUrl() public String getRejectUrl()
{ {
return rejectUrl; return rejectUrl;
} }
public void setSentInviteDate(Date sentInviteDate)
{
this.sentInviteDate = sentInviteDate;
}
public Date getSentInviteDate() public Date getSentInviteDate()
{ {
return sentInviteDate; return sentInviteDate;
} }
public void setTicket(String ticket)
{
this.ticket = ticket;
}
public String getTicket() public String getTicket()
{ {
return ticket; return ticket;
@@ -164,11 +145,6 @@ import org.alfresco.service.namespace.QName;
return inviterUserName; return inviterUserName;
} }
public void setInviterUserName(String inviterUserName)
{
this.inviterUserName= inviterUserName;
}
@Override @Override
public InvitationType getInvitationType() public InvitationType getInvitationType()
{ {

View File

@@ -41,6 +41,7 @@ public interface WorkflowModelModeratedInvitation
// tasks // tasks
public static final QName WF_START_TASK = QName.createQName(NAMESPACE_URI, "moderatedInvitationSubmitTask"); 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_REVIEW_TASK = QName.createQName(NAMESPACE_URI,"moderatedInvitationReviewTask");
public static final QName WF_ACTIVITI_REVIEW_TASK = QName.createQName(NAMESPACE_URI,"activitiModeratedInvitationReviewTask");
// associations // associations
static final QName ASSOC_GROUP_ASSIGNEE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "groupAssignee"); 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"; public static final String WORKFLOW_DEFINITION_NAME_ACTIVITI = "activiti$activitiInvitationNominated";
// tasks // tasks
public static final QName WF_INVITE_TASK_INVITE_TO_SITE = QName.createQName(NAMESPACE_URI, "inviteToSiteTask"); public static final QName WF_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_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_ACCEPT_INVITE = QName.createQName(NAMESPACE_URI, "acceptInviteTask");
public static final QName WF_TASK_REJECT_INVITE = QName.createQName(NAMESPACE_URI, "rejectInviteTask"); 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 * @author Frederik Heremans
* @since 4.0 * @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 String REJECT_TEMPLATE = "/alfresco/bootstrap/invite/moderated-reject-email.ftl";
private static final Log logger = LogFactory.getLog(RejectModeratedInviteDelegate.class); private static final Log logger = LogFactory.getLog(RejectModeratedInviteDelegate.class);

View File

@@ -1246,37 +1246,47 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
String msg = messageService.getMessage(ERR_END_UNEXISTING_TASK, taskId); String msg = messageService.getMessage(ERR_END_UNEXISTING_TASK, taskId);
throw new WorkflowException(msg); throw new WorkflowException(msg);
} }
setOutcome(task, transition);
// 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);
taskService.complete(localTaskId); taskService.complete(localTaskId);
// The task should have a historicTaskInstance // The task should have a historicTaskInstance
HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery().taskId(task.getId()).singleResult(); HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery().taskId(task.getId()).singleResult();
return typeConverter.convert(historicTask); 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); Map<QName, Serializable> properties = propertyConverter.getTaskProperties(task, false);
QName outcomePropName = (QName) properties.get(WorkflowModel.PROP_OUTCOME_PROPERTY_NAME); QName outcomePropName = (QName) properties.get(WorkflowModel.PROP_OUTCOME_PROPERTY_NAME);
if(outcomePropName !=null) if(outcomePropName !=null)
{ {
Serializable rawOutcome = properties.get(outcomePropName); if(transition != null)
String outcomeValue = ActivitiConstants.DEFAULT_TRANSITION_NAME;
if(rawOutcome != 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) private WorkflowTask endStartTask(String taskId, String localTaskId, String transition)

View File

@@ -60,6 +60,6 @@ public abstract class BaseJavaDelegate implements JavaDelegate
*/ */
protected String getName() 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.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef; 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.cmr.workflow.WorkflowException;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
@@ -600,6 +601,23 @@ public class ActivitiPropertyConverter
throw new WorkflowException(msg); 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") @SuppressWarnings("unchecked")
private Map<QName, Serializable> getNewTaskProperties(Task task, Map<QName, Serializable> properties, Map<QName, List<NodeRef>> add, private Map<QName, Serializable> getNewTaskProperties(Task task, Map<QName, Serializable> properties, Map<QName, List<NodeRef>> add,
Map<QName, List<NodeRef>> remove) Map<QName, List<NodeRef>> remove)

View File

@@ -32,6 +32,9 @@ import org.alfresco.service.namespace.QName;
*/ */
public class WorkflowTaskQuery public class WorkflowTaskQuery
{ {
// Engine Id
private String engineId = null;
// task predicates // task predicates
private String taskId; private String taskId;
private WorkflowTaskState taskState = WorkflowTaskState.IN_PROGRESS; private WorkflowTaskState taskState = WorkflowTaskState.IN_PROGRESS;
@@ -263,4 +266,20 @@ public class WorkflowTaskQuery
{ {
this.limit = limit; 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;
}
} }