ludc
2025-01-16 986aa62ed00bee39363bab41b4eeb8259d446efd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jbpm.pvm.internal.model.op;
 
import java.util.List;
 
import org.jbpm.api.listener.EventListener;
import org.jbpm.internal.log.Log;
import org.jbpm.pvm.internal.job.MessageImpl;
import org.jbpm.pvm.internal.model.EventImpl;
import org.jbpm.pvm.internal.model.EventListenerReference;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.jbpm.pvm.internal.model.ObservableElement;
import org.jbpm.pvm.internal.model.ObservableElementImpl;
 
 
/**
 * @author Tom Baeyens
 */
public class ExecuteEventListener extends AtomicOperation {
  
  private static final long serialVersionUID = 1L;
  
  private static Log log = Log.getLog(ExecuteEventListener.class.getName());
  
  public boolean isAsync(ExecutionImpl execution) {
    int eventListenerIndex = execution.getEventListenerIndex();
    EventImpl event = execution.getEvent();
    
    if ( (eventListenerIndex==0)
         && (event.isAsync())
       ) {
      return true;
    }
    
    List<EventListenerReference> eventListenerReferences = event.getListenerReferences();
    if ( (eventListenerReferences==null)
         || (eventListenerReferences.isEmpty())
       ) {
      return false;
    }
 
    EventListenerReference eventListenerReference = eventListenerReferences.get(eventListenerIndex);
    return eventListenerReference.isAsync();
  }
 
  public void perform(ExecutionImpl execution) {
    EventImpl event = execution.getEvent();
    ObservableElementImpl observableElement = event.getObservableElement();
    int eventListenerIndex = execution.getEventListenerIndex();
    List<EventListenerReference> eventListenerReferences = event.getListenerReferences();
    if ( (eventListenerReferences!=null)
         && (!eventListenerReferences.isEmpty())
       ) {
      EventListenerReference eventListenerReference = eventListenerReferences.get(eventListenerIndex);
      ObservableElement eventSource = execution.getEventSource();
      if ((eventSource == observableElement) || (eventListenerReference.isPropagationEnabled())) {
        EventListener eventListener = eventListenerReference.getEventListener();
        log.trace("executing " + eventListener + " for " + event);
        try {
          // TODO can/should this invocation be unified with the exception handler invocation of the event notification method?
          eventListener.notify(execution);
        } catch (Exception e) {
          log.trace("exception during action: " + e);
          execution.handleException((ObservableElementImpl) observableElement, event, eventListenerReference, e, "couldn't run action " + eventListener);
        }
      }
      // increment the event listener index
      eventListenerIndex++;
      execution.setEventListenerIndex(eventListenerIndex);
    }
    
    // if there are more listeners in this event
    if ( (eventListenerReferences!=null)
         && (eventListenerIndex < eventListenerReferences.size())
       ) {
      // execute the next listener
      execution.performAtomicOperation(AtomicOperation.EXECUTE_EVENT_LISTENER);
 
    } else {
      // there are no more listeners in this event
 
      ObservableElementImpl parent = observableElement.getParent();
      // find the next event with listeners
      EventImpl propagatedEvent = ExecutionImpl.findEvent(parent, event.getName());
 
      // if there is an propagated event with listeners 
      if (propagatedEvent != null) {
        // propagate to the that event
        execution.setEvent(propagatedEvent);
        execution.setEventListenerIndex(0);
        execution.performAtomicOperation(AtomicOperation.EXECUTE_EVENT_LISTENER);
 
      } else {
        // event is completed, perform the eventCompletedOperation 
        AtomicOperation eventCompletedOperation = execution.getEventCompletedOperation();
 
        execution.setEvent(null);
        execution.setEventSource(null);
        execution.setEventListenerIndex(0);
        execution.setEventCompletedOperation(null);
 
        if (eventCompletedOperation != null) {
          execution.performAtomicOperation(eventCompletedOperation);
        }
      }
    }
  }
 
  public MessageImpl< ? > createAsyncMessage(ExecutionImpl execution) {
    return new ExecuteEventListenerMessage(execution);
  }
 
  public String toString() {
    return "ExecuteEventListener";
  }
}