1 package cz.cuni.amis.pogamut.base.component.bus.event;
2
3 import java.util.concurrent.CountDownLatch;
4 import java.util.concurrent.TimeUnit;
5
6 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
7 import cz.cuni.amis.pogamut.base.component.bus.IComponentEvent;
8 import cz.cuni.amis.pogamut.base.component.bus.IComponentEventListener;
9 import cz.cuni.amis.utils.NullCheck;
10 import cz.cuni.amis.utils.exception.PogamutInterruptedException;
11 import cz.cuni.amis.utils.token.Token;
12
13
14
15
16
17
18 public class WaitForEvent {
19
20
21
22
23
24
25
26 public interface IEventFilter<T> {
27
28
29
30
31
32
33
34
35 public Class<T> getEventClass();
36
37
38
39
40
41 public Class getComponentClass();
42
43
44
45
46
47 public Token getComponentId();
48
49
50
51
52
53
54 public boolean accept(T event);
55
56 }
57
58 private final CountDownLatch eventLatch = new CountDownLatch(1);
59 private final IComponentBus componentBus;
60 private final IEventFilter acceptEvent;
61 private final IComponentEventListener listener;
62 private final IComponentEventListener fatalErrorListener;
63 private boolean fatalError = false;
64
65 public WaitForEvent(IComponentBus bus, IEventFilter accept) {
66 this.componentBus = bus;
67 NullCheck.check(this.componentBus, "bus");
68 this.acceptEvent = accept;
69 NullCheck.check(accept.getEventClass(), "accept.getEventClass()");
70 this.listener = new IComponentEventListener<IComponentEvent>() {
71
72 @Override
73 public void notify(IComponentEvent event) {
74 if (acceptEvent.accept(acceptEvent.getEventClass().cast(event))) {
75 try {
76 componentBus.removeEventListener(acceptEvent.getEventClass(), this);
77 componentBus.removeEventListener(IFatalErrorEvent.class, fatalErrorListener);
78 } finally {
79 eventLatch.countDown();
80 }
81 }
82 }
83
84 };
85
86 this.fatalErrorListener = new IComponentEventListener<IComponentEvent>() {
87
88 @Override
89 public void notify(IComponentEvent event) {
90 fatalError = true;
91 try {
92 componentBus.removeEventListener(acceptEvent.getEventClass(), this);
93 componentBus.removeEventListener(IFatalErrorEvent.class, fatalErrorListener);
94 } finally {
95 eventLatch.countDown();
96 }
97 }
98
99 };
100
101 if (!componentBus.isRunning()) {
102 fatalError = true;
103 eventLatch.countDown();
104 } else {
105 componentBus.addEventListener(IFatalErrorEvent.class, fatalErrorListener);
106 componentBus.addEventListener(acceptEvent.getEventClass(), listener);
107 if (!componentBus.isRunning()) {
108 fatalError = true;
109 eventLatch.countDown();
110 try {
111 componentBus.removeEventListener(IFatalErrorEvent.class, fatalErrorListener);
112 } catch (Exception e) {
113 } finally {
114 try {
115 componentBus.removeEventListener(acceptEvent.getEventClass(), listener);
116 } catch (Exception e) {
117 }
118 }
119 }
120 }
121 }
122
123
124
125
126
127
128 public boolean await() throws PogamutInterruptedException {
129 try {
130 eventLatch.await();
131 return !fatalError;
132 } catch (InterruptedException e) {
133 throw new PogamutInterruptedException(e, this);
134 }
135 }
136
137
138
139
140
141
142
143
144
145
146 public boolean await(long timeoutMillis) throws PogamutInterruptedException {
147 try {
148 eventLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
149 } catch (InterruptedException e) {
150 throw new PogamutInterruptedException(e, this);
151 }
152 return !fatalError && eventLatch.getCount() == 0;
153 }
154
155
156
157
158 public void destroy() {
159 componentBus.removeEventListener(acceptEvent.getEventClass(), listener);
160 eventLatch.countDown();
161 }
162
163 }