/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.greeks;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.tuple.Pair;
import com.opengamma.util.tuple.Pairs;
/**
*
*/
public class GreekResultCollection implements Iterable<Pair<Greek, Double>> {
// REVIEW kirk 2010-05-20 -- Ideas for speeding up:
// - For common cases, store SingleGreekResult in a double[], where the indices are ordinals
// for the greek in the enumeration. Super-fast lookup and small objects, but wasted
// space for the common case of one greek in a result collection.
// REVIEW kirk 2010-05-20 -- Does this need a set of fudge converters?
// REVIEW kirk 2010-05-20 -- Is this the best backing map?
// We might not want to use a Map<> at all, but we can't use an EnumMap<>
// as Greek is going to be promoted to an Object from an Enum.
// REVIEW elaine 2010-06-25 Greek is now an Object
/** The backing map */
private final Map<Greek, Double> _backingMap = new TreeMap<>();
/**
* Gets the value of a greek.
* @param greek The greek
* @return the value of the greek
*/
public Double get(final Greek greek) {
if (greek == null) {
return null;
}
return _backingMap.get(greek);
}
/**
* Adds a greek to the map
* @param greek The greek, not null
* @param result The result
*/
public void put(final Greek greek, final Double result) {
ArgumentChecker.notNull(greek, "Greek");
// NOTE kirk 2010-05-21 -- Per Elaine, a null result IS a legitimate result.
// We still put it in the backing map, so that we can tell that a particular
// greek WAS computed, but the result was also NULL.
_backingMap.put(greek, result);
}
/**
* @return true if this collection is empty
*/
public boolean isEmpty() {
return _backingMap.isEmpty();
}
/**
* @param greek The greek
* @return true if this collection contains a value for this greek
*/
public boolean contains(final Greek greek) {
return _backingMap.containsKey(greek);
}
/**
* @return The number of greeks in this collection
*/
public int size() {
return _backingMap.size();
}
/**
* @return All greeks in this collection
*/
public Set<Greek> keySet() {
return _backingMap.keySet();
}
/**
* @return All values of the greeks in this collection
*/
public Collection<Double> values() {
return Collections.unmodifiableCollection(_backingMap.values());
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("GreekResultCollection[");
final List<String> elements = new LinkedList<>();
for (final Map.Entry<Greek, Double> entry : _backingMap.entrySet()) {
final StringBuilder elementSb = new StringBuilder();
elementSb.append(entry.getKey()).append("=").append(entry.getValue());
elements.add(elementSb.toString());
}
sb.append(StringUtils.join(elements, ", "));
sb.append("]");
return sb.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
for (final Map.Entry<Greek, Double> entry : _backingMap.entrySet()) {
result = prime * result + entry.getKey().hashCode();
result = prime * result + entry.getValue().hashCode();
}
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof GreekResultCollection)) {
return false;
}
final GreekResultCollection other = (GreekResultCollection) obj;
// This is really bad and we'll want to change it when we're less reliant on just the backing map.
return ObjectUtils.equals(_backingMap, other._backingMap);
}
@Override
public Iterator<Pair<Greek, Double>> iterator() {
// TODO kirk 2010-05-20 -- This can be dramatically improved if we change the backing map
// to not be a backing map at all.
return new BackingMapGreekIterator(_backingMap.entrySet().iterator());
}
/**
* Iterates over the backing map
*/
protected static class BackingMapGreekIterator implements Iterator<Pair<Greek, Double>> {
/** The backing map iterator */
private final Iterator<Map.Entry<Greek, Double>> _backingIterator;
/**
* @param backingIterator The iterator of the backing map
*/
public BackingMapGreekIterator(final Iterator<Map.Entry<Greek, Double>> backingIterator) {
_backingIterator = backingIterator;
}
@Override
public boolean hasNext() {
return _backingIterator.hasNext();
}
@Override
public Pair<Greek, Double> next() {
final Map.Entry<Greek, Double> nextEntry = _backingIterator.next();
return Pairs.<Greek, Double>of(nextEntry.getKey(), nextEntry.getValue());
}
@Override
public void remove() {
throw new UnsupportedOperationException("Cannot remove from this iterator.");
}
}
}