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 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26
27 import com.allanbank.mongodb.ReadPreference;
28 import com.allanbank.mongodb.bson.Document;
29 import com.allanbank.mongodb.bson.io.BsonInputStream;
30 import com.allanbank.mongodb.bson.io.BsonOutputStream;
31 import com.allanbank.mongodb.bson.io.BufferingBsonOutputStream;
32 import com.allanbank.mongodb.bson.io.StringEncoder;
33 import com.allanbank.mongodb.client.Message;
34 import com.allanbank.mongodb.client.Operation;
35 import com.allanbank.mongodb.client.VersionRange;
36 import com.allanbank.mongodb.error.DocumentToLargeException;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class Insert extends AbstractMessage {
60
61
62 public static final int CONTINUE_ON_ERROR_BIT = 1;
63
64
65
66
67
68 private final boolean myContinueOnError;
69
70
71 private final List<Document> myDocuments;
72
73
74
75
76
77 private int myDocumentsSize;
78
79
80
81
82
83
84
85
86
87
88
89
90 public Insert(final Header header, final BsonInputStream in)
91 throws IOException {
92
93 final long position = in.getBytesRead();
94 final long end = (position + header.getLength()) - Header.SIZE;
95
96 final int flags = in.readInt();
97 init(in.readCString());
98
99
100 myDocuments = new ArrayList<Document>();
101 while (in.getBytesRead() < end) {
102 myDocuments.add(in.readDocument());
103 }
104
105 myContinueOnError = (flags & CONTINUE_ON_ERROR_BIT) == CONTINUE_ON_ERROR_BIT;
106 myDocumentsSize = -1;
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 public Insert(final String databaseName, final String collectionName,
123 final List<Document> documents, final boolean continueOnError) {
124 this(databaseName, collectionName, documents, continueOnError, null);
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 public Insert(final String databaseName, final String collectionName,
144 final List<Document> documents, final boolean continueOnError,
145 final VersionRange requiredServerVersion) {
146 super(databaseName, collectionName, ReadPreference.PRIMARY,
147 requiredServerVersion);
148
149 myDocuments = new ArrayList<Document>(documents);
150 myContinueOnError = continueOnError;
151 myDocumentsSize = -1;
152 }
153
154
155
156
157
158
159
160
161
162
163 @Override
164 public boolean equals(final Object object) {
165 boolean result = false;
166 if (this == object) {
167 result = true;
168 }
169 else if ((object != null) && (getClass() == object.getClass())) {
170 final Insert other = (Insert) object;
171
172 result = super.equals(object)
173 && (myContinueOnError == other.myContinueOnError)
174 && myDocuments.equals(other.myDocuments);
175 }
176 return result;
177 }
178
179
180
181
182
183
184 public List<Document> getDocuments() {
185 return Collections.unmodifiableList(myDocuments);
186 }
187
188
189
190
191
192
193
194 @Override
195 public String getOperationName() {
196 return Operation.INSERT.name();
197 }
198
199
200
201
202
203
204 @Override
205 public int hashCode() {
206 int result = 1;
207 result = (31 * result) + super.hashCode();
208 result = (31 * result) + (myContinueOnError ? 1 : 3);
209 result = (31 * result) + myDocuments.hashCode();
210 return result;
211 }
212
213
214
215
216
217
218
219
220 public boolean isContinueOnError() {
221 return myContinueOnError;
222 }
223
224
225
226
227
228
229
230 @Override
231 public int size() {
232
233 int size = HEADER_SIZE + 6;
234
235 size += StringEncoder.utf8Size(myDatabaseName);
236
237 size += StringEncoder.utf8Size(myCollectionName);
238
239 for (final Document document : myDocuments) {
240 size += document.size();
241 }
242
243 return size;
244 }
245
246
247
248
249
250
251
252 @Override
253 public String toString() {
254 return "Insert [myContinueOnError=" + myContinueOnError
255 + ", myDocuments=" + myDocuments + "]";
256 }
257
258
259
260
261
262
263
264
265 @Override
266 public void validateSize(final int maxDocumentSize)
267 throws DocumentToLargeException {
268 if (myDocumentsSize < 0) {
269 long size = 0;
270 for (final Document doc : myDocuments) {
271 size += doc.size();
272 }
273
274 myDocumentsSize = (int) size;
275 }
276
277 if (maxDocumentSize < myDocumentsSize) {
278 throw new DocumentToLargeException(myDocumentsSize,
279 maxDocumentSize, myDocuments.get(0));
280 }
281 }
282
283
284
285
286
287
288
289
290
291 @Override
292 public void write(final int messageId, final BsonOutputStream out)
293 throws IOException {
294 final int flags = computeFlags();
295
296 int size = HEADER_SIZE;
297 size += 4;
298 size += out.sizeOfCString(myDatabaseName, ".", myCollectionName);
299 for (final Document document : myDocuments) {
300 size += document.size();
301 }
302
303 writeHeader(out, messageId, 0, Operation.INSERT, size);
304 out.writeInt(flags);
305 out.writeCString(myDatabaseName, ".", myCollectionName);
306 for (final Document document : myDocuments) {
307 out.writeDocument(document);
308 }
309 }
310
311
312
313
314
315
316
317
318
319 @Override
320 public void write(final int messageId, final BufferingBsonOutputStream out)
321 throws IOException {
322 final int flags = computeFlags();
323
324 final long start = writeHeader(out, messageId, 0, Operation.INSERT);
325 out.writeInt(flags);
326 out.writeCString(myDatabaseName, ".", myCollectionName);
327 for (final Document document : myDocuments) {
328 out.writeDocument(document);
329 }
330 finishHeader(out, start);
331
332 out.flushBuffer();
333 }
334
335
336
337
338
339
340 private int computeFlags() {
341 int flags = 0;
342 if (myContinueOnError) {
343 flags += CONTINUE_ON_ERROR_BIT;
344 }
345 return flags;
346 }
347
348 }