/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.fudgemsg; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.fudgemsg.FudgeField; import org.fudgemsg.FudgeMsg; import org.fudgemsg.MutableFudgeMsg; import org.fudgemsg.mapping.FudgeBuilder; import org.fudgemsg.mapping.FudgeBuilderFor; import org.fudgemsg.mapping.FudgeDeserializer; import org.fudgemsg.mapping.FudgeSerializer; import org.threeten.bp.Period; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.analytics.financial.legalentity.LegalEntity; import com.opengamma.analytics.financial.legalentity.LegalEntityFilter; import com.opengamma.financial.analytics.curve.CurveConstructionConfiguration; import com.opengamma.financial.analytics.curve.CurveGroupConfiguration; import com.opengamma.financial.analytics.curve.CurveTypeConfiguration; import com.opengamma.financial.analytics.curve.DiscountingCurveTypeConfiguration; import com.opengamma.financial.analytics.curve.IborCurveTypeConfiguration; import com.opengamma.financial.analytics.curve.InflationCurveTypeConfiguration; import com.opengamma.financial.analytics.curve.InflationIssuerCurveTypeConfiguration; import com.opengamma.financial.analytics.curve.IssuerCurveTypeConfiguration; import com.opengamma.financial.analytics.curve.OvernightCurveTypeConfiguration; import com.opengamma.id.ExternalId; import com.opengamma.id.MutableUniqueIdentifiable; import com.opengamma.id.UniqueId; import com.opengamma.id.UniqueIdFudgeBuilder; import com.opengamma.id.UniqueIdentifiable; import com.opengamma.util.money.Currency; import com.opengamma.util.time.Tenor; /** * Builders for curve construction configurations. */ /* package */final class CurveConfigurationBuilders { /** The name field */ private static final String NAME_FIELD = "name"; /** The unique id field */ private static final String UNIQUE_ID_FIELD = "uniqueId"; /** * Private constructor. */ private CurveConfigurationBuilders() { } /** * Fudge builder for {@link DiscountingCurveTypeConfiguration} */ @FudgeBuilderFor(DiscountingCurveTypeConfiguration.class) public static class DiscountingCurveTypeConfigurationBuilder implements FudgeBuilder<DiscountingCurveTypeConfiguration> { /** The reference field */ private static final String REFERENCE_FIELD = "reference"; @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final DiscountingCurveTypeConfiguration object) { final MutableFudgeMsg message = serializer.newMessage(); message.add(null, 0, object.getClass().getName()); serializer.addToMessage(message, REFERENCE_FIELD, null, object.getReference()); return message; } @Override public DiscountingCurveTypeConfiguration buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final String reference = message.getString(REFERENCE_FIELD); final DiscountingCurveTypeConfiguration configuration = new DiscountingCurveTypeConfiguration(reference); return configuration; } } /** * Fudge builder for {@link IborCurveTypeConfiguration} */ @FudgeBuilderFor(IborCurveTypeConfiguration.class) public static class IborCurveTypeConfigurationBuilder implements FudgeBuilder<IborCurveTypeConfiguration> { /** The convention name field */ private static final String CONVENTION_FIELD = "convention"; /** The index type field */ private static final String TENOR_FIELD = "indexTenor"; @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final IborCurveTypeConfiguration object) { final MutableFudgeMsg message = serializer.newMessage(); message.add(null, 0, object.getClass().getName()); serializer.addToMessage(message, CONVENTION_FIELD, null, object.getConvention()); serializer.addToMessage(message, TENOR_FIELD, null, object.getTenor().getPeriod().toString()); return message; } @Override public IborCurveTypeConfiguration buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final ExternalId convention = deserializer.fieldValueToObject(ExternalId.class, message.getByName(CONVENTION_FIELD)); final Tenor tenor = Tenor.of(Period.parse(message.getString(TENOR_FIELD))); return new IborCurveTypeConfiguration(convention, tenor); } } /** * Fudge builder for {@link OvernightCurveTypeConfiguration} */ @FudgeBuilderFor(OvernightCurveTypeConfiguration.class) public static class OvernightCurveTypeConfigurationBuilder implements FudgeBuilder<OvernightCurveTypeConfiguration> { /** The convention name field */ private static final String CONVENTION_FIELD = "convention"; @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final OvernightCurveTypeConfiguration object) { final MutableFudgeMsg message = serializer.newMessage(); message.add(null, 0, object.getClass().getName()); serializer.addToMessage(message, CONVENTION_FIELD, null, object.getConvention()); return message; } @Override public OvernightCurveTypeConfiguration buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final ExternalId convention = deserializer.fieldValueToObject(ExternalId.class, message.getByName(CONVENTION_FIELD)); final OvernightCurveTypeConfiguration configuration = new OvernightCurveTypeConfiguration(convention); return configuration; } } /** * Fudge builder for {@link IssuerCurveTypeConfiguration} */ @FudgeBuilderFor(IssuerCurveTypeConfiguration.class) public static class IssuerCurveTypeConfigurationBuilder implements FudgeBuilder<IssuerCurveTypeConfiguration> { /** * The issuer type field * @deprecated This field is kept for backwards compatibility */ @Deprecated private static final String ISSUER_NAME_FIELD = "issuerName"; /** * The underlying reference field * @deprecated This field is kept for backwards compatibility */ @Deprecated private static final String UNDERLYING_REFERENCE_FIELD = "underlyingReference"; /** The key field */ private static final String KEY_FIELD = "key"; /** The key class field */ private static final String KEY_CLASS_FIELD = "keyClass"; /** The legal entity filter field */ private static final String LEGAL_ENTITY_FILTER_FIELD = "filter"; @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final IssuerCurveTypeConfiguration object) { final MutableFudgeMsg message = serializer.newMessage(); message.add(null, 0, object.getClass().getName()); for (final Object key : object.getKeys()) { serializer.addToMessageWithClassHeaders(message, KEY_FIELD, null, key); serializer.addToMessage(message, KEY_CLASS_FIELD, null, key.getClass()); } for (final LegalEntityFilter<LegalEntity> filter : object.getFilters().getFiltersToUse()) { serializer.addToMessageWithClassHeaders(message, LEGAL_ENTITY_FILTER_FIELD, null, filter); } return message; } @SuppressWarnings("deprecation") @Override public IssuerCurveTypeConfiguration buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { if (message.hasField(ISSUER_NAME_FIELD)) { if (message.hasField(UNDERLYING_REFERENCE_FIELD)) { final String issuerName = message.getString(ISSUER_NAME_FIELD); final String underlyingReference = message.getString(UNDERLYING_REFERENCE_FIELD); return new IssuerCurveTypeConfiguration(issuerName, underlyingReference); } throw new IllegalStateException("Configuration has " + ISSUER_NAME_FIELD + " but no " + UNDERLYING_REFERENCE_FIELD); } final List<FudgeField> keyFields = message.getAllByName(KEY_FIELD); final List<FudgeField> keyClassFields = message.getAllByName(KEY_CLASS_FIELD); final Set<Object> keys = new HashSet<>(); for (int i = 0; i < keyFields.size(); i++) { final Class<?> clazz = deserializer.fieldValueToObject(Class.class, keyClassFields.get(i)); final Object value = deserializer.fieldValueToObject(clazz, keyFields.get(i)); if (clazz.equals(String.class)) { try { keys.add(Currency.of((String) value)); } catch (final IllegalArgumentException e) { keys.add(value); } } else { keys.add(value); } } final List<FudgeField> filterFields = message.getAllByName(LEGAL_ENTITY_FILTER_FIELD); final Set<LegalEntityFilter<LegalEntity>> filters = new HashSet<>(); for (final FudgeField field : filterFields) { filters.add((LegalEntityFilter<LegalEntity>) deserializer.fieldValueToObject(field)); } return new IssuerCurveTypeConfiguration(keys, filters); } } /** * Fudge builder for {@link InflationCurveTypeConfiguration} */ @FudgeBuilderFor(InflationCurveTypeConfiguration.class) public static class InflationCurveTypeConfigurationBuilder implements FudgeBuilder<InflationCurveTypeConfiguration> { /** The reference field */ private static final String REFERENCE_FIELD = "reference"; /** The price index field */ private static final String PRICE_INDEX_FIELD = "priceIndex"; @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final InflationCurveTypeConfiguration object) { final MutableFudgeMsg message = serializer.newMessage(); message.add(null, 0, object.getClass().getName()); message.add(REFERENCE_FIELD, object.getReference()); serializer.addToMessage(message, PRICE_INDEX_FIELD, null, object.getPriceIndex()); return message; } @Override public InflationCurveTypeConfiguration buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final String reference = message.getString(REFERENCE_FIELD); final ExternalId priceIndex = deserializer.fieldValueToObject(ExternalId.class, message.getByName(PRICE_INDEX_FIELD)); final InflationCurveTypeConfiguration configuration = new InflationCurveTypeConfiguration(reference, priceIndex); return configuration; } } /** * Fudge builder for {@link InflationIssuerCurveTypeConfiguration} */ @FudgeBuilderFor(InflationIssuerCurveTypeConfiguration.class) public static class InflationIssuerCurveTypeConfigurationBuilder implements FudgeBuilder<InflationIssuerCurveTypeConfiguration> { /** The reference field */ private static final String REFERENCE_FIELD = "reference"; /** The price index field */ private static final String PRICE_INDEX_FIELD = "priceIndex"; @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final InflationIssuerCurveTypeConfiguration object) { final MutableFudgeMsg message = serializer.newMessage(); message.add(null, 0, object.getClass().getName()); message.add(REFERENCE_FIELD, object.getReference()); serializer.addToMessage(message, PRICE_INDEX_FIELD, null, object.getPriceIndex()); return message; } @Override public InflationIssuerCurveTypeConfiguration buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final String reference = message.getString(REFERENCE_FIELD); final ExternalId priceIndex = deserializer.fieldValueToObject(ExternalId.class, message.getByName(PRICE_INDEX_FIELD)); final InflationIssuerCurveTypeConfiguration configuration = new InflationIssuerCurveTypeConfiguration(reference, priceIndex); return configuration; } } /** * Fudge builder for {@link CurveGroupConfiguration} */ @FudgeBuilderFor(CurveGroupConfiguration.class) public static class CurveGroupConfigurationBuilder implements FudgeBuilder<CurveGroupConfiguration> { /** The order field */ private static final String ORDER_FIELD = "order"; /** The curve field */ private static final String CURVE_FIELD = "curveName"; /** The curve types field */ private static final String CURVE_TYPES_FIELD = "typesForCurve"; /** The curve type field */ private static final String CURVE_TYPE_FIELD = "type"; @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final CurveGroupConfiguration object) { final MutableFudgeMsg message = serializer.newMessage(); message.add(null, 0, object.getClass().getName()); serializer.addToMessage(message, ORDER_FIELD, null, object.getOrder()); for (final Map.Entry<String, List<? extends CurveTypeConfiguration>> entry : object.getTypesForCurves().entrySet()) { final MutableFudgeMsg subMessage = serializer.newMessage(); message.add(CURVE_FIELD, entry.getKey()); for (final CurveTypeConfiguration type : entry.getValue()) { serializer.addToMessageWithClassHeaders(subMessage, CURVE_TYPE_FIELD, null, type); } message.add(CURVE_TYPES_FIELD, subMessage); } return message; } @Override public CurveGroupConfiguration buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final int order = message.getInt(ORDER_FIELD); final List<FudgeField> curveFields = message.getAllByName(CURVE_FIELD); final List<FudgeField> typesForCurveFields = message.getAllByName(CURVE_TYPES_FIELD); final int n = curveFields.size(); if (typesForCurveFields.size() != n) { throw new OpenGammaRuntimeException("Did not have types for each curve name"); } final Map<String, List<? extends CurveTypeConfiguration>> curveTypes = new HashMap<>(); for (int i = 0; i < n; i++) { final FudgeField nameField = curveFields.get(i); final String name = deserializer.fieldValueToObject(String.class, nameField); final List<FudgeField> msgForCurve = ((FudgeMsg) typesForCurveFields.get(i).getValue()).getAllByName(CURVE_TYPE_FIELD); final List<CurveTypeConfiguration> list = new ArrayList<>(); for (final FudgeField field : msgForCurve) { list.add(deserializer.fieldValueToObject(CurveTypeConfiguration.class, field)); } curveTypes.put(name, list); } final CurveGroupConfiguration configuration = new CurveGroupConfiguration(order, curveTypes); return configuration; } } /** * Fudge builder for {@link CurveConstructionConfiguration} */ @FudgeBuilderFor(CurveConstructionConfiguration.class) public static class CurveConstructionConfigurationBuilder implements FudgeBuilder<CurveConstructionConfiguration> { /** The group field */ private static final String GROUP_FIELD = "group"; /** The exogenous configuration field */ private static final String EXOGENOUS_CONFIGURATION_FIELD = "exogenousConfiguration"; @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final CurveConstructionConfiguration object) { final MutableFudgeMsg message = serializer.newMessage(); message.add(null, 0, object.getClass().getName()); message.add(NAME_FIELD, object.getName()); for (final CurveGroupConfiguration curveType : object.getCurveGroups()) { serializer.addToMessageWithClassHeaders(message, GROUP_FIELD, null, curveType); } if (object.getExogenousConfigurations() != null) { for (final String exogenousConfig : object.getExogenousConfigurations()) { serializer.addToMessage(message, EXOGENOUS_CONFIGURATION_FIELD, null, exogenousConfig); } } addUniqueId(serializer, object, message); return message; } @Override public CurveConstructionConfiguration buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final String name = message.getString(NAME_FIELD); final List<FudgeField> curveTypeFields = message.getAllByName(GROUP_FIELD); final List<CurveGroupConfiguration> curveTypes = new ArrayList<>(); for (final FudgeField field : curveTypeFields) { curveTypes.add(deserializer.fieldValueToObject(CurveGroupConfiguration.class, field)); } List<String> exogenousConfigurations = new ArrayList<>(); for (final FudgeField field : message.getAllByName(EXOGENOUS_CONFIGURATION_FIELD)) { exogenousConfigurations.add((String) field.getValue()); } final CurveConstructionConfiguration configuration = new CurveConstructionConfiguration(name, curveTypes, exogenousConfigurations); setUniqueId(deserializer, message, configuration); return configuration; } } static void addUniqueId(final FudgeSerializer serializer, final UniqueIdentifiable object, final MutableFudgeMsg message) { if (object.getUniqueId() != null) { message.add(UNIQUE_ID_FIELD, null, UniqueIdFudgeBuilder.toFudgeMsg(serializer, object.getUniqueId())); } } static void setUniqueId(final FudgeDeserializer deserializer, final FudgeMsg message, final MutableUniqueIdentifiable configuration) { final FudgeField uniqueId = message.getByName(UNIQUE_ID_FIELD); if (uniqueId != null) { configuration.setUniqueId(deserializer.fieldValueToObject(UniqueId.class, uniqueId)); } } }