/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.fudgemsg; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; 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.fudgemsg.mapping.GenericFudgeBuilderFor; import org.fudgemsg.types.IndicatorType; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.function.FunctionParameters; import com.opengamma.engine.marketdata.manipulator.DistinctMarketDataSelector; import com.opengamma.engine.target.ComputationTargetReference; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.engine.view.compilation.CompiledViewCalculationConfiguration; import com.opengamma.engine.view.compilation.CompiledViewCalculationConfigurationImpl; /** * Fudge message builder for {@link CompiledViewCalculationConfiguration}. */ @GenericFudgeBuilderFor(CompiledViewCalculationConfiguration.class) @FudgeBuilderFor(CompiledViewCalculationConfigurationImpl.class) public class CompiledViewCalculationConfigurationFudgeBuilder implements FudgeBuilder<CompiledViewCalculationConfiguration> { private static final String NAME_FIELD = "name"; private static final String COMPUTATION_TARGETS_FIELD = "computationTargets"; private static final String TERMINAL_OUTPUT_SPECIFICATIONS_FIELD = "terminalOutputSpecifications"; private static final String MARKET_DATA_REQUIREMENTS_FIELD = "marketDataRequirements"; private static final String MARKET_DATA_ALIASES_FIELD = "marketDataAliases"; // private static final String MARKET_DATA_SELECTIONS_FIELD = "marketDataSelections"; // private static final String MARKET_DATA_SELECTION_FUNCTION_FIELD = "marketDataSelectionFunctionParameters"; private static final Integer MAP_KEY = 1; private static final Integer MAP_VALUE = 2; protected void encodeComputationTargets(final FudgeSerializer serializer, final MutableFudgeMsg msg, final Set<ComputationTargetSpecification> targets) { final MutableFudgeMsg submsg = msg.addSubMessage(COMPUTATION_TARGETS_FIELD, null); for (final ComputationTargetSpecification target : targets) { serializer.addToMessage(submsg, null, null, target); } } protected Set<ComputationTargetSpecification> decodeComputationTargets(final FudgeDeserializer deserializer, final FudgeMsg msg) { final FudgeMsg submsg = msg.getMessage(COMPUTATION_TARGETS_FIELD); if (submsg == null) { return Collections.emptySet(); } final Set<ComputationTargetSpecification> result = Sets.newHashSetWithExpectedSize(submsg.getNumFields()); for (final FudgeField field : submsg) { result.add(deserializer.fieldValueToObject(ComputationTargetReference.class, field).getSpecification()); } return result; } protected void encodeTerminalOutputSpecifications(final FudgeSerializer serializer, final MutableFudgeMsg msg, final Map<ValueSpecification, Set<ValueRequirement>> outputs) { final MutableFudgeMsg submsg = msg.addSubMessage(TERMINAL_OUTPUT_SPECIFICATIONS_FIELD, null); for (final Map.Entry<ValueSpecification, Set<ValueRequirement>> output : outputs.entrySet()) { serializer.addToMessage(submsg, null, MAP_KEY, output.getKey()); final MutableFudgeMsg submsg2 = submsg.addSubMessage(null, MAP_VALUE); for (final ValueRequirement requirement : output.getValue()) { serializer.addToMessage(submsg2, null, null, requirement); } } } @SuppressWarnings("unchecked") protected Map<ValueSpecification, Set<ValueRequirement>> decodeTerminalOutputSpecifications(final FudgeDeserializer deserializer, final FudgeMsg msg) { final FudgeMsg submsg = msg.getMessage(TERMINAL_OUTPUT_SPECIFICATIONS_FIELD); if (submsg == null) { return Collections.emptyMap(); } final Map<ValueSpecification, Set<ValueRequirement>> result = Maps.newHashMapWithExpectedSize(submsg.getNumFields() / 2); LinkedList<Object> overflow = null; ValueSpecification key = null; Set<ValueRequirement> value = null; for (final FudgeField field : submsg) { if (MAP_KEY.equals(field.getOrdinal())) { final ValueSpecification fieldValue = deserializer.fieldValueToObject(ValueSpecification.class, field); if (key == null) { if (value == null) { key = fieldValue; } else { result.put(fieldValue, value); if (overflow != null) { value = overflow.isEmpty() ? null : (Set<ValueRequirement>) overflow.removeFirst(); } else { value = null; } } } else { if (overflow == null) { overflow = new LinkedList<Object>(); } overflow.add(fieldValue); } } else if (MAP_VALUE.equals(field.getOrdinal())) { final FudgeMsg submsg2 = (FudgeMsg) field.getValue(); final Set<ValueRequirement> fieldValue = Sets.newHashSetWithExpectedSize(submsg2.getNumFields()); for (final FudgeField field2 : submsg2) { fieldValue.add(deserializer.fieldValueToObject(ValueRequirement.class, field2)); } if (value == null) { if (key == null) { value = fieldValue; } else { result.put(key, fieldValue); if (overflow != null) { key = overflow.isEmpty() ? null : (ValueSpecification) overflow.removeFirst(); } else { key = null; } } } else { if (overflow == null) { overflow = new LinkedList<Object>(); } overflow.add(fieldValue); } } } return result; } protected void encodeMarketDataAliases(final FudgeSerializer serializer, final MutableFudgeMsg msg, final Map<ValueSpecification, Collection<ValueSpecification>> marketDataEntries) { final MutableFudgeMsg msgRequirements = msg.addSubMessage(MARKET_DATA_REQUIREMENTS_FIELD, null); final MutableFudgeMsg msgAliases = msg.addSubMessage(MARKET_DATA_ALIASES_FIELD, null); for (final Map.Entry<ValueSpecification, Collection<ValueSpecification>> requirement : marketDataEntries.entrySet()) { final ValueSpecification marketData = requirement.getKey(); serializer.addToMessage(msgRequirements, null, null, marketData); if (requirement.getValue().size() == 1) { final ValueSpecification alias = requirement.getValue().iterator().next(); if (alias.equals(marketData)) { msgAliases.add(null, null, IndicatorType.INSTANCE); } else { serializer.addToMessage(msgAliases, null, null, alias); } } else { final MutableFudgeMsg aliases = msgAliases.addSubMessage(null, null); aliases.add(null, 0, "list"); for (ValueSpecification alias : requirement.getValue()) { if (alias.equals(marketData)) { msgAliases.add(null, null, IndicatorType.INSTANCE); } else { serializer.addToMessage(aliases, null, null, alias); } } } } } protected Map<ValueSpecification, Collection<ValueSpecification>> decodeMarketDataAliases(final FudgeDeserializer deserializer, final FudgeMsg msg) { final FudgeMsg msgRequirements = msg.getMessage(MARKET_DATA_REQUIREMENTS_FIELD); final FudgeMsg msgAliases = msg.getMessage(MARKET_DATA_ALIASES_FIELD); if ((msgRequirements == null) || (msgAliases == null) || msgRequirements.isEmpty()) { return Collections.emptyMap(); } final Map<ValueSpecification, Collection<ValueSpecification>> result = Maps.newHashMapWithExpectedSize(msgRequirements.getNumFields()); final Iterator<FudgeField> itrRequirements = msgRequirements.iterator(); final Iterator<FudgeField> itrAliases = msgAliases.iterator(); while (itrRequirements.hasNext() && itrAliases.hasNext()) { final FudgeField requirement = itrRequirements.next(); final FudgeField alias = itrAliases.next(); final ValueSpecification spec = deserializer.fieldValueToObject(ValueSpecification.class, requirement); if (alias.getValue() == IndicatorType.INSTANCE) { result.put(spec, Collections.singleton(spec)); } else { final FudgeMsg msgAlias = (FudgeMsg) alias.getValue(); final String clazz = msgAlias.getString(0); if ("list".equals(clazz)) { final Collection<ValueSpecification> aliases = new ArrayList<ValueSpecification>(msgAlias.getNumFields() - 1); for (FudgeField aliasField : msgAlias) { if (aliasField.getValue() == IndicatorType.INSTANCE) { aliases.add(spec); } else if (aliasField.getValue() instanceof FudgeMsg) { aliases.add(deserializer.fieldValueToObject(ValueSpecification.class, aliasField)); } } result.put(spec, aliases); } else { result.put(spec, Collections.singleton(deserializer.fieldValueToObject(ValueSpecification.class, alias))); } } } return result; } // TODO - implement private void encodeMarketDataSelections(FudgeSerializer serializer, MutableFudgeMsg msg, Map<DistinctMarketDataSelector, Set<ValueSpecification>> marketDataSelections) { } // TODO - implement private Map<DistinctMarketDataSelector, Set<ValueSpecification>> decodeMarketDataSelections(FudgeDeserializer deserializer, FudgeMsg msg) { return ImmutableMap.of(); } // TODO - implement private void encodeMarketDataFunctionParams(FudgeSerializer serializer, MutableFudgeMsg msg, Map<DistinctMarketDataSelector, FunctionParameters> marketDataSelectionFunctionParameters) { } // TODO - implement private Map<DistinctMarketDataSelector, FunctionParameters> decodeMarketDataFunctionParams(FudgeDeserializer deserializer, FudgeMsg msg) { return ImmutableMap.of(); } @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final CompiledViewCalculationConfiguration object) { final MutableFudgeMsg msg = serializer.newMessage(); serializer.addToMessage(msg, NAME_FIELD, null, object.getName()); encodeComputationTargets(serializer, msg, object.getComputationTargets()); encodeTerminalOutputSpecifications(serializer, msg, object.getTerminalOutputSpecifications()); encodeMarketDataAliases(serializer, msg, object.getMarketDataAliases()); encodeMarketDataSelections(serializer, msg, object.getMarketDataSelections()); encodeMarketDataFunctionParams(serializer, msg, object.getMarketDataSelectionFunctionParameters()); return msg; } @Override public CompiledViewCalculationConfigurationImpl buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { final String name = message.getString(NAME_FIELD); final Set<ComputationTargetSpecification> computationTargets = decodeComputationTargets(deserializer, message); final Map<ValueSpecification, Set<ValueRequirement>> terminalOutputSpecifications = decodeTerminalOutputSpecifications(deserializer, message); final Map<ValueSpecification, Collection<ValueSpecification>> marketDataAliases = decodeMarketDataAliases(deserializer, message); final Map<DistinctMarketDataSelector, Set<ValueSpecification>> marketDataSelections = decodeMarketDataSelections(deserializer, message); final Map<DistinctMarketDataSelector, FunctionParameters> marketDataFunctionParams = decodeMarketDataFunctionParams(deserializer, message); return new CompiledViewCalculationConfigurationImpl(name, computationTargets, terminalOutputSpecifications, marketDataAliases, marketDataSelections, marketDataFunctionParams); } }