/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.fudgemsg; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; import org.fudgemsg.FudgeField; import org.fudgemsg.FudgeMsg; import org.fudgemsg.MutableFudgeMsg; import org.fudgemsg.mapping.FudgeBuilderFor; import org.fudgemsg.mapping.FudgeDeserializer; import org.fudgemsg.mapping.FudgeSerializer; import com.opengamma.financial.analytics.DoubleCurrencyLabelledMatrix2D; import com.opengamma.financial.analytics.DoubleLabelledMatrix2D; import com.opengamma.util.ClassUtils; import com.opengamma.util.money.Currency; /** * */ final class LabelledMatrix2DBuilder { private static final String MATRIX_FIELD = "matrix"; private static final String X_TITLE_FIELD = "xTitle"; private static final String Y_TITLE_FIELD = "yTitle"; private static final String VALUES_TITLE_FIELD = "valuesTitle"; private static final int X_LABEL_TYPE_ORDINAL = 0; private static final int X_KEY_ORDINAL = 1; private static final int X_LABEL_ORDINAL = 2; private static final int Y_LABEL_TYPE_ORDINAL = 3; private static final int Y_KEY_ORDINAL = 4; private static final int Y_LABEL_ORDINAL = 5; private static final int VALUE_ORDINAL = 6; private LabelledMatrix2DBuilder() { } @FudgeBuilderFor(DoubleLabelledMatrix2D.class) public static final class DoubleLabelledMatrix2DBuilder extends AbstractFudgeBuilder<DoubleLabelledMatrix2D> { @Override protected void buildMessage(FudgeSerializer serializer, MutableFudgeMsg message, DoubleLabelledMatrix2D object) { MutableFudgeMsg msg = serializer.newMessage(); Double[] xKeys = object.getXKeys(); Object[] xLabels = object.getXLabels(); Double[] yKeys = object.getYKeys(); Object[] yLabels = object.getYLabels(); double[][] values = object.getValues(); int n = yKeys.length; int m = xKeys.length; for (int i = 0; i < n; i++) { msg.add(Y_LABEL_TYPE_ORDINAL, yLabels[i].getClass().getName()); msg.add(Y_KEY_ORDINAL, yKeys[i]); serializer.addToMessage(msg, null, Y_LABEL_ORDINAL, yLabels[i]); for (int j = 0; j < m; j++) { if (i == 0) { msg.add(X_LABEL_TYPE_ORDINAL, xLabels[j].getClass().getName()); msg.add(X_KEY_ORDINAL, xKeys[j]); serializer.addToMessage(msg, null, X_LABEL_ORDINAL, xLabels[j]); } msg.add(VALUE_ORDINAL, values[i][j]); } } message.add(MATRIX_FIELD, msg); if (object.getXTitle() != null) { message.add(X_TITLE_FIELD, object.getXTitle()); } if (object.getYTitle() != null) { message.add(Y_TITLE_FIELD, object.getYTitle()); } if (object.getValuesTitle() != null) { message.add(VALUES_TITLE_FIELD, object.getValuesTitle()); } } @Override public DoubleLabelledMatrix2D buildObject(FudgeDeserializer deserializer, FudgeMsg message) { FudgeMsg msg = message.getMessage(MATRIX_FIELD); Queue<String> xLabelTypes = new LinkedList<String>(); Queue<FudgeField> xLabelValues = new LinkedList<FudgeField>(); Queue<String> yLabelTypes = new LinkedList<String>(); Queue<FudgeField> yLabelValues = new LinkedList<FudgeField>(); final List<Double> xKeys = new LinkedList<Double>(); final List<Object> xLabels = new LinkedList<Object>(); final List<Double> yKeys = new LinkedList<Double>(); final List<Object> yLabels = new LinkedList<Object>(); final List<List<Double>> values = new LinkedList<List<Double>>(); boolean newRow = true; int count = -1; for (final FudgeField field : msg) { switch (field.getOrdinal()) { case X_LABEL_TYPE_ORDINAL: xLabelTypes.add((String) field.getValue()); break; case X_KEY_ORDINAL: xKeys.add((Double) field.getValue()); break; case X_LABEL_ORDINAL: xLabelValues.add(field); break; case Y_LABEL_TYPE_ORDINAL: newRow = true; count++; yLabelTypes.add((String) field.getValue()); break; case Y_KEY_ORDINAL: yKeys.add((Double) field.getValue()); break; case Y_LABEL_ORDINAL: yLabelValues.add(field); break; case VALUE_ORDINAL: Double value = (Double) field.getValue(); if (newRow) { List<Double> row = new ArrayList<Double>(); row.add(value); values.add(row); newRow = false; } else { values.get(count).add(value); } break; } if (!xLabelTypes.isEmpty() && !xLabelValues.isEmpty()) { // Have a type and a value, which can be consumed final String labelType = xLabelTypes.remove(); Class<?> labelClass = ClassUtils.loadClassRuntime(labelType); final FudgeField labelValue = xLabelValues.remove(); final Object label = deserializer.fieldValueToObject(labelClass, labelValue); xLabels.add(label); } if (!yLabelTypes.isEmpty() && !yLabelValues.isEmpty()) { // Have a type and a value, which can be consumed final String labelType = yLabelTypes.remove(); Class<?> labelClass = ClassUtils.loadClassRuntime(labelType); final FudgeField labelValue = yLabelValues.remove(); final Object label = deserializer.fieldValueToObject(labelClass, labelValue); yLabels.add(label); } } final String xTitle = message.getString(X_TITLE_FIELD); final String yTitle = message.getString(Y_TITLE_FIELD); final String valuesTitle = message.getString(VALUES_TITLE_FIELD); final int matrixRowSize = yKeys.size(); final int matrixColumnSize = xKeys.size(); final Double[] xKeysArray = new Double[matrixColumnSize]; final Object[] xLabelsArray = new Object[matrixColumnSize]; final Double[] yKeysArray = new Double[matrixRowSize]; final Object[] yLabelsArray = new Object[matrixRowSize]; final double[][] valuesArray = new double[matrixRowSize][matrixColumnSize]; for (int i = 0; i < matrixRowSize; i++) { yKeysArray[i] = yKeys.get(i); yLabelsArray[i] = yLabels.get(i); for (int j = 0; j < matrixColumnSize; j++) { if (i == 0) { xKeysArray[j] = xKeys.get(j); xLabelsArray[j] = xLabels.get(j); } valuesArray[i][j] = values.get(i).get(j); } } return new DoubleLabelledMatrix2D(xKeysArray, xLabelsArray, xTitle, yKeysArray, yLabelsArray, yTitle, valuesArray, valuesTitle); } } @FudgeBuilderFor(DoubleCurrencyLabelledMatrix2D.class) public static final class DoubleCurrencyLabelledMatrix2DBuilder extends AbstractFudgeBuilder<DoubleCurrencyLabelledMatrix2D> { @Override protected void buildMessage(FudgeSerializer serializer, MutableFudgeMsg message, DoubleCurrencyLabelledMatrix2D object) { MutableFudgeMsg msg = serializer.newMessage(); Double[] xKeys = object.getXKeys(); Object[] xLabels = object.getXLabels(); Currency[] yKeys = object.getYKeys(); Object[] yLabels = object.getYLabels(); double[][] values = object.getValues(); int n = yKeys.length; int m = xKeys.length; for (int i = 0; i < n; i++) { msg.add(Y_LABEL_TYPE_ORDINAL, yLabels[i].getClass().getName()); msg.add(Y_KEY_ORDINAL, yKeys[i]); serializer.addToMessage(msg, null, Y_LABEL_ORDINAL, yLabels[i]); for (int j = 0; j < m; j++) { if (i == 0) { msg.add(X_LABEL_TYPE_ORDINAL, xLabels[j].getClass().getName()); msg.add(X_KEY_ORDINAL, xKeys[j]); serializer.addToMessage(msg, null, X_LABEL_ORDINAL, xLabels[j]); } msg.add(VALUE_ORDINAL, values[i][j]); } } message.add(MATRIX_FIELD, msg); if (object.getXTitle() != null) { message.add(X_TITLE_FIELD, object.getXTitle()); } if (object.getYTitle() != null) { message.add(Y_TITLE_FIELD, object.getYTitle()); } if (object.getValuesTitle() != null) { message.add(VALUES_TITLE_FIELD, object.getValuesTitle()); } } @Override public DoubleCurrencyLabelledMatrix2D buildObject(FudgeDeserializer deserializer, FudgeMsg message) { FudgeMsg msg = message.getMessage(MATRIX_FIELD); Queue<String> xLabelTypes = new LinkedList<String>(); Queue<FudgeField> xLabelValues = new LinkedList<FudgeField>(); Queue<String> yLabelTypes = new LinkedList<String>(); Queue<FudgeField> yLabelValues = new LinkedList<FudgeField>(); final List<Double> xKeys = new LinkedList<Double>(); final List<Object> xLabels = new LinkedList<Object>(); final List<Currency> yKeys = new LinkedList<Currency>(); final List<Object> yLabels = new LinkedList<Object>(); final List<List<Double>> values = new LinkedList<List<Double>>(); boolean newRow = true; int count = -1; for (final FudgeField field : msg) { switch (field.getOrdinal()) { case X_LABEL_TYPE_ORDINAL: xLabelTypes.add((String) field.getValue()); break; case X_KEY_ORDINAL: xKeys.add((Double) field.getValue()); break; case X_LABEL_ORDINAL: xLabelValues.add(field); break; case Y_LABEL_TYPE_ORDINAL: newRow = true; count++; yLabelTypes.add((String) field.getValue()); break; case Y_KEY_ORDINAL: yKeys.add(deserializer.fieldValueToObject(Currency.class, field)); break; case Y_LABEL_ORDINAL: yLabelValues.add(field); break; case VALUE_ORDINAL: Double value = (Double) field.getValue(); if (newRow) { List<Double> row = new ArrayList<Double>(); row.add(value); values.add(row); newRow = false; } else { values.get(count).add(value); } break; } if (!xLabelTypes.isEmpty() && !xLabelValues.isEmpty()) { // Have a type and a value, which can be consumed final String labelType = xLabelTypes.remove(); Class<?> labelClass = ClassUtils.loadClassRuntime(labelType); final FudgeField labelValue = xLabelValues.remove(); final Object label = deserializer.fieldValueToObject(labelClass, labelValue); xLabels.add(label); } if (!yLabelTypes.isEmpty() && !yLabelValues.isEmpty()) { // Have a type and a value, which can be consumed final String labelType = yLabelTypes.remove(); Class<?> labelClass = ClassUtils.loadClassRuntime(labelType); final FudgeField labelValue = yLabelValues.remove(); final Object label = deserializer.fieldValueToObject(labelClass, labelValue); yLabels.add(label); } } final String xTitle = message.getString(X_TITLE_FIELD); final String yTitle = message.getString(Y_TITLE_FIELD); final String valuesTitle = message.getString(VALUES_TITLE_FIELD); final int matrixRowSize = yKeys.size(); final int matrixColumnSize = xKeys.size(); final Double[] xKeysArray = new Double[matrixColumnSize]; final Object[] xLabelsArray = new Object[matrixColumnSize]; final Currency[] yKeysArray = new Currency[matrixRowSize]; final Object[] yLabelsArray = new Object[matrixRowSize]; final double[][] valuesArray = new double[matrixRowSize][matrixColumnSize]; for (int i = 0; i < matrixRowSize; i++) { yKeysArray[i] = yKeys.get(i); yLabelsArray[i] = yLabels.get(i); for (int j = 0; j < matrixColumnSize; j++) { if (i == 0) { xKeysArray[j] = xKeys.get(j); xLabelsArray[j] = xLabels.get(j); } valuesArray[i][j] = values.get(i).get(j); } } return new DoubleCurrencyLabelledMatrix2D(xKeysArray, xLabelsArray, xTitle, yKeysArray, yLabelsArray, yTitle, valuesArray, valuesTitle); } } }