001package com.hfg.util.collection; 002 003import java.util.HashMap; 004import java.util.HashSet; 005import java.util.Map; 006import java.util.Set; 007 008//------------------------------------------------------------------------------ 009/** 010 * HashMap that keeps a dirty flag. 011 * @author J. Alex Taylor, hairyfatguy.com 012 */ 013//------------------------------------------------------------------------------ 014// com.hfg Library 015// 016// This library is free software; you can redistribute it and/or 017// modify it under the terms of the GNU Lesser General Public 018// License as published by the Free Software Foundation; either 019// version 2.1 of the License, or (at your option) any later version. 020// 021// This library is distributed in the hope that it will be useful, 022// but WITHOUT ANY WARRANTY; without even the implied warranty of 023// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 024// Lesser General Public License for more details. 025// 026// You should have received a copy of the GNU Lesser General Public 027// License along with this library; if not, write to the Free Software 028// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 029// 030// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 031// jataylor@hairyfatguy.com 032//------------------------------------------------------------------------------ 033 034public class DirtyMap<K, V> extends HashMap<K, V> 035{ 036 private boolean mIsDirty; 037 private Set<K> mDirtyKeySet; 038 039 //########################################################################## 040 // CONSTRUCTORS 041 //########################################################################## 042 043 //-------------------------------------------------------------------------- 044 public DirtyMap() 045 { 046 super(); 047 } 048 049 //-------------------------------------------------------------------------- 050 public DirtyMap(int inInitialCapacity) 051 { 052 super(inInitialCapacity); 053 } 054 055 //-------------------------------------------------------------------------- 056 public DirtyMap(int inInitialCapacity, float inLoadFactor) 057 { 058 super(inInitialCapacity, inLoadFactor); 059 } 060 061 //-------------------------------------------------------------------------- 062 public DirtyMap(Map<? extends K,? extends V> inMap) 063 { 064 super(inMap); 065 } 066 067 //########################################################################## 068 // PUBLIC METHODS 069 //########################################################################## 070 071 //-------------------------------------------------------------------------- 072 public void bless() 073 { 074 mIsDirty = false; 075 mDirtyKeySet = null; 076 } 077 078 //-------------------------------------------------------------------------- 079 public boolean isDirty() 080 { 081 return mIsDirty; 082 } 083 084 //-------------------------------------------------------------------------- 085 public Set<K> dirtyKeySet() 086 { 087 return CollectionUtil.hasValues(mDirtyKeySet) ? mDirtyKeySet : null; 088 } 089 090 //-------------------------------------------------------------------------- 091 @Override 092 public void clear() 093 { 094 if (size() > 0) 095 { 096 mIsDirty = true; 097 super.clear(); 098 099 mDirtyKeySet = null; 100 } 101 } 102 103 //-------------------------------------------------------------------------- 104 @Override 105 public V put(K inKey, V inValue) 106 { 107 if (containsKey(inKey)) 108 { 109 V currentValue = get(inKey); 110 111 boolean changed; 112 if (null == inValue) 113 { 114 changed = (currentValue != null); 115 } 116 else if (null == currentValue) 117 { 118 changed = true; 119 } 120 else 121 { 122 changed = !currentValue.equals(inValue); 123 } 124 125 if (changed) 126 { 127 if (null == mDirtyKeySet) 128 { 129 mDirtyKeySet = new HashSet<>(size()); 130 } 131 132 mDirtyKeySet.add(inKey); 133 134 if (!isDirty()) 135 { 136 mIsDirty = changed; 137 } 138 } 139 } 140 else 141 { 142 // New key 143 if (null == mDirtyKeySet) 144 { 145 mDirtyKeySet = new HashSet<>(size()); 146 } 147 148 mDirtyKeySet.add(inKey); 149 150 mIsDirty = true; 151 } 152 153 return super.put(inKey, inValue); 154 } 155 156 //-------------------------------------------------------------------------- 157 @Override 158 public void putAll(Map<? extends K,? extends V> m) 159 { 160 for (K key : m.keySet()) 161 { 162 put(key, m.get(key)); 163 } 164 } 165 166 //-------------------------------------------------------------------------- 167 @Override 168 public V remove(Object inKey) 169 { 170 boolean containsKey = containsKey(inKey); 171 if (mDirtyKeySet != null 172 && containsKey) 173 { 174 mDirtyKeySet.remove(inKey); 175 } 176 177 if (! isDirty() 178 && containsKey) 179 { 180 mIsDirty = true; 181 } 182 183 return super.remove(inKey); 184 } 185 186}