All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.camunda.bpm.engine.impl.cmd.RecalculateJobDuedateCmd Maven / Gradle / Ivy

There is a newer version: 7.23.0-alpha1
Show newest version
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. Camunda licenses this file to you under the Apache License,
 * Version 2.0; 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.camunda.bpm.engine.impl.cmd;

import static org.camunda.bpm.engine.impl.util.EnsureUtil.ensureNotEmpty;
import static org.camunda.bpm.engine.impl.util.EnsureUtil.ensureNotNull;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.camunda.bpm.engine.ProcessEngineException;
import org.camunda.bpm.engine.exception.NotFoundException;
import org.camunda.bpm.engine.history.UserOperationLogEntry;
import org.camunda.bpm.engine.impl.bpmn.parser.BpmnParse;
import org.camunda.bpm.engine.impl.cfg.CommandChecker;
import org.camunda.bpm.engine.impl.context.ProcessApplicationContextUtil;
import org.camunda.bpm.engine.impl.interceptor.Command;
import org.camunda.bpm.engine.impl.interceptor.CommandContext;
import org.camunda.bpm.engine.impl.jobexecutor.JobHandlerConfiguration;
import org.camunda.bpm.engine.impl.jobexecutor.TimerCatchIntermediateEventJobHandler;
import org.camunda.bpm.engine.impl.jobexecutor.TimerDeclarationImpl;
import org.camunda.bpm.engine.impl.jobexecutor.TimerExecuteNestedActivityJobHandler;
import org.camunda.bpm.engine.impl.jobexecutor.TimerStartEventJobHandler;
import org.camunda.bpm.engine.impl.jobexecutor.TimerStartEventSubprocessJobHandler;
import org.camunda.bpm.engine.impl.jobexecutor.TimerTaskListenerJobHandler;
import org.camunda.bpm.engine.impl.jobexecutor.TimerEventJobHandler.TimerJobConfiguration;
import org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity;
import org.camunda.bpm.engine.impl.persistence.entity.JobEntity;
import org.camunda.bpm.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.camunda.bpm.engine.impl.persistence.entity.PropertyChange;
import org.camunda.bpm.engine.impl.persistence.entity.TimerEntity;
import org.camunda.bpm.engine.impl.pvm.process.ActivityImpl;


/**
 * @author Tobias Metzke
 */
public class RecalculateJobDuedateCmd implements Command, Serializable {

  private static final long serialVersionUID = 1L;

  private final String jobId;
  private boolean creationDateBased;

  public RecalculateJobDuedateCmd(String jobId, boolean creationDateBased) {
    ensureNotEmpty("The job id is mandatory", "jobId", jobId);
    this.jobId = jobId;
    this.creationDateBased = creationDateBased;
  }

  public Void execute(final CommandContext commandContext) {
    final JobEntity job = commandContext.getJobManager().findJobById(jobId);
    ensureNotNull(NotFoundException.class, "No job found with id '" + jobId + "'", "job", job);

    // allow timer jobs only
    checkJobType(job);

    for(CommandChecker checker : commandContext.getProcessEngineConfiguration().getCommandCheckers()) {
      checker.checkUpdateJob(job);
    }

    // prepare recalculation
    final TimerDeclarationImpl timerDeclaration = findTimerDeclaration(commandContext, job);
    final TimerEntity timer = (TimerEntity) job;
    Date oldDuedate = job.getDuedate();
    Runnable runnable = new Runnable() {
      @Override
      public void run() {
        timerDeclaration.resolveAndSetDuedate(timer.getExecution(), timer, creationDateBased);
      }
    };

    // run recalculation in correct context
    ProcessDefinitionEntity contextDefinition = commandContext
        .getProcessEngineConfiguration()
        .getDeploymentCache()
        .findDeployedProcessDefinitionById(job.getProcessDefinitionId());
    ProcessApplicationContextUtil.doContextSwitch(runnable, contextDefinition);

    // log operation
    List propertyChanges = new ArrayList<>();
    propertyChanges.add(new PropertyChange("duedate", oldDuedate, job.getDuedate()));
    propertyChanges.add(new PropertyChange("creationDateBased", null, creationDateBased));
    commandContext.getOperationLogManager().logJobOperation(UserOperationLogEntry.OPERATION_TYPE_RECALC_DUEDATE, jobId,
        job.getJobDefinitionId(), job.getProcessInstanceId(), job.getProcessDefinitionId(), job.getProcessDefinitionKey(),
        propertyChanges);

    return null;
  }

  protected void checkJobType(JobEntity job) {
    String type = job.getJobHandlerType();
    if (!(TimerExecuteNestedActivityJobHandler.TYPE.equals(type) ||
        TimerCatchIntermediateEventJobHandler.TYPE.equals(type) ||
        TimerStartEventJobHandler.TYPE.equals(type) ||
        TimerStartEventSubprocessJobHandler.TYPE.equals(type) ||
        TimerTaskListenerJobHandler.TYPE.equals(type)) ||
        !(job instanceof TimerEntity)) {
      throw new ProcessEngineException("Only timer jobs can be recalculated, but the job with id '" + jobId + "' is of type '" + type + "'.");
    }
  }

  protected TimerDeclarationImpl findTimerDeclaration(CommandContext commandContext, JobEntity job) {
    TimerDeclarationImpl timerDeclaration = null;
    if (job.getExecutionId() != null) {
      // timeout listener or boundary / intermediate / subprocess start event
      timerDeclaration = findTimerDeclarationForActivity(commandContext, job);
    } else {
      // process instance start event
      timerDeclaration = findTimerDeclarationForProcessStartEvent(commandContext, job);
    }

    if (timerDeclaration == null) {
      throw new ProcessEngineException("No timer declaration found for job id '" + jobId + "'.");
    }
    return timerDeclaration;
  }

  protected TimerDeclarationImpl findTimerDeclarationForActivity(CommandContext commandContext, JobEntity job) {
    ExecutionEntity execution = commandContext.getExecutionManager().findExecutionById(job.getExecutionId());
    if (execution == null) {
      throw new ProcessEngineException("No execution found with id '" + job.getExecutionId() + "' for job id '" + jobId + "'.");
    }
    ActivityImpl activity = execution.getProcessDefinition().findActivity(job.getActivityId());
    if (activity != null) {
      if (TimerTaskListenerJobHandler.TYPE.equals(job.getJobHandlerType())) {
        return findTimeoutListenerDeclaration(job, activity);
      }
      Map timerDeclarations = TimerDeclarationImpl.getDeclarationsForScope(activity.getEventScope());
      if (!timerDeclarations.isEmpty() && timerDeclarations.containsKey(job.getActivityId())) {
        return  timerDeclarations.get(job.getActivityId());
      }
    }
    return null;
  }

  protected TimerDeclarationImpl findTimeoutListenerDeclaration(JobEntity job, ActivityImpl activity) {
    Map> timeoutDeclarations = TimerDeclarationImpl.getTimeoutListenerDeclarationsForScope(activity.getEventScope());
    if (!timeoutDeclarations.isEmpty()) {
      Map activityTimeouts = timeoutDeclarations.get(job.getActivityId());
      if (activityTimeouts != null && !activityTimeouts.isEmpty()) {
        JobHandlerConfiguration jobHandlerConfiguration = job.getJobHandlerConfiguration();
        if (jobHandlerConfiguration instanceof TimerJobConfiguration) {
          return activityTimeouts.get(((TimerJobConfiguration) jobHandlerConfiguration).getTimerElementSecondaryKey());
        }
      }
    }
    return null;
  }

  protected TimerDeclarationImpl findTimerDeclarationForProcessStartEvent(CommandContext commandContext, JobEntity job) {
    ProcessDefinitionEntity processDefinition = commandContext.getProcessEngineConfiguration().getDeploymentCache().findDeployedProcessDefinitionById(job.getProcessDefinitionId());
    @SuppressWarnings("unchecked")
    List timerDeclarations = (List) processDefinition.getProperty(BpmnParse.PROPERTYNAME_START_TIMER);
    for (TimerDeclarationImpl timerDeclarationCandidate : timerDeclarations) {
      if (timerDeclarationCandidate.getJobDefinitionId().equals(job.getJobDefinitionId())) {
        return timerDeclarationCandidate;
      }
    }
    return null;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy