1 package cz.cuni.amis.pogamut.ut2004.communication.worldview;
2
3 import java.util.ArrayList;
4 import java.util.LinkedList;
5 import java.util.List;
6 import java.util.Queue;
7
8 import com.google.inject.Inject;
9 import com.google.inject.name.Named;
10
11 import cz.cuni.amis.pogamut.base.communication.mediator.IMediator;
12 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldChangeEvent;
13 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
14 import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentNotRunningException;
15 import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
16 import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
17 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
18 import cz.cuni.amis.pogamut.base3d.ILockableVisionWorldView;
19 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.BeginMessage;
20 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
21 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Player;
22
23 import java.util.logging.Level;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 @AgentScoped
43 public class UT2004LockableWorldView extends UT2004WorldView implements ILockableVisionWorldView {
44
45 public static final String WORLDVIEW_DEPENDENCY = "UT2004LockableWorldViewDependency";
46
47
48
49
50 private Queue<List<IWorldChangeEvent>> batches = new LinkedList<List<IWorldChangeEvent>>();
51
52
53
54
55 private List<IWorldChangeEvent> currentBatch = new ArrayList<IWorldChangeEvent>();
56
57
58
59
60 private boolean locked = false;
61
62
63
64
65 private boolean beginCame = false;
66
67
68
69
70 private final Object objectMutex = new Object();
71
72 @Inject
73 public UT2004LockableWorldView(@Named(WORLDVIEW_DEPENDENCY) ComponentDependencies dependencies, IMediator mediator, IComponentBus bus, IAgentLogger log) {
74 super(dependencies, mediator, bus, log);
75 }
76
77
78
79
80 public void lock() throws ComponentNotRunningException {
81 if (!isRunning()) throw new ComponentNotRunningException(controller.getState().getFlag(), this);
82 synchronized(objectMutex) {
83 if (isLocked()) return;
84 locked = true;
85 if (log.isLoggable(Level.FINER)) log.finer("World view locked.");
86 }
87 }
88
89
90
91
92
93 public void unlock() throws ComponentNotRunningException {
94 synchronized(objectMutex) {
95 if (!isLocked()) return;
96 if (log.isLoggable(Level.FINER)) log.finer("World view is being unlocked.");
97 locked = false;
98 for (List<IWorldChangeEvent> batch : batches) {
99 processBatch(batch);
100 }
101 batches.clear();
102 if (log.isLoggable(Level.FINER)) log.finer("World view unlocked.");
103 }
104 }
105
106 public boolean isLocked() {
107 return locked;
108 }
109
110 public boolean hasBatchesToProcess() {
111 return !batches.isEmpty();
112 }
113
114
115
116
117
118
119
120 private void processBatch(List<IWorldChangeEvent> batch) {
121 for (IWorldChangeEvent event : batch) {
122 super.notify(event);
123 }
124 }
125
126
127
128
129 @Override
130 public void notify(IWorldChangeEvent event) {
131
132
133 if (!isRunning()) throw new ComponentNotRunningException(controller.getState().getFlag(), this);
134 synchronized(objectMutex) {
135 if (!beginCame) {
136 if (event instanceof BeginMessage) {
137 beginCame = true;
138 } else {
139 super.notify(event);
140 return;
141 }
142 }
143 if (isLocked()) {
144 if (event instanceof EndMessage) {
145 currentBatch.add(event);
146 batches.add(currentBatch);
147 currentBatch = new ArrayList<IWorldChangeEvent>(currentBatch.size()+20);
148 } else {
149 currentBatch.add(event);
150 }
151 } else {
152 if (event instanceof EndMessage) {
153 currentBatch.add(event);
154 processBatch(currentBatch);
155 currentBatch.clear();
156 } else {
157 currentBatch.add(event);
158 }
159 }
160 }
161 }
162
163
164 }