/*
* This file is part of JGAP.
*
* JGAP offers a dual license model containing the LGPL as well as the MPL.
*
* For licensing information please see the file license.txt included with JGAP
* or have a look at the top of class org.jgap.Chromosome which representatively
* includes the JGAP license policy applicable for any file delivered with JGAP.
*/
package org.jgap.audit;
import java.io.*;
import java.util.*;
import org.jgap.util.*;
/**
* A collection of (key, value) tupels
*
* @author Klaus Meffert
* @since 2.3
*/
public class KeyedValues
implements ICloneable, Serializable {
/** String containing the CVS revision. Read out via reflection!*/
private static final String CVS_REVISION = "$Revision: 1.7 $";
/** Data storage */
private List m_data;
/**
* Creates a new collection (initially empty).
*
* @author Klaus Meffert
* @since 2.3
*/
public KeyedValues() {
m_data = Collections.synchronizedList(new ArrayList());
}
/**
* @return number of items in the collection
*
* @author Klaus Meffert
* @since 2.3
*/
public int size() {
return m_data.size();
}
/**
* @param a_index the index of the item to return the value for
* @return the value at given index
*
* @author Klaus Meffert
* @since 2.3
*/
public Number getValue(final int a_index) {
Number result;
final KeyedValue kval = (KeyedValue) m_data.get(a_index);
if (kval != null) {
result = kval.getValue();
}
else {
result = null;
}
return result;
}
/**
* @param a_index the item index to retrieve the key for, starting at 0
*
* @return the row key for item at given index
*
* @author Klaus Meffert
* @since 2.3
*/
public Comparable getKey(final int a_index) {
Comparable result;
final KeyedValue item = (KeyedValue) m_data.get(a_index);
if (item != null) {
result = item.getKey();
}
else {
result = null;
}
return result;
}
/**
* @param a_key the key to search for
*
* @return index for a given key or -1 if the key is not found
*
* @author Klaus Meffert
* @since 2.3
*/
public int getIndex(final Comparable a_key) {
int i = 0;
final Iterator iterator = m_data.iterator();
while (iterator.hasNext()) {
final KeyedValue kv = (KeyedValue) iterator.next();
if (kv.getKey() != null) {
if (kv.getKey().equals(a_key)) {
return i;
}
}
else {
if (a_key == null) {
return i;
}
}
i++;
}
// key not found
return -1;
}
/**
* Returns the keys for the values in the collection
*
* @return The keys (never null)
*
* @author Klaus Meffert
* @since 2.3
*/
public List getKeys() {
final List result = new java.util.ArrayList();
final Iterator iterator = m_data.iterator();
while (iterator.hasNext()) {
final KeyedValue kv = (KeyedValue) iterator.next();
result.add(kv.getKey());
}
return result;
}
/**
* Returns the value for a given key. For unknown keys, null is returned
*
* @param a_key the key
*
* @return the value for the key
*
* @author Klaus Meffert
* @since 2.3
*/
public Number getValue(final Comparable a_key) {
Number result;
final int index = getIndex(a_key);
if (index >= 0) {
result = getValue(index);
}
else {
result = null;
}
return result;
}
/**
* Updates an existing value, or adds a new value to the collection
*
* @param a_key the key
* @param a_value the value
*
* @author Klaus Meffert
* @since 2.3
*/
public void setValue(final Comparable a_key, final Number a_value) {
final int keyIndex = getIndex(a_key);
if (keyIndex >= 0) {
final KeyedValue kv = (KeyedValue) m_data.get(keyIndex);
kv.setValue(a_value);
}
else {
final KeyedValue kv = new KeyedValue(a_key, a_value);
m_data.add(kv);
}
}
/**
* Tests if this object is equal to another
*
* @param a_obj the other object
*
* @return true: this object is equal to the other one
*
* @author Klaus Meffert
* @since 2.3
*/
public boolean equals(final Object a_obj) {
if (a_obj == null) {
return false;
}
if (a_obj == this) {
return true;
}
if (! (a_obj instanceof KeyedValues)) {
return false;
}
final KeyedValues kvs = (KeyedValues) a_obj;
final int count = size();
if (count != kvs.size()) {
return false;
}
for (int i = 0; i < count; i++) {
final Comparable k1 = getKey(i);
final Comparable k2 = kvs.getKey(i);
if (!k1.equals(k2)) {
return false;
}
final Number v1 = getValue(i);
final Number v2 = kvs.getValue(i);
if (v1 == null) {
if (v2 != null) {
return false;
}
}
else {
if (!v1.equals(v2)) {
return false;
}
}
}
return true;
}
/**
* @return hash code of the instance
*
* @author Klaus Meffert
* @since 2.3
*/
public int hashCode() {
if (m_data.size() == 0) {
return -29;
}
else {
return m_data.hashCode();
}
}
/**
* @return clone of the current instance
*
* @author Klaus Meffert
* @since 2.3
*/
public Object clone() {
try {
final KeyedValues clone = (KeyedValues)super.clone();
clone.m_data = Collections.synchronizedList(new ArrayList());
final Iterator iterator = m_data.iterator();
while (iterator.hasNext()) {
final KeyedValue kv = (KeyedValue) iterator.next();
clone.m_data.add(kv.clone());
}
return clone;
} catch (CloneNotSupportedException cex) {
throw new CloneException(cex);
}
}
}