/*
* This file is part of Mockey, a tool for testing application
* interactions over HTTP, with a focus on testing web services,
* specifically web applications that consume XML, JSON, and HTML.
*
* Copyright (C) 2009-2010 Authors:
*
* chad.lafontaine (chad.lafontaine AT gmail DOT com)
* neil.cronin (neil AT rackle DOT com)
* lorin.kobashigawa (lkb AT kgawa DOT com)
* rob.meyer (rob AT bigdis DOT com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
package com.mockey;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.List;
import java.util.Map;
import com.mockey.model.PersistableItem;
/**
* Keeps an ordered map of items, with a key of an number based on 'when defined
* and added to this object'. Sort of like an auto-incrementing column in a db.
* <p>
* So:
* <p>
* <code>
* OrderedMap<MyObj> myMap = new OrderedMap<MyObj>();<br>
* 0 == myMap.save(new MyObj()).getId();<br>
* 1 == myMap.save(new MyObj()).getId();<br>
* 2 == myMap.save(new MyObj()).getId();<br>
* </code>
*
* @author chad.lafontaine
*
*/
public class OrderedMap<T extends PersistableItem> extends ConcurrentHashMap<Long, T> implements Map<Long, T> {
private static final long serialVersionUID = -1654150132938363942L;
private Integer maxSize = null;
/**
* Will save item. If maximum size of this Map is set (non-null, positive),
* this method will purge the oldest value, the value with the smallest key
* value.
*
* @param item
* @return item saved, with ID set.
* @see #getMaxSize()
*/
public PersistableItem save(T item) {
if (item != null) {
if (item.getId() != null) {
this.put(item.getId(), item);
} else {
Long nextNumber = this.getNextValue();
item.setId(nextNumber);
this.put(nextNumber, item);
}
}
if (this.maxSize != null && this.maxSize > 0) {
while (this.size() > this.maxSize) {
Long removeMe = getSmallestValue();
this.remove(removeMe);
}
}
return item;
}
public T get(Object key) {
if (key == null) {
return null;
}
return super.get(key);
}
private Long getSmallestValue() {
Long smallestValue = null;
for (Long key : this.keySet()) {
if (smallestValue == null) {
smallestValue = key;
} else if (key < smallestValue) {
smallestValue = key;
}
}
return smallestValue;
}
private Long getNextValue() {
Long nextValue = new Long(0);
for (Long key : this.keySet()) {
if (key > nextValue) {
nextValue = key;
}
}
nextValue = new Long(nextValue.longValue() + 1);
return nextValue;
}
public List<T> getOrderedList() {
List<Long> orderedListOfKeys = new ArrayList<Long>();
for (Long key : this.keySet()) {
int index = 0;
for (Long current : orderedListOfKeys) {
if (current > key) {
break;
}
index++;
}
orderedListOfKeys.add(index, key);
}
// Ordered key list.
List<T> orderedListOfValues = new ArrayList<T>();
for (Long key : orderedListOfKeys) {
orderedListOfValues.add(this.get(key));
}
return orderedListOfValues;
}
/**
*
* @param maxSize
* @see #getMaxSize()
*/
public void setMaxSize(Integer maxSize) {
this.maxSize = maxSize;
}
/**
* Maximum number of <code>PersistableItem</code> allowed in this ordered
* map. Once this map has reached its limit, if set, it takes a first-in,
* first-out (FIFO) persistence approach, purging the oldest object.
*
* @return null if not set (no size limit), otherwise returns the maximum
* size value.
*/
public Integer getMaxSize() {
return maxSize;
}
}