1 package org.sourceforge.jemm.client;
2
3 import java.util.Map.Entry;
4
5 import org.sourceforge.jemm.client.shared.Encodable;
6 import org.sourceforge.jemm.client.shared.ValueEncoder;
7 import org.sourceforge.jemm.database.ClassId;
8 import org.sourceforge.jemm.database.ClassInfo;
9 import org.sourceforge.jemm.database.ClientId;
10 import org.sourceforge.jemm.database.ClientThreadId;
11 import org.sourceforge.jemm.database.Database;
12 import org.sourceforge.jemm.database.EnumId;
13 import org.sourceforge.jemm.database.EnumInfo;
14 import org.sourceforge.jemm.database.FieldInfo;
15 import org.sourceforge.jemm.database.FieldType;
16 import org.sourceforge.jemm.database.GetObjectResp;
17 import org.sourceforge.jemm.database.LockAcquiredListener;
18 import org.sourceforge.jemm.database.ObjectSyncData;
19 import org.sourceforge.jemm.database.ObjectSyncResp;
20 import org.sourceforge.jemm.database.StructureModifiedException;
21 import org.sourceforge.jemm.lifecycle.TypeRequest;
22 import org.sourceforge.jemm.lifecycle.TypeResponse;
23 import org.sourceforge.jemm.types.ID;
24 import org.sourceforge.jemm.util.JEMMObject;
25
26
27
28
29
30
31
32
33
34
35
36
37
38 public class DatabaseAdapter implements ObjectDatabase {
39 protected final ClientId clientId = new ClientId("CLIENT");
40
41 protected final Database database;
42 protected JEMMObjectFactory objectFactory;
43
44 protected JEMMObjectCreator objectCreator;
45
46
47 public DatabaseAdapter(final Database database,JEMMObjectCreator creator) {
48 this.database = database;
49 this.objectCreator = creator;
50
51 if(objectCreator == null)
52 objectCreator = new JEMMObjectCreatorImpl(null,this);
53
54 objectFactory = new JEMMObjectFactory() {
55
56 @Override
57 protected JEMMObject createValue(ID id) {
58 GetObjectResp resp = database.getObject(clientId,id);
59 ClassInfo ci = database.getClassInfo(clientId,resp.getClassId());
60 return objectCreator.createObject(resp,ci);
61 }
62 };
63 }
64
65 public DatabaseAdapter(Database database) {
66 this(database,null);
67 }
68
69 public void setObjectCreator(JEMMObjectCreator creator) {
70 this.objectCreator = creator;
71 }
72
73
74
75
76
77
78
79
80
81
82
83
84 @Override
85 public JEMMObject getObject(ID jemmId) {
86 return objectFactory.create(jemmId);
87 }
88
89 public JEMMObject getRefreshedObject(ID jemmId) {
90 if(objectFactory.contains(jemmId)) {
91 JEMMObject obj = objectFactory.create(jemmId);
92 refreshObject(obj);
93 return obj;
94 }
95 return getObject(jemmId);
96 }
97
98
99
100
101
102
103
104
105
106 public void refreshObject(JEMMObject obj) {
107 Entity mainObjectEntity = new Entity(obj);
108 ObjectAccessor oa = new ObjectAccessor(obj,null);
109 GetObjectResp response = database.getObject(clientId,mainObjectEntity.getID());
110 objectCreator.refreshPrimitiveState(obj, response);
111 refreshInitialisedFields(oa,response);
112 }
113
114 private void refreshInitialisedFields(ObjectAccessor oa, GetObjectResp response) {
115 for(Entry<FieldKey,JEMMObject> entry : oa.getInitialisedObjectFields().entrySet()) {
116
117 ID objID = (entry.getValue()==null) ? null : new Entity(entry.getValue()).getID();
118 FieldKey fKey = entry.getKey();
119 FieldInfo fi = new FieldInfo(fKey.getName(),fKey.getClazz(),FieldType.OBJECT);
120
121 ID refreshValue = (ID)response.fieldValues.get(fi);
122
123 if(refreshValue==null && objID == null) {
124 continue;
125 } else if(refreshValue == null && objID!=null) {
126 oa.setField(fKey.getClazz(), fKey.getName(), null);
127 } else if(refreshValue.equals(objID)) {
128 refreshObject(entry.getValue());
129 } else {
130 JEMMObject newValue = getRefreshedObject(refreshValue);
131 oa.setField(fKey.getClazz(), fKey.getName(), newValue);
132 }
133 }
134 }
135
136
137
138
139
140
141
142 @Override
143 public void synchroniseObject(JEMMObject jo) {
144
145 ObjectSyncData syncData = objectCreator.getSyncData(jo);
146
147 ObjectSyncResp response = database.synchroniseObject(clientId, syncData.jemmId, syncData);
148 objectCreator.syncResponseUpdateObject(jo, response);
149 }
150
151 @Override
152 public void setRoot(String rootName, JEMMObject newValue) {
153 if(newValue == null)
154 database.setRoot(clientId,rootName, null);
155 else {
156 ID id = new Entity(newValue).getID();
157 database.setRoot(clientId,rootName, id);
158 }
159 }
160
161 @Override
162 public JEMMObject setRootIfNull(String rootName, JEMMObject newValue) {
163 if(newValue == null)
164 throw new NullPointerException("New value cannot be null");
165 ID newId = new Entity(newValue).getID();
166 ID postSetValueId = database.setRootIfNull(clientId,rootName, newId);
167 return getObject(postSetValueId);
168 }
169
170 @Override
171 public JEMMObject getRoot(String rootName) {
172 ID rootID = database.getRoot(clientId,rootName);
173 if(rootID==null)
174 return null;
175 else
176 return getObject(rootID);
177 }
178
179 public int cacheSize() {
180 return objectFactory.size();
181 }
182
183 @Override
184 public void acquireLock(ClientThreadId threadId, ID jemmId) {
185 database.acquireLock(threadId, jemmId);
186 }
187
188 @Override
189 public void setClientLockAcquiredListener(ClientId clientId,
190 LockAcquiredListener listener) {
191 database.setClientLockAcquiredListener(clientId, listener);
192 }
193
194 @Override
195 public ClassInfo getClassInfo(ClassId classId) {
196 return database.getClassInfo(clientId,classId);
197 }
198
199 @Override
200 public EnumInfo getEnumInfo(EnumId enumId) {
201 return database.getEnumInfo(clientId,enumId);
202 }
203
204 @Override
205 public ID newObject(ClassId classId,JEMMObject target) {
206 ID id = database.newObject(clientId,classId);
207 objectFactory.put(id,target);
208 return id;
209 }
210
211 @Override
212 public ClassId registerClass(ClassInfo classInfo) throws StructureModifiedException {
213 return database.registerClass(clientId,classInfo);
214 }
215
216 @Override
217 public EnumId registerEnum(EnumInfo enumInfo) throws StructureModifiedException {
218 return database.registerEnum(clientId,enumInfo);
219 }
220
221 @Override
222 public void releaseLock(ClientThreadId threadId, ID jemmId) {
223 database.releaseLock(threadId, jemmId);
224 }
225
226 @Override
227 public void removeLockAcquiredListener(ClientId clientId) {
228 database.removeLockAcquiredListener(clientId);
229 }
230
231 abstract class FieldValueEncoder extends ValueEncoder {
232 @SuppressWarnings("unchecked")
233 @Override public <K> K encode(K value) {
234 if(value == null)
235 return value;
236 if(value instanceof Encodable) {
237 return (K) ((Encodable) value).encode(this);
238 }
239
240 if(value instanceof Object[]) {
241 Object[] arr = ((Object[]) value).clone();
242 for(int i=0; i<arr.length; i++)
243 arr[i] = encode(arr[i]);
244 return (K) arr;
245 }
246
247 return encodeSingle(value);
248 }
249
250 public abstract <K> K encodeSingle(K value);
251 }
252
253 ValueEncoder toIdEncoder = new FieldValueEncoder() {
254 @SuppressWarnings("unchecked")
255 @Override public <K> K encodeSingle(K value) {
256 if(value instanceof JEMMObject)
257 return (K) (new Entity((JEMMObject) value)).getID();
258 else
259 return value;
260 }
261 };
262
263 ValueEncoder toObjectEncoder = new FieldValueEncoder() {
264 @SuppressWarnings("unchecked")
265 @Override public <K> K encodeSingle(K value) {
266 if(value instanceof ID)
267 return (K) getObject((ID) value);
268 else
269 return value;
270 }
271 };
272
273 @Override
274 public TypeResponse<?> processTypeRequest(JEMMObject obj,ClassId classId,TypeRequest<?> request) {
275
276 ID objId = new Entity(obj).getID();
277 TypeRequest<?> encodedRequest = toIdEncoder.encode(request);
278 TypeResponse<?> encodedResp = database.processTypeRequest(clientId, classId,
279 objId,encodedRequest);
280
281 return toObjectEncoder.encode(encodedResp);
282 }
283
284 public void shutdown() {
285 objectFactory.shutdown();
286 }
287 }