View Javadoc
1   /*
2    * #%L
3    * ArrayBuilderImpl.java - mongodb-async-driver - Allanbank Consulting, Inc.
4    * %%
5    * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.allanbank.mongodb.bson.builder.impl;
21  
22  import java.io.StringWriter;
23  import java.util.Date;
24  import java.util.List;
25  import java.util.UUID;
26  import java.util.regex.Pattern;
27  
28  import com.allanbank.mongodb.bson.DocumentAssignable;
29  import com.allanbank.mongodb.bson.Element;
30  import com.allanbank.mongodb.bson.ElementAssignable;
31  import com.allanbank.mongodb.bson.builder.ArrayBuilder;
32  import com.allanbank.mongodb.bson.builder.BuilderFactory;
33  import com.allanbank.mongodb.bson.builder.DocumentBuilder;
34  import com.allanbank.mongodb.bson.element.ArrayElement;
35  import com.allanbank.mongodb.bson.element.BinaryElement;
36  import com.allanbank.mongodb.bson.element.BooleanElement;
37  import com.allanbank.mongodb.bson.element.DocumentElement;
38  import com.allanbank.mongodb.bson.element.DoubleElement;
39  import com.allanbank.mongodb.bson.element.IntegerElement;
40  import com.allanbank.mongodb.bson.element.JavaScriptElement;
41  import com.allanbank.mongodb.bson.element.JavaScriptWithScopeElement;
42  import com.allanbank.mongodb.bson.element.JsonSerializationVisitor;
43  import com.allanbank.mongodb.bson.element.LongElement;
44  import com.allanbank.mongodb.bson.element.MaxKeyElement;
45  import com.allanbank.mongodb.bson.element.MinKeyElement;
46  import com.allanbank.mongodb.bson.element.MongoTimestampElement;
47  import com.allanbank.mongodb.bson.element.NullElement;
48  import com.allanbank.mongodb.bson.element.ObjectId;
49  import com.allanbank.mongodb.bson.element.ObjectIdElement;
50  import com.allanbank.mongodb.bson.element.RegularExpressionElement;
51  import com.allanbank.mongodb.bson.element.StringElement;
52  import com.allanbank.mongodb.bson.element.SymbolElement;
53  import com.allanbank.mongodb.bson.element.TimestampElement;
54  import com.allanbank.mongodb.bson.element.UuidElement;
55  
56  /**
57   * A builder for BSON arrays.
58   * 
59   * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
60   *         mutated in incompatible ways between any two releases of the driver.
61   * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
62   */
63  public class ArrayBuilderImpl extends AbstractBuilder implements ArrayBuilder {
64  
65      /**
66       * Creates a new {@link ArrayBuilderImpl}.
67       */
68      public ArrayBuilderImpl() {
69          this(null);
70      }
71  
72      /**
73       * Creates a new {@link ArrayBuilderImpl}.
74       * 
75       * @param outerBuilder
76       *            The outer builder scope.
77       */
78      public ArrayBuilderImpl(final AbstractBuilder outerBuilder) {
79          super(outerBuilder);
80      }
81  
82      /**
83       * {@inheritDoc}
84       */
85      @Override
86      public ArrayBuilder add(final boolean value) {
87          return addBoolean(value);
88      }
89  
90      /**
91       * {@inheritDoc}
92       */
93      @Override
94      public ArrayBuilder add(final byte subType, final byte[] data)
95              throws IllegalArgumentException {
96          return addBinary(subType, data);
97      }
98  
99      /**
100      * {@inheritDoc}
101      */
102     @Override
103     public ArrayBuilder add(final byte[] data) {
104         if (data == null) {
105             return addNull();
106         }
107         return addBinary(data);
108     }
109 
110     /**
111      * {@inheritDoc}
112      */
113     @Override
114     public ArrayBuilder add(final Date timestamp) {
115         if (timestamp == null) {
116             return addNull();
117         }
118         return addTimestamp(timestamp.getTime());
119     }
120 
121     /**
122      * {@inheritDoc}
123      */
124     @Override
125     public ArrayBuilder add(final DocumentAssignable document) {
126         if (document == null) {
127             return addNull();
128         }
129         return addDocument(document);
130     }
131 
132     /**
133      * {@inheritDoc}
134      */
135     @Override
136     public ArrayBuilder add(final DocumentElement document) {
137         if (document == null) {
138             return addNull();
139         }
140         return addDocument(document);
141     }
142 
143     /**
144      * {@inheritDoc}
145      */
146     @Override
147     public ArrayBuilder add(final double value) {
148         return addDouble(value);
149     }
150 
151     /**
152      * 
153      * {@inheritDoc}
154      */
155     @Override
156     public ArrayBuilder add(final ElementAssignable element)
157             throws IllegalArgumentException {
158         if (element == null) {
159             throw new IllegalArgumentException("Cannot add a null element.");
160         }
161         myElements.add(element.asElement().withName(nextIndex()));
162         return this;
163     }
164 
165     /**
166      * {@inheritDoc}
167      */
168     @Override
169     public ArrayBuilder add(final int value) {
170         return addInteger(value);
171     }
172 
173     /**
174      * {@inheritDoc}
175      */
176     @Override
177     public ArrayBuilder add(final long value) {
178         return addLong(value);
179     }
180 
181     /**
182      * {@inheritDoc}
183      */
184     @Override
185     public ArrayBuilder add(final Object value) throws IllegalArgumentException {
186         myElements.add(BuilderFactory.e(nextIndex(), value));
187         return this;
188     }
189 
190     /**
191      * {@inheritDoc}
192      */
193     @Override
194     public ArrayBuilder add(final ObjectId id) {
195         if (id == null) {
196             return addNull();
197         }
198         return addObjectId(id);
199     }
200 
201     /**
202      * {@inheritDoc}
203      */
204     @Override
205     public ArrayBuilder add(final Pattern pattern) {
206         if (pattern == null) {
207             return addNull();
208         }
209         return addRegularExpression(pattern);
210     }
211 
212     /**
213      * {@inheritDoc}
214      */
215     @Override
216     public ArrayBuilder add(final String value) {
217         if (value == null) {
218             return addNull();
219         }
220         return addString(value);
221     }
222 
223     /**
224      * {@inheritDoc}
225      */
226     @Override
227     @Deprecated
228     public ArrayBuilder add(final String databaseName,
229             final String collectionName, final ObjectId id)
230             throws IllegalArgumentException {
231         return addDBPointer(databaseName, collectionName, id);
232     }
233 
234     /**
235      * {@inheritDoc}
236      */
237     @Override
238     public ArrayBuilder add(final UUID uuid) throws IllegalArgumentException {
239         if (uuid == null) {
240             return addNull();
241         }
242         return addUuid(uuid);
243     }
244 
245     /**
246      * {@inheritDoc}
247      */
248     @Override
249     public ArrayBuilder addBinary(final byte subType, final byte[] value)
250             throws IllegalArgumentException {
251         myElements.add(new BinaryElement(nextIndex(), subType, value));
252         return this;
253     }
254 
255     /**
256      * {@inheritDoc}
257      */
258     @Override
259     public ArrayBuilder addBinary(final byte[] value)
260             throws IllegalArgumentException {
261         myElements.add(new BinaryElement(nextIndex(), value));
262         return this;
263     }
264 
265     /**
266      * {@inheritDoc}
267      */
268     @Override
269     public ArrayBuilder addBoolean(final boolean value) {
270         myElements.add(new BooleanElement(nextIndex(), value));
271         return this;
272     }
273 
274     /**
275      * {@inheritDoc}
276      */
277     @Override
278     @Deprecated
279     public ArrayBuilder addDBPointer(final String databaseName,
280             final String collectionName, final ObjectId id)
281             throws IllegalArgumentException {
282         myElements.add(new com.allanbank.mongodb.bson.element.DBPointerElement(
283                 nextIndex(), databaseName, collectionName, id));
284         return this;
285     }
286 
287     /**
288      * {@inheritDoc}
289      */
290     @Override
291     public ArrayBuilder addDocument(final DocumentAssignable document)
292             throws IllegalArgumentException {
293         myElements.add(new DocumentElement(nextIndex(), document.asDocument()));
294         return this;
295     }
296 
297     /**
298      * {@inheritDoc}
299      */
300     @Override
301     public ArrayBuilder addDouble(final double value) {
302         myElements.add(new DoubleElement(nextIndex(), value));
303         return this;
304     }
305 
306     /**
307      * {@inheritDoc}
308      */
309     @Override
310     public ArrayBuilder addInteger(final int value) {
311         myElements.add(new IntegerElement(nextIndex(), value));
312         return this;
313     }
314 
315     /**
316      * {@inheritDoc}
317      */
318     @Override
319     public ArrayBuilder addJavaScript(final String code)
320             throws IllegalArgumentException {
321         myElements.add(new JavaScriptElement(nextIndex(), code));
322         return this;
323     }
324 
325     /**
326      * {@inheritDoc}
327      */
328     @Override
329     public ArrayBuilder addJavaScript(final String code,
330             final DocumentAssignable scope) throws IllegalArgumentException {
331         myElements.add(new JavaScriptWithScopeElement(nextIndex(), code, scope
332                 .asDocument()));
333         return this;
334     }
335 
336     /**
337      * {@inheritDoc}
338      */
339     @Override
340     public ArrayBuilder addLegacyUuid(final UUID uuid)
341             throws IllegalArgumentException {
342         myElements.add(new UuidElement(nextIndex(),
343                 UuidElement.LEGACY_UUID_SUBTTYPE, uuid));
344         return this;
345     }
346 
347     /**
348      * {@inheritDoc}
349      */
350     @Override
351     public ArrayBuilder addLong(final long value) {
352         myElements.add(new LongElement(nextIndex(), value));
353         return this;
354     }
355 
356     /**
357      * {@inheritDoc}
358      */
359     @Override
360     public ArrayBuilder addMaxKey() {
361         myElements.add(new MaxKeyElement(nextIndex()));
362         return this;
363     }
364 
365     /**
366      * {@inheritDoc}
367      */
368     @Override
369     public ArrayBuilder addMinKey() {
370         myElements.add(new MinKeyElement(nextIndex()));
371         return this;
372     }
373 
374     /**
375      * {@inheritDoc}
376      */
377     @Override
378     public ArrayBuilder addMongoTimestamp(final long value) {
379         myElements.add(new MongoTimestampElement(nextIndex(), value));
380         return this;
381     }
382 
383     /**
384      * {@inheritDoc}
385      */
386     @Override
387     public ArrayBuilder addNull() {
388         myElements.add(new NullElement(nextIndex()));
389         return this;
390     }
391 
392     /**
393      * {@inheritDoc}
394      */
395     @Override
396     public ArrayBuilder addObjectId(final ObjectId id)
397             throws IllegalArgumentException {
398         myElements.add(new ObjectIdElement(nextIndex(), id));
399         return this;
400     }
401 
402     /**
403      * {@inheritDoc}
404      */
405     @Override
406     public ArrayBuilder addRegularExpression(final Pattern pattern)
407             throws IllegalArgumentException {
408         myElements.add(new RegularExpressionElement(nextIndex(), pattern));
409         return this;
410     }
411 
412     /**
413      * {@inheritDoc}
414      */
415     @Override
416     public ArrayBuilder addRegularExpression(final String pattern,
417             final String options) throws IllegalArgumentException {
418         myElements.add(new RegularExpressionElement(nextIndex(), pattern,
419                 options));
420         return this;
421     }
422 
423     /**
424      * {@inheritDoc}
425      */
426     @Override
427     public ArrayBuilder addString(final String value)
428             throws IllegalArgumentException {
429         myElements.add(new StringElement(nextIndex(), value));
430         return this;
431     }
432 
433     /**
434      * {@inheritDoc}
435      */
436     @Override
437     public ArrayBuilder addSymbol(final String symbol)
438             throws IllegalArgumentException {
439         myElements.add(new SymbolElement(nextIndex(), symbol));
440         return this;
441     }
442 
443     /**
444      * {@inheritDoc}
445      */
446     @Override
447     public ArrayBuilder addTimestamp(final long timestamp) {
448         myElements.add(new TimestampElement(nextIndex(), timestamp));
449         return this;
450     }
451 
452     /**
453      * {@inheritDoc}
454      */
455     @Override
456     public ArrayBuilder addUuid(final UUID uuid)
457             throws IllegalArgumentException {
458         myElements.add(new UuidElement(nextIndex(), UuidElement.UUID_SUBTTYPE,
459                 uuid));
460         return this;
461     }
462 
463     /**
464      * {@inheritDoc}
465      * <p>
466      * Overridden to return an array of the built elements.
467      * </p>
468      */
469     @Override
470     public Element[] build() {
471         final List<Element> elements = subElements();
472         return elements.toArray(new Element[elements.size()]);
473     }
474 
475     /**
476      * {@inheritDoc}
477      * <p>
478      * Overridden to return an {@link ArrayElement}.
479      * </p>
480      */
481     @Override
482     public ArrayElement build(final String name) {
483         return new ArrayElement(name, subElements());
484     }
485 
486     /**
487      * {@inheritDoc}
488      */
489     @Override
490     public DocumentBuilder push() {
491         return doPush(nextIndex());
492     }
493 
494     /**
495      * {@inheritDoc}
496      */
497     @Override
498     public ArrayBuilder pushArray() {
499         return doPushArray(nextIndex());
500     }
501 
502     /**
503      * {@inheritDoc}
504      */
505     @Override
506     public ArrayBuilder reset() {
507         super.reset();
508         return this;
509     }
510 
511     /**
512      * {@inheritDoc}
513      * <p>
514      * Overridden to return the current state of the builder as an array
515      * element.
516      * </p>
517      */
518     @Override
519     public String toString() {
520         final StringWriter writer = new StringWriter();
521         final JsonSerializationVisitor visitor = new JsonSerializationVisitor(
522                 writer, false);
523 
524         visitor.visitArray("elements", myElements);
525 
526         return writer.toString();
527     }
528 
529     /**
530      * Returns the next index value for an element.
531      * 
532      * @return The next index value for an element.
533      */
534     private String nextIndex() {
535         return ArrayElement.nameFor(myElements.size());
536     }
537 }