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.Map; 019import org.modeshape.schematic.document.Document; 020import org.modeshape.schematic.document.EditableArray; 021import org.modeshape.schematic.document.EditableDocument; 022import org.modeshape.schematic.document.Path; 023import org.modeshape.schematic.internal.delta.DocumentObserver; 024import org.modeshape.schematic.internal.delta.PutIfAbsentOperation; 025import org.modeshape.schematic.internal.delta.PutOperation; 026import org.modeshape.schematic.internal.delta.RemoveOperation; 027 028public class ObservableDocumentEditor extends DocumentEditor { 029 030 private static final long serialVersionUID = 1L; 031 032 private transient final Path path; 033 private transient final DocumentObserver observer; 034 035 public ObservableDocumentEditor( MutableDocument document, 036 Path path, 037 DocumentObserver observer, 038 DocumentValueFactory factory ) { 039 super(document, factory); 040 this.path = path; 041 this.observer = observer; 042 } 043 044 @Override 045 protected Object doSetValue( String name, 046 Object newValue ) { 047 Object oldValue = super.doSetValue(name, newValue); 048 observer.addOperation(new PutOperation(path, name, copy(oldValue), copy(newValue))); 049 return oldValue; 050 } 051 052 @Override 053 protected Object doSetValueIfAbsent( String name, 054 Object value ) { 055 Object oldValue = super.doSetValue(name, value); 056 observer.addOperation(new PutIfAbsentOperation(path, name, copy(value))); 057 return oldValue; 058 } 059 060 @Override 061 protected void doSetAllValues( Document values ) { 062 if (values != null && !values.isEmpty()) { 063 for (Field field : values.fields()) { 064 doSetValue(field.getName(), field.getValue()); 065 } 066 } 067 } 068 069 @Override 070 protected void doSetAllValues( Map<? extends String, ?> values ) { 071 if (values != null && !values.isEmpty()) { 072 for (Map.Entry<? extends String, ?> entry : values.entrySet()) { 073 doSetValue(entry.getKey(), entry.getValue()); 074 } 075 } 076 } 077 078 @Override 079 public Object remove( String name ) { 080 Object oldValue = super.remove(name); 081 observer.addOperation(new RemoveOperation(path, name, copy(oldValue))); 082 return oldValue; 083 } 084 085 protected Object copy( Object value ) { 086 if (value instanceof MutableArray) return ((MutableArray)value).clone(); 087 if (value instanceof MutableDocument) return ((MutableDocument)value).clone(); 088 return value; 089 } 090 091 @Override 092 public void removeAll() { 093 super.removeAll(); 094 observer.addOperation(new PutOperation(path.parent(), path.getLast(), copy(unwrap()), new BasicDocument())); 095 } 096 097 @Override 098 protected EditableDocument createEditableDocument( MutableDocument document, 099 String fieldName, 100 DocumentValueFactory factory ) { 101 return new ObservableDocumentEditor(document, path.with(fieldName), observer, factory); 102 } 103 104 @Override 105 protected EditableArray createEditableArray( MutableArray array, 106 String fieldName, 107 DocumentValueFactory factory ) { 108 return new ObservableArrayEditor(array, path.with(fieldName), observer, factory); 109 } 110 111}