commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brentwor...@apache.org
Subject svn commit: r1377492 - in /commons/proper/collections/trunk/src: main/java/org/apache/commons/collections/map/PassiveExpiringMap.java test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java
Date Sun, 26 Aug 2012 19:35:46 GMT
Author: brentworden
Date: Sun Aug 26 19:35:45 2012
New Revision: 1377492

URL: http://svn.apache.org/viewvc?rev=1377492&view=rev
Log:
fix indentation

Modified:
    commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/map/PassiveExpiringMap.java
    commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java

Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/map/PassiveExpiringMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/map/PassiveExpiringMap.java?rev=1377492&r1=1377491&r2=1377492&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/map/PassiveExpiringMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/map/PassiveExpiringMap.java Sun Aug 26 19:35:45 2012
@@ -55,523 +55,484 @@ import java.util.concurrent.TimeUnit;
  * synchronization.
  * </p>
  * 
- * @param <K>
- *            the type of the keys in the map
- * 
- * @param <V>
- *            the type of the values in the map
- * 
+ * @param <K> the type of the keys in the map
+ * @param <V> the type of the values in the map
  * @since 4.0
  * @version $Id: $
  */
-public class PassiveExpiringMap<K, V> extends AbstractMapDecorator<K, V>
-		implements Serializable {
-
-	/**
-	 * A {@link ExpirationPolicy} that returns a expiration time that is a
-	 * constant about of time in the future from the current time.
-	 * 
-	 * @param <K>
-	 *            the type of the keys in the map
-	 * @param <V>
-	 *            the type of the values in the map
-	 * 
-	 * @since 4.0
-	 * @version $Id: $
-	 */
-	public static class ConstantTimeToLiveExpirationPolicy<K, V> implements
-			ExpirationPolicy<K, V> {
-
-		/** Serialization version */
-		private static final long serialVersionUID = 1L;
-
-		/** the constant time-to-live value measured in milliseconds. */
-		private final long timeToLiveMillis;
-
-		/**
-		 * Default constructor. Constructs a policy using a negative
-		 * time-to-live value that results in entries never expiring.
-		 */
-		public ConstantTimeToLiveExpirationPolicy() {
-			this(-1L);
-		}
-
-		/**
-		 * Construct a policy with the given time-to-live constant measured in
-		 * milliseconds. A negative time-to-live value indicates entries never
-		 * expire. A zero time-to-live value indicates entries expire (nearly)
-		 * immediately.
-		 * 
-		 * @param timeToLiveMillis
-		 *            the constant amount of time (in milliseconds) an entry is
-		 *            available before it expires. A negative value results in
-		 *            entries that NEVER expire. A zero value results in entries
-		 *            that ALWAYS expire.
-		 */
-		public ConstantTimeToLiveExpirationPolicy(long timeToLiveMillis) {
-			super();
-			this.timeToLiveMillis = timeToLiveMillis;
-		}
-
-		/**
-		 * Construct a policy with the given time-to-live constant measured in
-		 * the given time unit of measure.
-		 * 
-		 * @param timeToLive
-		 *            the constant amount of time an entry is available before
-		 *            it expires. A negative value results in entries that NEVER
-		 *            expire. A zero value results in entries that ALWAYS
-		 *            expire.
-		 * @param timeUnit
-		 *            the unit of time for the <code>timeToLive</code>
-		 *            parameter, must not be null.
-		 * @throws IllegalArgumentException
-		 *             if the time unit is null.
-		 */
-		public ConstantTimeToLiveExpirationPolicy(long timeToLive,
-				TimeUnit timeUnit) {
-			this(validateAndConvertToMillis(timeToLive, TimeUnit.MILLISECONDS));
-		}
-
-		/**
-		 * Determine the expiration time for the given key-value entry.
-		 * 
-		 * @param key
-		 *            the key for the entry (ignored).
-		 * @param value
-		 *            the value for the entry (ignored).
-		 * @return if {@link #timeToLiveMillis} &ge; 0, an expiration time of
-		 *         {@link #timeToLiveMillis} +
-		 *         {@link System#currentTimeMillis()} is returned. Otherwise, -1
-		 *         is returned indicating the entry never expires.
-		 */
-		public long expirationTime(K key, V value) {
-			if (timeToLiveMillis >= 0L) {
-				// avoid numerical overflow
-				long now = System.currentTimeMillis();
-				if (now > Long.MAX_VALUE - timeToLiveMillis) {
-					// expiration would be greater than Long.MAX_VALUE
-					// never expire
-					return -1;
-				}
-
-				// timeToLiveMillis in the future
-				return now + timeToLiveMillis;
-			}
-			
-			// never expire
-			return -1L;
-		}
-	}
-
-	/**
-	 * A policy to determine the expiration time for key-value entries.
-	 * 
-	 * @param <K>
-	 *            the key object type.
-	 * @param <V>
-	 *            the value object type
-	 * 
-	 * @since 4.0
-	 * @version $Id: $
-	 */
-	public static interface ExpirationPolicy<K, V> extends Serializable {
-		/**
-		 * Determine the expiration time for the given key-value entry.
-		 * 
-		 * @param key
-		 *            the key for the entry.
-		 * @param value
-		 *            the value for the entry.
-		 * @return the expiration time value measured in milliseconds. A
-		 *         negative return value indicates the entry never expires.
-		 */
-		long expirationTime(K key, V value);
-	}
-
-	/** Serialization version */
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * First validate the input parameters. If the parameters are valid, convert
-	 * the given time measured in the given units to the same time measured in
-	 * milliseconds. If the parameters are invalid, an
-	 * {@link IllegalArgumentException} is thrown.
-	 * 
-	 * @param timeToLive
-	 *            the constant amount of time an entry is available before it
-	 *            expires. A negative value results in entries that NEVER
-	 *            expire. A zero value results in entries that ALWAYS expire.
-	 * @param timeUnit
-	 *            the unit of time for the <code>timeToLive</code> parameter,
-	 *            must not be null.
-	 * @throws IllegalArgumentException
-	 *             if the time unit is null.
-	 */
-	private static long validateAndConvertToMillis(long timeToLive,
-			TimeUnit timeUnit) {
-		if (timeUnit == null) {
-			throw new IllegalArgumentException("Time unit must not be null");
-		}
-		return timeUnit.convert(timeToLive, TimeUnit.MILLISECONDS);
-	}
-
-	/** map used to manage expiration times for the actual map entries. */
-	private final Map<Object, Long> expirationMap = new HashMap<Object, Long>();
-
-	/** the policy used to determine time-to-live values for map entries. */
-	private final ExpirationPolicy<K, V> expiringPolicy;
-
-	/**
-	 * Default constructor. Constructs a map decorator that results in entries
-	 * NEVER expiring.
-	 */
-	public PassiveExpiringMap() {
-		this(-1L);
-	}
-
-	/**
-	 * Construct a map decorator using the given expiration policy to determine
-	 * expiration times.
-	 * 
-	 * @param expiringPolicy
-	 *            the policy used to determine expiration times of entries as
-	 *            they are added.
-	 */
-	public PassiveExpiringMap(ExpirationPolicy<K, V> expiringPolicy) {
-		this(expiringPolicy, new HashMap<K, V>());
-	}
-
-	/**
-	 * Construct a map decorator that decorates the given map and uses the given
-	 * expiration policy to determine expiration times. If there are any
-	 * elements already in the map being decorated, they will NEVER expire
-	 * unless they are replaced.
-	 * 
-	 * @param expiringPolicy
-	 *            the policy used to determine expiration times of entries as
-	 *            they are added.
-	 * @param map
-	 *            the map to decorate, must not be null.
-	 * @throws IllegalArgumentException
-	 *             if the map is null.
-	 */
-	public PassiveExpiringMap(ExpirationPolicy<K, V> expiringPolicy,
-			Map<K, V> map) {
-		super(map);
-		if (expiringPolicy == null) {
-			throw new IllegalArgumentException("Policy must not be null.");
-		}
-		this.expiringPolicy = expiringPolicy;
-	}
-
-	/**
-	 * Construct a map decorator that decorates the given map using the given
-	 * time-to-live value measured in milliseconds to create and use a
-	 * {@link ConstantTimeToLiveExpirationPolicy} expiration policy.
-	 * 
-	 * @param timeToLiveMillis
-	 *            the constant amount of time (in milliseconds) an entry is
-	 *            available before it expires. A negative value results in
-	 *            entries that NEVER expire. A zero value results in entries
-	 *            that ALWAYS expire.
-	 */
-	public PassiveExpiringMap(long timeToLiveMillis) {
-		this(new ConstantTimeToLiveExpirationPolicy<K, V>(timeToLiveMillis),
-				new HashMap<K, V>());
-	}
-
-	/**
-	 * Construct a map decorator using the given time-to-live value measured in
-	 * milliseconds to create and use a
-	 * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. If there
-	 * are any elements already in the map being decorated, they will NEVER
-	 * expire unless they are replaced.
-	 * 
-	 * @param timeToLiveMillis
-	 *            the constant amount of time (in milliseconds) an entry is
-	 *            available before it expires. A negative value results in
-	 *            entries that NEVER expire. A zero value results in entries
-	 *            that ALWAYS expire.
-	 * @param map
-	 *            the map to decorate, must not be null.
-	 * @throws IllegalArgumentException
-	 *             if the map is null.
-	 */
-	public PassiveExpiringMap(long timeToLiveMillis, Map<K, V> map) {
-		this(new ConstantTimeToLiveExpirationPolicy<K, V>(timeToLiveMillis),
-				map);
-	}
-
-	/**
-	 * Construct a map decorator using the given time-to-live value measured in
-	 * the given time units of measure to create and use a
-	 * {@link ConstantTimeToLiveExpirationPolicy} expiration policy.
-	 * 
-	 * @param timeToLive
-	 *            the constant amount of time an entry is available before it
-	 *            expires. A negative value results in entries that NEVER
-	 *            expire. A zero value results in entries that ALWAYS expire.
-	 * @param timeUnit
-	 *            the unit of time for the <code>timeToLive</code> parameter,
-	 *            must not be null.
-	 * @throws IllegalArgumentException
-	 *             if the time unit is null.
-	 */
-	public PassiveExpiringMap(long timeToLive, TimeUnit timeUnit) {
-		this(validateAndConvertToMillis(timeToLive, timeUnit));
-	}
-
-	/**
-	 * Construct a map decorator that decorates the given map using the given
-	 * time-to-live value measured in the given time units of measure to create
-	 * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. This policy
-	 * is used to determine expiration times. If there are any elements already
-	 * in the map being decorated, they will NEVER expire unless they are
-	 * replaced.
-	 * 
-	 * @param timeToLive
-	 *            the constant amount of time an entry is available before it
-	 *            expires. A negative value results in entries that NEVER
-	 *            expire. A zero value results in entries that ALWAYS expire.
-	 * @param timeUnit
-	 *            the unit of time for the <code>timeToLive</code> parameter,
-	 *            must not be null.
-	 * @throws IllegalArgumentException
-	 *             if the time unit is null.
-	 * @param map
-	 *            the map to decorate, must not be null.
-	 * @throws IllegalArgumentException
-	 *             if the map is null.
-	 */
-	public PassiveExpiringMap(long timeToLive, TimeUnit timeUnit, Map<K, V> map) {
-		this(validateAndConvertToMillis(timeToLive, timeUnit), map);
-	}
-
-	/**
-	 * Constructs a map decorator that decorates the given map and results in
-	 * entries NEVER expiring. If there are any elements already in the map
-	 * being decorated, they also will NEVER expire.
-	 * 
-	 * @param map
-	 *            the map to decorate, must not be null.
-	 * @throws IllegalArgumentException
-	 *             if the map is null.
-	 */
-	public PassiveExpiringMap(Map<K, V> map) {
-		this(-1L, map);
-	}
-
-	/**
-	 * Normal {@link Map#clear()} behavior with the addition of clearing all
-	 * expiration entries as well.
-	 */
-	@Override
-	public void clear() {
-		super.clear();
-		expirationMap.clear();
-	}
-
-	/**
-	 * All expired entries are removed from the map prior to determining the
-	 * contains result.
-	 */
-	@Override
-	public boolean containsKey(Object key) {
-		removeIfExpired(key, now());
-		return super.containsKey(key);
-	}
-
-	/**
-	 * All expired entries are removed from the map prior to determining the
-	 * contains result.
-	 */
-	@Override
-	public boolean containsValue(Object value) {
-		removeAllExpired(now());
-		return super.containsValue(value);
-	}
-
-	/**
-	 * All expired entries are removed from the map prior to returning the entry
-	 * set.
-	 */
-	@Override
-	public Set<Entry<K, V>> entrySet() {
-		removeAllExpired(now());
-		return super.entrySet();
-	}
-
-	/**
-	 * All expired entries are removed from the map prior to returning the entry
-	 * value.
-	 */
-	@Override
-	public V get(Object key) {
-		removeIfExpired(key, now());
-		return super.get(key);
-	}
-
-	/**
-	 * All expired entries are removed from the map prior to determining if it
-	 * is empty.
-	 */
-	@Override
-	public boolean isEmpty() {
-		removeAllExpired(now());
-		return super.isEmpty();
-	}
-
-	/**
-	 * Determines if the given expiration time is less than <code>now</code>
-	 * 
-	 * @param now
-	 *            the time in milliseconds used to compare against the
-	 *            expiration time.
-	 * @param expirationTimeObject
-	 *            the expiration time value retrieved from
-	 *            {@link #expirationMap}, can be null.
-	 * @return <code>true</code> if <code>expirationTimeObject</code> is &ge; 0
-	 *         and <code>expirationTimeObject</code> &lt; <code>now</code>.
-	 *         <code>false</code> otherwise.
-	 */
-	private boolean isExpired(long now, Long expirationTimeObject) {
-		if (expirationTimeObject != null) {
-			long expirationTime = expirationTimeObject.longValue();
-			return (expirationTime >= 0 && now >= expirationTime);
-		}
-		return false;
-	}
-
-	/**
-	 * All expired entries are removed from the map prior to returning the key
-	 * set.
-	 */
-	@Override
-	public Set<K> keySet() {
-		removeAllExpired(now());
-		return super.keySet();
-	}
-
-	/**
-	 * The current time in milliseconds.
-	 */
-	private long now() {
-		return System.currentTimeMillis();
-	}
-
-	@Override
-	public V put(K key, V value) {
-		return put(key, value, now());
-	}
-
-	/**
-	 * Add the given key-value pair to this map as well as recording the entry's
-	 * expiration time based on the current time in milliseconds,
-	 * <code>now</code> and this map's {@link #expiringPolicy}.
-	 */
-	private V put(K key, V value, long now) {
-		// record expiration time of new entry
-		long expirationTime = expiringPolicy.expirationTime(key, value);
-		expirationMap.put(key, Long.valueOf(expirationTime));
-
-		return super.put(key, value);
-	}
-
-	@Override
-	public void putAll(Map<? extends K, ? extends V> mapToCopy) {
-		for (Map.Entry<? extends K, ? extends V> entry : mapToCopy.entrySet()) {
-			put(entry.getKey(), entry.getValue());
-		}
-	}
-
-	/**
-	 * Normal {@link Map#remove(Object)} behavior with the addition of removing
-	 * any expiration entry as well.
-	 */
-	@Override
-	public V remove(Object key) {
-		expirationMap.remove(key);
-		return super.remove(key);
-	}
-
-	/**
-	 * Removes all entries in the map whose expiration time is less than
-	 * <code>now</code>. The exceptions are entries with negative expiration
-	 * times; those entries are never removed.
-	 * 
-	 * @see #isExpired(long, Long)
-	 */
-	private void removeAllExpired(long now) {
-		Iterator<Map.Entry<Object, Long>> iter = expirationMap.entrySet()
-				.iterator();
-		while (iter.hasNext()) {
-			Map.Entry<Object, Long> expirationEntry = iter.next();
-			if (isExpired(now, expirationEntry.getValue())) {
-				// remove entry from collection
-				super.remove(expirationEntry.getKey());
-				// remove entry from expiration map
-				iter.remove();
-			}
-		}
-	}
-
-	/**
-	 * Removes the entry with the given key if the entry's expiration time is
-	 * less than <code>now</code>. If the entry has a negative expiration time,
-	 * the entry is never removed.
-	 */
-	private void removeIfExpired(Object key, long now) {
-		Long expirationTimeObject = expirationMap.get(key);
-		if (isExpired(now, expirationTimeObject)) {
-			remove(key);
-		}
-	}
-
-	/**
-	 * All expired entries are removed from the map prior to returning the size.
-	 */
-	@Override
-	public int size() {
-		removeAllExpired(now());
-		return super.size();
-	}
-
-	/**
-	 * Read the map in using a custom routine.
-	 * 
-	 * @param in
-	 *            the input stream
-	 * @throws IOException
-	 * @throws ClassNotFoundException
-	 */
-	@SuppressWarnings("unchecked")
-	// (1) should only fail if input stream is incorrect
-	private void readObject(ObjectInputStream in) throws IOException,
-			ClassNotFoundException {
-		in.defaultReadObject();
-		map = (Map<K, V>) in.readObject(); // (1)
-	}
-
-	/**
-	 * Write the map out using a custom routine.
-	 * 
-	 * @param out
-	 *            the output stream
-	 * @throws IOException
-	 */
-	private void writeObject(ObjectOutputStream out) throws IOException {
-		out.defaultWriteObject();
-		out.writeObject(map);
-	}
-
-	/**
-	 * All expired entries are removed from the map prior to returning the value
-	 * collection.
-	 */
-	@Override
-	public Collection<V> values() {
-		removeAllExpired(now());
-		return super.values();
-	}
+public class PassiveExpiringMap<K, V>
+    extends AbstractMapDecorator<K, V>
+    implements Serializable {
+
+    /**
+     * A {@link ExpirationPolicy} that returns a expiration time that is a
+     * constant about of time in the future from the current time.
+     * 
+     * @param <K> the type of the keys in the map
+     * @param <V> the type of the values in the map
+     * @since 4.0
+     * @version $Id: $
+     */
+    public static class ConstantTimeToLiveExpirationPolicy<K, V>
+        implements ExpirationPolicy<K, V> {
+
+        /** Serialization version */
+        private static final long serialVersionUID = 1L;
+
+        /** the constant time-to-live value measured in milliseconds. */
+        private final long timeToLiveMillis;
+
+        /**
+         * Default constructor. Constructs a policy using a negative
+         * time-to-live value that results in entries never expiring.
+         */
+        public ConstantTimeToLiveExpirationPolicy() {
+            this(-1L);
+        }
+
+        /**
+         * Construct a policy with the given time-to-live constant measured in
+         * milliseconds. A negative time-to-live value indicates entries never
+         * expire. A zero time-to-live value indicates entries expire (nearly)
+         * immediately.
+         * 
+         * @param timeToLiveMillis the constant amount of time (in milliseconds)
+         *        an entry is available before it expires. A negative value
+         *        results in entries that NEVER expire. A zero value results in
+         *        entries that ALWAYS expire.
+         */
+        public ConstantTimeToLiveExpirationPolicy(long timeToLiveMillis) {
+            super();
+            this.timeToLiveMillis = timeToLiveMillis;
+        }
+
+        /**
+         * Construct a policy with the given time-to-live constant measured in
+         * the given time unit of measure.
+         * 
+         * @param timeToLive the constant amount of time an entry is available
+         *        before it expires. A negative value results in entries that
+         *        NEVER expire. A zero value results in entries that ALWAYS
+         *        expire.
+         * @param timeUnit the unit of time for the <code>timeToLive</code>
+         *        parameter, must not be null.
+         * @throws IllegalArgumentException if the time unit is null.
+         */
+        public ConstantTimeToLiveExpirationPolicy(long timeToLive,
+                                                  TimeUnit timeUnit) {
+            this(validateAndConvertToMillis(timeToLive, TimeUnit.MILLISECONDS));
+        }
+
+        /**
+         * Determine the expiration time for the given key-value entry.
+         * 
+         * @param key the key for the entry (ignored).
+         * @param value the value for the entry (ignored).
+         * @return if {@link #timeToLiveMillis} &ge; 0, an expiration time of
+         *         {@link #timeToLiveMillis} +
+         *         {@link System#currentTimeMillis()} is returned. Otherwise, -1
+         *         is returned indicating the entry never expires.
+         */
+        public long expirationTime(K key, V value) {
+            if (timeToLiveMillis >= 0L) {
+                // avoid numerical overflow
+                long now = System.currentTimeMillis();
+                if (now > Long.MAX_VALUE - timeToLiveMillis) {
+                    // expiration would be greater than Long.MAX_VALUE
+                    // never expire
+                    return -1;
+                }
+
+                // timeToLiveMillis in the future
+                return now + timeToLiveMillis;
+            }
+
+            // never expire
+            return -1L;
+        }
+    }
+
+    /**
+     * A policy to determine the expiration time for key-value entries.
+     * 
+     * @param <K> the key object type.
+     * @param <V> the value object type
+     * @since 4.0
+     * @version $Id: $
+     */
+    public static interface ExpirationPolicy<K, V>
+        extends Serializable {
+
+        /**
+         * Determine the expiration time for the given key-value entry.
+         * 
+         * @param key the key for the entry.
+         * @param value the value for the entry.
+         * @return the expiration time value measured in milliseconds. A
+         *         negative return value indicates the entry never expires.
+         */
+        long expirationTime(K key, V value);
+    }
+
+    /** Serialization version */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * First validate the input parameters. If the parameters are valid, convert
+     * the given time measured in the given units to the same time measured in
+     * milliseconds. If the parameters are invalid, an
+     * {@link IllegalArgumentException} is thrown.
+     * 
+     * @param timeToLive the constant amount of time an entry is available
+     *        before it expires. A negative value results in entries that NEVER
+     *        expire. A zero value results in entries that ALWAYS expire.
+     * @param timeUnit the unit of time for the <code>timeToLive</code>
+     *        parameter, must not be null.
+     * @throws IllegalArgumentException if the time unit is null.
+     */
+    private static long validateAndConvertToMillis(long timeToLive,
+                                                   TimeUnit timeUnit) {
+        if (timeUnit == null) {
+            throw new IllegalArgumentException("Time unit must not be null");
+        }
+        return timeUnit.convert(timeToLive, TimeUnit.MILLISECONDS);
+    }
+
+    /** map used to manage expiration times for the actual map entries. */
+    private final Map<Object, Long> expirationMap = new HashMap<Object, Long>();
+
+    /** the policy used to determine time-to-live values for map entries. */
+    private final ExpirationPolicy<K, V> expiringPolicy;
+
+    /**
+     * Default constructor. Constructs a map decorator that results in entries
+     * NEVER expiring.
+     */
+    public PassiveExpiringMap() {
+        this(-1L);
+    }
+
+    /**
+     * Construct a map decorator using the given expiration policy to determine
+     * expiration times.
+     * 
+     * @param expiringPolicy the policy used to determine expiration times of
+     *        entries as they are added.
+     */
+    public PassiveExpiringMap(ExpirationPolicy<K, V> expiringPolicy) {
+        this(expiringPolicy, new HashMap<K, V>());
+    }
+
+    /**
+     * Construct a map decorator that decorates the given map and uses the given
+     * expiration policy to determine expiration times. If there are any
+     * elements already in the map being decorated, they will NEVER expire
+     * unless they are replaced.
+     * 
+     * @param expiringPolicy the policy used to determine expiration times of
+     *        entries as they are added.
+     * @param map the map to decorate, must not be null.
+     * @throws IllegalArgumentException if the map is null.
+     */
+    public PassiveExpiringMap(ExpirationPolicy<K, V> expiringPolicy,
+                              Map<K, V> map) {
+        super(map);
+        if (expiringPolicy == null) {
+            throw new IllegalArgumentException("Policy must not be null.");
+        }
+        this.expiringPolicy = expiringPolicy;
+    }
+
+    /**
+     * Construct a map decorator that decorates the given map using the given
+     * time-to-live value measured in milliseconds to create and use a
+     * {@link ConstantTimeToLiveExpirationPolicy} expiration policy.
+     * 
+     * @param timeToLiveMillis the constant amount of time (in milliseconds) an
+     *        entry is available before it expires. A negative value results in
+     *        entries that NEVER expire. A zero value results in entries that
+     *        ALWAYS expire.
+     */
+    public PassiveExpiringMap(long timeToLiveMillis) {
+        this(new ConstantTimeToLiveExpirationPolicy<K, V>(timeToLiveMillis),
+             new HashMap<K, V>());
+    }
+
+    /**
+     * Construct a map decorator using the given time-to-live value measured in
+     * milliseconds to create and use a
+     * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. If there
+     * are any elements already in the map being decorated, they will NEVER
+     * expire unless they are replaced.
+     * 
+     * @param timeToLiveMillis the constant amount of time (in milliseconds) an
+     *        entry is available before it expires. A negative value results in
+     *        entries that NEVER expire. A zero value results in entries that
+     *        ALWAYS expire.
+     * @param map the map to decorate, must not be null.
+     * @throws IllegalArgumentException if the map is null.
+     */
+    public PassiveExpiringMap(long timeToLiveMillis, Map<K, V> map) {
+        this(new ConstantTimeToLiveExpirationPolicy<K, V>(timeToLiveMillis),
+             map);
+    }
+
+    /**
+     * Construct a map decorator using the given time-to-live value measured in
+     * the given time units of measure to create and use a
+     * {@link ConstantTimeToLiveExpirationPolicy} expiration policy.
+     * 
+     * @param timeToLive the constant amount of time an entry is available
+     *        before it expires. A negative value results in entries that NEVER
+     *        expire. A zero value results in entries that ALWAYS expire.
+     * @param timeUnit the unit of time for the <code>timeToLive</code>
+     *        parameter, must not be null.
+     * @throws IllegalArgumentException if the time unit is null.
+     */
+    public PassiveExpiringMap(long timeToLive, TimeUnit timeUnit) {
+        this(validateAndConvertToMillis(timeToLive, timeUnit));
+    }
+
+    /**
+     * Construct a map decorator that decorates the given map using the given
+     * time-to-live value measured in the given time units of measure to create
+     * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. This policy
+     * is used to determine expiration times. If there are any elements already
+     * in the map being decorated, they will NEVER expire unless they are
+     * replaced.
+     * 
+     * @param timeToLive the constant amount of time an entry is available
+     *        before it expires. A negative value results in entries that NEVER
+     *        expire. A zero value results in entries that ALWAYS expire.
+     * @param timeUnit the unit of time for the <code>timeToLive</code>
+     *        parameter, must not be null.
+     * @throws IllegalArgumentException if the time unit is null.
+     * @param map the map to decorate, must not be null.
+     * @throws IllegalArgumentException if the map is null.
+     */
+    public PassiveExpiringMap(long timeToLive, TimeUnit timeUnit, Map<K, V> map) {
+        this(validateAndConvertToMillis(timeToLive, timeUnit), map);
+    }
+
+    /**
+     * Constructs a map decorator that decorates the given map and results in
+     * entries NEVER expiring. If there are any elements already in the map
+     * being decorated, they also will NEVER expire.
+     * 
+     * @param map the map to decorate, must not be null.
+     * @throws IllegalArgumentException if the map is null.
+     */
+    public PassiveExpiringMap(Map<K, V> map) {
+        this(-1L, map);
+    }
+
+    /**
+     * Normal {@link Map#clear()} behavior with the addition of clearing all
+     * expiration entries as well.
+     */
+    @Override
+    public void clear() {
+        super.clear();
+        expirationMap.clear();
+    }
+
+    /**
+     * All expired entries are removed from the map prior to determining the
+     * contains result.
+     */
+    @Override
+    public boolean containsKey(Object key) {
+        removeIfExpired(key, now());
+        return super.containsKey(key);
+    }
+
+    /**
+     * All expired entries are removed from the map prior to determining the
+     * contains result.
+     */
+    @Override
+    public boolean containsValue(Object value) {
+        removeAllExpired(now());
+        return super.containsValue(value);
+    }
+
+    /**
+     * All expired entries are removed from the map prior to returning the entry
+     * set.
+     */
+    @Override
+    public Set<Entry<K, V>> entrySet() {
+        removeAllExpired(now());
+        return super.entrySet();
+    }
+
+    /**
+     * All expired entries are removed from the map prior to returning the entry
+     * value.
+     */
+    @Override
+    public V get(Object key) {
+        removeIfExpired(key, now());
+        return super.get(key);
+    }
+
+    /**
+     * All expired entries are removed from the map prior to determining if it
+     * is empty.
+     */
+    @Override
+    public boolean isEmpty() {
+        removeAllExpired(now());
+        return super.isEmpty();
+    }
+
+    /**
+     * Determines if the given expiration time is less than <code>now</code>
+     * 
+     * @param now the time in milliseconds used to compare against the
+     *        expiration time.
+     * @param expirationTimeObject the expiration time value retrieved from
+     *        {@link #expirationMap}, can be null.
+     * @return <code>true</code> if <code>expirationTimeObject</code> is &ge; 0
+     *         and <code>expirationTimeObject</code> &lt; <code>now</code>.
+     *         <code>false</code> otherwise.
+     */
+    private boolean isExpired(long now, Long expirationTimeObject) {
+        if (expirationTimeObject != null) {
+            long expirationTime = expirationTimeObject.longValue();
+            return (expirationTime >= 0 && now >= expirationTime);
+        }
+        return false;
+    }
+
+    /**
+     * All expired entries are removed from the map prior to returning the key
+     * set.
+     */
+    @Override
+    public Set<K> keySet() {
+        removeAllExpired(now());
+        return super.keySet();
+    }
+
+    /**
+     * The current time in milliseconds.
+     */
+    private long now() {
+        return System.currentTimeMillis();
+    }
+
+    @Override
+    public V put(K key, V value) {
+        return put(key, value, now());
+    }
+
+    /**
+     * Add the given key-value pair to this map as well as recording the entry's
+     * expiration time based on the current time in milliseconds,
+     * <code>now</code> and this map's {@link #expiringPolicy}.
+     */
+    private V put(K key, V value, long now) {
+        // record expiration time of new entry
+        long expirationTime = expiringPolicy.expirationTime(key, value);
+        expirationMap.put(key, Long.valueOf(expirationTime));
+
+        return super.put(key, value);
+    }
+
+    @Override
+    public void putAll(Map<? extends K, ? extends V> mapToCopy) {
+        for (Map.Entry<? extends K, ? extends V> entry : mapToCopy.entrySet()) {
+            put(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
+     * Normal {@link Map#remove(Object)} behavior with the addition of removing
+     * any expiration entry as well.
+     */
+    @Override
+    public V remove(Object key) {
+        expirationMap.remove(key);
+        return super.remove(key);
+    }
+
+    /**
+     * Removes all entries in the map whose expiration time is less than
+     * <code>now</code>. The exceptions are entries with negative expiration
+     * times; those entries are never removed.
+     * 
+     * @see #isExpired(long, Long)
+     */
+    private void removeAllExpired(long now) {
+        Iterator<Map.Entry<Object, Long>> iter = expirationMap.entrySet()
+            .iterator();
+        while (iter.hasNext()) {
+            Map.Entry<Object, Long> expirationEntry = iter.next();
+            if (isExpired(now, expirationEntry.getValue())) {
+                // remove entry from collection
+                super.remove(expirationEntry.getKey());
+                // remove entry from expiration map
+                iter.remove();
+            }
+        }
+    }
+
+    /**
+     * Removes the entry with the given key if the entry's expiration time is
+     * less than <code>now</code>. If the entry has a negative expiration time,
+     * the entry is never removed.
+     */
+    private void removeIfExpired(Object key, long now) {
+        Long expirationTimeObject = expirationMap.get(key);
+        if (isExpired(now, expirationTimeObject)) {
+            remove(key);
+        }
+    }
+
+    /**
+     * All expired entries are removed from the map prior to returning the size.
+     */
+    @Override
+    public int size() {
+        removeAllExpired(now());
+        return super.size();
+    }
+
+    /**
+     * Read the map in using a custom routine.
+     * 
+     * @param in the input stream
+     * @throws IOException
+     * @throws ClassNotFoundException
+     */
+    @SuppressWarnings("unchecked")
+    // (1) should only fail if input stream is incorrect
+    private void readObject(ObjectInputStream in)
+        throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        map = (Map<K, V>) in.readObject(); // (1)
+    }
+
+    /**
+     * Write the map out using a custom routine.
+     * 
+     * @param out the output stream
+     * @throws IOException
+     */
+    private void writeObject(ObjectOutputStream out)
+        throws IOException {
+        out.defaultWriteObject();
+        out.writeObject(map);
+    }
+
+    /**
+     * All expired entries are removed from the map prior to returning the value
+     * collection.
+     */
+    @Override
+    public Collection<V> values() {
+        removeAllExpired(now());
+        return super.values();
+    }
 }

Modified: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java?rev=1377492&r1=1377491&r2=1377492&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java (original)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java Sun Aug 26 19:35:45 2012
@@ -9,199 +9,201 @@ import junit.framework.Test;
 import org.apache.commons.collections.BulkTest;
 import org.apache.commons.collections.map.PassiveExpiringMap.ExpirationPolicy;
 
-public class TestPassiveExpiringMap<K, V> extends AbstractTestMap<K, V> {
+public class TestPassiveExpiringMap<K, V>
+    extends AbstractTestMap<K, V> {
 
-	private static class TestExpirationPolicy implements
-			ExpirationPolicy<Integer, String> {
+    private static class TestExpirationPolicy
+        implements ExpirationPolicy<Integer, String> {
 
-		private static final long serialVersionUID = 1L;
+        private static final long serialVersionUID = 1L;
 
-		public long expirationTime(Integer key, String value) {
-			// odd keys expire immediately, even keys never expire
-			if (key == null) {
-				return 0;
-			}
-
-			if (key.intValue() % 2 == 0) {
-				return -1;
-			}
-
-			return 0;
-		}
-	}
-
-	public static Test suite() {
-		return BulkTest.makeSuite(TestPassiveExpiringMap.class);
-	}
-
-	public TestPassiveExpiringMap(String testName) {
-		super(testName);
-	}
-
-	// public void testCreate() throws Exception {
-	// writeExternalFormToDisk((java.io.Serializable) makeObject(),
-	// "PassiveExpiringMap.emptyCollection.version4.obj");
-	//
-	// writeExternalFormToDisk((java.io.Serializable) makeFullMap(),
-	// "PassiveExpiringMap.fullCollection.version4.obj");
-	// }
-
-	@Override
-	public String getCompatibilityVersion() {
-		return "4";
-	}
-
-	private Map<Integer, String> makeDecoratedTestMap() {
-		Map<Integer, String> m = new HashMap<Integer, String>();
-		m.put(Integer.valueOf(1), "one");
-		m.put(Integer.valueOf(2), "two");
-		m.put(Integer.valueOf(3), "three");
-		m.put(Integer.valueOf(4), "four");
-		m.put(Integer.valueOf(5), "five");
-		m.put(Integer.valueOf(6), "six");
-		return new PassiveExpiringMap<Integer, String>(
-				new TestExpirationPolicy(), m);
-	}
-
-	@Override
-	public Map<K, V> makeObject() {
-		return new PassiveExpiringMap<K, V>();
-	}
-
-	private Map<Integer, String> makeTestMap() {
-		Map<Integer, String> m = new PassiveExpiringMap<Integer, String>(
-				new TestExpirationPolicy());
-		m.put(Integer.valueOf(1), "one");
-		m.put(Integer.valueOf(2), "two");
-		m.put(Integer.valueOf(3), "three");
-		m.put(Integer.valueOf(4), "four");
-		m.put(Integer.valueOf(5), "five");
-		m.put(Integer.valueOf(6), "six");
-		return m;
-	}
-
-	public void testConstructors() {
-		try {
-			Map<String, String> map = null;
-			new PassiveExpiringMap<String, String>(map);
-			fail("constructor - exception should have been thrown.");
-		} catch (IllegalArgumentException ex) {
-			// success
-		}
-
-		try {
-			ExpirationPolicy<String, String> policy = null;
-			new PassiveExpiringMap<String, String>(policy);
-			fail("constructor - exception should have been thrown.");
-		} catch (IllegalArgumentException ex) {
-			// success
-		}
-
-		try {
-			TimeUnit unit = null;
-			new PassiveExpiringMap<String, String>(10L, unit);
-			fail("constructor - exception should have been thrown.");
-		} catch (IllegalArgumentException ex) {
-			// success
-		}
-	}
-
-	public void testContainsKey() {
-		Map<Integer, String> m = makeTestMap();
-		assertFalse(m.containsKey(Integer.valueOf(1)));
-		assertFalse(m.containsKey(Integer.valueOf(3)));
-		assertFalse(m.containsKey(Integer.valueOf(5)));
-		assertTrue(m.containsKey(Integer.valueOf(2)));
-		assertTrue(m.containsKey(Integer.valueOf(4)));
-		assertTrue(m.containsKey(Integer.valueOf(6)));
-	}
-
-	public void testContainsValue() {
-		Map<Integer, String> m = makeTestMap();
-		assertFalse(m.containsValue("one"));
-		assertFalse(m.containsValue("three"));
-		assertFalse(m.containsValue("five"));
-		assertTrue(m.containsValue("two"));
-		assertTrue(m.containsValue("four"));
-		assertTrue(m.containsValue("six"));
-	}
-
-	public void testDecoratedMap() {
-		// entries shouldn't expire
-		Map<Integer, String> m = makeDecoratedTestMap();
-		assertEquals(6, m.size());
-		assertEquals("one", m.get(Integer.valueOf(1)));
-
-		// removing a single item shouldn't affect any other items
-		assertEquals("two", m.get(Integer.valueOf(2)));
-		m.remove(Integer.valueOf(2));
-		assertEquals(5, m.size());
-		assertEquals("one", m.get(Integer.valueOf(1)));
-		assertNull(m.get(Integer.valueOf(2)));
-
-		// adding a single, even item shouldn't affect any other items
-		assertNull(m.get(Integer.valueOf(2)));
-		m.put(Integer.valueOf(2), "two");
-		assertEquals(6, m.size());
-		assertEquals("one", m.get(Integer.valueOf(1)));
-		assertEquals("two", m.get(Integer.valueOf(2)));
-
-		// adding a single, odd item (one that expires) shouldn't affect any
-		// other items
-		// put the entry expires immediately
-		m.put(Integer.valueOf(1), "one-one");
-		assertEquals(5, m.size());
-		assertNull(m.get(Integer.valueOf(1)));
-		assertEquals("two", m.get(Integer.valueOf(2)));
-	}
-
-	public void testEntrySet() {
-		Map<Integer, String> m = makeTestMap();
-		assertEquals(3, m.entrySet().size());
-	}
-
-	public void testGet() {
-		Map<Integer, String> m = makeTestMap();
-		assertNull(m.get(Integer.valueOf(1)));
-		assertEquals("two", m.get(Integer.valueOf(2)));
-		assertNull(m.get(Integer.valueOf(3)));
-		assertEquals("four", m.get(Integer.valueOf(4)));
-		assertNull(m.get(Integer.valueOf(5)));
-		assertEquals("six", m.get(Integer.valueOf(6)));
-	}
-
-	public void testIsEmpty() {
-		Map<Integer, String> m = makeTestMap();
-		assertFalse(m.isEmpty());
-
-		// remove just evens
-		m = makeTestMap();
-		m.remove(Integer.valueOf(2));
-		m.remove(Integer.valueOf(4));
-		m.remove(Integer.valueOf(6));
-		assertTrue(m.isEmpty());
-	}
-
-	public void testKeySet() {
-		Map<Integer, String> m = makeTestMap();
-		assertEquals(3, m.keySet().size());
-	}
-
-	public void testSize() {
-		Map<Integer, String> m = makeTestMap();
-		assertEquals(3, m.size());
-	}
-
-	public void testValues() {
-		Map<Integer, String> m = makeTestMap();
-		assertEquals(3, m.values().size());
-	}
-
-	public void testZeroTimeToLive() {
-		// item should not be available
-		PassiveExpiringMap<String, String> m = new PassiveExpiringMap<String, String>(
-				0L);
-		m.put("a", "b");
-		assertNull(m.get("a"));
-	}
+        public long expirationTime(Integer key, String value) {
+            // odd keys expire immediately, even keys never expire
+            if (key == null) {
+                return 0;
+            }
+
+            if (key.intValue() % 2 == 0) {
+                return -1;
+            }
+
+            return 0;
+        }
+    }
+
+    public static Test suite() {
+        return BulkTest.makeSuite(TestPassiveExpiringMap.class);
+    }
+
+    public TestPassiveExpiringMap(String testName) {
+        super(testName);
+    }
+
+    // public void testCreate() throws Exception {
+    // writeExternalFormToDisk((java.io.Serializable) makeObject(),
+    // "PassiveExpiringMap.emptyCollection.version4.obj");
+    //
+    // writeExternalFormToDisk((java.io.Serializable) makeFullMap(),
+    // "PassiveExpiringMap.fullCollection.version4.obj");
+    // }
+
+    @Override
+    public String getCompatibilityVersion() {
+        return "4";
+    }
+
+    private Map<Integer, String> makeDecoratedTestMap() {
+        Map<Integer, String> m = new HashMap<Integer, String>();
+        m.put(Integer.valueOf(1), "one");
+        m.put(Integer.valueOf(2), "two");
+        m.put(Integer.valueOf(3), "three");
+        m.put(Integer.valueOf(4), "four");
+        m.put(Integer.valueOf(5), "five");
+        m.put(Integer.valueOf(6), "six");
+        return new PassiveExpiringMap<Integer, String>(
+                                                       new TestExpirationPolicy(),
+                                                       m);
+    }
+
+    @Override
+    public Map<K, V> makeObject() {
+        return new PassiveExpiringMap<K, V>();
+    }
+
+    private Map<Integer, String> makeTestMap() {
+        Map<Integer, String> m = new PassiveExpiringMap<Integer, String>(
+                                                                         new TestExpirationPolicy());
+        m.put(Integer.valueOf(1), "one");
+        m.put(Integer.valueOf(2), "two");
+        m.put(Integer.valueOf(3), "three");
+        m.put(Integer.valueOf(4), "four");
+        m.put(Integer.valueOf(5), "five");
+        m.put(Integer.valueOf(6), "six");
+        return m;
+    }
+
+    public void testConstructors() {
+        try {
+            Map<String, String> map = null;
+            new PassiveExpiringMap<String, String>(map);
+            fail("constructor - exception should have been thrown.");
+        } catch (IllegalArgumentException ex) {
+            // success
+        }
+
+        try {
+            ExpirationPolicy<String, String> policy = null;
+            new PassiveExpiringMap<String, String>(policy);
+            fail("constructor - exception should have been thrown.");
+        } catch (IllegalArgumentException ex) {
+            // success
+        }
+
+        try {
+            TimeUnit unit = null;
+            new PassiveExpiringMap<String, String>(10L, unit);
+            fail("constructor - exception should have been thrown.");
+        } catch (IllegalArgumentException ex) {
+            // success
+        }
+    }
+
+    public void testContainsKey() {
+        Map<Integer, String> m = makeTestMap();
+        assertFalse(m.containsKey(Integer.valueOf(1)));
+        assertFalse(m.containsKey(Integer.valueOf(3)));
+        assertFalse(m.containsKey(Integer.valueOf(5)));
+        assertTrue(m.containsKey(Integer.valueOf(2)));
+        assertTrue(m.containsKey(Integer.valueOf(4)));
+        assertTrue(m.containsKey(Integer.valueOf(6)));
+    }
+
+    public void testContainsValue() {
+        Map<Integer, String> m = makeTestMap();
+        assertFalse(m.containsValue("one"));
+        assertFalse(m.containsValue("three"));
+        assertFalse(m.containsValue("five"));
+        assertTrue(m.containsValue("two"));
+        assertTrue(m.containsValue("four"));
+        assertTrue(m.containsValue("six"));
+    }
+
+    public void testDecoratedMap() {
+        // entries shouldn't expire
+        Map<Integer, String> m = makeDecoratedTestMap();
+        assertEquals(6, m.size());
+        assertEquals("one", m.get(Integer.valueOf(1)));
+
+        // removing a single item shouldn't affect any other items
+        assertEquals("two", m.get(Integer.valueOf(2)));
+        m.remove(Integer.valueOf(2));
+        assertEquals(5, m.size());
+        assertEquals("one", m.get(Integer.valueOf(1)));
+        assertNull(m.get(Integer.valueOf(2)));
+
+        // adding a single, even item shouldn't affect any other items
+        assertNull(m.get(Integer.valueOf(2)));
+        m.put(Integer.valueOf(2), "two");
+        assertEquals(6, m.size());
+        assertEquals("one", m.get(Integer.valueOf(1)));
+        assertEquals("two", m.get(Integer.valueOf(2)));
+
+        // adding a single, odd item (one that expires) shouldn't affect any
+        // other items
+        // put the entry expires immediately
+        m.put(Integer.valueOf(1), "one-one");
+        assertEquals(5, m.size());
+        assertNull(m.get(Integer.valueOf(1)));
+        assertEquals("two", m.get(Integer.valueOf(2)));
+    }
+
+    public void testEntrySet() {
+        Map<Integer, String> m = makeTestMap();
+        assertEquals(3, m.entrySet().size());
+    }
+
+    public void testGet() {
+        Map<Integer, String> m = makeTestMap();
+        assertNull(m.get(Integer.valueOf(1)));
+        assertEquals("two", m.get(Integer.valueOf(2)));
+        assertNull(m.get(Integer.valueOf(3)));
+        assertEquals("four", m.get(Integer.valueOf(4)));
+        assertNull(m.get(Integer.valueOf(5)));
+        assertEquals("six", m.get(Integer.valueOf(6)));
+    }
+
+    public void testIsEmpty() {
+        Map<Integer, String> m = makeTestMap();
+        assertFalse(m.isEmpty());
+
+        // remove just evens
+        m = makeTestMap();
+        m.remove(Integer.valueOf(2));
+        m.remove(Integer.valueOf(4));
+        m.remove(Integer.valueOf(6));
+        assertTrue(m.isEmpty());
+    }
+
+    public void testKeySet() {
+        Map<Integer, String> m = makeTestMap();
+        assertEquals(3, m.keySet().size());
+    }
+
+    public void testSize() {
+        Map<Integer, String> m = makeTestMap();
+        assertEquals(3, m.size());
+    }
+
+    public void testValues() {
+        Map<Integer, String> m = makeTestMap();
+        assertEquals(3, m.values().size());
+    }
+
+    public void testZeroTimeToLive() {
+        // item should not be available
+        PassiveExpiringMap<String, String> m = new PassiveExpiringMap<String, String>(
+                                                                                      0L);
+        m.put("a", "b");
+        assertNull(m.get("a"));
+    }
 }



Mime
View raw message