All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.quartz.utils.DirtyFlagMap Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
/*
 * Copyright 2001-2009 Terracotta, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 */

package org.quartz.utils;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 

* An implementation of Map that wraps another Map * and flags itself 'dirty' when it is modified. *

* * @author James House */ public class DirtyFlagMap implements Map, Cloneable, java.io.Serializable { /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Data members. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ private static final long serialVersionUID = 1433884852607126222L; private boolean dirty = false; private Map map; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** *

* Create a DirtyFlagMap that 'wraps' a HashMap. *

* * @see java.util.HashMap */ public DirtyFlagMap() { map = new HashMap(); } /** *

* Create a DirtyFlagMap that 'wraps' a HashMap that has the * given initial capacity. *

* * @see java.util.HashMap */ public DirtyFlagMap(final int initialCapacity) { map = new HashMap(initialCapacity); } /** *

* Create a DirtyFlagMap that 'wraps' a HashMap that has the * given initial capacity and load factor. *

* * @see java.util.HashMap */ public DirtyFlagMap(final int initialCapacity, final float loadFactor) { map = new HashMap(initialCapacity, loadFactor); } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** *

* Clear the 'dirty' flag (set dirty flag to false). *

*/ public void clearDirtyFlag() { dirty = false; } /** *

* Determine whether the Map is flagged dirty. *

*/ public boolean isDirty() { return dirty; } /** *

* Get a direct handle to the underlying Map. *

*/ public Map getWrappedMap() { return map; } public void clear() { if (!map.isEmpty()) { dirty = true; } map.clear(); } public boolean containsKey(final Object key) { return map.containsKey(key); } public boolean containsValue(final Object val) { return map.containsValue(val); } public Set> entrySet() { return new DirtyFlagMapEntrySet(map.entrySet()); } @Override public boolean equals(final Object obj) { if (obj == null || !(obj instanceof DirtyFlagMap)) { return false; } return map.equals(((DirtyFlagMap) obj).getWrappedMap()); } @Override public int hashCode() { return map.hashCode(); } public V get(final Object key) { return map.get(key); } public boolean isEmpty() { return map.isEmpty(); } public Set keySet() { return new DirtyFlagSet(map.keySet()); } public V put(final K key, final V val) { dirty = true; return map.put(key, val); } public void putAll(final Map t) { if (!t.isEmpty()) { dirty = true; } map.putAll(t); } public V remove(final Object key) { V obj = map.remove(key); if (obj != null) { dirty = true; } return obj; } public int size() { return map.size(); } public Collection values() { return new DirtyFlagCollection(map.values()); } @Override @SuppressWarnings("unchecked") // suppress warnings on generic cast of super.clone() and map.clone() lines. public Object clone() { DirtyFlagMap copy; try { copy = (DirtyFlagMap) super.clone(); if (map instanceof HashMap) { copy.map = (Map)((HashMap)map).clone(); } } catch (CloneNotSupportedException ex) { throw new IncompatibleClassChangeError("Not Cloneable."); } return copy; } /** * Wrap a Collection so we can mark the DirtyFlagMap as dirty if * the underlying Collection is modified. */ private class DirtyFlagCollection implements Collection { private Collection collection; public DirtyFlagCollection(final Collection c) { collection = c; } protected Collection getWrappedCollection() { return collection; } public Iterator iterator() { return new DirtyFlagIterator(collection.iterator()); } public boolean remove(final Object o) { boolean removed = collection.remove(o); if (removed) { dirty = true; } return removed; } public boolean removeAll(final Collection c) { boolean changed = collection.removeAll(c); if (changed) { dirty = true; } return changed; } public boolean retainAll(final Collection c) { boolean changed = collection.retainAll(c); if (changed) { dirty = true; } return changed; } public void clear() { if (collection.isEmpty() == false) { dirty = true; } collection.clear(); } // Pure wrapper methods public int size() { return collection.size(); } public boolean isEmpty() { return collection.isEmpty(); } public boolean contains(final Object o) { return collection.contains(o); } public boolean add(final T o) { return collection.add(o); } // Not supported public boolean addAll(final Collection c) { return collection.addAll(c); } // Not supported public boolean containsAll(final Collection c) { return collection.containsAll(c); } public Object[] toArray() { return collection.toArray(); } public U[] toArray(final U[] array) { return collection.toArray(array); } } /** * Wrap a Set so we can mark the DirtyFlagMap as dirty if * the underlying Collection is modified. */ private class DirtyFlagSet extends DirtyFlagCollection implements Set { public DirtyFlagSet(final Set set) { super(set); } protected Set getWrappedSet() { return (Set)getWrappedCollection(); } } /** * Wrap an Iterator so that we can mark the DirtyFlagMap as dirty if an * element is removed. */ private class DirtyFlagIterator implements Iterator { private Iterator iterator; public DirtyFlagIterator(final Iterator iterator) { this.iterator = iterator; } public void remove() { dirty = true; iterator.remove(); } // Pure wrapper methods public boolean hasNext() { return iterator.hasNext(); } public T next() { return iterator.next(); } } /** * Wrap a Map.Entry Set so we can mark the Map as dirty if * the Set is modified, and return Map.Entry objects * wrapped in the DirtyFlagMapEntry class. */ private class DirtyFlagMapEntrySet extends DirtyFlagSet> { public DirtyFlagMapEntrySet(final Set> set) { super(set); } @Override public Iterator> iterator() { return new DirtyFlagMapEntryIterator(getWrappedSet().iterator()); } @Override public Object[] toArray() { return toArray(new Object[super.size()]); } @SuppressWarnings("unchecked") // suppress warnings on both U[] and U casting. @Override public U[] toArray(final U[] array) { if (array.getClass().getComponentType().isAssignableFrom(Map.Entry.class) == false) { throw new IllegalArgumentException("Array must be of type assignable from Map.Entry"); } int size = super.size(); U[] result = array.length < size ? (U[])Array.newInstance(array.getClass().getComponentType(), size) : array; Iterator> entryIter = iterator(); // Will return DirtyFlagMapEntry objects for (int i = 0; i < size; i++) { result[i] = ( U ) entryIter.next(); } if (result.length > size) { result[size] = null; } return result; } } /** * Wrap an Iterator over Map.Entry objects so that we can * mark the Map as dirty if an element is removed or modified. */ private class DirtyFlagMapEntryIterator extends DirtyFlagIterator> { public DirtyFlagMapEntryIterator(final Iterator> iterator) { super(iterator); } @Override public DirtyFlagMapEntry next() { return new DirtyFlagMapEntry(super.next()); } } /** * Wrap a Map.Entry so we can mark the Map as dirty if * a value is set. */ private class DirtyFlagMapEntry implements Map.Entry { private Map.Entry entry; public DirtyFlagMapEntry(final Map.Entry entry) { this.entry = entry; } public V setValue(final V o) { dirty = true; return entry.setValue(o); } // Pure wrapper methods public K getKey() { return entry.getKey(); } public V getValue() { return entry.getValue(); } } }