content: /*
   * Copyright 2010-2025 Hyland Software, Inc. and its affiliates.
   *
   * 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.activiti.examples.bpmn.executionlistener;
  
  import static org.assertj.core.api.Assertions.assertThat;
  
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import org.activiti.engine.impl.test.PluggableActivitiTestCase;
  import org.activiti.engine.runtime.ProcessInstance;
  import org.activiti.engine.task.Task;
  import org.activiti.engine.test.Deployment;
  import org.activiti.examples.bpmn.executionlistener.CurrentActivityExecutionListener.CurrentActivity;
  import org.activiti.examples.bpmn.executionlistener.RecorderExecutionListener.RecordedEvent;
  
  /**
  
   */
  public class ExecutionListenerTest extends PluggableActivitiTestCase {
  
      @Deployment(resources = { "org/activiti/examples/bpmn/executionlistener/ExecutionListenersProcess.bpmn20.xml" })
      public void testExecutionListenersOnAllPossibleElements() {
          RecorderExecutionListener.clear();
  
          // Process start executionListener will have executionListener class
          // that sets 2 variables
          ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
              "executionListenersProcess",
              "businessKey123"
          );
  
          String varSetInExecutionListener = (String) runtimeService.getVariable(
              processInstance.getId(),
              "variableSetInExecutionListener"
          );
          assertThat(varSetInExecutionListener).isNotNull();
          assertThat(varSetInExecutionListener).isEqualTo("firstValue");
  
          // Check if business key was available in execution listener
          String businessKey = (String) runtimeService.getVariable(processInstance.getId(), "businessKeyInExecution");
          assertThat(businessKey).isNotNull();
          assertThat(businessKey).isEqualTo("businessKey123");
  
          // Transition take executionListener will set 2 variables
          Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
          assertThat(task).isNotNull();
          taskService.complete(task.getId());
  
          varSetInExecutionListener = (String) runtimeService.getVariable(
              processInstance.getId(),
              "variableSetInExecutionListener"
          );
  
          assertThat(varSetInExecutionListener).isNotNull();
          assertThat(varSetInExecutionListener).isEqualTo("secondValue");
  
          ExampleExecutionListenerPojo myPojo = new ExampleExecutionListenerPojo();
          runtimeService.setVariable(processInstance.getId(), "myPojo", myPojo);
  
          task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
          assertThat(task).isNotNull();
          taskService.complete(task.getId());
  
          // First usertask uses a method-expression as executionListener:
          // ${myPojo.myMethod(execution.eventName)}
          ExampleExecutionListenerPojo pojoVariable = (ExampleExecutionListenerPojo) runtimeService.getVariable(
              processInstance.getId(),
              "myPojo"
          );
          assertThat(pojoVariable.getReceivedEventName()).isNotNull();
          assertThat(pojoVariable.getReceivedEventName()).isEqualTo("end");
  
          task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
          assertThat(task).isNotNull();
          taskService.complete(task.getId());
  
          assertProcessEnded(processInstance.getId());
  
          List<RecordedEvent> events = RecorderExecutionListener.getRecordedEvents();
          assertThat(events).hasSize(1);
          RecordedEvent event = events.get(0);
          assertThat(event.getParameter()).isEqualTo("End Process Listener");
      }
  
      @Deployment(
          resources = { "org/activiti/examples/bpmn/executionlistener/ExecutionListenersStartEndEvent.bpmn20.xml" }
      )
      public void testExecutionListenersOnStartEndEvents() {
          RecorderExecutionListener.clear();
  
          ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("executionListenersProcess");
          assertProcessEnded(processInstance.getId());
  
          List<RecordedEvent> recordedEvents = RecorderExecutionListener.getRecordedEvents();
          assertThat(recordedEvents).hasSize(4);
  
          assertThat(recordedEvents.get(0).getActivityId()).isEqualTo("theStart");
          assertThat(recordedEvents.get(0).getActivityName()).isEqualTo("Start Event");
          assertThat(recordedEvents.get(0).getParameter()).isEqualTo("Start Event Listener");
          assertThat(recordedEvents.get(0).getEventName()).isEqualTo("end");
  
          assertThat(recordedEvents.get(1).getActivityId()).isEqualTo("noneEvent");
          assertThat(recordedEvents.get(1).getActivityName()).isEqualTo("None Event");
          assertThat(recordedEvents.get(1).getParameter()).isEqualTo("Intermediate Catch Event Listener");
          assertThat(recordedEvents.get(1).getEventName()).isEqualTo("end");
  
          assertThat(recordedEvents.get(2).getActivityId()).isEqualTo("signalEvent");
          assertThat(recordedEvents.get(2).getActivityName()).isEqualTo("Signal Event");
          assertThat(recordedEvents.get(2).getParameter()).isEqualTo("Intermediate Throw Event Listener");
          assertThat(recordedEvents.get(2).getEventName()).isEqualTo("start");
  
          assertThat(recordedEvents.get(3).getActivityId()).isEqualTo("theEnd");
          assertThat(recordedEvents.get(3).getActivityName()).isEqualTo("End Event");
          assertThat(recordedEvents.get(3).getParameter()).isEqualTo("End Event Listener");
          assertThat(recordedEvents.get(3).getEventName()).isEqualTo("start");
      }
  
      @Deployment(
          resources = {
              "org/activiti/examples/bpmn/executionlistener/ExecutionListenersFieldInjectionProcess.bpmn20.xml",
          }
      )
      public void testExecutionListenerFieldInjection() {
          Map<String, Object> variables = new HashMap<String, Object>();
          variables.put("myVar", "listening!");
  
          ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
              "executionListenersProcess",
              variables
          );
  
          Object varSetByListener = runtimeService.getVariable(processInstance.getId(), "var");
          assertThat(varSetByListener).isNotNull();
          assertThat(varSetByListener).isInstanceOf(String.class);
  
          // Result is a concatenation of fixed injected field and injected expression
          assertThat(varSetByListener).isEqualTo("Yes, I am listening!");
      }
  
      @Deployment(
          resources = { "org/activiti/examples/bpmn/executionlistener/ExecutionListenersCurrentActivity.bpmn20.xml" }
      )
      public void testExecutionListenerCurrentActivity() {
          CurrentActivityExecutionListener.clear();
  
          ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("executionListenersProcess");
          assertProcessEnded(processInstance.getId());
  
          List<CurrentActivity> currentActivities = CurrentActivityExecutionListener.getCurrentActivities();
          assertThat(currentActivities).hasSize(3);
  
          assertThat(currentActivities.get(0).getActivityId()).isEqualTo("theStart");
          assertThat(currentActivities.get(0).getActivityName()).isEqualTo("Start Event");
  
          assertThat(currentActivities.get(1).getActivityId()).isEqualTo("noneEvent");
          assertThat(currentActivities.get(1).getActivityName()).isEqualTo("None Event");
  
          assertThat(currentActivities.get(2).getActivityId()).isEqualTo("theEnd");
          assertThat(currentActivities.get(2).getActivityName()).isEqualTo("End Event");
      }
  
      @Deployment(
          resources = {
              "org/activiti/examples/bpmn/executionlistener/ExecutionListenersForSubprocessStartEndEvent.bpmn20.xml",
          }
      )
      public void testExecutionListenersForSubprocessStartEndEvents() {
          RecorderExecutionListener.clear();
  
          ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("executionListenersProcess");
  
          List<RecordedEvent> recordedEvents = RecorderExecutionListener.getRecordedEvents();
          assertThat(recordedEvents).hasSize(1);
          assertThat(recordedEvents.get(0).getParameter()).isEqualTo("Process Start");
  
          RecorderExecutionListener.clear();
  
          Task task = taskService.createTaskQuery().singleResult();
          taskService.complete(task.getId());
  
          assertProcessEnded(processInstance.getId());
  
          recordedEvents = RecorderExecutionListener.getRecordedEvents();
  
          assertThat(recordedEvents).hasSize(3);
          assertThat(recordedEvents.get(0).getParameter()).isEqualTo("Subprocess Start");
          assertThat(recordedEvents.get(1).getParameter()).isEqualTo("Subprocess End");
          assertThat(recordedEvents.get(2).getParameter()).isEqualTo("Process End");
      }
  
      @Deployment(
          resources = {
              "org/activiti/examples/bpmn/executionlistener/ExecutionListenersOnProcessEndWhenProcessIsDeleted.bpmn20.xml",
          }
      )
      public void testExecutionListenerOnProcessEndWhenProcessIsDeleted() {
          RecorderExecutionListener.clear();
  
          // GIVEN: a process with an executionListener to be executed at the end of the process
          ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("executionListenersProcess");
  
          // WHEN: we delete the process
          runtimeService.deleteProcessInstance(processInstance.getProcessInstanceId(), null);
  
          // THEN: the process should end and
          assertProcessEnded(processInstance.getId());
  
          // THEN: and the executionListener should have run
          List<RecordedEvent> recordedEvents = RecorderExecutionListener.getRecordedEvents();
          assertThat(recordedEvents).hasSize(1);
          assertThat(recordedEvents.get(0).getParameter()).isEqualTo("Process has ended");
      }
  }
  