1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
package net.wotonomy.test;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.wotonomy.control.EOEditingContext;
import net.wotonomy.control.EOFetchSpecification;
import net.wotonomy.control.EOGlobalID;
import net.wotonomy.control.EOObjectStore;
import net.wotonomy.control.EOObserverCenter;
import net.wotonomy.test.DataKeyID;
import net.wotonomy.datastore.DataSoup;
import net.wotonomy.datastore.DataView;
import net.wotonomy.datastore.XMLFileSoup;
import net.wotonomy.foundation.NSArray;
import net.wotonomy.foundation.NSMutableArray;
import net.wotonomy.foundation.internal.Duplicator;
import net.wotonomy.foundation.internal.WotonomyException;
/**
* An object store that wraps a datastore for vending test objects.
*/
public class TestObjectStore extends EOObjectStore {
DataSoup soup;
/**
* Constructor specifies path to datastore.
*/
public TestObjectStore(String aPath) {
soup = new XMLFileSoup(aPath);
}
/**
* This implementation simply returns objectsWithSourceGlobalID.
*/
@Override
public NSArray arrayFaultWithSourceGlobalID(EOGlobalID aGlobalID, String aRelationship, EOEditingContext aContext) {
return objectsForSourceGlobalID(aGlobalID, aRelationship, aContext);
}
/**
* This implementation returns the actual object for the specified id.
*/
@Override
public Object faultForGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) {
System.out.println("TestObjectStore: * reading object * : " + aGlobalID);
return soup.getObjectByKey(((DataKeyID) aGlobalID).getKey());
}
/**
* Returns a fault representing an object of the specified entity type with
* values from the specified dictionary. The fault should belong to the
* specified editing context.
*/
@Override
public Object faultForRawRow(Map aDictionary, String anEntityName, EOEditingContext aContext) {
// TODO: faults are not yet supported
throw new WotonomyException("Faults are not yet supported.");
}
/**
* Given a newly instantiated object, this method initializes its properties to
* values appropriate for the specified id. The object should belong to the
* specified editing context. This method is called to populate faults.
*/
@Override
public void initializeObject(Object anObject, EOGlobalID aGlobalID, EOEditingContext aContext) {
System.out.println("TestObjectStore: * reading object * : " + aGlobalID);
Object original = soup.getObjectByKey(((DataKeyID) aGlobalID).getKey());
EOObserverCenter.notifyObserversObjectWillChange(anObject);
Duplicator.deepCopy(original, anObject);
// TODO: need to handle child object registration in aContext
}
/**
* Remove all values from all objects in memory, turning them into faults, and
* posts a notification that all objects have been invalidated.
*/
@Override
public void invalidateAllObjects() {
// does nothing
}
/**
* Removes values with the specified ids from memory, turning them into faults,
* and posts a notification that those objects have been invalidated.
*/
@Override
public void invalidateObjectsWithGlobalIDs(List aList) {
// does nothing
}
/**
* Returns false because locking is not permitted.
*/
@Override
public boolean isObjectLockedWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) {
return false;
}
/**
* Does nothing because locking is not permitted.
*/
@Override
public void lockObjectWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) {
// does nothing
}
/**
* Returns a List of objects associated with the object with the specified id
* for the specified property relationship. Faults are not allowed in the array.
* All objects should belong to the specified editing context.
*/
@Override
public NSArray objectsForSourceGlobalID(EOGlobalID aGlobalID, String aRelationship, EOEditingContext aContext) {
// TODO: relationships are not yet supported
throw new WotonomyException("Relationships are not yet supported.");
}
/**
* Returns a List of objects the meet the criteria of the supplied
* specification. Faults are not allowed in the array. Each object is registered
* with the specified editing context. If any object is already registered in
* the specified context, it is not refetched and that object should be used in
* the array.
*/
@Override
public NSArray objectsWithFetchSpecification(EOFetchSpecification aFetchSpec, EOEditingContext aContext) {
// TODO: fetch specs are not yet supported
DataView view = soup.queryObjects(null, null);
System.out.println("TestObjectStore: ** querying all objects **");
NSMutableArray result = new NSMutableArray();
Object o;
Object existing;
DataKeyID id;
Iterator it = view.iterator();
while (it.hasNext()) {
o = it.next();
id = new DataKeyID(view.getKeyForObject(o));
existing = aContext.objectForGlobalID(id);
if (existing != null) {
o = existing;
} else {
aContext.recordObject(o, id);
}
result.addObject(o);
}
return result;
}
/**
* Removes all values from the specified object, converting it into a fault for
* the specified id. New or deleted objects should not be refaulted.
*/
@Override
public void refaultObject(Object anObject, EOGlobalID aGlobalID, EOEditingContext aContext) {
// TODO: faults are not yet supported
// just re-initialize the object
initializeObject(anObject, aGlobalID, aContext);
}
/**
* Writes all changes in the specified editing context to the respository.
*/
@Override
public void saveChangesInEditingContext(EOEditingContext aContext) {
Object o;
DataKeyID id;
Iterator it;
System.out.println(aContext.updatedObjects());
// process updates
it = aContext.updatedObjects().iterator();
while (it.hasNext()) {
o = it.next();
id = (DataKeyID) aContext.globalIDForObject(o);
System.out.println("TestObjectStore: * updating object * : " + id);
soup.updateObject(id.getKey(), o);
}
// process deletes
it = aContext.deletedObjects().iterator();
while (it.hasNext()) {
o = it.next();
id = (DataKeyID) aContext.globalIDForObject(o);
System.out.println("TestObjectStore: * deleting object * : " + id);
soup.removeObject(id.getKey());
// remove object from editing context
aContext.forgetObject(o);
}
// process inserts
it = aContext.insertedObjects().iterator();
while (it.hasNext()) {
o = it.next();
id = new DataKeyID(soup.addObject(o));
System.out.println("TestObjectStore: * adding object * : " + id);
// register object in editing context with new id
aContext.forgetObject(o);
aContext.recordObject(o, id);
}
}
}
|