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.util.Collection;
019import java.util.List;
020import org.modeshape.schematic.document.Array;
021import org.modeshape.schematic.document.EditableArray;
022import org.modeshape.schematic.document.EditableDocument;
023import org.modeshape.schematic.document.Path;
024import org.modeshape.schematic.internal.delta.AddValueIfAbsentOperation;
025import org.modeshape.schematic.internal.delta.AddValueOperation;
026import org.modeshape.schematic.internal.delta.ClearOperation;
027import org.modeshape.schematic.internal.delta.DocumentObserver;
028import org.modeshape.schematic.internal.delta.RemoveAllValuesOperation;
029import org.modeshape.schematic.internal.delta.RemoveAtIndexOperation;
030import org.modeshape.schematic.internal.delta.RemoveValueOperation;
031import org.modeshape.schematic.internal.delta.RetainAllValuesOperation;
032import org.modeshape.schematic.internal.delta.SetValueOperation;
033
034public class ObservableArrayEditor extends ArrayEditor {
035
036    private static final long serialVersionUID = 1L;
037
038    private final Path path;
039    private final DocumentObserver observer;
040
041    public ObservableArrayEditor( MutableArray array,
042                                  Path path,
043                                  DocumentObserver observer,
044                                  DocumentValueFactory factory ) {
045        super(array, factory);
046        this.path = path;
047        this.observer = observer;
048    }
049
050    @Override
051    protected boolean doAddAll( Collection<?> c ) {
052        return doAddAll(size(), c);
053    }
054
055    @Override
056    protected boolean doAddAll( int index,
057                                Collection<?> c ) {
058        c = Utility.unwrapValues(c);
059        if (super.doAddAll(index, c)) {
060            for (Object value : c) {
061                value = Utility.unwrap(value);
062                observer.addOperation(new AddValueOperation(this.path, value));
063            }
064            return true;
065        }
066        return false;
067    }
068
069    @Override
070    protected void doAddValue( int index,
071                               Object value ) {
072        value = Utility.unwrap(value);
073        super.doAddValue(index, value);
074        observer.addOperation(new AddValueOperation(this.path, value, index));
075    }
076
077    @Override
078    protected int doAddValue( Object value ) {
079        value = Utility.unwrap(value);
080        int index = super.doAddValue(value);
081        observer.addOperation(new AddValueOperation(this.path, value));
082        return index;
083    }
084
085    @Override
086    protected boolean doAddValueIfAbsent( Object value ) {
087        value = Utility.unwrap(value);
088        if (super.doAddValueIfAbsent(value)) {
089            observer.addOperation(new AddValueIfAbsentOperation(this.path, value));
090            return true;
091        }
092        return false;
093    }
094
095    @Override
096    protected void doClear() {
097        super.doClear();
098        observer.addOperation(new ClearOperation(this.path));
099    }
100
101    @Override
102    protected List<Array.Entry> doRemoveAll( Collection<?> c ) {
103        c = Utility.unwrapValues(c);
104        List<Array.Entry> removed = super.doRemoveAll(c);
105        observer.addOperation(new RemoveAllValuesOperation(this.path, c));
106        return removed;
107    }
108
109    @Override
110    protected Object doRemoveValue( int index ) {
111        Object removed = super.doRemoveValue(index);
112        if (removed != null) {
113            observer.addOperation(new RemoveAtIndexOperation(this.path, index));
114        }
115        return removed;
116    }
117
118    @Override
119    protected boolean doRemoveValue( Object value ) {
120        value = Utility.unwrap(value);
121        if (super.doRemoveValue(value)) {
122            observer.addOperation(new RemoveValueOperation(this.path, value));
123        }
124        return false;
125    }
126
127    @Override
128    protected List<Array.Entry> doRetainAll( Collection<?> c ) {
129        c = Utility.unwrapValues(c);
130        List<Array.Entry> removed = super.doRetainAll(c);
131        observer.addOperation(new RetainAllValuesOperation(this.path, c));
132        return removed;
133    }
134
135    @Override
136    protected Object doSetValue( int index,
137                                 Object value ) {
138        value = Utility.unwrap(value);
139        Object oldValue = super.doSetValue(index, value);
140        observer.addOperation(new SetValueOperation(path, value, index));
141        return oldValue;
142    }
143
144    @Override
145    protected EditableDocument createEditableDocument( MutableDocument document,
146                                                       int index,
147                                                       DocumentValueFactory factory ) {
148        return new ObservableDocumentEditor(document, path.with(Integer.toString(index)), observer, factory);
149    }
150
151    @Override
152    protected EditableArray createEditableArray( MutableArray array,
153                                                 int index,
154                                                 DocumentValueFactory factory ) {
155        return new ObservableArrayEditor(array, path.with(Integer.toString(index)), observer, factory);
156    }
157
158    @Override
159    protected EditableArray createEditableSublist( MutableArray array,
160                                                   DocumentValueFactory factory ) {
161        return new ObservableArrayEditor(array, path, observer, factory);
162    }
163}