mq5.0-source.main.comm-util.src.main.java.com.sun.messaging.jmq.util.lists.SimpleNFLHashMap Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2000-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
/*
* @(#)SimpleNFLHashMap.java 1.16 06/29/07
*/
package com.sun.messaging.jmq.util.lists;
import java.util.*;
import java.lang.ref.*;
public class SimpleNFLHashMap extends HashMap implements EventBroadcaster, Limitable
{
EventBroadcastHelper ebh = new EventBroadcastHelper();
private boolean enforceLimits = true;
private int highWaterCnt = 0;
private long highWaterBytes = 0;
private long largestMessageHighWater = 0;
private float averageCount = 0.0F;
private double averageBytes = 0.0D;
private double messageAverage = 0.0D;
private long numberSamples = 0;
protected int maxCapacity = UNLIMITED_CAPACITY;
protected long maxByteCapacity = UNLIMITED_BYTES;
protected long bytes = 0;
protected long maxBytePerObject = UNLIMITED_BYTES;
Object limitLock = new Object();
private NLMapEntry oldEntry = new NLMapEntry();
private NLMapEntry newEntry = new NLMapEntry();
// resets counters
public void reset() {
highWaterCnt = 0;
highWaterBytes = 0;
largestMessageHighWater = 0;
averageCount = 0.0F;
averageBytes = 0.0D;
messageAverage = 0.0D;
numberSamples = 0;
}
public SimpleNFLHashMap() {
super();
}
Map comparatorSets = null;
Map filterMaps = null;
/**
* removes all entries that match from this
* collection and returns a set of the values that
* were removed.
*
* @param c set of object to remove
* @returns set of values removed
*/
public Set removeAll(Collection c) {
return removeAll(c, null);
}
/**
* removes all entries that match from this
* collection and returns a set of the values that
* were removed.
*
* @param c set of object to remove
* @param r reason we were removed
* @returns set of values removed
*/
public Set removeAll(Collection c, Reason r) {
Iterator itr = c.iterator();
Set s = new HashSet();
while (itr.hasNext()) {
Object mine = itr.next();
Object o =remove(mine, r);
if (o != null)
s.add(o);
}
return s;
}
/**
* Removes all mappings from this map.
*/
public void clear() {
Set m = null;
synchronized (this) {
m = new HashSet(this.keySet());
}
removeAll(m, null);
}
/**
* returns a map that contains all
* objects matching the filter.
* Changes made to this new map will be reflected
* in the original map (and changes in the original
* set will reflect in the map). For example,
* if you remove an object from the original map it
* will also be removed from the new map.
* @param f filter to use when matching
* @returns a map of matching objects
* @see #getAll(Filter)
*/
public Map subMap(Filter f) {
if (true) {
throw new RuntimeException("Implementation not complete");
}
// we need to add support for clearing main map when
// filter map is cleared
Map s = new FilterMap(f);
synchronized (this) {
Iterator itr = entrySet().iterator();
while (itr.hasNext()) {
Map.Entry me = (Map.Entry)itr.next();
if (f == null || f.matches(me.getValue())) {
s.put(me.getKey(), me.getValue());
}
}
if (filterMaps == null)
filterMaps = Collections.synchronizedMap(new WeakValueHashMap("filter"));
filterMaps.put(f,s);
}
return s;
}
/**
* returns the objects in the values of this map ordered
* by the comparator.
* Changes in the original
* map will reflect in the subset).
For example,
* if you remove an object from the original map it
* will also be removed from the subset.
* @param c comparator to use when sorting the objects
* @returns a set ordered by the comparator
*/
public Set subSet(Comparator f) {
Set s = new TreeSet(f);
synchronized (this) {
s.addAll(values());
if (comparatorSets == null)
comparatorSets = Collections.synchronizedMap(new WeakValueHashMap("Comparator"));
comparatorSets.put(f, s);
}
return s;
}
/**
* Copies all of the mappings from the specified map to this map
* These mappings will replace any mappings that
* this map had for any of the keys currently in the specified map.
*
* @param m mappings to be stored in this map.
* @throws NullPointerException if the specified map is null.
* @see #putAll(Map, Reason)
*/
public void putAll(Map m) {
putAll(m, null);
}
/**
* Copies all of the mappings from the specified map to this map
* These mappings will replace any mappings that
* this map had for any of the keys currently in the specified map.
*
* @param m mappings to be stored in this map.
* @param reason why this map was added.
* @throws NullPointerException if the specified map is null.
*/
public void putAll(Map m, Reason r) {
Iterator itr =m.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry me = (Map.Entry)itr.next();
put(me.getKey(), me.getValue(), r);
}
}
/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for this key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated.
* @param value value to be associated with the specified key.
* @return previous value associated with specified key, or null
* if there was no mapping for key. A null return can
* also indicate that the HashMap previously associated
* null with the specified key.
* @see #put(Object, Object, Reason)
*/
public Object put(Object key, Object value) {
return this.put(key,value, null);
}
/**
* Removes the mapping for this key from this map if present.
*
* @param key key whose mapping is to be removed from the map.
* @param reason why this event occurred (used during notification).
* @return previous value associated with specified key, or null
* if there was no mapping for key. A null return can
* also indicate that the map previously associated null
* with the specified key.
* @see #remove(Object, Reason)
*/
public Object remove(Object key) {
return this.remove(key, null);
}
/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for this key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated.
* @param value value to be associated with the specified key.
* @param reason why this value was added.
* @return previous value associated with specified key, or null
* if there was no mapping for key. A null return can
* also indicate that the HashMap previously associated
* null with the specified key.
*/
public Object put(Object key, Object value, Reason reason ) {
return this.put(key, value, reason, true);
}
/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for this key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated.
* @param value value to be associated with the specified key.
* @param reason why this value was added.
* @return previous value associated with specified key, or null
* if there was no mapping for key. A null return can
* also indicate that the HashMap previously associated
* null with the specified key.
*/
public Object put(Object key, Object value, Reason reason, boolean overwrite ) {
return put(key, value, reason, overwrite, true);
}
public Object put(Object key, Object value, Reason reason,
boolean overwrite, boolean checklimit) {
boolean myenforceLimits = enforceLimits && checklimit;
if (hasListeners(EventType.SET_CHANGED_REQUEST))
notifyChange(EventType.SET_CHANGED_REQUEST, null,
value, reason);
if (key == null && value == null) {
throw new NullPointerException("Unable to support null "
+ "keys or values");
}
if (maxByteCapacity != UNLIMITED_BYTES &&
!(value instanceof Sized))
{
throw new ClassCastException(
"Unable to add object not of"
+ " type Sized when byteCapacity has been set");
}
if (maxBytePerObject != UNLIMITED_BYTES &&
!(value instanceof Sized))
{
throw new ClassCastException(
"Unable to add object not of"
+ " type Sized when maxByteSize has been set");
}
long objsize = 0;
if (value instanceof Sized) {
objsize = ((Sized)value).byteSize();
}
long oldBytes = 0;
long newBytes = 0;
int oldSize = 0;
int newSize =0;
boolean wasEmpty = false;
boolean isEmpty = false;
boolean wasFull = false;
boolean isFull = false;
Object ret = null;
synchronized (this) {
oldBytes = bytes;
oldSize = size();
newSize = oldSize +1;
wasEmpty = oldSize == 0;
isEmpty = newSize == 0;
newBytes = bytes + objsize;
wasFull = isFull();
isFull = (maxCapacity > 0 && newSize>= maxCapacity)
|| (maxByteCapacity > 0 &&
newBytes >=maxByteCapacity);
if (myenforceLimits && maxBytePerObject != UNLIMITED_BYTES &&
objsize > maxBytePerObject) {
throw new OutOfLimitsException(
OutOfLimitsException.ITEM_SIZE_EXCEEDED,
new Long(objsize),
new Long(maxBytePerObject));
}
if (myenforceLimits && maxCapacity != UNLIMITED_CAPACITY &&
((maxCapacity -newSize) < 0)) {
throw new OutOfLimitsException(
OutOfLimitsException.CAPACITY_EXCEEDED,
new Integer(newSize),
new Integer(maxCapacity));
}
if (myenforceLimits && maxByteCapacity != UNLIMITED_BYTES &&
((maxByteCapacity -newBytes) < 0)) {
throw new OutOfLimitsException(
OutOfLimitsException.BYTE_CAPACITY_EXCEEDED,
new Long(newBytes),
new Long(maxByteCapacity));
}
// we're good to go
bytes = newBytes;
if (!overwrite && super.get(key) != null) {
throw new IllegalStateException(
"Message exist in the store");
}
ret = super.put(key, value);
if (ret != null && ret instanceof Sized) { // replaced
bytes -= ((Sized)ret).byteSize();
}
}
synchronized (limitLock) {
if (newSize > highWaterCnt) {
highWaterCnt = newSize;
}
if (objsize > largestMessageHighWater) {
largestMessageHighWater = objsize;
}
if (bytes > highWaterBytes) {
highWaterBytes = bytes;
}
averageCount = (((float)numberSamples*averageCount
+ (float)newSize)/((float)numberSamples+1.0F));
averageBytes = ((double)numberSamples*averageBytes
+ (double)newBytes)/((double)numberSamples+1.0D);
messageAverage = ((double)numberSamples*messageAverage
+ (double)objsize)/((double)numberSamples+1.0F);
numberSamples ++;
}
// OK -> deal w/ comparator sets
if (comparatorSets != null && !comparatorSets.isEmpty()) {
synchronized (comparatorSets) {
Iterator itr = comparatorSets.values().iterator();
while (itr.hasNext()) {
Set s = (Set)itr.next();
if (s != null)
synchronized(s) {
s.add(value);
}
else
itr.remove();
}
}
}
// OK -> deal w/ filter sets
if (filterMaps != null && !filterMaps.isEmpty()) {
synchronized (filterMaps) {
Iterator itr = filterMaps.values().iterator();
while (itr.hasNext()) {
FilterMap s = (FilterMap)itr.next();
if (s != null && (s.getFilter() == null ||
s.getFilter().matches(value)))
s.put(key, value);
else if (s == null)
itr.remove();
}
}
}
// notify listeners
if (hasListeners(EventType.SIZE_CHANGED) && oldSize != newSize) {
notifyChange(EventType.SIZE_CHANGED,
new Integer(oldSize),
new Integer(newSize),
reason);
}
if (hasListeners(EventType.BYTES_CHANGED) && oldBytes != newBytes) {
notifyChange(EventType.BYTES_CHANGED,
new Long(oldBytes),
new Long(newBytes),
reason);
}
if (hasListeners(EventType.SET_CHANGED)) {
Object oldv = null;
newEntry.update(key,value);
if (ret != null) {
oldEntry.update(key, ret);
oldv = oldEntry;
}
notifyChange(EventType.SET_CHANGED, oldv,
newEntry, reason);
}
if (hasListeners(EventType.EMPTY) &&
wasEmpty != isEmpty) {
notifyChange(EventType.EMPTY, Boolean.valueOf(wasEmpty),
Boolean.valueOf(isEmpty), reason);
}
if (hasListeners(EventType.FULL) &&
wasFull != isFull)
{
notifyChange(EventType.FULL, Boolean.valueOf(wasFull),
Boolean.valueOf(isFull), reason);
}
return ret;
}
/**
* determines if the map should throw an exeption
* if the size is exceeded, or just call the FULL event
* listeners
* @param b if true, exceptions are thrown when limits are exceeded.
*/
public void enforceLimits(boolean b) {
enforceLimits = b;
}
/**
* returns the current value of enforceLimits
* @returns true if limits are enforces, false otherwise
*/
public boolean getEnforceLimits() {
return enforceLimits;
}
/**
* Returns the value to which the specified key is mapped in this identity
* hash map, or null if the map contains no mapping for this key.
* A return value of null does not necessarily indicate
* that the map contains no mapping for the key; it is also possible that
* the map explicitly maps the key to null. The
* containsKey method may be used to distinguish these two cases.
*
* @param key the key whose associated value is to be returned.
* @return the value to which this map maps the specified key, or
* null if the map contains no mapping for this key.
* @see #put(Object, Object)
*/
public Object get(Object key) {
synchronized (this) {
return super.get(key);
}
}
/**
* Removes the mapping for this key from this map if present.
*
* @param key key whose mapping is to be removed from the map.
* @param reason why this event occurred (used during notification).
* @return previous value associated with specified key, or null
* if there was no mapping for key. A null return can
* also indicate that the map previously associated null
* with the specified key.
*/
public Object remove(Object key, Reason reason) {
return removeWithValue(key, null, null, reason);
}
/**
* @return errValue if expectedValue not null and
* if to be removed value not null and != expectedValue
*/
public Object removeWithValue(Object key, Object expectedValue,
Object errValue, Reason reason) {
Object value = null;
long oldBytes = 0;
long newBytes = 0;
int oldSize = 0;
int newSize =0;
boolean wasEmpty = false;
boolean isEmpty = false;
boolean wasFull = false;
boolean isFull = false;
long objsize = 0;
synchronized (this) {
if (expectedValue != null) {
value = super.get(key);
if (value != null && value != expectedValue) {
return errValue;
}
}
value = super.remove(key);
if (value == null) {
return null;
}
if (value instanceof Sized) {
objsize = ((Sized)value).byteSize();
}
oldBytes = bytes;
oldSize = size() + 1;
newSize = oldSize -1;
wasEmpty = oldSize == 0;
isEmpty = newSize == 0;
newBytes = bytes - objsize;
wasFull = (maxCapacity > 0 && oldSize>= maxCapacity)
|| (maxByteCapacity > 0 &&
oldBytes >=maxByteCapacity);
isFull = (maxCapacity > 0 && newSize>= maxCapacity)
|| (maxByteCapacity > 0 &&
newBytes >=maxByteCapacity);
// we're good to go
bytes = newBytes;
}
if (hasListeners(EventType.SET_CHANGED_REQUEST))
notifyChange(EventType.SET_CHANGED_REQUEST, value,
null, reason);
synchronized (limitLock) {
averageCount = (((float)numberSamples*averageCount
+ (float)newSize)/((float)numberSamples+1.0F));
averageBytes = ((double)numberSamples*averageBytes
+ (double)newBytes)/((double)numberSamples+1.0D);
messageAverage = ((double)numberSamples*messageAverage
+ (double)objsize)/((double)numberSamples+1.0F);
numberSamples ++;
}
// OK -> deal w/ comparator sets
if (comparatorSets != null && !comparatorSets.isEmpty()) {
synchronized (comparatorSets) {
Iterator itr = comparatorSets.values().iterator();
while (itr.hasNext()) {
Set s = (Set)itr.next();
if (s != null)
synchronized(s) {
s.remove(value);
}
else
itr.remove();
}
}
}
// OK -> deal w/ filter sets
if (filterMaps != null && !filterMaps.isEmpty()) {
synchronized (filterMaps) {
Iterator itr = filterMaps.values().iterator();
while (itr.hasNext()) {
Set s = (Set)itr.next();
if (s != null)
s.remove(key);
else
itr.remove();
}
}
}
// notify listeners
if (hasListeners(EventType.SIZE_CHANGED) && oldSize != newSize) {
notifyChange(EventType.SIZE_CHANGED,
new Integer(oldSize),
new Integer(newSize),
reason);
}
if (hasListeners(EventType.BYTES_CHANGED) && oldBytes != newBytes) {
notifyChange(EventType.BYTES_CHANGED,
new Long(oldBytes),
new Long(newBytes),
reason);
}
if (hasListeners(EventType.SET_CHANGED) && value != null) {
Object oldv = oldEntry;
oldEntry.update(key,value);
Map.Entry newv = null;
notifyChange(EventType.SET_CHANGED, oldv,
newv, reason);
}
if (hasListeners(EventType.EMPTY) &&
wasEmpty != isEmpty) {
notifyChange(EventType.EMPTY, Boolean.valueOf(wasEmpty),
Boolean.valueOf(isEmpty), reason);
}
if (hasListeners(EventType.FULL) &&
wasFull != isFull)
{
notifyChange(EventType.FULL, Boolean.valueOf(wasFull),
Boolean.valueOf(isFull), reason);
}
return value;
}
/**
* returns a new map that contains all
* objects matching the filter.
* This new map will not be updated to reflect
* changes in the original set.
* @param f filter to use when matching
* @returns a new map of matching objects
* @see #subMap(Filter)
*/
public Map getAll(Filter f) {
synchronized (this) {
Map m = new HashMap();
Set entrySet = this.entrySet();
Iterator itr = entrySet.iterator();
while(itr.hasNext()) {
Map.Entry e = (Map.Entry)itr.next();
Object o = e.getValue();
if (f == null || f.matches(o)) {
m.put(e.getKey(), o);
}
}
return m;
}
}
// ----------------------------------------------------
// Notification Events
// ----------------------------------------------------
/**
* Request notification when the specific event occurs.
* @param listener object to notify when the event occurs
* @param type event which must occur for notification
* @param userData optional data sent with any notifications
* @return an id associated with this notification
*/
public Object addEventListener(EventListener listener,
EventType type, Object user_data)
{
return ebh.addEventListener(listener, type,
user_data);
}
/**
* Request notification when the specific event occurs AND
* the reason matched the passed in reason.
* @param listener object to notify when the event occurs
* @param type event which must occur for notification
* @param userData optional data sent with any notifications
* @param reason reason which must be associated with the
* event (or null for all events)
* @return an id associated with this notification
*/
public Object addEventListener(EventListener listener,
EventType type, Reason reason,
Object userData)
{
return ebh.addEventListener(listener, type,
reason, userData);
}
/**
* remove the listener registered with the passed in
* id.
* @return the listener which was removed
*/
public Object removeEventListener(Object id)
{
return ebh.removeEventListener(id);
}
protected boolean hasListeners(EventType e) {
return ebh.hasListeners(e);
}
protected void notifyChange(EventType e, Object oldval, Object newval, Reason r) {
ebh.notifyChange(e, r, this, oldval, newval);
}
/**
* sets the maximum size of an entry allowed
* to be added to the collection
* @param bytes maximum number of bytes for
* an object added to the list or
* UNLIMITED_BYTES if there is no limit
*/
public void setMaxByteSize(long bytes){
if (bytes < UNLIMITED_BYTES) {
bytes = UNLIMITED_BYTES;
}
maxBytePerObject=bytes;
}
/**
* returns the maximum size of an entry allowed
* to be added to the collection
* @return maximum number of bytes for an object
* added to the list or
* UNLIMITED_BYTES if there is no limit
*/
public long maxByteSize() { return maxBytePerObject; }
/**
* Sets the capacity (size limit).
*
* @param cnt the capacity for this set (or
* UNLIMITED_CAPACITY if unlimited).
*/
public void setCapacity(int cnt){
if (cnt < UNLIMITED_CAPACITY) {
cnt = UNLIMITED_CAPACITY;
}
if (!hasListeners(EventType.FULL)) {
maxCapacity = cnt;
return;
}
boolean wasFull = false;
boolean isFull = false;
synchronized (this) {
wasFull= isFull();
maxCapacity = cnt;
isFull = isFull();
}
if (wasFull != isFull) {
notifyChange(EventType.FULL, Boolean.valueOf(wasFull),
Boolean.valueOf(isFull), null);
}
}
/**
* Sets the byte capacity. Once the byte capacity
* is set, only objects which implement Sized
* can be added to the class
*
* @param size the byte capacity for this set (or
* UNLIMITED_BYTES if unlimited).
*/
public void setByteCapacity(long size){
if (size < UNLIMITED_BYTES) {
size = UNLIMITED_BYTES;
}
if (!hasListeners(EventType.FULL)) {
maxByteCapacity = size;
return;
}
boolean wasFull = false;
boolean isFull = false;
synchronized (this) {
wasFull= isFull();
maxByteCapacity = size;
isFull = isFull();
}
if (wasFull != isFull) {
notifyChange(EventType.FULL, Boolean.valueOf(wasFull),
Boolean.valueOf(isFull), null);
}
}
/**
* Returns the capacity (count limit) or UNLIMITED_CAPACITY
* if its not set.
*
* @return the capacity of the list
*/
public int capacity(){
return maxCapacity;
}
/**
* Returns the byte capacity (or UNLIMITED_BYTES if its not set).
*
* @return the byte capacity for this set.
*/
public long byteCapacity(){
return maxByteCapacity;
}
/**
* Returns true if either the bytes limit
* or the count limit is set and
* has been reached or exceeded.
*
* @return true if the count limit is set and
* has been reached or exceeded.
*/
public boolean isFull() {
return (maxCapacity > 0 && size()>= maxCapacity)
|| (maxByteCapacity > 0 &&
bytes >=maxByteCapacity);
}
/**
* Returns number of entries remaining in the
* lists to reach full capacity or
* UNLIMITED_CAPACITY if the capacity
* has not been set
*
* @return the amount of free space
*/
public int freeSpace(){
if (maxCapacity == UNLIMITED_CAPACITY)
return UNLIMITED_CAPACITY;
int val = maxCapacity - size();
if (val < 0) return 0;
return val;
}
/**
* Returns the number of bytesremaining in the
* lists to reach full capacity, 0
* if the list is greater than the
* capacity or UNLIMITED_BYTES if
* the capacity has not been set
*
* @return the amount of free space
*/
public long freeBytes(){
if (maxByteCapacity == UNLIMITED_CAPACITY)
return UNLIMITED_CAPACITY;
synchronized (this) {
long val = maxByteCapacity - bytes;
if (val < 0) return 0L;
return val;
}
}
/**
* Returns the number of bytes used by all entries in this set which implement
* Sized. If this
* set contains more than Long.MAX_VALUE elements, returns
* Long.MAX_VALUE.
*
* @return the total bytes of data from all objects implementing
* Sized in this set.
* @see Sized
* @see #size
*/
public long byteSize() {
return bytes;
}
/**
* Returns the number of entries in this collection. If this
* set contains more than Long.MAX_VALUE elements, returns
* Long.MAX_VALUE.
*
* @return the total bytes of data from all objects implementing
* Sized in this set.
* @see Sized
* @see #size
*/
public int size() {
synchronized (this) {
return super.size();
}
}
/**
* Maximum number of messages stored in this
* list at any time since its creation.
*
* @return the highest number of messages this set
* has held since it was created.
*/
public int highWaterCount(){
return highWaterCnt;
}
/**
* Maximum number of bytes stored in this
* list at any time since its creation.
*
* @return the largest size (in bytes) of
* the objects in this list since it was
* created.
*/
public long highWaterBytes(){
return highWaterBytes;
}
/**
* The largest message (which implements Sized)
* which has ever been stored in this list.
*
* @return the number of bytes of the largest
* message ever stored on this list.
*/
public long highWaterLargestMessageBytes(){
return largestMessageHighWater;
}
/**
* Average number of messages stored in this
* list at any time since its creation.
*
* @return the average number of messages this set
* has held since it was created.
*/
public float averageCount(){
return averageCount;
}
/**
* Average number of bytes stored in this
* list at any time since its creation.
*
* @return the largest size (in bytes) of
* the objects in this list since it was
* created.
*/
public double averageBytes(){
return averageBytes;
}
/**
* The average message size (which implements Sized)
* of messages which has been stored in this list.
*
* @return the number of bytes of the average
* message stored on this list.
*/
public double averageMessageBytes() {
return messageAverage;
}
static class NLMapEntry implements Map.Entry
{
Object key = null;
Object value = null;
public NLMapEntry() {
this.key = null;
this.value = null;
}
public void update(Object k, Object v) {
this.key = k;
this.value = v;
}
public boolean equals(Object o) {
if (o instanceof Map.Entry) {
Map.Entry me = (Map.Entry)o;
return (me.getKey() == key ||
(key != null && key.equals(me.getKey())))
&&
(me.getValue() == value ||
(value != null && value.equals(me.getValue())));
}
return false;
}
public Object getKey() {
return key;
}
public Object getValue() {
return value;
}
public int hashCode() {
return key.hashCode();
}
public Object setValue(Object o) {
throw new UnsupportedOperationException(
"Can not set values on the entry");
}
}
}
class FilterMap extends HashMap
{
Filter f = null;
public FilterMap(Filter f) {
this.f = f;
}
public Filter getFilter() {
return f;
}
}