/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.copier.snapshot.reader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.threeten.bp.Instant;
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.core.marketdatasnapshot.impl.ManageableCurveSnapshot;
import com.opengamma.core.marketdatasnapshot.impl.ManageableUnstructuredMarketDataSnapshot;
import com.opengamma.core.marketdatasnapshot.impl.ManageableVolatilitySurfaceSnapshot;
import com.opengamma.core.marketdatasnapshot.impl.ManageableYieldCurveSnapshot;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.UniqueId;
import com.opengamma.integration.copier.sheet.reader.XlsSheetReader;
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.money.Currency;
import com.opengamma.util.tuple.ObjectsPair;
import com.opengamma.util.tuple.Pair;
/**
* Reads a snapshot from an imported file
*/
public class XlsSnapshotReader implements SnapshotReader {
private Map<CurveKey, CurveSnapshot> _curves;
private UnstructuredMarketDataSnapshot _global;
private Map<VolatilitySurfaceKey, VolatilitySurfaceSnapshot> _surface;
private Map<YieldCurveKey, YieldCurveSnapshot> _yieldCurve;
private String _name;
private String _basisName;
private XlsSheetReader _nameSheet;
private XlsSheetReader _globalsSheet;
private XlsSheetReader _yieldCurveSheet;
private XlsSheetReader _curveSheet;
private XlsSheetReader _surfaceSheet;
private Workbook _workbook;
private InputStream _fileInputStream;
private final String _valueObject = "Market_Value";
public XlsSnapshotReader(String filename) {
_fileInputStream = openFile(filename);
_workbook = getWorkbook(_fileInputStream);
_curves = new HashMap<>();
_surface = new HashMap<>();
_yieldCurve = new HashMap<>();
buildNameData();
buildGlobalData();
buildYieldCurveData();
buildCurveData();
buildSurfaceData();
}
/**
* Build surface data from xls data, made up of a key/value block of details, a matrix block of market values and
* a matrix block of override values, each block separated by a empty row
*/
private void buildSurfaceData() {
_surfaceSheet = new XlsSheetReader(_workbook, SnapshotType.VOL_SURFACE.get());
//continue reading in each surface object until current row incrementing returns no data
while (true) {
Map<String, String> details = _surfaceSheet.readKeyValueBlock(_surfaceSheet.getCurrentRowIndex(), 0);
if (details.isEmpty() || details == null) {
break;
}
Map<Pair<String, String>, String> marketValues = _surfaceSheet.readMatrix(_surfaceSheet.getCurrentRowIndex(), 0);
Map<Pair<String, String>, String> overrideValues = _surfaceSheet.readMatrix(_surfaceSheet.getCurrentRowIndex(), 0);
ManageableVolatilitySurfaceSnapshot surface = new ManageableVolatilitySurfaceSnapshot();
VolatilitySurfaceKey key = VolatilitySurfaceKey.of(UniqueId.parse(details.get(SnapshotColumns.SURFACE_TARGET.get())),
details.get(SnapshotColumns.NAME.get()),
details.get(SnapshotColumns.SURFACE_INSTRUMENT_TYPE.get()),
details.get(SnapshotColumns.SURFACE_QUOTE_TYPE.get()),
details.get(SnapshotColumns.SURFACE_QUOTE_UNITS.get()));
HashMap<Pair<Object, Object>, ValueSnapshot> values = new HashMap<>();
// use the market value map to add the value and 'lookup' the corresponding override value
for (Map.Entry<Pair<String, String>, String> entry : marketValues.entrySet()) {
Pair rawOrdinals = entry.getKey();
Pair ordinals = MarketDataSnapshotToolUtils.createOrdinatePair(rawOrdinals.getFirst().toString(),
rawOrdinals.getSecond().toString());
String override = overrideValues.get(rawOrdinals);
String market = entry.getValue();
values.put(ordinals, MarketDataSnapshotToolUtils.createValueSnapshot(market, override));
}
surface.setValues(values);
_surface.put(key, surface);
}
}
private Workbook getWorkbook(InputStream inputStream) {
try {
return new HSSFWorkbook(inputStream);
} catch (IOException ex) {
throw new OpenGammaRuntimeException("Error opening Excel workbook: " + ex.getMessage());
}
}
private ExternalIdBundle createExternalIdBundle(String idBundle) {
Iterable<String> iterable = Arrays.asList(idBundle.split("\\|"));
return ExternalIdBundle.parse(iterable);
}
/**
* Build yield curve data from xls data, made up of a key/value block of details and a key/value-pair block of values
* built by getManageableUnstructuredMarketDataSnapshot, each block separated by a empty row
*/
private void buildYieldCurveData() {
_yieldCurveSheet = new XlsSheetReader(_workbook, SnapshotType.YIELD_CURVE.get());
while (true) {
Map<String, String> details = _yieldCurveSheet.readKeyValueBlock(_yieldCurveSheet.getCurrentRowIndex(), 0);
if (details.isEmpty() || details == null) {
break;
}
YieldCurveKey key = YieldCurveKey.of(Currency.of(details.get(SnapshotColumns.YIELD_CURVE_CURRENCY.get())),
details.get(SnapshotColumns.NAME.get()));
Instant instant = Instant.parse(details.get(SnapshotColumns.INSTANT.get()));
ManageableUnstructuredMarketDataSnapshot snapshot = getManageableUnstructuredMarketDataSnapshot(_yieldCurveSheet);
ManageableYieldCurveSnapshot curve = ManageableYieldCurveSnapshot.of(instant, snapshot);
_yieldCurve.put(key, curve);
}
}
/**
* Build curve data from xls data, made up of a key/value block of details and a key/value-pair block of values
* built by getManageableUnstructuredMarketDataSnapshot, each block separated by a empty row
*/
private void buildCurveData() {
_curveSheet = new XlsSheetReader(_workbook, SnapshotType.CURVE.get());
while (true) {
Map<String, String> details = _curveSheet.readKeyValueBlock(_curveSheet.getCurrentRowIndex(), 0);
if (details.isEmpty() || details == null) {
break;
}
ManageableCurveSnapshot curve = new ManageableCurveSnapshot();
ManageableUnstructuredMarketDataSnapshot snapshot = getManageableUnstructuredMarketDataSnapshot(_curveSheet);
Instant instant = Instant.parse(details.get(SnapshotColumns.INSTANT.get()));
curve.setValuationTime(instant);
curve.setValues(snapshot);
_curves.put(CurveKey.of(details.get(SnapshotColumns.NAME.get())), curve);
}
}
private ManageableUnstructuredMarketDataSnapshot getManageableUnstructuredMarketDataSnapshot(XlsSheetReader sheet) {
//Skip the header row
Map<String, ObjectsPair<String, String>> map = sheet.readKeyPairBlock(sheet.getCurrentRowIndex() + 1, 0);
ManageableUnstructuredMarketDataSnapshot builder = new ManageableUnstructuredMarketDataSnapshot();
for (Map.Entry<String, ObjectsPair<String, String>> entry : map.entrySet()) {
builder.putValue(createExternalIdBundle(entry.getKey()),
_valueObject,
MarketDataSnapshotToolUtils.createValueSnapshot(entry.getValue().getFirst(),
entry.getValue().getSecond()));
}
return builder;
}
/**
* Build global data from xls data, made up of a key/value-pair block of values
* built by getManageableUnstructuredMarketDataSnapshot, should only consist of one block
*/
private void buildGlobalData() {
_globalsSheet = new XlsSheetReader(_workbook, SnapshotType.GLOBAL_VALUES.get());
_global = getManageableUnstructuredMarketDataSnapshot(_globalsSheet);
}
/**
* Name data is made up of two separate blocks (name and basis name) which are special cased on writing the data
* so that they can be read in as on key value block
*/
private void buildNameData() {
_nameSheet = new XlsSheetReader(_workbook, SnapshotType.NAME.get());
Map<String, String> nameMap = _nameSheet.readKeyValueBlock(_nameSheet.getCurrentRowIndex(), 0);
_name = nameMap.get(SnapshotType.NAME.get());
_basisName = nameMap.get(SnapshotType.BASIS_NAME.get());
}
protected static InputStream openFile(String filename) {
// Open input file for reading
FileInputStream fileInputStream;
try {
fileInputStream = new FileInputStream(filename);
} catch (FileNotFoundException ex) {
throw new OpenGammaRuntimeException("Could not open file " + filename + " for reading, exiting immediately.");
}
return fileInputStream;
}
@Override
public Map<CurveKey, CurveSnapshot> readCurves() {
return _curves;
}
@Override
public UnstructuredMarketDataSnapshot readGlobalValues() {
return _global;
}
@Override
public Map<VolatilitySurfaceKey, VolatilitySurfaceSnapshot> readVolatilitySurfaces() {
return _surface;
}
@Override
public Map<YieldCurveKey, YieldCurveSnapshot> readYieldCurves() {
return _yieldCurve;
}
@Override
public void close() {
//XlsSheetReader takes care of closing the input stream
}
@Override
public String getName() {
return _name;
}
@Override
public String getBasisViewName() {
return _basisName;
}
}