/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.fudgemsg; 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.FudgeDeserializer; import org.fudgemsg.mapping.FudgeSerializer; import org.fudgemsg.mapping.GenericFudgeBuilderFor; import org.fudgemsg.types.IndicatorType; import org.fudgemsg.wire.types.FudgeWireType; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.function.resolver.ResolutionRuleTransform; import com.opengamma.engine.target.ComputationTargetType; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.view.DeltaDefinition; import com.opengamma.engine.view.ResultModelDefinition; import com.opengamma.engine.view.ViewCalculationConfiguration; import com.opengamma.engine.view.ViewCalculationConfiguration.MergedOutput; import com.opengamma.engine.view.ViewCalculationConfiguration.MergedOutputAggregationType; import com.opengamma.engine.view.ViewDefinition; import com.opengamma.id.UniqueId; import com.opengamma.livedata.UserPrincipal; import com.opengamma.util.money.Currency; import com.opengamma.util.money.UnorderedCurrencyPair; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Pairs; /** * Fudge message builder for {@link ViewDefinition} and {@link ViewCalculationConfiguration}. */ @GenericFudgeBuilderFor(ViewDefinition.class) public class ViewDefinitionFudgeBuilder implements FudgeBuilder<ViewDefinition> { // private static final String UNIQUE_ID_FIELD = "uniqueId"; private static final String NAME_FIELD = "name"; private static final String PORTFOLIO_ID_FIELD = "identifier"; private static final String USER_FIELD = "user"; private static final String MIN_DELTA_CALC_PERIOD_FIELD = "minDeltaCalcPeriod"; private static final String MAX_DELTA_CALC_PERIOD_FIELD = "maxDeltaCalcPeriod"; private static final String MIN_FULL_CALC_PERIOD_FIELD = "minFullCalcPeriod"; private static final String MAX_FULL_CALC_PERIOD_FIELD = "maxFullCalcPeriod"; private static final String PERSISTENT_FIELD = "persistent"; private static final String RESULT_MODEL_DEFINITION_FIELD = "resultModelDefinition"; private static final String CALCULATION_CONFIGURATION_FIELD = "calculationConfiguration"; private static final String PORTFOLIO_REQUIREMENTS_BY_SECURITY_TYPE_FIELD = "portfolioRequirementsBySecurityType"; private static final String SECURITY_TYPE_FIELD = "securityType"; private static final String PORTFOLIO_REQUIREMENT_FIELD = "portfolioRequirement"; private static final String PORTFOLIO_REQUIREMENT_REQUIRED_OUTPUT_FIELD = "requiredOutput"; private static final String PORTFOLIO_REQUIREMENT_CONSTRAINTS_FIELD = "constraints"; private static final String SPECIFIC_REQUIREMENT_FIELD = "specificRequirement"; private static final String DELTA_DEFINITION_FIELD = "deltaDefinition"; private static final String CURRENCY_FIELD = "currency"; private static final String DEFAULT_PROPERTIES_FIELD = "defaultProperties"; private static final String RESOLUTION_RULE_TRANSFORM_FIELD = "resolutionRuleTransform"; private static final String SCENARIO_ID_FIELD = "scenarioId"; private static final String SCENARIO_PARAMETERS_ID_FIELD = "scenarioParametersId"; private static final String MERGED_OUTPUTS_FIELD = "mergedOutputs"; private static final String MERGED_OUTPUT_FIELD = "mergedOutput"; private static final String MERGED_OUTPUT_AGGREGATION_TYPE_FIELD = "aggregationType"; // field names for column data private static final String COLUMNS_FIELD = "columns"; private static final String HEADER_FIELD = "header"; private static final String VALUE_NAME_FIELD = "valueName"; @Override public MutableFudgeMsg buildMessage(FudgeSerializer serializer, ViewDefinition viewDefinition) { // REVIEW jonathan 2010-08-13 -- This is really messy, but there's a cycle of references between ViewDefinition and // ViewCalculationConfiguration, so we have to handle both at once. MutableFudgeMsg message = serializer.newMessage(); message.add(NAME_FIELD, null, viewDefinition.getName()); serializer.addToMessage(message, PORTFOLIO_ID_FIELD, null, viewDefinition.getPortfolioId()); serializer.addToMessage(message, USER_FIELD, null, viewDefinition.getMarketDataUser()); serializer.addToMessage(message, RESULT_MODEL_DEFINITION_FIELD, null, viewDefinition.getResultModelDefinition()); Currency defaultCurrency = viewDefinition.getDefaultCurrency(); if (defaultCurrency != null) { message.add(CURRENCY_FIELD, null, defaultCurrency.getCode()); } if (viewDefinition.getMinDeltaCalculationPeriod() != null) { message.add(MIN_DELTA_CALC_PERIOD_FIELD, null, viewDefinition.getMinDeltaCalculationPeriod()); } if (viewDefinition.getMaxDeltaCalculationPeriod() != null) { message.add(MAX_DELTA_CALC_PERIOD_FIELD, null, viewDefinition.getMaxDeltaCalculationPeriod()); } if (viewDefinition.getMinFullCalculationPeriod() != null) { message.add(MIN_FULL_CALC_PERIOD_FIELD, null, viewDefinition.getMinFullCalculationPeriod()); } if (viewDefinition.getMaxFullCalculationPeriod() != null) { message.add(MAX_FULL_CALC_PERIOD_FIELD, null, viewDefinition.getMaxFullCalculationPeriod()); } if (viewDefinition.isPersistent()) { message.add(PERSISTENT_FIELD, null, FudgeWireType.INDICATOR, IndicatorType.INSTANCE); } Map<String, ViewCalculationConfiguration> calculationConfigurations = viewDefinition.getAllCalculationConfigurationsByName(); for (ViewCalculationConfiguration calcConfig : calculationConfigurations.values()) { MutableFudgeMsg calcConfigMsg = serializer.newMessage(); calcConfigMsg.add(NAME_FIELD, null, calcConfig.getName()); // Can't use the default map serialisation here because every field needs to have a name for Mongo for (Map.Entry<String, Set<Pair<String, ValueProperties>>> securityTypeRequirements : calcConfig.getPortfolioRequirementsBySecurityType().entrySet()) { MutableFudgeMsg securityTypeRequirementsMsg = serializer.newMessage(); securityTypeRequirementsMsg.add(SECURITY_TYPE_FIELD, securityTypeRequirements.getKey()); for (Pair<String, ValueProperties> requirement : securityTypeRequirements.getValue()) { MutableFudgeMsg reqMsg = serializer.newMessage(); reqMsg.add(PORTFOLIO_REQUIREMENT_REQUIRED_OUTPUT_FIELD, requirement.getFirst()); serializer.addToMessage(reqMsg, PORTFOLIO_REQUIREMENT_CONSTRAINTS_FIELD, null, requirement.getSecond()); securityTypeRequirementsMsg.add(PORTFOLIO_REQUIREMENT_FIELD, reqMsg); } calcConfigMsg.add(PORTFOLIO_REQUIREMENTS_BY_SECURITY_TYPE_FIELD, securityTypeRequirementsMsg); } for (ValueRequirement specificRequirement : calcConfig.getSpecificRequirements()) { calcConfigMsg.add(SPECIFIC_REQUIREMENT_FIELD, serializer.objectToFudgeMsg(specificRequirement)); } serializer.addToMessage(calcConfigMsg, DELTA_DEFINITION_FIELD, null, calcConfig.getDeltaDefinition()); serializer.addToMessage(calcConfigMsg, DEFAULT_PROPERTIES_FIELD, null, calcConfig.getDefaultProperties()); serializer.addToMessage(calcConfigMsg, RESOLUTION_RULE_TRANSFORM_FIELD, null, calcConfig.getResolutionRuleTransform()); UniqueId scenarioId = calcConfig.getScenarioId(); if (scenarioId != null) { serializer.addToMessageWithClassHeaders(calcConfigMsg, SCENARIO_ID_FIELD, null, scenarioId, UniqueId.class); } UniqueId scenarioParametersId = calcConfig.getScenarioParametersId(); if (scenarioParametersId != null) { serializer.addToMessageWithClassHeaders(calcConfigMsg, SCENARIO_PARAMETERS_ID_FIELD, null, scenarioParametersId, UniqueId.class); } if (!calcConfig.getMergedOutputs().isEmpty()) { MutableFudgeMsg mergedOutputsMsg = serializer.newMessage(); for (ViewCalculationConfiguration.MergedOutput mergedOutput : calcConfig.getMergedOutputs()) { MutableFudgeMsg mergedOutputMsg = serializer.newMessage(); serializer.addToMessage(mergedOutputMsg, NAME_FIELD, null, mergedOutput.getMergedOutputName()); mergedOutputMsg.add(MERGED_OUTPUT_AGGREGATION_TYPE_FIELD, mergedOutput.getAggregationType().toString()); for (Pair<String, ValueProperties> portfolioRequirement : mergedOutput.getPortfolioRequirements()) { MutableFudgeMsg reqMsg = serializer.newMessage(); serializer.addToMessage(reqMsg, PORTFOLIO_REQUIREMENT_REQUIRED_OUTPUT_FIELD, null, portfolioRequirement.getFirst()); serializer.addToMessage(reqMsg, PORTFOLIO_REQUIREMENT_CONSTRAINTS_FIELD, null, portfolioRequirement.getSecond()); serializer.addToMessage(mergedOutputMsg, PORTFOLIO_REQUIREMENT_FIELD, null, reqMsg); } serializer.addToMessage(mergedOutputsMsg, MERGED_OUTPUT_FIELD, null, mergedOutputMsg); } serializer.addToMessage(calcConfigMsg, MERGED_OUTPUTS_FIELD, null, mergedOutputsMsg); } MutableFudgeMsg columnsMsg = serializer.newMessage(); for (ViewCalculationConfiguration.Column column : calcConfig.getColumns()) { MutableFudgeMsg columnMsg = serializer.newMessage(); serializer.addToMessage(columnMsg, HEADER_FIELD, null, column.getHeader()); serializer.addToMessage(columnMsg, VALUE_NAME_FIELD, null, column.getValueName()); serializer.addToMessage(columnMsg, PORTFOLIO_REQUIREMENT_CONSTRAINTS_FIELD, null, column.getProperties()); serializer.addToMessage(columnsMsg, null, null, columnMsg); } serializer.addToMessage(calcConfigMsg, COLUMNS_FIELD, null, columnsMsg); message.add(CALCULATION_CONFIGURATION_FIELD, null, calcConfigMsg); } serializer.addToMessageWithClassHeaders(message, "uniqueId", null, viewDefinition.getUniqueId(), UniqueId.class); return message; } /** * Support translation from pre-2286 type specifications, such as CTSpec[PRIMITIVE, CurrencyISO~USD], to resolvable types. * * @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 ValueRequirement plat2286Translate(final ValueRequirement valueRequirement) { if (valueRequirement.getTargetReference() instanceof ComputationTargetSpecification) { final ComputationTargetSpecification targetSpec = valueRequirement.getTargetReference().getSpecification(); final ComputationTargetType type; if (targetSpec.getUniqueId() == null) { return valueRequirement; } if (Currency.OBJECT_SCHEME.equals(targetSpec.getUniqueId().getScheme())) { type = ComputationTargetType.CURRENCY; } else if (UnorderedCurrencyPair.OBJECT_SCHEME.equals(targetSpec.getUniqueId().getScheme())) { type = ComputationTargetType.UNORDERED_CURRENCY_PAIR; } else { return valueRequirement; } return new ValueRequirement(valueRequirement.getValueName(), new ComputationTargetSpecification(type, targetSpec.getUniqueId()), valueRequirement.getConstraints()); } else { return valueRequirement; } } @Override public ViewDefinition buildObject(FudgeDeserializer deserializer, FudgeMsg message) { final FudgeField portfolioIdField = message.getByName(PORTFOLIO_ID_FIELD); final UniqueId portfolioId = portfolioIdField == null ? null : deserializer.fieldValueToObject(UniqueId.class, portfolioIdField); final String name = message.getFieldValue(String.class, message.getByName(NAME_FIELD)); final UserPrincipal user = deserializer.fieldValueToObject(UserPrincipal.class, message.getByName(USER_FIELD)); final ResultModelDefinition model = deserializer.fieldValueToObject(ResultModelDefinition.class, message.getByName(RESULT_MODEL_DEFINITION_FIELD)); ViewDefinition viewDefinition = new ViewDefinition( name, portfolioId, user, model); // FudgeField currencyField = message.getByName(CURRENCY_FIELD); // if (currencyField != null) { // viewDefinition.setDefaultCurrency(context.fieldValueToObject(Currency.class, currencyField)); // } if (message.hasField(CURRENCY_FIELD)) { String isoCode = message.getString(CURRENCY_FIELD); viewDefinition.setDefaultCurrency(Currency.of(isoCode)); } if (message.hasField(MIN_DELTA_CALC_PERIOD_FIELD)) { viewDefinition.setMinDeltaCalculationPeriod(message.getLong(MIN_DELTA_CALC_PERIOD_FIELD)); } if (message.hasField(MAX_DELTA_CALC_PERIOD_FIELD)) { viewDefinition.setMaxDeltaCalculationPeriod(message.getLong(MAX_DELTA_CALC_PERIOD_FIELD)); } if (message.hasField(MIN_FULL_CALC_PERIOD_FIELD)) { viewDefinition.setMinFullCalculationPeriod(message.getLong(MIN_FULL_CALC_PERIOD_FIELD)); } //for backward compatibility of renaming fullDeltaCalcPeriod to minFullCalcPeriod if (message.hasField("fullDeltaCalcPeriod")) { viewDefinition.setMinFullCalculationPeriod(message.getLong("fullDeltaCalcPeriod")); } if (message.hasField(MAX_FULL_CALC_PERIOD_FIELD)) { viewDefinition.setMaxFullCalculationPeriod(message.getLong(MAX_FULL_CALC_PERIOD_FIELD)); } if (message.hasField(PERSISTENT_FIELD)) { viewDefinition.setPersistent(true); } List<FudgeField> calcConfigs = message.getAllByName(CALCULATION_CONFIGURATION_FIELD); for (FudgeField calcConfigField : calcConfigs) { FudgeMsg calcConfigMsg = message.getFieldValue(FudgeMsg.class, calcConfigField); final ViewCalculationConfiguration calcConfig = new ViewCalculationConfiguration(viewDefinition, message.getFieldValue(String.class, calcConfigMsg.getByName(NAME_FIELD))); for (FudgeField securityTypeRequirementsField : calcConfigMsg.getAllByName(PORTFOLIO_REQUIREMENTS_BY_SECURITY_TYPE_FIELD)) { FudgeMsg securityTypeRequirementsMsg = (FudgeMsg) securityTypeRequirementsField.getValue(); String securityType = securityTypeRequirementsMsg.getString(SECURITY_TYPE_FIELD); Set<Pair<String, ValueProperties>> requirements = Sets.newLinkedHashSet(); for (FudgeField requirement : securityTypeRequirementsMsg.getAllByName(PORTFOLIO_REQUIREMENT_FIELD)) { FudgeMsg reqMsg = (FudgeMsg) requirement.getValue(); String requiredOutput = reqMsg.getString(PORTFOLIO_REQUIREMENT_REQUIRED_OUTPUT_FIELD); ValueProperties constraints = deserializer.fieldValueToObject(ValueProperties.class, reqMsg.getByName(PORTFOLIO_REQUIREMENT_CONSTRAINTS_FIELD)); requirements.add(Pairs.of(requiredOutput, constraints)); } calcConfig.addPortfolioRequirements(securityType, requirements); } for (FudgeField specificRequirementField : calcConfigMsg.getAllByName(SPECIFIC_REQUIREMENT_FIELD)) { calcConfig.addSpecificRequirement(plat2286Translate(deserializer.fieldValueToObject(ValueRequirement.class, specificRequirementField))); } if (calcConfigMsg.hasField(DELTA_DEFINITION_FIELD)) { calcConfig.setDeltaDefinition(deserializer.fieldValueToObject(DeltaDefinition.class, calcConfigMsg.getByName(DELTA_DEFINITION_FIELD))); } if (calcConfigMsg.hasField(DEFAULT_PROPERTIES_FIELD)) { calcConfig.setDefaultProperties(deserializer.fieldValueToObject(ValueProperties.class, calcConfigMsg.getByName(DEFAULT_PROPERTIES_FIELD))); } if (calcConfigMsg.hasField(RESOLUTION_RULE_TRANSFORM_FIELD)) { calcConfig.setResolutionRuleTransform(deserializer.fieldValueToObject(ResolutionRuleTransform.class, calcConfigMsg.getByName( RESOLUTION_RULE_TRANSFORM_FIELD))); } if (calcConfigMsg.hasField(SCENARIO_ID_FIELD)) { calcConfig.setScenarioId(deserializer.fieldValueToObject(UniqueId.class, calcConfigMsg.getByName(SCENARIO_ID_FIELD))); } if (calcConfigMsg.hasField(SCENARIO_PARAMETERS_ID_FIELD)) { calcConfig.setScenarioParametersId(deserializer.fieldValueToObject(UniqueId.class, calcConfigMsg.getByName(SCENARIO_PARAMETERS_ID_FIELD))); } List<ViewCalculationConfiguration.Column> columns = Lists.newArrayList(); if (calcConfigMsg.hasField(MERGED_OUTPUTS_FIELD)) { FudgeMsg mergedOutputsMsg = calcConfigMsg.getMessage(MERGED_OUTPUTS_FIELD); for (FudgeField mergedOutputField : mergedOutputsMsg.getAllByName(MERGED_OUTPUT_FIELD)) { FudgeMsg mergedOutputMsg = (FudgeMsg) mergedOutputField.getValue(); String mergedOutputName = mergedOutputMsg.getString(NAME_FIELD); MergedOutputAggregationType aggregationType = MergedOutputAggregationType.valueOf(mergedOutputMsg.getString(MERGED_OUTPUT_AGGREGATION_TYPE_FIELD)); MergedOutput mergedOutput = new MergedOutput(mergedOutputName, aggregationType); for (FudgeField reqField : mergedOutputMsg.getAllByName(PORTFOLIO_REQUIREMENT_FIELD)) { FudgeMsg reqMsg = (FudgeMsg) reqField.getValue(); String valueName = reqMsg.getString(PORTFOLIO_REQUIREMENT_REQUIRED_OUTPUT_FIELD); ValueProperties constraints = deserializer.fieldValueToObject(ValueProperties.class, reqMsg.getByName(PORTFOLIO_REQUIREMENT_CONSTRAINTS_FIELD)); mergedOutput.addMergedRequirement(valueName, constraints); } calcConfig.addMergedOutput(mergedOutput); } } if (calcConfigMsg.hasField(COLUMNS_FIELD)) { FudgeMsg columnsMsg = calcConfigMsg.getMessage(COLUMNS_FIELD); for (FudgeField field : columnsMsg.getAllFields()) { FudgeMsg columnMsg = (FudgeMsg) field.getValue(); String header = deserializer.fieldValueToObject(String.class, columnMsg.getByName(HEADER_FIELD)); String valueName = deserializer.fieldValueToObject(String.class, columnMsg.getByName(VALUE_NAME_FIELD)); ValueProperties properties = deserializer.fieldValueToObject(ValueProperties.class, columnMsg.getByName(PORTFOLIO_REQUIREMENT_CONSTRAINTS_FIELD)); columns.add(new ViewCalculationConfiguration.Column(header, valueName, properties)); } } calcConfig.setColumns(columns); viewDefinition.addViewCalculationConfiguration(calcConfig); } FudgeField uniqueId = message.getByName("uniqueId"); if (uniqueId != null) { viewDefinition.setUniqueId(deserializer.fieldValueToObject(UniqueId.class, uniqueId)); } return viewDefinition; } }