1 package cz.cuni.amis.pogamut.defcon.communication.messages.infos;
2
3 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult;
4 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult.Result;
5 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult.WorldObjectUpdateResult;
6 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdatedEvent;
7 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObject;
8 import cz.cuni.amis.pogamut.base.communication.worldview.object.WorldObjectId;
9 import cz.cuni.amis.pogamut.defcon.communication.messages.Updatable;
10 import cz.cuni.amis.utils.exception.PogamutException;
11
12 import java.lang.reflect.Field;
13
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18
19 import javabot.PogamutJBotSupport;
20
21
22
23
24
25
26
27
28
29 public class DefConObjectUpdate implements IWorldObjectUpdatedEvent {
30
31
32
33 private static Map<Class<?>, Updater> updaters = new HashMap<Class<?>, Updater>();
34
35
36
37
38 private double time = 0;
39
40
41
42
43 private DefConObject source;
44
45
46
47
48
49
50 public DefConObjectUpdate(DefConObject source) {
51 this.source = source;
52 }
53
54
55
56
57
58
59
60
61 public synchronized static Updater getUpdater(Class<?> cls) {
62 Updater updater = updaters.get(cls);
63
64 if (updater != null) {
65 return updater;
66 }
67
68 updater = new Updater(cls);
69 updaters.put(cls, updater);
70
71 return updater;
72 }
73
74
75
76
77
78
79 public DefConObject getSource() {
80 return this.source;
81 }
82
83
84
85
86
87
88 @Override
89 public WorldObjectId getId() {
90 return (source == null) ? null : source.getId();
91 }
92
93
94
95
96
97
98
99
100 @Override
101 public IWorldObjectUpdateResult update(IWorldObject obj) {
102 if (source == null) {
103 return null;
104 }
105
106 if (obj == null) {
107 return new WorldObjectUpdateResult(Result.CREATED, source);
108 }
109
110 if (!obj.getClass().equals(source.getClass())) {
111 throw new PogamutException("Can't update object of class " + obj.getClass().getName() +
112 " with information from object of class " + source.getClass().getName(), this);
113 }
114
115 if (source.getDestroyed()) {
116 return new WorldObjectUpdateResult(Result.DESTROYED, obj);
117 }
118
119 getUpdater(obj.getClass()).update(obj, source);
120
121 return new WorldObjectUpdateResult(Result.UPDATED, obj);
122 }
123
124
125
126
127
128
129 public double getLastSeenTime() {
130 return time;
131 }
132
133
134
135
136
137
138 protected void setLastSeenTime(double time) {
139 this.time = time;
140 }
141
142
143
144
145
146
147 @Override
148 public long getSimTime() {
149 return (long) time;
150 }
151
152
153
154
155
156
157
158 private static class Updater {
159
160
161
162 private Class<?> cls;
163
164
165
166
167 private List<Field> fields = new ArrayList<Field>();
168
169
170
171
172
173
174 public Updater(Class<?> cls) {
175 this.cls = cls;
176
177 do {
178 for (Field field : cls.getDeclaredFields()) {
179 if (field.isAnnotationPresent(Updatable.class)) {
180 fields.add(field);
181 }
182 }
183 } while ((cls = cls.getSuperclass()) != null);
184 }
185
186
187
188
189
190
191 public Class getUpdaterClass() {
192 return cls;
193 }
194
195
196
197
198
199
200
201
202 public void update(Object oldObj, Object newObj) {
203 if (!oldObj.getClass().equals(cls) || !newObj.getClass().equals(cls)) {
204 throw new PogamutException("Can't update object of class " +
205 oldObj.getClass().getName() + " with information from object of class " +
206 newObj.getClass().getName() + " because they bot must be of class " +
207 cls.getName(), this);
208 }
209
210 for (Field field : fields) {
211 try {
212 field.setAccessible(true);
213
214 Object value = field.get(newObj);
215
216 if (value == null) {
217 continue;
218 }
219
220 try {
221
222 field.set(oldObj, value);
223 } catch (Exception e) {
224 throw new PogamutException("Could not set value " + value +
225 " to the field '" + field.getName() + "' of the object " + newObj +
226 " because: " + e.getMessage(), e, this);
227 }
228 } catch (Exception e) {
229 throw new PogamutException("Could not obtain field '" + field.getName() +
230 "' from object " + newObj + " because: " + e.getMessage(), e, this);
231 } finally {
232 field.setAccessible(false);
233 }
234 }
235 }
236 }
237 }