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.delta; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Iterator; 021import java.util.List; 022import org.modeshape.schematic.document.Array.Entry; 023import org.modeshape.schematic.document.Path; 024import org.modeshape.schematic.internal.HashCode; 025import org.modeshape.schematic.internal.document.BasicArray; 026import org.modeshape.schematic.internal.document.MutableArray; 027import org.modeshape.schematic.internal.document.MutableDocument; 028 029/** 030 * An atomic array add operation for SchematicValueDelta. 031 * 032 * @author Randall Hauch <rhauch@redhat.com> (C) 2011 Red Hat Inc. 033 */ 034public class RemoveAllValuesOperation extends ArrayOperation { 035 036 protected final Collection<?> values; 037 protected transient int[] actualIndexes; 038 039 public RemoveAllValuesOperation( Path path, 040 Collection<?> values ) { 041 super(path, HashCode.compute(path, values)); 042 this.values = values; 043 } 044 045 @Override 046 public RemoveAllValuesOperation clone() { 047 return new RemoveAllValuesOperation(getParentPath(), cloneValues(values)); 048 } 049 050 public Collection<?> getValuesToRemove() { 051 return values; 052 } 053 054 public synchronized List<Entry> getRemovedEntries() { 055 List<Entry> entries = new ArrayList<>(this.values.size()); 056 Iterator<?> valueIter = values.iterator(); 057 for (int i = 0; i != actualIndexes.length; ++i) { 058 int index = actualIndexes[i]; 059 Object value = valueIter.next(); 060 entries.add(new BasicArray.BasicEntry(index, value)); 061 } 062 return entries; 063 } 064 065 @Override 066 public synchronized void rollback( MutableDocument delegate ) { 067 if (actualIndexes != null) { 068 MutableArray array = mutableParent(delegate); 069 // Add into the same locations ... 070 int i = 0; 071 for (Object value : values) { 072 int index = actualIndexes[i++]; 073 if (index != -1) array.add(index, value); 074 } 075 } 076 } 077 078 @Override 079 public synchronized void replay( MutableDocument delegate ) { 080 if (!values.isEmpty()) { 081 actualIndexes = new int[values.size()]; 082 int i = 0; 083 MutableArray array = mutableParent(delegate); 084 for (Object value : values) { 085 int actualIndex = array.indexOf(value); 086 array.remove(actualIndex); 087 actualIndexes[i++] = actualIndex; 088 } 089 } else { 090 actualIndexes = null; 091 } 092 } 093 094 @Override 095 public int hashCode() { 096 return super.hashCode(); 097 } 098 099 @Override 100 public String toString() { 101 return "Remove at '" + parentPath + "' the values: " + values; 102 } 103 104 @Override 105 public boolean equals( Object obj ) { 106 if (obj instanceof RemoveAllValuesOperation) { 107 RemoveAllValuesOperation other = (RemoveAllValuesOperation)obj; 108 return equalsIfNotNull(values, other.values) && equalsIfNotNull(getParentPath(), other.getParentPath()); 109 110 } 111 return false; 112 } 113}