001package com.hfg.util.collection;
002
003import java.util.HashSet;
004import java.util.Map;
005import java.util.Properties;
006
007
008//------------------------------------------------------------------------------
009/**
010 * Properties 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 DirtyProperties extends Properties
035{
036   private boolean mIsDirty;
037
038   private HashSet<Object> mDirtyProperties = new HashSet<>(25);
039
040   //##########################################################################
041   // CONSTRUCTORS
042   //##########################################################################
043
044   //--------------------------------------------------------------------------
045   public DirtyProperties()
046   {
047      super();
048   }
049
050   //--------------------------------------------------------------------------
051   /**
052    Creates an empty property list with the specified defaults.
053    @param   inDefaults   the defaults.
054    */
055   public DirtyProperties(Properties inDefaults)
056   {
057      super(inDefaults);
058   }
059
060
061   //##########################################################################
062   // PUBLIC METHODS
063   //##########################################################################
064
065   //--------------------------------------------------------------------------
066   /**
067    * Flags all properties as not being dirty.
068    */
069   public void bless()
070   {
071      mIsDirty = false;
072      mDirtyProperties.clear();
073   }
074
075   //--------------------------------------------------------------------------
076   /**
077    * Returns whether or not the properties set as a whole is dirty (has been changed).
078    * @return whether or not the properties set as a whole is dirty.
079    */
080   public boolean isDirty()
081   {
082      return mIsDirty;
083   }
084
085   //--------------------------------------------------------------------------
086   /**
087    * Returns whether or not the value for the specified key is dirty (has been changed).
088    * @param inKey the specified key to check
089    * @return whether or not the value for the specified key is dirty.
090    */
091   public boolean isDirty(String inKey)
092   {
093      return mDirtyProperties.contains(inKey);
094   }
095
096   //--------------------------------------------------------------------------
097   @Override
098   public void clear()
099   {
100      if (size() > 0)
101      {
102         mIsDirty = true;
103         mDirtyProperties.clear();
104         super.clear();
105      }
106   }
107
108   //--------------------------------------------------------------------------
109   @Override
110   public synchronized Object setProperty(String inKey, String inValue)
111   {
112      return put(inKey, inValue);
113   }
114
115   //--------------------------------------------------------------------------
116   @Override
117   public Object put(Object inKey, Object inValue)
118   {
119      boolean valueChanged = valueChanged(inKey, inValue);
120
121      if (! isDirty())
122      {
123         mIsDirty = valueChanged;
124      }
125
126      if (valueChanged)
127      {
128         mDirtyProperties.add(inKey);
129      }
130
131      return super.put(inKey, inValue);
132   }
133
134   //--------------------------------------------------------------------------
135   @Override
136   public void putAll(Map<? extends Object,? extends Object> m)
137   {
138      for (Object key : m.keySet())
139      {
140         put(key, m.get(key));
141      }
142   }
143
144   //--------------------------------------------------------------------------
145   @Override
146   public Object remove(Object inKey)
147   {
148      if (! isDirty()
149            && containsKey(inKey))
150      {
151         mIsDirty = true;
152         mDirtyProperties.remove(inKey);
153      }
154
155      return super.remove(inKey);
156   }
157
158   //--------------------------------------------------------------------------
159   private boolean valueChanged(Object inKey, Object inNewValue)
160   {
161      Object currentValue = get(inKey);
162      return ((null == currentValue
163               && inNewValue != null)
164              || (currentValue != null
165                  && ! currentValue.equals(inNewValue)));
166   }
167
168}