Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ public interface PlanItemInstanceTransitionBuilder {
* Starts a plan item instance, this typically will executes it associated behavior.
*/
void start();

/**
* Suspend a plan item instance.
*/
void suspend();

/**
* Sets the plan item instance to available state.
*/
void resume();

/**
* Manually terminates a plan item instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,15 @@ public interface CmmnEngineAgenda extends Agenda {

void planExitPlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity, String exitCriterionId, String exitType, String exitEventType);

void planSuspendPlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity);

void planTerminatePlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity, String exitType, String exitEventType);

void planTriggerPlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity);

void planChangePlanItemInstanceToAvailableOperation(PlanItemInstanceEntity planItemInstanceEntity);

void planResumePlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity);

void planCompleteCaseInstanceOperation(CaseInstanceEntity caseInstanceEntity);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
import org.flowable.cmmn.engine.impl.agenda.operation.ReactivateCaseInstanceOperation;
import org.flowable.cmmn.engine.impl.agenda.operation.ReactivatePlanItemInstanceOperation;
import org.flowable.cmmn.engine.impl.agenda.operation.ReactivatePlanModelInstanceOperation;
import org.flowable.cmmn.engine.impl.agenda.operation.ResumePlanItemInstanceOperation;
import org.flowable.cmmn.engine.impl.agenda.operation.StartPlanItemInstanceOperation;
import org.flowable.cmmn.engine.impl.agenda.operation.SuspendPlanItemInstanceOperation;
import org.flowable.cmmn.engine.impl.agenda.operation.TerminateCaseInstanceOperation;
import org.flowable.cmmn.engine.impl.agenda.operation.TerminatePlanItemInstanceOperation;
import org.flowable.cmmn.engine.impl.agenda.operation.TriggerPlanItemInstanceOperation;
Expand Down Expand Up @@ -253,6 +255,11 @@ public void planOccurPlanItemInstanceOperation(PlanItemInstanceEntity planItemIn
public void planExitPlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity, String exitCriterionId, String exitType, String exitEventType) {
addOperation(new ExitPlanItemInstanceOperation(commandContext, planItemInstanceEntity, exitCriterionId, exitType, exitEventType));
}

@Override
public void planSuspendPlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity) {
addOperation(new SuspendPlanItemInstanceOperation(commandContext, planItemInstanceEntity));
}

@Override
public void planTerminatePlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity, String exitType, String exitEventType) {
Expand All @@ -263,6 +270,11 @@ public void planTerminatePlanItemInstanceOperation(PlanItemInstanceEntity planIt
public void planChangePlanItemInstanceToAvailableOperation(PlanItemInstanceEntity planItemInstanceEntity) {
addOperation(new ChangePlanItemInstanceToAvailableOperation(commandContext, planItemInstanceEntity));
}

@Override
public void planResumePlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity) {
addOperation(new ResumePlanItemInstanceOperation(commandContext, planItemInstanceEntity));
}

@Override
public void planTriggerPlanItemInstanceOperation(PlanItemInstanceEntity planItemInstanceEntity) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.cmmn.engine.impl.agenda.operation;

import java.util.List;

import org.flowable.cmmn.api.runtime.PlanItemInstanceState;
import org.flowable.cmmn.engine.CmmnEngineConfiguration;
import org.flowable.cmmn.engine.impl.persistence.entity.PlanItemInstanceEntity;
import org.flowable.cmmn.engine.impl.util.CommandContextUtil;
import org.flowable.cmmn.model.PlanItemDefinition;
import org.flowable.cmmn.model.PlanItemTransition;
import org.flowable.cmmn.model.TimerEventListener;
import org.flowable.common.engine.api.FlowableIllegalStateException;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.job.service.impl.persistence.entity.SuspendedJobEntity;

/**
* @author Tijs Rademakers
*/
public class ResumePlanItemInstanceOperation extends AbstractChangePlanItemInstanceStateOperation {

public ResumePlanItemInstanceOperation(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {
super(commandContext, planItemInstanceEntity);
}

@Override
public String getLifeCycleTransition() {
return PlanItemTransition.SUSPEND;
}

@Override
public String getNewState() {
return PlanItemInstanceState.AVAILABLE;
}

@Override
protected void internalExecute() {
planItemInstanceEntity.setLastAvailableTime(getCurrentTime(commandContext));

PlanItemDefinition planItemDefinition = planItemInstanceEntity.getPlanItem().getPlanItemDefinition();
if (planItemDefinition instanceof TimerEventListener) {
CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
List<SuspendedJobEntity> suspendedJobs = cmmnEngineConfiguration.getJobServiceConfiguration().getSuspendedJobEntityManager().findJobsBySubScopeId(planItemInstanceEntity.getId());
if (suspendedJobs != null && !suspendedJobs.isEmpty()) {
cmmnEngineConfiguration.getJobServiceConfiguration().getJobService().activateSuspendedJob(suspendedJobs.get(0));
}
}

CommandContextUtil.getCmmnHistoryManager(commandContext).recordPlanItemInstanceAvailable(planItemInstanceEntity);
}

@Override
public boolean isStateNotChanged(String oldState, String newState) {
if (oldState != null && !PlanItemInstanceState.SUSPENDED.equals(oldState)) {
throw new FlowableIllegalStateException("plan item instance can only be resumed if the state is suspended");
}

return oldState != null && oldState.equals(newState) && abortOperationIfNewStateEqualsOldState();
}

@Override
public boolean abortOperationIfNewStateEqualsOldState() {
return true;
}

@Override
public String getOperationName() {
return null; // Default one is ok.
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.cmmn.engine.impl.agenda.operation;

import java.util.List;

import org.flowable.cmmn.api.runtime.PlanItemInstanceState;
import org.flowable.cmmn.engine.CmmnEngineConfiguration;
import org.flowable.cmmn.engine.impl.persistence.entity.PlanItemInstanceEntity;
import org.flowable.cmmn.engine.impl.util.CommandContextUtil;
import org.flowable.cmmn.model.PlanItemDefinition;
import org.flowable.cmmn.model.PlanItemTransition;
import org.flowable.cmmn.model.TimerEventListener;
import org.flowable.common.engine.api.FlowableIllegalStateException;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;

public class SuspendPlanItemInstanceOperation extends AbstractChangePlanItemInstanceStateOperation {

public SuspendPlanItemInstanceOperation(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {
super(commandContext, planItemInstanceEntity);
}

@Override
public String getNewState() {
return PlanItemInstanceState.SUSPENDED;
}

@Override
public String getLifeCycleTransition() {
return PlanItemTransition.SUSPEND;
}

@Override
protected void internalExecute() {
planItemInstanceEntity.setLastSuspendedTime(getCurrentTime(commandContext));

PlanItemDefinition planItemDefinition = planItemInstanceEntity.getPlanItem().getPlanItemDefinition();
if (planItemDefinition instanceof TimerEventListener) {
CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
List<TimerJobEntity> timerJobs = cmmnEngineConfiguration.getJobServiceConfiguration().getTimerJobEntityManager().findJobsByScopeIdAndSubScopeId(
planItemInstanceEntity.getCaseInstanceId(), planItemInstanceEntity.getId());
if (timerJobs != null && !timerJobs.isEmpty()) {
cmmnEngineConfiguration.getJobServiceConfiguration().getJobService().moveJobToSuspendedJob(timerJobs.get(0));
}
}

CommandContextUtil.getCmmnHistoryManager(commandContext).recordPlanItemInstanceSuspended(planItemInstanceEntity);
}

@Override
public boolean isStateNotChanged(String oldState, String newState) {
if (oldState != null && oldState.equals(newState)) {
throw new FlowableIllegalStateException("plan item instance is already suspended");
}

return false;
}

@Override
public boolean abortOperationIfNewStateEqualsOldState() {
return true;
}

@Override
public String getOperationName() {
return "[Suspend plan item]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import org.apache.commons.lang3.StringUtils;
import org.flowable.cmmn.api.delegate.DelegatePlanItemInstance;
import org.flowable.cmmn.api.runtime.PlanItemInstanceState;
import org.flowable.cmmn.engine.CmmnEngineConfiguration;
import org.flowable.cmmn.engine.impl.behavior.CmmnActivityBehavior;
import org.flowable.cmmn.engine.impl.behavior.CoreCmmnActivityBehavior;
Expand All @@ -45,6 +46,8 @@
import org.flowable.common.engine.impl.util.DateUtil;
import org.flowable.job.service.JobServiceConfiguration;
import org.flowable.job.service.impl.persistence.entity.JobEntity;
import org.flowable.job.service.impl.persistence.entity.SuspendedJobEntity;
import org.flowable.job.service.impl.persistence.entity.SuspendedJobEntityManager;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntityManager;
import org.joda.time.DateTime;
Expand Down Expand Up @@ -73,7 +76,12 @@ public void onStateTransition(CommandContext commandContext, DelegatePlanItemIns
|| PlanItemTransition.TERMINATE.equals(transition)
|| PlanItemTransition.EXIT.equals(transition)) {

removeTimerJob(commandContext, (PlanItemInstanceEntity) planItemInstance);
if (PlanItemInstanceState.SUSPENDED.equals(planItemInstance.getState())) {
removeSuspendedJob(commandContext, (PlanItemInstanceEntity) planItemInstance);

} else {
removeTimerJob(commandContext, (PlanItemInstanceEntity) planItemInstance);
}
}
}

Expand Down Expand Up @@ -214,11 +222,20 @@ protected void scheduleTimerJob(CommandContext commandContext, PlanItemInstanceE
protected void removeTimerJob(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {
TimerJobEntityManager timerJobEntityManager = CommandContextUtil.getCmmnEngineConfiguration(commandContext).getJobServiceConfiguration().getTimerJobEntityManager();
List<TimerJobEntity> timerJobsEntities = timerJobEntityManager
.findJobsByScopeIdAndSubScopeId(planItemInstanceEntity.getCaseInstanceId(), planItemInstanceEntity.getId());
.findJobsByScopeIdAndSubScopeId(planItemInstanceEntity.getCaseInstanceId(), planItemInstanceEntity.getId());
for (TimerJobEntity timerJobEntity : timerJobsEntities) {
timerJobEntityManager.delete(timerJobEntity);
}
}

protected void removeSuspendedJob(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {
SuspendedJobEntityManager suspendedJobEntityManager = CommandContextUtil.getCmmnEngineConfiguration(commandContext).getJobServiceConfiguration().getSuspendedJobEntityManager();
List<SuspendedJobEntity> suspendedJobsEntities = suspendedJobEntityManager
.findJobsBySubScopeId(planItemInstanceEntity.getId());
for (SuspendedJobEntity suspendedJobEntity : suspendedJobsEntities) {
suspendedJobEntityManager.delete(suspendedJobEntity);
}
}

protected Object resolveTimerExpression(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {
ExpressionManager expressionManager = CommandContextUtil.getExpressionManager(commandContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
package org.flowable.cmmn.engine.impl.cmd;

import java.util.Date;
import java.util.List;

import org.flowable.cmmn.api.runtime.PlanItemInstanceState;
import org.flowable.cmmn.engine.CmmnEngineConfiguration;
import org.flowable.cmmn.engine.impl.persistence.entity.PlanItemInstanceEntity;
import org.flowable.cmmn.engine.impl.util.CommandContextUtil;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableIllegalArgumentException;
Expand Down Expand Up @@ -72,6 +75,14 @@ public Void execute(CommandContext commandContext) {
}
task.setSuspensionState(SuspensionState.ACTIVE.getStateCode());

List<PlanItemInstanceEntity> planItemInstances = cmmnEngineConfiguration.getPlanItemInstanceEntityManager().findByReferenceId(task.getId());

if (planItemInstances != null && !planItemInstances.isEmpty()) {
planItemInstances.get(0).setState(PlanItemInstanceState.ACTIVE);

cmmnEngineConfiguration.getCmmnHistoryManager().recordPlanItemInstanceUpdated(planItemInstances.get(0));
}

HistoricTaskService historicTaskService = cmmnEngineConfiguration.getTaskServiceConfiguration().getHistoricTaskService();
historicTaskService.recordTaskInfoChange(task, updateTime, cmmnEngineConfiguration);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.cmmn.engine.impl.cmd;

import org.flowable.cmmn.engine.impl.persistence.entity.PlanItemInstanceEntity;
import org.flowable.cmmn.engine.impl.util.CommandContextUtil;
import org.flowable.common.engine.impl.interceptor.CommandContext;

public class ResumePlanItemInstanceCmd extends AbstractNeedsPlanItemInstanceCmd {

public ResumePlanItemInstanceCmd(String planItemInstanceId) {
super(planItemInstanceId);
}

@Override
protected void internalExecute(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {
CommandContextUtil.getAgenda(commandContext).planResumePlanItemInstanceOperation(planItemInstanceEntity);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.cmmn.engine.impl.cmd;

import org.flowable.cmmn.engine.impl.persistence.entity.PlanItemInstanceEntity;
import org.flowable.cmmn.engine.impl.util.CommandContextUtil;
import org.flowable.common.engine.impl.interceptor.CommandContext;

public class SuspendPlanItemInstanceCmd extends AbstractNeedsPlanItemInstanceCmd {

public SuspendPlanItemInstanceCmd(String planItemInstanceId) {
super(planItemInstanceId);
}

@Override
protected void internalExecute(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {
CommandContextUtil.getAgenda(commandContext).planSuspendPlanItemInstanceOperation(planItemInstanceEntity);
}

}
Loading
Loading