com.twelvemonkeys.util.AbstractDecoratedMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.fop Show documentation
Show all versions of org.apache.fop Show documentation
The core maven build properties
The newest version!
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.util;
import java.io.Serializable;
import java.util.*;
/**
* AbstractDecoratedMap
*
* @author Harald Kuhr
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/util/AbstractDecoratedMap.java#2 $
*/
// TODO: The generics in this class looks suspicious..
abstract class AbstractDecoratedMap extends AbstractMap implements Map, Serializable, Cloneable {
protected Map> entries;
protected transient volatile int modCount;
private transient volatile Set> entrySet = null;
private transient volatile Set keySet = null;
private transient volatile Collection values = null;
/**
* Creates a {@code Map} backed by a {@code HashMap}.
*/
public AbstractDecoratedMap() {
this(new HashMap>(), null);
}
/**
* Creates a {@code Map} backed by a {@code HashMap}, containing all
* key/value mappings from the given {@code Map}.
*
* This is constructor is here to comply with the reccomendations for
* "standard" constructors in the {@code Map} interface.
*
*
* @see #AbstractDecoratedMap(java.util.Map, java.util.Map)
*
* @param pContents the map whose mappings are to be placed in this map.
* May be {@code null}.
*/
public AbstractDecoratedMap(Map extends K, ? extends V> pContents) {
this(new HashMap>(), pContents);
}
/**
* Creates a {@code Map} backed by the given backing-{@code Map},
* containing all key/value mappings from the given contents-{@code Map}.
*
* NOTE: The backing map is structuraly cahnged, and it should NOT be
* accessed directly, after the wrapped map is created.
*
*
* @param pBacking the backing map of this map. Must be either empty, or
* the same map as {@code pContents}.
* @param pContents the map whose mappings are to be placed in this map.
* May be {@code null}.
*
* @throws IllegalArgumentException if {@code pBacking} is {@code null}
* or if {@code pBacking} differs from {@code pContent} and is not empty.
*/
public AbstractDecoratedMap(Map> pBacking, Map extends K, ? extends V> pContents) {
if (pBacking == null) {
throw new IllegalArgumentException("backing == null");
}
Entry extends K, ? extends V>[] entries = null;
if (pBacking == pContents) {
// NOTE: Special treatment to avoid ClassCastExceptions
Set extends Entry extends K, ? extends V>> es = pContents.entrySet();
//noinspection unchecked
entries = new Entry[es.size()];
entries = es.toArray(entries);
pContents = null;
pBacking.clear();
}
else if (!pBacking.isEmpty()) {
throw new IllegalArgumentException("backing must be empty");
}
this.entries = pBacking;
init();
if (pContents != null) {
putAll(pContents);
}
else if (entries != null) {
// Reinsert entries, this time wrapped
for (Entry extends K, ? extends V> entry : entries) {
put(entry.getKey(), entry.getValue());
}
}
}
/**
* Default implementation, does nothing.
*/
protected void init() {
}
public int size() {
return entries.size();
}
public void clear() {
entries.clear();
modCount++;
init();
}
public boolean isEmpty() {
return entries.isEmpty();
}
public boolean containsKey(Object pKey) {
return entries.containsKey(pKey);
}
/**
* Returns {@code true} if this map maps one or more keys to the
* specified pValue. More formally, returns {@code true} if and only if
* this map contains at least one mapping to a pValue {@code v} such that
* {@code (pValue==null ? v==null : pValue.equals(v))}.
*
* This implementation requires time linear in the map size for this
* operation.
*
*
* @param pValue pValue whose presence in this map is to be tested.
* @return {@code true} if this map maps one or more keys to the
* specified pValue.
*/
public boolean containsValue(Object pValue) {
for (V value : values()) {
if (value == pValue || (value != null && value.equals(pValue))) {
return true;
}
}
return false;
}
public Collection values() {
Collection values = this.values;
return values != null ? values : (this.values = new Values());
}
public Set> entrySet() {
Set> es = entrySet;
return es != null ? es : (entrySet = new EntrySet());
}
public Set keySet() {
Set ks = keySet;
return ks != null ? ks : (keySet = new KeySet());
}
/**
* Returns a shallow copy of this {@code AbstractMap} instance: the keys
* and values themselves are not cloned.
*
* @return a shallow copy of this map.
*/
protected Object clone() throws CloneNotSupportedException {
AbstractDecoratedMap map = (AbstractDecoratedMap) super.clone();
map.values = null;
map.entrySet = null;
map.keySet = null;
// TODO: Implement: Need to clone the backing map...
return map;
}
// Subclass overrides these to alter behavior of views' iterator() method
protected abstract Iterator newKeyIterator();
protected abstract Iterator newValueIterator();
protected abstract Iterator> newEntryIterator();
// TODO: Implement these (get/put/remove)?
public abstract V get(Object pKey);
public abstract V remove(Object pKey);
public abstract V put(K pKey, V pValue);
/*protected*/ Entry createEntry(K pKey, V pValue) {
return new BasicEntry(pKey, pValue);
}
/*protected*/ Entry getEntry(K pKey) {
return entries.get(pKey);
}
/**
* Removes the given entry from the Map.
*
* @param pEntry the entry to be removed
*
* @return the removed entry, or {@code null} if nothing was removed.
*/
protected Entry removeEntry(Entry pEntry) {
if (pEntry == null) {
return null;
}
// Find candidate entry for this key
Entry candidate = getEntry(pEntry.getKey());
if (candidate == pEntry || (candidate != null && candidate.equals(pEntry))) {
// Remove
remove(pEntry.getKey());
return pEntry;
}
return null;
}
protected class Values extends AbstractCollection {
public Iterator iterator() {
return newValueIterator();
}
public int size() {
return AbstractDecoratedMap.this.size();
}
public boolean contains(Object o) {
return containsValue(o);
}
public void clear() {
AbstractDecoratedMap.this.clear();
}
}
protected class EntrySet extends AbstractSet> {
public Iterator> iterator() {
return newEntryIterator();
}
public boolean contains(Object o) {
if (!(o instanceof Entry))
return false;
Entry e = (Entry) o;
//noinspection SuspiciousMethodCalls
Entry candidate = entries.get(e.getKey());
return candidate != null && candidate.equals(e);
}
public boolean remove(Object o) {
if (!(o instanceof Entry)) {
return false;
}
/*
// NOTE: Extra cautions is taken, to only remove the entry if it
// equals the entry in the map
Object key = ((Entry) o).getKey();
Entry entry = (Entry) entries.get(key);
// Same entry?
if (entry != null && entry.equals(o)) {
return AbstractWrappedMap.this.remove(key) != null;
}
return false;
*/
//noinspection unchecked
return AbstractDecoratedMap.this.removeEntry((Entry) o) != null;
}
public int size() {
return AbstractDecoratedMap.this.size();
}
public void clear() {
AbstractDecoratedMap.this.clear();
}
}
protected class KeySet extends AbstractSet {
public Iterator iterator() {
return newKeyIterator();
}
public int size() {
return AbstractDecoratedMap.this.size();
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return AbstractDecoratedMap.this.remove(o) != null;
}
public void clear() {
AbstractDecoratedMap.this.clear();
}
}
/**
* A simple Map.Entry implementation.
*/
static class BasicEntry implements Entry, Serializable {
K mKey;
V mValue;
BasicEntry(K pKey, V pValue) {
mKey = pKey;
mValue = pValue;
}
/**
* Default implementation does nothing.
*
* @param pMap the map that is accessed
*/
protected void recordAccess(Map pMap) {
}
/**
* Default implementation does nothing.
* @param pMap the map that is removed from
*/
protected void recordRemoval(Map pMap) {
}
public V getValue() {
return mValue;
}
public V setValue(V pValue) {
V oldValue = mValue;
mValue = pValue;
return oldValue;
}
public K getKey() {
return mKey;
}
public boolean equals(Object pOther) {
if (!(pOther instanceof Map.Entry)) {
return false;
}
Map.Entry entry = (Map.Entry) pOther;
Object k1 = mKey;
Object k2 = entry.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
Object v1 = mValue;
Object v2 = entry.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2))) {
return true;
}
}
return false;
}
public int hashCode() {
return (mKey == null ? 0 : mKey.hashCode()) ^
(mValue == null ? 0 : mValue.hashCode());
}
public String toString() {
return getKey() + "=" + getValue();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy