/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.currency;
import org.fudgemsg.FudgeMsg;
import org.fudgemsg.MutableFudgeMsg;
import org.fudgemsg.mapping.FudgeDeserializer;
import org.fudgemsg.mapping.FudgeSerializer;
import org.fudgemsg.wire.types.FudgeWireType;
import org.springframework.util.ObjectUtils;
import com.opengamma.core.id.ExternalSchemes;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.target.ComputationTargetRequirement;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.id.ExternalId;
import com.opengamma.id.UniqueId;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.Currency;
/**
* Represents a entry within a {@link CurrencyMatrix}.
*/
public abstract class CurrencyMatrixValue {
/**
* A fixed conversion rate from one currency to another.
*/
public static final class CurrencyMatrixFixed extends CurrencyMatrixValue {
private final double _fixedValue;
private CurrencyMatrixFixed(final double fixedValue) {
_fixedValue = fixedValue;
}
@Override
public <T> T accept(final CurrencyMatrixValueVisitor<T> visitor) {
return visitor.visitFixed(this);
}
public double getFixedValue() {
return _fixedValue;
}
@Override
public CurrencyMatrixFixed getReciprocal() {
if (getFixedValue() == 1.0) {
return this;
} else {
return new CurrencyMatrixFixed(1 / getFixedValue());
}
}
@Override
public boolean equals(final Object o) {
if (o == this) {
return true;
}
if (!(o instanceof CurrencyMatrixFixed)) {
return false;
}
return ((CurrencyMatrixFixed) o).getFixedValue() == getFixedValue();
}
@Override
public int hashCode() {
return ObjectUtils.hashCode(getFixedValue());
}
@Override
public String toString() {
return "CurrencyMatrixValue[" + getFixedValue() + "]";
}
}
/**
* A conversion rate from one currency to another supplied by another node in the dependency graph. This might be a live data sourcing function to use current market data, or a calculated value
* based on something else.
*/
public static final class CurrencyMatrixValueRequirement extends CurrencyMatrixValue {
private final ValueRequirement _valueRequirement;
private final boolean _reciprocal;
private CurrencyMatrixValueRequirement(final ValueRequirement valueRequirement, boolean reciprocal) {
_valueRequirement = valueRequirement;
_reciprocal = reciprocal;
}
@Override
public <T> T accept(final CurrencyMatrixValueVisitor<T> visitor) {
return visitor.visitValueRequirement(this);
}
public ValueRequirement getValueRequirement() {
return _valueRequirement;
}
public boolean isReciprocal() {
return _reciprocal;
}
@Override
public CurrencyMatrixValueRequirement getReciprocal() {
return new CurrencyMatrixValueRequirement(getValueRequirement(), !isReciprocal());
}
@Override
public boolean equals(final Object o) {
if (o == this) {
return true;
}
if (!(o instanceof CurrencyMatrixValueRequirement)) {
return false;
}
final CurrencyMatrixValueRequirement oc = (CurrencyMatrixValueRequirement) o;
return getValueRequirement().equals(oc.getValueRequirement()) && (isReciprocal() == oc.isReciprocal());
}
@Override
public int hashCode() {
return getValueRequirement().hashCode() * 17 + ObjectUtils.hashCode(isReciprocal());
}
public MutableFudgeMsg toFudgeMsg(final FudgeSerializer serializer) {
final MutableFudgeMsg msg = serializer.objectToFudgeMsg(getValueRequirement());
msg.add("reciprocal", null, FudgeWireType.BOOLEAN, isReciprocal());
return msg;
}
/**
* Support translation from pre-3044 type specifications, such as CTSpec[PRIMITIVE, BLOOMBERG_TICKER~USD Curncy], to the correct CTReq[PRIMITIVE, BLOOMBERGTICKER~USD Curncy].
*
* @param valueRequirement the possibly legacy specification, not null
* @return the updated specification, not null
* @deprecated shouldn't be relying on this, a configuration database upgrade script to apply the transformation would be better
*/
@Deprecated
private static ValueRequirement plat3044Translate(final ValueRequirement valueRequirement) {
if (valueRequirement.getTargetReference() instanceof ComputationTargetSpecification) {
final ComputationTargetSpecification spec = valueRequirement.getTargetReference().getSpecification();
if (spec.getType().equals(ComputationTargetType.PRIMITIVE)) {
final UniqueId uid = spec.getUniqueId();
if (ExternalSchemes.BLOOMBERG_TICKER.getName().equals(uid.getScheme())) {
return new ValueRequirement(valueRequirement.getValueName(), new ComputationTargetRequirement(spec.getType(), ExternalId.of(ExternalSchemes.BLOOMBERG_TICKER, uid.getValue())),
valueRequirement.getConstraints());
}
}
}
return valueRequirement;
}
public static CurrencyMatrixValueRequirement fromFudgeMsg(final FudgeDeserializer deserializer, final FudgeMsg msg) {
ValueRequirement requirement = deserializer.fudgeMsgToObject(ValueRequirement.class, msg);
return new CurrencyMatrixValueRequirement(plat3044Translate(requirement), msg.getBoolean("reciprocal"));
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("CurrencyMatrixValue[");
sb.append(getValueRequirement().toString());
if (isReciprocal()) {
sb.append(" ^-1");
}
return sb.append("]").toString();
}
}
/**
* A conversion rate from one currency to another via an intermediate currency.
*/
public static final class CurrencyMatrixCross extends CurrencyMatrixValue {
private final Currency _crossCurrency;
private CurrencyMatrixCross(final Currency crossCurrency) {
_crossCurrency = crossCurrency;
}
@Override
public <T> T accept(final CurrencyMatrixValueVisitor<T> visitor) {
return visitor.visitCross(this);
}
public Currency getCrossCurrency() {
return _crossCurrency;
}
@Override
public CurrencyMatrixCross getReciprocal() {
return this;
}
@Override
public boolean equals(final Object o) {
if (o == this) {
return true;
}
if (!(o instanceof CurrencyMatrixCross)) {
return false;
}
return getCrossCurrency().equals(((CurrencyMatrixCross) o).getCrossCurrency());
}
@Override
public int hashCode() {
return getCrossCurrency().hashCode();
}
@Override
public String toString() {
return "CurrencyMatrixValue[" + getCrossCurrency() + "]";
}
}
/**
* Creates a matrix value that is a given constant value.
*
* @param fixedValue the value
* @return the matrix value
*/
public static CurrencyMatrixFixed of(final double fixedValue) {
ArgumentChecker.notZero(fixedValue, 0, "fixedValue");
return new CurrencyMatrixFixed(fixedValue);
}
/**
* Creates a matrix value that is obtained from an arbitrary value produced by the dependency graph. This may be a requirement satisfied by a live data provider or a value calculated by other
* functions.
*
* @param valueRequirement identifies the value to use
* @return the matrix value
*/
public static CurrencyMatrixValueRequirement of(final ValueRequirement valueRequirement) {
return new CurrencyMatrixValueRequirement(valueRequirement, false);
}
/**
* Creates a matrix value that indicates a conversion between currencies should be performed using the rates of each to/from an intermediate currency.
*
* @param currency the intermediate currency
* @return the matrix value
*/
public static CurrencyMatrixCross of(final Currency currency) {
return new CurrencyMatrixCross(currency);
}
public abstract <T> T accept(final CurrencyMatrixValueVisitor<T> visitor);
public abstract CurrencyMatrixValue getReciprocal();
@Override
public abstract boolean equals(final Object o);
@Override
public abstract int hashCode();
}