/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.integration.copier.snapshot.writer; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.core.marketdatasnapshot.CurveKey; import com.opengamma.core.marketdatasnapshot.CurveSnapshot; import com.opengamma.core.marketdatasnapshot.UnstructuredMarketDataSnapshot; import com.opengamma.core.marketdatasnapshot.ValueSnapshot; import com.opengamma.core.marketdatasnapshot.VolatilitySurfaceKey; import com.opengamma.core.marketdatasnapshot.VolatilitySurfaceSnapshot; import com.opengamma.core.marketdatasnapshot.YieldCurveKey; import com.opengamma.core.marketdatasnapshot.YieldCurveSnapshot; import com.opengamma.id.ExternalIdBundle; import com.opengamma.integration.copier.sheet.writer.XlsSheetWriter; import com.opengamma.integration.copier.sheet.writer.XlsWriter; import com.opengamma.integration.copier.snapshot.SnapshotColumns; import com.opengamma.integration.copier.snapshot.SnapshotType; import com.opengamma.integration.tool.marketdata.MarketDataSnapshotToolUtils; import com.opengamma.util.tuple.ObjectsPair; import com.opengamma.util.tuple.Pair; /** * Export snapshot to XLS, separating snapshot elements into workbook sheets */ public class XlsSnapshotWriter implements SnapshotWriter { private XlsWriter _xlsWriter; private XlsSheetWriter _nameSheet; private XlsSheetWriter _curveSheet; private XlsSheetWriter _yieldCurveSheet; private XlsSheetWriter _globalsSheet; private XlsSheetWriter _surfaceSheet; private static final Logger s_logger = LoggerFactory.getLogger(XlsSnapshotWriter.class); public XlsSnapshotWriter(String filename) { if (filename == null) { throw new OpenGammaRuntimeException("File name omitted, cannot export to file"); } _xlsWriter = new XlsWriter(filename); _nameSheet = new XlsSheetWriter(_xlsWriter.getWorkbook(), SnapshotType.NAME.get()); _curveSheet = new XlsSheetWriter(_xlsWriter.getWorkbook(), SnapshotType.CURVE.get()); _yieldCurveSheet = new XlsSheetWriter(_xlsWriter.getWorkbook(), SnapshotType.YIELD_CURVE.get()); _globalsSheet = new XlsSheetWriter(_xlsWriter.getWorkbook(), SnapshotType.GLOBAL_VALUES.get()); _surfaceSheet = new XlsSheetWriter(_xlsWriter.getWorkbook(), SnapshotType.VOL_SURFACE.get()); } /** * @param snapshot UnstructuredMarketDataSnapshot * @return Map of ID Bundle (delimited with |) to Pair of market and override value */ private Map<String, ObjectsPair<String, String>> buildUnstructuredMarketDataSnapshotMap(UnstructuredMarketDataSnapshot snapshot) { Map<String, ObjectsPair<String, String>> values = new LinkedHashMap<>(); values.put(SnapshotColumns.ID_BUNDLE.get(), ObjectsPair.of(SnapshotColumns.MARKET_VALUE.get(), SnapshotColumns.OVERRIDE_VALUE.get())); for (ExternalIdBundle eib : snapshot.getTargets()) { Map<String, ValueSnapshot> valueSnapshots = snapshot.getTargetValues(eib); if (valueSnapshots.size() > 1) { throw new OpenGammaRuntimeException("XML export only supports a single value snapshot for UnstructuredMarketDataSnapshot. " + eib.toString() + " contains " + valueSnapshots.size() + " ValueSnapshots. " + "Export to CSV in this instance."); } ValueSnapshot valueSnapshot = valueSnapshots.entrySet().iterator().next().getValue(); String market = (valueSnapshot.getMarketValue() == null) ? "" : valueSnapshot.getMarketValue().toString(); String override = (valueSnapshot.getOverrideValue() == null) ? "" : valueSnapshot.getOverrideValue().toString(); values.put(StringUtils.join(eib.getExternalIds(), '|'), ObjectsPair.of(market, override)); } return values; } @Override public void writeVolatilitySurface(Map<VolatilitySurfaceKey, VolatilitySurfaceSnapshot> volatilitySurface) { if (volatilitySurface == null || volatilitySurface.isEmpty()) { s_logger.warn("Snapshot does not contain any Volatility Surfaces."); return; } for (Map.Entry<VolatilitySurfaceKey, VolatilitySurfaceSnapshot> entry : volatilitySurface.entrySet()) { VolatilitySurfaceSnapshot surface = entry.getValue(); Map<String, String> details = new HashMap<>(); details.put(SnapshotColumns.TYPE.get(), SnapshotType.VOL_SURFACE.get()); details.put(SnapshotColumns.NAME.get(), entry.getKey().getName()); details.put(SnapshotColumns.SURFACE_TARGET.get(), entry.getKey().getTarget().toString()); details.put(SnapshotColumns.SURFACE_INSTRUMENT_TYPE.get(), entry.getKey().getInstrumentType()); details.put(SnapshotColumns.SURFACE_QUOTE_TYPE.get(), entry.getKey().getQuoteType()); details.put(SnapshotColumns.SURFACE_QUOTE_UNITS.get(), entry.getKey().getQuoteUnits()); Map<Pair<String, String>, String> marketValueMap = new LinkedHashMap<>(); Map<Pair<String, String>, String> overrideValueMap = new LinkedHashMap<>(); Set<String> xMap = new HashSet<>(); Set<String> yMap = new HashSet<>(); for (Map.Entry<Pair<Object, Object>, ValueSnapshot> value : surface.getValues().entrySet()) { Pair<String, String> ordinals = MarketDataSnapshotToolUtils.ordinalsAsString(value.getKey()); xMap.add(ordinals.getFirst()); yMap.add(ordinals.getSecond()); ValueSnapshot valueSnapshot = value.getValue(); String market = (valueSnapshot.getMarketValue() == null) ? "" : valueSnapshot.getMarketValue().toString(); String override = (valueSnapshot.getOverrideValue() == null) ? "" : valueSnapshot.getOverrideValue().toString(); marketValueMap.put(ordinals, market); overrideValueMap.put(ordinals, override); } _surfaceSheet.writeKeyValueBlock(details); _surfaceSheet.writeMatrix(xMap, yMap, SnapshotColumns.MARKET_VALUE.get(), marketValueMap, Cell.CELL_TYPE_NUMERIC); _surfaceSheet.writeMatrix(xMap, yMap, SnapshotColumns.OVERRIDE_VALUE.get(), overrideValueMap, Cell.CELL_TYPE_NUMERIC); } } @Override public void writeGlobalValues(UnstructuredMarketDataSnapshot globalValues) { if (globalValues == null || globalValues.isEmpty()) { s_logger.warn("Snapshot does not contain any Global Values."); return; } _globalsSheet.writeKeyPairBlock(buildUnstructuredMarketDataSnapshotMap(globalValues)); } @Override public void writeYieldCurves(Map<YieldCurveKey, YieldCurveSnapshot> yieldCurves) { if (yieldCurves == null || yieldCurves.isEmpty()) { s_logger.warn("Snapshot does not contain any Yield Curve Snapshots."); return; } for (Map.Entry<YieldCurveKey, YieldCurveSnapshot> entry : yieldCurves.entrySet()) { YieldCurveSnapshot curve = entry.getValue(); Map<String, String> details = new LinkedHashMap<>(); details.put(SnapshotColumns.NAME.get(), entry.getKey().getName()); details.put(SnapshotColumns.YIELD_CURVE_CURRENCY.get(), entry.getKey().getCurrency().toString()); details.put(SnapshotColumns.INSTANT.get(), curve.getValuationTime().toString()); _yieldCurveSheet.writeKeyValueBlock(details); _yieldCurveSheet.writeKeyPairBlock(buildUnstructuredMarketDataSnapshotMap(curve.getValues())); } } @Override public void writeCurves(Map<CurveKey, CurveSnapshot> curves) { if (curves == null || curves.isEmpty()) { s_logger.warn("Snapshot does not contain any Curve Snapshots."); return; } for (Map.Entry<CurveKey, CurveSnapshot> entry : curves.entrySet()) { CurveSnapshot curve = entry.getValue(); Map<String, String> details = new LinkedHashMap<>(); details.put(SnapshotColumns.NAME.get(), entry.getKey().getName()); details.put(SnapshotColumns.INSTANT.get(), curve.getValuationTime().toString()); _curveSheet.writeKeyValueBlock(details); _curveSheet.writeKeyPairBlock(buildUnstructuredMarketDataSnapshotMap(curve.getValues())); } } @Override public void writeName(String name) { Map<String, String> detail = new HashMap<>(); detail.put(SnapshotType.NAME.get(), name); _nameSheet.writeKeyValueBlock(detail); _nameSheet.decrementCurrentRowIndex(); //this ensures basis name is directly after name, rather than a new block } @Override public void writeBasisViewName(String basisName) { Map<String, String> detail = new HashMap<>(); detail.put(SnapshotType.BASIS_NAME.get(), basisName); _nameSheet.writeKeyValueBlock(detail); } @Override public void close() { _nameSheet.autoSizeAllColumns(); _curveSheet.autoSizeAllColumns(); _yieldCurveSheet.autoSizeAllColumns(); _globalsSheet.autoSizeAllColumns(); _surfaceSheet.autoSizeAllColumns(); _xlsWriter.close(); } @Override public void flush() { // not used here } }