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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
/*
Wotonomy: OpenStep design patterns for pure Java applications.
Copyright (C) 2001 Michael Powers
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see http://www.gnu.org
*/
package net.wotonomy.access;
import net.wotonomy.control.EOFetchSpecification;
import net.wotonomy.control.EOQualifier;
import net.wotonomy.foundation.NSArray;
import net.wotonomy.foundation.NSDictionary;
import net.wotonomy.foundation.NSMutableDictionary;
/**
*
* @author ezamudio@nasoft.com
* @author $Author: cgruber $
* @version $Revision: 894 $
*/
public abstract class EOAdaptorChannel {
protected EOAdaptorContext _context;
public EOAdaptorChannel(EOAdaptorContext context) {
super();
_context = context;
}
public EOAdaptorContext adaptorContext() {
return _context;
}
public void addStoredProceduresNamed(NSArray<String> names, EOModel model) {
}
public abstract NSArray attributesToFetch();
public abstract void cancelFetch();
public abstract void closeChannel();
public abstract NSArray describeResults();
public abstract int deleteRowsDescribedByQualifier(EOQualifier q, EOEntity entity);
public abstract void evaluateExpression(EOSQLExpression sql);
public abstract void executeStoredProcedure(EOStoredProcedure proc, NSDictionary values);
public abstract NSMutableDictionary fetchRow();
public abstract void insertRow(NSDictionary row, EOEntity entity);
public abstract boolean isFetchInProgress();
public abstract boolean isOpen();
public abstract void openChannel();
public abstract NSDictionary returnValuesForLastStoredProcedureInvocation();
public abstract void selectAttributes(NSArray atts, EOFetchSpecification fspec, boolean lock, EOEntity entity);
public abstract void setAttributesToFetch(NSArray atts);
public abstract int updateValuesInRowsDescribedByQualifier(NSDictionary row, EOQualifier q, EOEntity entity);
public void deleteRowDescribedByQualifier(EOQualifier q, EOEntity entity) {
adaptorContext().beginTransaction();
int count = deleteRowsDescribedByQualifier(q, entity);
if (count != 1) {
adaptorContext().rollbackTransaction();
throw new EOGeneralAdaptorException("Qualifier deleted " + count + " rows instead of exactly one.");
}
adaptorContext().commitTransaction();
}
public EOModel describeModelWithTableNames(NSArray names) {
return null;
}
public NSArray describeStoredProcedureNames() {
return NSArray.EmptyArray;
}
public NSArray describeTableNames() {
return NSArray.EmptyArray;
}
public NSMutableDictionary dictionaryWithObjectsForAttributes(Object[] values, NSArray attributes) {
Object[] keys = new Object[attributes.count()];
for (int i = 0; i < attributes.count(); i++)
keys[i] = ((EOAttribute) attributes.objectAtIndex(i)).name();
return new NSMutableDictionary(values, keys);
}
public void lockRowComparingAttributes(NSArray atts, EOEntity entity, EOQualifier q, NSDictionary snapshot) {
EOFetchSpecification fspec = new EOFetchSpecification(entity.name(), q, null);
adaptorContext().beginTransaction();
selectAttributes(atts, fspec, true, entity);
if (isFetchInProgress()) {
NSDictionary row = fetchRow();
if (row == null) {
cancelFetch();
adaptorContext().rollbackTransaction();
throw new EOGeneralAdaptorException("Cannot obtain row to lock. Probably modified from the outside.");
}
if (isFetchInProgress()) {
if (fetchRow() != null) {
cancelFetch();
adaptorContext().rollbackTransaction();
throw new EOGeneralAdaptorException("Qualifier returns more than one row.");
}
}
java.util.Enumeration enumeration = snapshot.keyEnumerator();
while (enumeration.hasMoreElements()) {
Object key = enumeration.nextElement();
Object svalue = snapshot.objectForKey(key);
Object rvalue = row.objectForKey(key);
if (rvalue == null) {
cancelFetch();
adaptorContext().rollbackTransaction();
throw new EOGeneralAdaptorException("Value for key " + key + " not found in locked row.");
}
if (!rvalue.equals(svalue)) {
cancelFetch();
adaptorContext().rollbackTransaction();
throw new EOGeneralAdaptorException("Value for key " + key + " differes from snapshot.");
}
}
adaptorContext().commitTransaction();
return;
}
adaptorContext().rollbackTransaction();
throw new EOGeneralAdaptorException("A fetch was never generated.");
}
public void performAdaptorOperation(EOAdaptorOperation operation) {
int opcode = operation.adaptorOperator();
switch (opcode) {
case EODatabaseOperation.AdaptorLockOperator:
if (operation.entity() == null)
throw new EOGeneralAdaptorException("A lock operation must have an entity assigned to it.",
new NSDictionary(operation, "operation"));
if (operation.qualifier() == null)
throw new EOGeneralAdaptorException("A lock operation must have a qualifier assigned to it.",
new NSDictionary(operation, "operation"));
if (operation.qualifier() == null)
throw new EOGeneralAdaptorException("A lock operation must have changedValues assigned to it.",
new NSDictionary(operation, "operation"));
lockRowComparingAttributes(operation.attributes(), operation.entity(), operation.qualifier(),
operation.changedValues());
break;
case EODatabaseOperation.AdaptorInsertOperator:
if (operation.entity() == null)
throw new EOGeneralAdaptorException("An insert operation must have an entity assigned to it.",
new NSDictionary(operation, "operation"));
if (operation.changedValues() == null)
throw new EOGeneralAdaptorException("An insert operation must have changedValues assigned to it.",
new NSDictionary(operation, "operation"));
insertRow(operation.changedValues(), operation.entity());
break;
case EODatabaseOperation.AdaptorUpdateOperator:
if (operation.entity() == null)
throw new EOGeneralAdaptorException("An update operation must have an entity assigned to it.",
new NSDictionary(operation, "operation"));
if (operation.changedValues() == null)
throw new EOGeneralAdaptorException("An update operation must have changedValues assigned to it.",
new NSDictionary(operation, "operation"));
updateValuesInRowsDescribedByQualifier(operation.changedValues(), operation.qualifier(),
operation.entity());
break;
case EODatabaseOperation.AdaptorDeleteOperator:
if (operation.entity() == null)
throw new EOGeneralAdaptorException("A delete operation must have an entity assigned to it.",
new NSDictionary(operation, "operation"));
deleteRowsDescribedByQualifier(operation.qualifier(), operation.entity());
break;
case EODatabaseOperation.AdaptorStoredProcedureOperator:
if (operation.storedProcedure() == null)
throw new EOGeneralAdaptorException(
"A stored procedure operation must have a stored procedure assigned to it.",
new NSDictionary(operation, "operation"));
executeStoredProcedure(operation.storedProcedure(), operation.changedValues());
break;
default:
throw new EOGeneralAdaptorException("I don't know how to perform an operation with code " + opcode,
new NSDictionary(operation, "operation"));
}
}
public void performAdaptorOperations(NSArray ops) {
for (int i = 0; i < ops.count(); i++) {
EOAdaptorOperation adop = (EOAdaptorOperation) ops.objectAtIndex(i);
performAdaptorOperation(adop);
}
}
public NSArray primaryKeysForNewRowsWithEntity(int count, EOEntity entity) {
NSDictionary[] keys = new NSDictionary[count];
for (int i = 0; i < count; i++)
keys[i] = NSDictionary.EmptyDictionary;
return new NSArray(keys);
}
public void updateValuesInRowDescribedByQualifier(NSDictionary row, EOQualifier q, EOEntity entity) {
adaptorContext().beginTransaction();
int count = updateValuesInRowsDescribedByQualifier(row, q, entity);
if (count != 1) {
adaptorContext().rollbackTransaction();
throw new EOGeneralAdaptorException(
"The qualifier should describe exactly one row (updated " + count + " rows)");
}
adaptorContext().commitTransaction();
}
}
/*
* $Log$ Revision 1.2 2006/02/16 16:47:14 cgruber Move some classes in to
* "internal" packages and re-work imports, etc.
*
* Also use UnsupportedOperationExceptions where appropriate, instead of
* WotonomyExceptions.
*
* Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in
* eclipse-friendly maven-enabled packages.
*
* Revision 1.2 2005/05/11 15:21:53 cgruber Change enum to enumeration, since
* enum is now a keyword as of Java 5.0
*
* A few other comments in the code.
*
* Revision 1.1 2003/08/13 00:37:45 chochos an almost complete implementation of
* the abstract adaptor-layer classes
*
*/
|