1 package cz.cuni.amis.pogamut.base.communication.worldview.impl;
2
3 import java.util.LinkedList;
4 import java.util.Queue;
5
6 import com.google.inject.Inject;
7 import com.google.inject.name.Named;
8
9 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldChangeEvent;
10 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldEventWrapper;
11 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult;
12 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdatedEvent;
13 import cz.cuni.amis.pogamut.base.communication.worldview.IWorldChangeEventInput;
14 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEvent;
15 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObject;
16 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectDestroyedEvent;
17 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectFirstEncounteredEvent;
18 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
19 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
20 import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentNotRunningException;
21 import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentPausedException;
22 import cz.cuni.amis.pogamut.base.component.controller.ComponentController;
23 import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
24 import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
25 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
26 import cz.cuni.amis.utils.NullCheck;
27 import cz.cuni.amis.utils.exception.PogamutException;
28 import java.util.logging.Level;
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 @AgentScoped
74 public class EventDrivenWorldView extends AbstractWorldView {
75
76 public static final String WORLDVIEW_DEPENDENCY = "EventDrivenWorldViewDependency";
77
78
79
80
81
82
83 protected boolean receiveEventProcessing = false;
84
85
86
87
88
89
90 protected LinkedList<IWorldChangeEvent> notifyEventsList = new LinkedList<IWorldChangeEvent>();
91
92 @Inject
93 public EventDrivenWorldView(@Named(WORLDVIEW_DEPENDENCY) ComponentDependencies dependencies, IComponentBus bus, IAgentLogger log) {
94 super(dependencies, bus, log);
95 }
96
97
98
99
100 @Override
101 protected void raiseEvent(IWorldEvent event) {
102 try {
103 if (log != null && log.isLoggable(Level.FINER)) log.finer("raising event " + event);
104 super.raiseEvent(event);
105 } catch (Exception e) {
106 this.controller.fatalError("Exception raising event " + event, e);
107 this.kill();
108 }
109 }
110
111
112
113
114
115
116
117
118
119
120 protected void innerNotify(IWorldChangeEvent event) {
121 NullCheck.check(event, "event");
122 if (log.isLoggable(Level.FINEST)) {
123 log.finest("processing " + event);
124 }
125
126 if (event instanceof IWorldObjectUpdatedEvent) {
127 objectUpdatedEvent((IWorldObjectUpdatedEvent)event);
128 } else {
129 if (event instanceof IWorldEventWrapper) {
130 raiseEvent(((IWorldEventWrapper) event).getWorldEvent());
131 } else
132 if (event instanceof IWorldEvent) {
133 raiseEvent((IWorldEvent)event);
134 } else {
135 throw new PogamutException("Unsupported event type received (" + event.getClass() + ").", this);
136 }
137 }
138 }
139
140
141
142
143
144
145
146 protected void objectUpdatedEvent(IWorldObjectUpdatedEvent updateEvent) {
147 IWorldObject obj = get(updateEvent.getId());
148 IWorldObjectUpdateResult updateResult = updateEvent.update(obj);
149 switch (updateResult.getResult()) {
150 case CREATED:
151 objectCreated(updateResult.getObject());
152 return;
153 case UPDATED:
154 if (updateResult.getObject() != obj) {
155 throw new PogamutException("Update event " + updateEvent + " does not returned the same instance of the object (result UPDATED).", this);
156 }
157 objectUpdated(obj);
158 return;
159 case SAME:
160 if (log.isLoggable(Level.FINEST)) {
161 log.finest("no update for " + updateEvent);
162 }
163 return;
164 case DESTROYED:
165 objectDestroyed(obj);
166 return;
167 default:
168 throw new PogamutException("Unhandled object update result " + updateResult.getResult() + " for the object " + obj + ".", this);
169 }
170 }
171
172
173
174
175
176
177
178 protected void objectCreated(IWorldObject obj) {
179 addWorldObject(obj);
180 raiseEvent(new WorldObjectFirstEncounteredEvent<IWorldObject>(obj, obj.getSimTime()));
181 objectUpdated(obj);
182 }
183
184
185
186
187
188
189
190
191
192 protected void objectUpdated(IWorldObject obj) {
193 raiseEvent(new WorldObjectUpdatedEvent<IWorldObject>(obj, obj.getSimTime()));
194 }
195
196
197
198
199
200
201
202
203 protected void objectDestroyed(IWorldObject obj) {
204 removeWorldObject(obj);
205 raiseEvent(new WorldObjectDestroyedEvent<IWorldObject>(obj, obj.getSimTime()));
206 }
207
208 @Override
209 public synchronized void notify(IWorldChangeEvent event) throws ComponentNotRunningException, ComponentPausedException {
210 if (isPaused()) {
211 throw new ComponentPausedException(controller.getState().getFlag(), this);
212 }
213 if (!isRunning()) {
214 throw new ComponentNotRunningException(controller.getState().getFlag(), this);
215 }
216
217
218 if (receiveEventProcessing) {
219
220
221
222 notifyEventsList.add(event);
223 return;
224 } else {
225
226 receiveEventProcessing = true;
227 }
228
229 try {
230 innerNotify(event);
231
232 while (notifyEventsList.size() != 0) {
233
234 innerNotify(notifyEventsList.poll());
235 }
236 } finally {
237
238 receiveEventProcessing = false;
239 }
240 }
241
242 @Override
243 public synchronized void notifyAfterPropagation(IWorldChangeEvent event) throws ComponentNotRunningException, ComponentPausedException {
244 notifyEventsList.addFirst(event);
245 }
246
247 @Override
248 public synchronized void notifyImmediately(IWorldChangeEvent event) throws ComponentNotRunningException, ComponentPausedException {
249 innerNotify(event);
250 }
251
252 }