/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.greeks;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import com.opengamma.analytics.financial.pnl.UnderlyingType;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.tuple.Pair;
import com.opengamma.util.tuple.Pairs;
/**
*
*/
public class BucketedGreekResultCollection implements Iterable<Pair<Greek, double[][]>> {
/** The bucketed vega for a strike / time surface */
public static final Greek BUCKETED_VEGA = new Greek(new NthOrderUnderlying(1, UnderlyingType.IMPLIED_VOLATILITY), "Bucketed vega") {
@Override
public <T> T accept(final GreekVisitor<T> visitor) {
throw new UnsupportedOperationException();
}
};
private final Map<Greek, double[][]> _dataMap = new TreeMap<>();
private final double[][] _strikes;
private final double[] _expiries;
private final int _nExpiries;
//TODO change strikes to StrikeType
public BucketedGreekResultCollection(final double[] expiries, final double[][] strikes) {
ArgumentChecker.notNull(expiries, "expiries");
ArgumentChecker.notNull(strikes, "strikes");
_expiries = expiries;
_nExpiries = expiries.length;
_strikes = strikes;
}
public double[][] getBucketedGreeks(final Greek greek) {
ArgumentChecker.notNull(greek, "greek");
return _dataMap.get(greek);
}
public void put(final Greek greek, final double[][] result) {
ArgumentChecker.notNull(greek, "greek");
if (result != null) {
ArgumentChecker.isTrue(result.length == _nExpiries, "Wrong number of expiry buckets; have {}, need {}", result.length, _nExpiries);
for (int i = 0; i < result.length; i++) {
ArgumentChecker.isTrue(result[i].length == _strikes[i].length, "Wrong number of strike buckets; have {}, need {}", result[i].length, _strikes[i].length);
}
}
_dataMap.put(greek, result);
}
public boolean isEmpty() {
return _dataMap.isEmpty();
}
public boolean contains(final Greek greek) {
return _dataMap.containsKey(greek);
}
public int size() {
return _dataMap.size();
}
public Set<Greek> keySet() {
return Collections.unmodifiableSet(_dataMap.keySet());
}
public Collection<double[][]> values() {
return Collections.unmodifiableCollection(_dataMap.values());
}
public double[][] getStrikes() {
return _strikes;
}
public double[] getExpiries() {
return _expiries;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + _dataMap.hashCode();
result = prime * result + Arrays.hashCode(_expiries);
result = prime * result + Arrays.hashCode(_strikes);
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final BucketedGreekResultCollection other = (BucketedGreekResultCollection) obj;
if (!Arrays.equals(_expiries, other._expiries)) {
return false;
}
if (!Arrays.equals(_strikes, other._strikes)) {
return false;
}
if (size() != other.size()) {
return false;
}
for (final Map.Entry<Greek, double[][]> entry : _dataMap.entrySet()) {
if (!other._dataMap.containsKey(entry.getKey())) {
return false;
}
if (!Arrays.deepEquals(entry.getValue(), _dataMap.get(entry.getKey()))) {
return false;
}
}
return true;
}
@Override
public Iterator<Pair<Greek, double[][]>> iterator() {
return new BackingMapGreekIterator(_dataMap.entrySet().iterator());
}
private static class BackingMapGreekIterator implements Iterator<Pair<Greek, double[][]>> {
private final Iterator<Map.Entry<Greek, double[][]>> _backingIterator;
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");
}
}
}