001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.schematic.internal.document;
017
018import java.text.ParseException;
019import java.util.Arrays;
020import java.util.Collection;
021import java.util.Date;
022import java.util.Iterator;
023import java.util.List;
024import java.util.ListIterator;
025import java.util.Map;
026import java.util.Properties;
027import java.util.Set;
028import java.util.UUID;
029import java.util.regex.Pattern;
030import org.modeshape.schematic.document.Array;
031import org.modeshape.schematic.document.Binary;
032import org.modeshape.schematic.document.Code;
033import org.modeshape.schematic.document.CodeWithScope;
034import org.modeshape.schematic.document.Document;
035import org.modeshape.schematic.document.EditableArray;
036import org.modeshape.schematic.document.EditableDocument;
037import org.modeshape.schematic.document.MaxKey;
038import org.modeshape.schematic.document.MinKey;
039import org.modeshape.schematic.document.ObjectId;
040import org.modeshape.schematic.document.Symbol;
041
042public class ArrayEditor implements EditableArray {
043
044    private static final long serialVersionUID = 1L;
045
046    private final MutableArray array;
047    private final DocumentValueFactory factory;
048
049    public ArrayEditor( MutableArray array,
050                        DocumentValueFactory factory ) {
051        assert array != null;
052        this.array = array;
053        this.factory = factory != null ? factory : DefaultDocumentValueFactory.INSTANCE;
054    }
055
056    @Override
057    public ArrayEditor clone() {
058        return new ArrayEditor(this.array.clone(), factory);
059    }
060
061    @Override
062    public ArrayEditor with( Map<String, Object> changedFields ) {
063        return new ArrayEditor((MutableArray)this.array.with(changedFields), factory);
064    }
065
066    @Override
067    public Document with( String fieldName,
068                          Object value ) {
069        return new ArrayEditor((MutableArray)this.array.with(fieldName, value), factory);
070    }
071
072    @Override
073    public ArrayEditor with( ValueTransformer transformer ) {
074        return new ArrayEditor((MutableArray)this.array.with(transformer), factory);
075    }
076
077    @Override
078    public Document withVariablesReplaced( Properties properties ) {
079        return new ArrayEditor((MutableArray)this.array.withVariablesReplaced(properties), factory);
080    }
081
082    @Override
083    public Document withVariablesReplacedWithSystemProperties() {
084        return new ArrayEditor((MutableArray)this.array.withVariablesReplacedWithSystemProperties(), factory);
085    }
086
087    @Override
088    public Array unwrap() {
089        return array;
090    }
091
092    @Override
093    public MutableDocument asMutableDocument() {
094        return array;
095    }
096
097    @Override
098    public Object get( String name ) {
099        return array.get(name);
100    }
101
102    @Override
103    public Boolean getBoolean( String name ) {
104        return array.getBoolean(name);
105    }
106
107    @Override
108    public boolean getBoolean( String name,
109                               boolean defaultValue ) {
110        return array.getBoolean(name, defaultValue);
111    }
112
113    public Object put( String name,
114                       Object value ) {
115        return array.put(name, value);
116    }
117
118    @Override
119    public void putAll( Document object ) {
120        array.putAll(object);
121    }
122
123    @Override
124    public void putAll( Map<? extends String, ? extends Object> map ) {
125        array.putAll(map);
126    }
127
128    @Override
129    public void merge( Document other ) {
130        array.putAll(other);
131    }
132
133    @Override
134    public Object remove( String name ) {
135        return array.remove(name);
136    }
137
138    @Override
139    public Integer getInteger( String name ) {
140        return array.getInteger(name);
141    }
142
143    @Override
144    public int getInteger( String name,
145                           int defaultValue ) {
146        return array.getInteger(name, defaultValue);
147    }
148
149    @Override
150    public Long getLong( String name ) {
151        return array.getLong(name);
152    }
153
154    @Override
155    public long getLong( String name,
156                         long defaultValue ) {
157        return array.getLong(name, defaultValue);
158    }
159
160    @Override
161    public Double getDouble( String name ) {
162        return array.getDouble(name);
163    }
164
165    @Override
166    public double getDouble( String name,
167                             double defaultValue ) {
168        return array.getDouble(name, defaultValue);
169    }
170
171    @Override
172    public Number getNumber( String name ) {
173        return array.getNumber(name);
174    }
175
176    @Override
177    public Number getNumber( String name,
178                             Number defaultValue ) {
179        return array.getNumber(name, defaultValue);
180    }
181
182    @Override
183    public String getString( String name ) {
184        return array.getString(name);
185    }
186
187    @Override
188    public String getString( String name,
189                             String defaultValue ) {
190        return array.getString(name, defaultValue);
191    }
192
193    @Override
194    public EditableArray getArray( String name ) {
195        return editable(array.getArray(name), indexFrom(name));
196    }
197
198    @Override
199    public EditableArray getOrCreateArray( String name ) {
200        List<?> existing = array.getArray(name);
201        return existing != null ? editable(existing, indexFrom(name)) : setArray(name);
202    }
203
204    @Override
205    public EditableDocument getDocument( String name ) {
206        return editable(array.getDocument(name), indexFrom(name));
207    }
208
209    @Override
210    public EditableDocument getOrCreateDocument( String name ) {
211        Document existing = array.getDocument(name);
212        return existing != null ? editable(existing, indexFrom(name)) : setDocument(name);
213    }
214
215    @Override
216    public boolean isNull( String name ) {
217        return array.isNull(name);
218    }
219
220    @Override
221    public boolean isNullOrMissing( String name ) {
222        return array.isNullOrMissing(name);
223    }
224
225    @Override
226    public MaxKey getMaxKey( String name ) {
227        return array.getMaxKey(name);
228    }
229
230    @Override
231    public MinKey getMinKey( String name ) {
232        return array.getMinKey(name);
233    }
234
235    @Override
236    public Code getCode( String name ) {
237        return array.getCode(name);
238    }
239
240    @Override
241    public CodeWithScope getCodeWithScope( String name ) {
242        return array.getCodeWithScope(name);
243    }
244
245    @Override
246    public ObjectId getObjectId( String name ) {
247        return array.getObjectId(name);
248    }
249
250    @Override
251    public Binary getBinary( String name ) {
252        return array.getBinary(name);
253    }
254    
255    @Override
256    public Date getDate(String name) {
257        return array.getDate(name);
258    }
259    
260    @Override
261    public Symbol getSymbol( String name ) {
262        return array.getSymbol(name);
263    }
264
265    @Override
266    public Pattern getPattern( String name ) {
267        return array.getPattern(name);
268    }
269
270    @Override
271    public UUID getUuid( String name ) {
272        return array.getUuid(name);
273    }
274
275    @Override
276    public UUID getUuid( String name,
277                         UUID defaultValue ) {
278        return array.getUuid(name, defaultValue);
279    }
280
281    @Override
282    public int getType( String name ) {
283        return array.getType(name);
284    }
285
286    @Override
287    public Map<String, ?> toMap() {
288        return array.toMap();
289    }
290
291    @Override
292    public Iterable<Field> fields() {
293        return array.fields();
294    }
295
296    @Override
297    public boolean containsField( String name ) {
298        return array.containsField(name);
299    }
300
301    @Override
302    public boolean containsAll( Document document ) {
303        return array.containsAll(document);
304    }
305
306    @Override
307    public Set<String> keySet() {
308        return array.keySet();
309    }
310
311    @Override
312    public int size() {
313        return array.size();
314    }
315
316    @Override
317    public void removeAll() {
318        array.removeAll();
319    }
320
321    @Override
322    public EditableArray setBoolean( String name,
323                                     boolean value ) {
324        return setValue(name, factory.createBoolean(value));
325    }
326
327    @Override
328    public EditableArray setNumber( String name,
329                                    int value ) {
330        return setValue(name, factory.createInt(value));
331    }
332
333    @Override
334    public EditableArray setNumber( String name,
335                                    long value ) {
336        return setValue(name, factory.createLong(value));
337    }
338
339    @Override
340    public EditableArray setNumber( String name,
341                                    float value ) {
342        return setValue(name, factory.createDouble(value));
343    }
344
345    @Override
346    public EditableArray setNumber( String name,
347                                    double value ) {
348        return setValue(name, factory.createDouble(value));
349    }
350
351    @Override
352    public EditableArray setString( String name,
353                                    String value ) {
354        return setValue(name, factory.createString(value));
355    }
356
357    @Override
358    public EditableArray setSymbol( String name,
359                                    String value ) {
360        return setValue(name, factory.createSymbol(value));
361    }
362
363    @Override
364    public EditableDocument setDocument( String name ) {
365        BasicDocument doc = new BasicDocument();
366        setValue(name, doc);
367        return editable(doc, indexFrom(name));
368    }
369
370    @Override
371    public EditableDocument setDocument( String name,
372                                         Document document ) {
373        setValue(name, document);
374        return editable(document, indexFrom(name));
375    }
376
377    @Override
378    public EditableArray setArray( String name ) {
379        List<?> array = new BasicArray();
380        setValue(name, array);
381        return editable(array, indexFrom(name));
382    }
383
384    @Override
385    public EditableArray setArray( String name,
386                                   Array array ) {
387        setValue(name, array);
388        return editable((List<?>)array, indexFrom(name));
389    }
390
391    @Override
392    public EditableArray setArray( String name,
393                                   Object... values ) {
394        setValue(name, Arrays.asList(values));
395        return editable((List<?>)array, indexFrom(name));
396    }
397
398    @Override
399    public EditableArray setDate( String name,
400                                  Date value ) {
401        return setValue(name, value);
402    }
403
404    @Override
405    public EditableArray setDate( String name,
406                                  String isoDate ) throws ParseException {
407        return setValue(name, factory.createDate(isoDate));
408    }
409
410    @Override
411    public EditableArray setTimestamp( String name,
412                                       int timeInSeconds,
413                                       int increment ) {
414        return setValue(name, factory.createTimestamp(timeInSeconds, increment));
415    }
416
417    @Override
418    public EditableArray setObjectId( String name,
419                                      String hex ) {
420        return setValue(name, factory.createObjectId(hex));
421    }
422
423    @Override
424    public EditableArray setObjectId( String name,
425                                      byte[] bytes ) {
426        return setValue(name, factory.createObjectId(bytes));
427    }
428
429    @Override
430    public EditableArray setObjectId( String name,
431                                      int time,
432                                      int machine,
433                                      int process,
434                                      int inc ) {
435        return setValue(name, factory.createObjectId(time, machine, process, inc));
436    }
437
438    @Override
439    public EditableArray setRegularExpression( String name,
440                                               String pattern ) {
441        return setValue(name, factory.createRegex(pattern, null));
442    }
443
444    @Override
445    public EditableArray setRegularExpression( String name,
446                                               String pattern,
447                                               int flags ) {
448        return setValue(name, factory.createRegex(pattern, BsonUtils.regexFlagsFor(flags)));
449    }
450
451    @Override
452    public EditableArray setNull( String name ) {
453        return setValue(name, factory.createNull());
454    }
455
456    @Override
457    public EditableArray setBinary( String name,
458                                    byte type,
459                                    byte[] data ) {
460        return setValue(name, factory.createBinary(type, data));
461    }
462
463    @Override
464    public EditableArray setUuid( String name,
465                                  UUID uuid ) {
466        return setValue(name, uuid);
467    }
468
469    @Override
470    public EditableDocument setCode( String name,
471                                     String code,
472                                     boolean includeScope ) {
473        if (includeScope) {
474            BasicDocument scope = new BasicDocument();
475            setValue(name, factory.createCode(code, scope));
476            return editable(scope, indexFrom(name));
477        }
478        return setValue(name, factory.createCode(code));
479    }
480
481    @Override
482    public EditableDocument setCode( String name,
483                                     String code,
484                                     Document scope ) {
485        if (scope != null) {
486            setValue(name, factory.createCode(code, scope));
487            return editable(scope, indexFrom(name));
488        }
489        return setValue(name, factory.createCode(code));
490    }
491
492    protected EditableArray setValue( String name,
493                                      Object value ) {
494        doSetValue(name, value);
495        return this;
496    }
497
498    @Override
499    public EditableArray setValue( int index,
500                                   Object value ) {
501        doSetValue(index, value);
502        return this;
503    }
504
505    @Override
506    public EditableArray addValue( Object value ) {
507        doAddValue(value);
508        return this;
509    }
510
511    @Override
512    public EditableArray addValueIfAbsent( Object value ) {
513        doAddValueIfAbsent(value);
514        return this;
515    }
516
517    @Override
518    public EditableArray addValue( int index,
519                                   Object value ) {
520        doAddValue(index, value);
521        return this;
522    }
523
524    protected final int indexFrom( String name ) {
525        return Integer.parseInt(name);
526    }
527
528    protected Object doSetValue( String name,
529                                 Object value ) {
530        int index = indexFrom(name);
531        return doSetValue(index, value);
532    }
533
534    protected Object doSetValue( int index,
535                                 Object value ) {
536        value = Utility.unwrap(value);
537        return array.setValue(index, value);
538    }
539
540    protected int doAddValue( Object value ) {
541        value = Utility.unwrap(value);
542        return array.addValue(value);
543    }
544
545    protected void doAddValue( int index,
546                               Object value ) {
547        value = Utility.unwrap(value);
548        array.addValue(index, value);
549    }
550
551    protected boolean doAddValueIfAbsent( Object value ) {
552        value = Utility.unwrap(value);
553        return array.addValueIfAbsent(value);
554    }
555
556    protected boolean doRemoveValue( Object value ) {
557        value = Utility.unwrap(value);
558        return array.removeValue(value);
559    }
560
561    protected Object doRemoveValue( int index ) {
562        return array.removeValue(index);
563    }
564
565    protected boolean doAddAll( Collection<? extends Object> c ) {
566        if (c == null || c.isEmpty()) return false;
567        for (Object value : c) {
568            doAddValue(value);
569        }
570        return true;
571    }
572
573    protected boolean doAddAll( int index,
574                                Collection<?> c ) {
575        if (c == null || c.isEmpty()) return false;
576        for (Object value : c) {
577            doAddValue(value);
578        }
579        return true;
580    }
581
582    protected List<Entry> doRemoveAll( Collection<?> c ) {
583        return array.removeAllValues(Utility.unwrapValues(c));
584    }
585
586    protected List<Entry> doRetainAll( Collection<?> c ) {
587        return array.retainAllValues(Utility.unwrapValues(c));
588    }
589
590    protected void doClear() {
591        array.removeAll();
592    }
593
594    protected EditableDocument editable( Document doc,
595                                         int index ) {
596        if (doc == null) return null;
597        assert !(doc instanceof DocumentEditor) : "The document value should not be a DocumentEditor instance";
598        if (doc instanceof MutableArray) {
599            return createEditableArray((MutableArray)doc, index, factory);
600        }
601        assert doc instanceof MutableDocument;
602        return createEditableDocument((MutableDocument)doc, index, factory);
603    }
604
605    protected EditableArray editable( List<?> array,
606                                      int index ) {
607        if (array == null) return null;
608        assert !(array instanceof ArrayEditor) : "The array value should not be an ArrayEditor instance";
609        return createEditableArray((BasicArray)array, index, factory);
610    }
611
612    private EditableArray editableSublist( List<?> sublist ) {
613        assert sublist != null;
614        if (sublist instanceof EditableArray) return (EditableArray)array;
615        return createEditableSublist((BasicArray)sublist, factory);
616    }
617
618    protected EditableDocument createEditableDocument( MutableDocument document,
619                                                       int index,
620                                                       DocumentValueFactory factory ) {
621        return new DocumentEditor(document, factory);
622    }
623
624    protected EditableArray createEditableArray( MutableArray array,
625                                                 int index,
626                                                 DocumentValueFactory factory ) {
627        return new ArrayEditor(array, factory);
628    }
629
630    protected EditableArray createEditableSublist( MutableArray array,
631                                                   DocumentValueFactory factory ) {
632        return new ArrayEditor(array, factory);
633    }
634
635    @Override
636    public boolean isEmpty() {
637        return array.isEmpty();
638    }
639
640    @Override
641    public boolean contains( Object o ) {
642        return array.contains(o);
643    }
644
645    @Override
646    public Iterator<Object> iterator() {
647        return array.iterator();
648    }
649
650    @Override
651    public Object[] toArray() {
652        return array.toArray();
653    }
654
655    @Override
656    public <T> T[] toArray( T[] a ) {
657        return array.toArray(a);
658    }
659
660    @Override
661    public boolean add( Object e ) {
662        return doAddValue(e) != -1;
663    }
664
665    @Override
666    public boolean remove( Object o ) {
667        return doRemoveValue(o);
668    }
669
670    @Override
671    public boolean containsAll( Collection<?> c ) {
672        return array.containsAll(c);
673    }
674
675    @Override
676    public boolean addAll( Collection<?> c ) {
677        return doAddAll(c);
678    }
679
680    @Override
681    public boolean addAll( int index,
682                           Collection<?> c ) {
683        return doAddAll(index, c);
684    }
685
686    @Override
687    public boolean removeAll( Collection<?> c ) {
688        List<Entry> removed = doRemoveAll(c);
689        return !removed.isEmpty();
690    }
691
692    @Override
693    public boolean retainAll( Collection<?> c ) {
694        List<Entry> removed = doRetainAll(c);
695        return !removed.isEmpty();
696    }
697
698    @Override
699    public void clear() {
700        doClear();
701    }
702
703    @Override
704    public Object get( int index ) {
705        Object value = array.get(index);
706        if (value instanceof Document) {
707            value = editable((Document)value, index);
708        } else if (value instanceof List) {
709            value = editable((List<?>)value, index);
710        }
711        return value;
712    }
713
714    @Override
715    public Object set( int index,
716                       Object element ) {
717        return doSetValue(index, element);
718    }
719
720    @Override
721    public void add( int index,
722                     Object element ) {
723        doAddValue(index, element);
724    }
725
726    @Override
727    public Object remove( int index ) {
728        return doRemoveValue(index);
729    }
730
731    @Override
732    public int indexOf( Object o ) {
733        return indexOf(o);
734    }
735
736    @Override
737    public int lastIndexOf( Object o ) {
738        return array.lastIndexOf(o);
739    }
740
741    @Override
742    public Iterable<Entry> getEntries() {
743        return array.getEntries();
744    }
745
746    @Override
747    public ListIterator<Object> listIterator() {
748        return array.listIterator();
749    }
750
751    @Override
752    public ListIterator<Object> listIterator( int index ) {
753        return array.listIterator(index);
754    }
755
756    @Override
757    public List<Object> subList( int fromIndex,
758                                 int toIndex ) {
759        return editableSublist(array.subList(fromIndex, toIndex));
760    }
761
762    @Override
763    public EditableArray set( String name,
764                              Object value ) {
765        return setValue(name, value);
766    }
767
768    @Override
769    public EditableArray setBoolean( int index,
770                                     boolean value ) {
771        return setValue(index, factory.createBoolean(value));
772    }
773
774    @Override
775    public EditableArray setNumber( int index,
776                                    int value ) {
777        return setValue(index, factory.createInt(value));
778    }
779
780    @Override
781    public EditableArray setNumber( int index,
782                                    long value ) {
783        return setValue(index, factory.createLong(value));
784    }
785
786    @Override
787    public EditableArray setNumber( int index,
788                                    float value ) {
789        return setValue(index, factory.createDouble(value));
790    }
791
792    @Override
793    public EditableArray setNumber( int index,
794                                    double value ) {
795        return setValue(index, factory.createDouble(value));
796    }
797
798    @Override
799    public EditableArray setString( int index,
800                                    String value ) {
801        return setValue(index, factory.createString(value));
802    }
803
804    @Override
805    public EditableArray setSymbol( int index,
806                                    String value ) {
807        return setValue(index, factory.createSymbol(value));
808    }
809
810    @Override
811    public EditableDocument setDocument( int index ) {
812        BasicDocument doc = new BasicDocument();
813        setValue(index, doc);
814        return editable(doc, index);
815    }
816
817    @Override
818    public EditableDocument setDocument( int index,
819                                         Document document ) {
820        if (document instanceof DocumentEditor) document = ((DocumentEditor)document).unwrap();
821        setValue(index, document);
822        return editable(document, index);
823    }
824
825    @Override
826    public EditableArray setArray( int index ) {
827        List<?> array = new BasicArray();
828        setValue(index, array);
829        return editable(array, index);
830    }
831
832    @Override
833    public EditableArray setArray( int index,
834                                   Array array ) {
835        setValue(index, array);
836        return editable((List<?>)array, index);
837    }
838
839    @Override
840    public EditableArray setDate( int index,
841                                  Date value ) {
842        setValue(index, value);
843        return this;
844    }
845
846    @Override
847    public EditableArray setDate( int index,
848                                  String isoDate ) throws ParseException {
849        setValue(index, factory.createDate(isoDate));
850        return this;
851    }
852
853    @Override
854    public EditableArray setTimestamp( int index,
855                                       int timeInSeconds,
856                                       int increment ) {
857        return setValue(index, factory.createTimestamp(timeInSeconds, increment));
858    }
859
860    @Override
861    public EditableArray setObjectId( int index,
862                                      String hex ) {
863        return setValue(index, factory.createObjectId(hex));
864    }
865
866    @Override
867    public EditableArray setObjectId( int index,
868                                      byte[] bytes ) {
869        return setValue(index, factory.createObjectId(bytes));
870    }
871
872    @Override
873    public EditableArray setObjectId( int index,
874                                      int time,
875                                      int machine,
876                                      int process,
877                                      int inc ) {
878        return setValue(index, factory.createObjectId(time, machine, process, inc));
879    }
880
881    @Override
882    public EditableArray setRegularExpression( int index,
883                                               String pattern ) {
884        return setValue(index, factory.createRegex(pattern, null));
885    }
886
887    @Override
888    public EditableArray setRegularExpression( int index,
889                                               String pattern,
890                                               int flags ) {
891        return setValue(index, factory.createRegex(pattern, flags));
892    }
893
894    @Override
895    public EditableArray setNull( int index ) {
896        return setValue(index, factory.createNull());
897    }
898
899    @Override
900    public EditableArray setBinary( int index,
901                                    byte type,
902                                    byte[] data ) {
903        return setValue(index, factory.createBinary(type, data));
904    }
905
906    @Override
907    public EditableArray setUuid( int index,
908                                  UUID uuid ) {
909        return setValue(index, uuid);
910    }
911
912    @Override
913    public EditableDocument setCode( int index,
914                                     String code,
915                                     boolean includeScope ) {
916        if (includeScope) {
917            BasicDocument scope = new BasicDocument();
918            setValue(index, factory.createCode(code, scope));
919            return editable(scope, index);
920        }
921        return setValue(index, factory.createCode(code));
922    }
923
924    @Override
925    public EditableDocument setCode( int index,
926                                     String code,
927                                     Document scope ) {
928        if (scope != null) {
929            setValue(index, factory.createCode(code, scope));
930            return editable(scope, index);
931        }
932        return setValue(index, factory.createCode(code));
933    }
934
935    @Override
936    public EditableArray addBoolean( int index,
937                                     boolean value ) {
938        return addValue(index, factory.createBoolean(value));
939    }
940
941    @Override
942    public EditableArray addNumber( int index,
943                                    int value ) {
944        return addValue(index, factory.createInt(value));
945    }
946
947    @Override
948    public EditableArray addNumber( int index,
949                                    long value ) {
950        return addValue(index, factory.createLong(value));
951    }
952
953    @Override
954    public EditableArray addNumber( int index,
955                                    float value ) {
956        return addValue(index, factory.createDouble(value));
957    }
958
959    @Override
960    public EditableArray addNumber( int index,
961                                    double value ) {
962        return addValue(index, factory.createDouble(value));
963    }
964
965    @Override
966    public EditableArray addString( int index,
967                                    String value ) {
968        return addValue(index, factory.createString(value));
969    }
970
971    @Override
972    public EditableArray addSymbol( int index,
973                                    String value ) {
974        return addValue(index, factory.createSymbol(value));
975    }
976
977    @Override
978    public EditableDocument addDocument( int index ) {
979        BasicDocument doc = new BasicDocument();
980        addValue(index, doc);
981        return editable(doc, index);
982    }
983
984    @Override
985    public EditableDocument addDocument( int index,
986                                         Document document ) {
987        if (document instanceof DocumentEditor) document = ((DocumentEditor)document).unwrap();
988        addValue(index, document);
989        return editable(document, index);
990    }
991
992    @Override
993    public EditableArray addArray( int index ) {
994        List<?> array = new BasicArray();
995        addValue(index, array);
996        return editable(array, index);
997    }
998
999    @Override
1000    public EditableArray addArray( int index,
1001                                   Array array ) {
1002        addValue(index, array);
1003        return editable((List<?>)array, index);
1004    }
1005
1006    @Override
1007    public EditableArray addDate( int index,
1008                                  Date value ) {
1009        addValue(index, value);
1010        return this;
1011    }
1012
1013    @Override
1014    public EditableArray addDate( int index,
1015                                  String isoDate ) throws ParseException {
1016        addValue(index, factory.createDate(isoDate));
1017        return this;
1018    }
1019
1020    @Override
1021    public EditableArray addTimestamp( int index,
1022                                       int timeInSeconds,
1023                                       int increment ) {
1024        return addValue(index, factory.createTimestamp(timeInSeconds, increment));
1025    }
1026
1027    @Override
1028    public EditableArray addObjectId( int index,
1029                                      String hex ) {
1030        return addValue(index, factory.createObjectId(hex));
1031    }
1032
1033    @Override
1034    public EditableArray addObjectId( int index,
1035                                      byte[] bytes ) {
1036        return addValue(index, factory.createObjectId(bytes));
1037    }
1038
1039    @Override
1040    public EditableArray addObjectId( int index,
1041                                      int time,
1042                                      int machine,
1043                                      int process,
1044                                      int inc ) {
1045        return addValue(index, factory.createObjectId(time, machine, process, inc));
1046    }
1047
1048    @Override
1049    public EditableArray addRegularExpression( int index,
1050                                               String pattern ) {
1051        return addValue(index, factory.createRegex(pattern, null));
1052    }
1053
1054    @Override
1055    public EditableArray addRegularExpression( int index,
1056                                               String pattern,
1057                                               int flags ) {
1058        return addValue(index, factory.createRegex(pattern, flags));
1059    }
1060
1061    @Override
1062    public EditableArray addNull( int index ) {
1063        return addValue(index, factory.createNull());
1064    }
1065
1066    @Override
1067    public EditableArray addBinary( int index,
1068                                    byte type,
1069                                    byte[] data ) {
1070        return addValue(index, factory.createBinary(type, data));
1071    }
1072
1073    @Override
1074    public EditableArray addUuid( int index,
1075                                  UUID uuid ) {
1076        return addValue(index, uuid);
1077    }
1078
1079    @Override
1080    public EditableDocument addCode( int index,
1081                                     String code,
1082                                     boolean includeScope ) {
1083        if (includeScope) {
1084            BasicDocument scope = new BasicDocument();
1085            addValue(index, factory.createCode(code, scope));
1086            return editable(scope, index);
1087        }
1088        return addValue(index, factory.createCode(code));
1089    }
1090
1091    @Override
1092    public EditableDocument addCode( int index,
1093                                     String code,
1094                                     Document scope ) {
1095        if (scope != null) {
1096            addValue(index, factory.createCode(code, scope));
1097            return editable(scope, index);
1098        }
1099        return addValue(index, factory.createCode(code));
1100    }
1101
1102    @Override
1103    public EditableArray addBoolean( boolean value ) {
1104        return addValue(factory.createBoolean(value));
1105    }
1106
1107    @Override
1108    public EditableArray addNumber( int value ) {
1109        return addValue(factory.createInt(value));
1110    }
1111
1112    @Override
1113    public EditableArray addNumber( long value ) {
1114        return addValue(factory.createLong(value));
1115    }
1116
1117    @Override
1118    public EditableArray addNumber( float value ) {
1119        return addValue(factory.createDouble(value));
1120    }
1121
1122    @Override
1123    public EditableArray addNumber( double value ) {
1124        return addValue(factory.createDouble(value));
1125    }
1126
1127    @Override
1128    public EditableArray addString( String value ) {
1129        return addValue(factory.createString(value));
1130    }
1131
1132    @Override
1133    public EditableArray addSymbol( String value ) {
1134        return addValue(factory.createSymbol(value));
1135    }
1136
1137    @Override
1138    public EditableDocument addDocument() {
1139        BasicDocument doc = new BasicDocument();
1140        addValue(doc);
1141        return editable(doc, size());
1142    }
1143
1144    @Override
1145    public EditableDocument addDocument( Document document ) {
1146        if (document instanceof DocumentEditor) document = ((DocumentEditor)document).unwrap();
1147        addValue(document);
1148        return editable(document, size());
1149    }
1150
1151    @Override
1152    public EditableArray addArray() {
1153        List<?> array = new BasicArray();
1154        addValue(array);
1155        return editable(array, size());
1156    }
1157
1158    @Override
1159    public EditableArray addArray( Array array ) {
1160        addValue(array);
1161        return editable((List<?>)array, size());
1162    }
1163
1164    @Override
1165    public EditableArray addDate( Date value ) {
1166        return addValue(value);
1167    }
1168
1169    @Override
1170    public EditableArray addDate( String isoDate ) throws ParseException {
1171        return addValue(factory.createDate(isoDate));
1172    }
1173
1174    @Override
1175    public EditableArray addTimestamp( int timeInSeconds,
1176                                       int increment ) {
1177        return addValue(factory.createTimestamp(timeInSeconds, increment));
1178    }
1179
1180    @Override
1181    public EditableArray addObjectId( String hex ) {
1182        return addValue(factory.createObjectId(hex));
1183    }
1184
1185    @Override
1186    public EditableArray addObjectId( byte[] bytes ) {
1187        return addValue(factory.createObjectId(bytes));
1188    }
1189
1190    @Override
1191    public EditableArray addObjectId( int time,
1192                                      int machine,
1193                                      int process,
1194                                      int inc ) {
1195        return addValue(factory.createObjectId(time, machine, process, inc));
1196    }
1197
1198    @Override
1199    public EditableArray addRegularExpression( String pattern ) {
1200        return addValue(factory.createRegex(pattern, null));
1201    }
1202
1203    @Override
1204    public EditableArray addRegularExpression( String pattern,
1205                                               int flags ) {
1206        return addValue(factory.createRegex(pattern, flags));
1207    }
1208
1209    @Override
1210    public EditableArray addNull() {
1211        return addValue(factory.createNull());
1212    }
1213
1214    @Override
1215    public EditableArray addBinary( byte type,
1216                                    byte[] data ) {
1217        return addValue(factory.createBinary(type, data));
1218    }
1219
1220    @Override
1221    public EditableArray addUuid( UUID uuid ) {
1222        return addValue(uuid);
1223    }
1224
1225    @Override
1226    public EditableDocument addCode( String code,
1227                                     boolean includeScope ) {
1228        if (includeScope) {
1229            BasicDocument scope = new BasicDocument();
1230            addValue(factory.createCode(code, scope));
1231            return editable(scope, size());
1232        }
1233        return addValue(factory.createCode(code));
1234    }
1235
1236    @Override
1237    public EditableDocument addCode( String code,
1238                                     Document scope ) {
1239        if (scope != null) {
1240            addValue(factory.createCode(code, scope));
1241            return editable(scope, size());
1242        }
1243        return addValue(factory.createCode(code));
1244    }
1245
1246    @Override
1247    public EditableArray addBooleanIfAbsent( boolean value ) {
1248        return addValueIfAbsent(factory.createBoolean(value));
1249    }
1250
1251    @Override
1252    public EditableArray addNumberIfAbsent( int value ) {
1253        return addValueIfAbsent(factory.createInt(value));
1254    }
1255
1256    @Override
1257    public EditableArray addNumberIfAbsent( long value ) {
1258        return addValueIfAbsent(factory.createLong(value));
1259    }
1260
1261    @Override
1262    public EditableArray addNumberIfAbsent( float value ) {
1263        return addValueIfAbsent(factory.createDouble(value));
1264    }
1265
1266    @Override
1267    public EditableArray addNumberIfAbsent( double value ) {
1268        return addValueIfAbsent(factory.createDouble(value));
1269    }
1270
1271    @Override
1272    public EditableArray addStringIfAbsent( String value ) {
1273        return addValueIfAbsent(factory.createString(value));
1274    }
1275
1276    @Override
1277    public EditableArray addSymbolIfAbsent( String value ) {
1278        return addValueIfAbsent(factory.createSymbol(value));
1279    }
1280
1281    @Override
1282    public EditableDocument addDocumentIfAbsent( Document document ) {
1283        if (document instanceof DocumentEditor) document = ((DocumentEditor)document).unwrap();
1284        return doAddValueIfAbsent(document) ? editable(document, size()) : null;
1285    }
1286
1287    @Override
1288    public EditableArray addArrayIfAbsent( Array array ) {
1289        return doAddValueIfAbsent(array) ? editable((List<?>)array, size()) : null;
1290    }
1291
1292    @Override
1293    public EditableArray addDateIfAbsent( Date value ) {
1294        return addValueIfAbsent(value);
1295    }
1296
1297    @Override
1298    public EditableArray addDateIfAbsent( String isoDate ) throws ParseException {
1299        return addValueIfAbsent(factory.createDate(isoDate));
1300    }
1301
1302    @Override
1303    public EditableArray addTimestampIfAbsent( int timeInSeconds,
1304                                               int increment ) {
1305        return addValueIfAbsent(factory.createTimestamp(timeInSeconds, increment));
1306    }
1307
1308    @Override
1309    public EditableArray addObjectIdIfAbsent( String hex ) {
1310        return addValueIfAbsent(factory.createObjectId(hex));
1311    }
1312
1313    @Override
1314    public EditableArray addObjectIdIfAbsent( byte[] bytes ) {
1315        return addValueIfAbsent(factory.createObjectId(bytes));
1316    }
1317
1318    @Override
1319    public EditableArray addObjectIdIfAbsent( int time,
1320                                              int machine,
1321                                              int process,
1322                                              int inc ) {
1323        return addValueIfAbsent(factory.createObjectId(time, machine, process, inc));
1324    }
1325
1326    @Override
1327    public EditableArray addRegularExpressionIfAbsent( String pattern ) {
1328        return addValueIfAbsent(factory.createRegex(pattern, null));
1329    }
1330
1331    @Override
1332    public EditableArray addRegularExpressionIfAbsent( String pattern,
1333                                                       int flags ) {
1334        return addValueIfAbsent(factory.createRegex(pattern, flags));
1335    }
1336
1337    @Override
1338    public EditableArray addNullIfAbsent() {
1339        return addValueIfAbsent(factory.createNull());
1340    }
1341
1342    @Override
1343    public EditableArray addBinaryIfAbsent( byte type,
1344                                            byte[] data ) {
1345        return addValueIfAbsent(factory.createBinary(type, data));
1346    }
1347
1348    @Override
1349    public EditableArray addUuidIfAbsent( UUID uuid ) {
1350        return addValueIfAbsent(uuid);
1351    }
1352
1353    @Override
1354    public EditableDocument addCodeIfAbsent( String code,
1355                                             Document scope ) {
1356        if (scope != null) {
1357            return doAddValueIfAbsent(factory.createCode(code, scope)) ? editable(scope, size()) : null;
1358        }
1359        return addValueIfAbsent(factory.createCode(code));
1360    }
1361
1362    @Override
1363    public String toString() {
1364        return array.toString();
1365    }
1366
1367}