1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.allanbank.mongodb.client.message;
21
22 import java.io.IOException;
23
24 import com.allanbank.mongodb.ReadPreference;
25 import com.allanbank.mongodb.bson.Document;
26 import com.allanbank.mongodb.bson.io.BsonInputStream;
27 import com.allanbank.mongodb.bson.io.BsonOutputStream;
28 import com.allanbank.mongodb.bson.io.BufferingBsonOutputStream;
29 import com.allanbank.mongodb.bson.io.StringEncoder;
30 import com.allanbank.mongodb.client.Message;
31 import com.allanbank.mongodb.client.Operation;
32 import com.allanbank.mongodb.error.DocumentToLargeException;
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 public class Update extends AbstractMessage {
58
59
60 public static final int MULTIUPDATE_FLAG_BIT = 0x02;
61
62
63 public static final int UPSERT_FLAG_BIT = 0x01;
64
65
66
67
68
69 private final boolean myMultiUpdate;
70
71
72 private final Document myQuery;
73
74
75 private final Document myUpdate;
76
77
78
79
80
81 private final boolean myUpsert;
82
83
84
85
86
87
88
89
90
91 public Update(final BsonInputStream in) throws IOException {
92 in.readInt();
93 init(in.readCString());
94 final int flags = in.readInt();
95 myQuery = in.readDocument();
96 myUpdate = in.readDocument();
97
98 myUpsert = (flags & UPSERT_FLAG_BIT) == UPSERT_FLAG_BIT;
99 myMultiUpdate = (flags & MULTIUPDATE_FLAG_BIT) == MULTIUPDATE_FLAG_BIT;
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 public Update(final String databaseName, final String collectionName,
121 final Document query, final Document update,
122 final boolean multiUpdate, final boolean upsert) {
123 super(databaseName, collectionName, ReadPreference.PRIMARY);
124 myQuery = query;
125 myUpdate = update;
126 myMultiUpdate = multiUpdate;
127 myUpsert = upsert;
128 }
129
130
131
132
133
134
135
136
137
138
139 @Override
140 public boolean equals(final Object object) {
141 boolean result = false;
142 if (this == object) {
143 result = true;
144 }
145 else if ((object != null) && (getClass() == object.getClass())) {
146 final Update other = (Update) object;
147
148 result = super.equals(object)
149 && (myMultiUpdate == other.myMultiUpdate)
150 && (myUpsert == other.myUpsert)
151 && myUpdate.equals(other.myUpdate)
152 && myQuery.equals(other.myQuery);
153 }
154 return result;
155 }
156
157
158
159
160
161
162
163 @Override
164 public String getOperationName() {
165 return Operation.UPDATE.name();
166 }
167
168
169
170
171
172
173 public Document getQuery() {
174 return myQuery;
175 }
176
177
178
179
180
181
182 public Document getUpdate() {
183 return myUpdate;
184 }
185
186
187
188
189
190
191 @Override
192 public int hashCode() {
193 int result = 1;
194 result = (31 * result) + super.hashCode();
195 result = (31 * result) + (myMultiUpdate ? 1 : 3);
196 result = (31 * result) + (myUpsert ? 1 : 3);
197 result = (31 * result) + myUpdate.hashCode();
198 result = (31 * result) + myQuery.hashCode();
199 return result;
200 }
201
202
203
204
205
206
207
208
209 public boolean isMultiUpdate() {
210 return myMultiUpdate;
211 }
212
213
214
215
216
217
218
219
220 public boolean isUpsert() {
221 return myUpsert;
222 }
223
224
225
226
227
228
229
230 @Override
231 public int size() {
232
233 int size = HEADER_SIZE + 10;
234
235 size += StringEncoder.utf8Size(myDatabaseName);
236
237 size += StringEncoder.utf8Size(myCollectionName);
238
239
240 size += myQuery.size();
241 size += myUpdate.size();
242
243 return size;
244 }
245
246
247
248
249
250
251
252
253 @Override
254 public void validateSize(final int maxDocumentSize)
255 throws DocumentToLargeException {
256 final long querySize = (myQuery != null) ? myQuery.size() : 0;
257 if (maxDocumentSize < querySize) {
258 throw new DocumentToLargeException((int) querySize,
259 maxDocumentSize, myQuery);
260 }
261 final long updateSize = (myUpdate != null) ? myUpdate.size() : 0;
262 if (maxDocumentSize < updateSize) {
263 throw new DocumentToLargeException((int) updateSize,
264 maxDocumentSize, myUpdate);
265 }
266 }
267
268
269
270
271
272
273
274
275
276 @Override
277 public void write(final int messageId, final BsonOutputStream out)
278 throws IOException {
279
280 final int flags = computeFlags();
281
282 int size = HEADER_SIZE;
283 size += 4;
284 size += out.sizeOfCString(myDatabaseName, ".", myCollectionName);
285 size += 4;
286 size += myQuery.size();
287 size += myUpdate.size();
288
289 writeHeader(out, messageId, 0, Operation.UPDATE, size);
290 out.writeInt(0);
291 out.writeCString(myDatabaseName, ".", myCollectionName);
292 out.writeInt(flags);
293 out.writeDocument(myQuery);
294 out.writeDocument(myUpdate);
295 }
296
297
298
299
300
301
302
303
304
305 @Override
306 public void write(final int messageId, final BufferingBsonOutputStream out)
307 throws IOException {
308
309 final int flags = computeFlags();
310
311 final long start = writeHeader(out, messageId, 0, Operation.UPDATE);
312 out.writeInt(0);
313 out.writeCString(myDatabaseName, ".", myCollectionName);
314 out.writeInt(flags);
315 out.writeDocument(myQuery);
316 out.writeDocument(myUpdate);
317 finishHeader(out, start);
318
319 out.flushBuffer();
320 }
321
322
323
324
325
326
327 private int computeFlags() {
328 int flags = 0;
329 if (myMultiUpdate) {
330 flags += MULTIUPDATE_FLAG_BIT;
331 }
332 if (myUpsert) {
333 flags += UPSERT_FLAG_BIT;
334 }
335 return flags;
336 }
337 }