/** * 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.ArrayList; import java.util.List; 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.wire.types.FudgeWireType; import com.opengamma.engine.value.ValueProperties; /** * Fudge message builder for {@link ValueProperties}. Messages can take the form: * <ul> * <li>The empty property set is an empty message. * <li>A simple property set has a field named {@code with} that contains a sub-message. This in turn contains a field per property - the name of the field is the name of the property. This is either * a: * <ul> * <li>Simple string value * <li>An indicator indicating a wild-card property value * <li>A sub-message containing un-named fields with each possible value of the property. * </ul> * If the property is optional, the sub-message form is used with a field named {@code optional}. If the field is an optional wild-card the sub-message form is used which contains only the * {@code optional} field. * <li>The infinite property set ({@link ValueProperties#all}) has a field named {@code without} that contains an empty sub-message. * <li>The near-infinite property set has a field named {@code without} that contains a field for each of absent entries, the string value of each field is the property name. * </ul> */ @GenericFudgeBuilderFor(ValueProperties.class) public class ValuePropertiesFudgeBuilder implements FudgeBuilder<ValueProperties> { // TODO: The message format described above is not particularly efficient or convenient, but kept for compatibility /** * Field name for the sub-message containing property values. */ public static final String WITH_FIELD = "with"; /** * Field name for the sub-message representing the infinite or near-infinite property set. */ public static final String WITHOUT_FIELD = "without"; /** * Field name for the 'optional' flag. */ public static final String OPTIONAL_FIELD = "optional"; @Override public MutableFudgeMsg buildMessage(final FudgeSerializer serializer, final ValueProperties object) { final MutableFudgeMsg message = serializer.newMessage(); object.toFudgeMsg(message); return message; } @Override public ValueProperties buildObject(final FudgeDeserializer deserializer, final FudgeMsg message) { if (message.isEmpty()) { return ValueProperties.none(); } FudgeMsg subMsg = message.getMessage(WITHOUT_FIELD); if (subMsg != null) { if (subMsg.isEmpty()) { // Infinite return ValueProperties.all(); } else { // Near-infinite final ValueProperties.Builder builder = ValueProperties.all().copy(); for (FudgeField field : subMsg) { if (field.getType().getTypeId() == FudgeWireType.STRING_TYPE_ID) { builder.withoutAny((String) field.getValue()); } } return builder.get(); } } subMsg = message.getMessage(WITH_FIELD); if (subMsg == null) { return ValueProperties.none(); } final ValueProperties.Builder builder = ValueProperties.builder(); for (FudgeField field : subMsg) { final String propertyName = field.getName(); switch (field.getType().getTypeId()) { case FudgeWireType.INDICATOR_TYPE_ID: builder.withAny(propertyName); break; case FudgeWireType.STRING_TYPE_ID: builder.with(propertyName, (String) field.getValue()); break; case FudgeWireType.SUB_MESSAGE_TYPE_ID: { final FudgeMsg subMsg2 = (FudgeMsg) field.getValue(); final List<String> values = new ArrayList<String>(subMsg2.getNumFields()); for (FudgeField field2 : subMsg2) { switch (field2.getType().getTypeId()) { case FudgeWireType.INDICATOR_TYPE_ID: builder.withOptional(propertyName); break; case FudgeWireType.STRING_TYPE_ID: values.add((String) field2.getValue()); break; } } if (!values.isEmpty()) { builder.with(propertyName, values); } break; } } } return builder.get(); } }