/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.copier.portfolio.writer;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.joda.beans.JodaBeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.opengamma.integration.copier.portfolio.rowparser.JodaBeanRowParser;
import com.opengamma.integration.copier.portfolio.rowparser.RowParser;
import com.opengamma.integration.copier.sheet.SheetFormat;
import com.opengamma.integration.copier.sheet.writer.SheetWriter;
import com.opengamma.master.portfolio.ManageablePortfolio;
import com.opengamma.master.portfolio.ManageablePortfolioNode;
import com.opengamma.master.position.ManageablePosition;
import com.opengamma.master.position.ManageableTrade;
import com.opengamma.master.security.ManageableSecurity;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.tuple.ObjectsPair;
/**
* This class writes a portfolio that might contain multiple security types into a single sheet. The columns are
* established from the set of row parsers that are supplied to the constructor.
*/
public class SingleSheetMultiParserPositionWriter extends SingleSheetPositionWriter {
private static final Logger s_logger = LoggerFactory.getLogger(SingleSheetMultiParserPositionWriter.class);
private Map<String, RowParser> _parserMap = new HashMap<String, RowParser>();
// current row context
private Map<String, String> _currentRow = new HashMap<String, String>();
private RowParser _currentParser;
private ManageablePortfolioNode _currentNode;
private ManageablePortfolio _portfolio;
/** Generate one row per trade instead of one row per position */
private boolean _includeTrades;
public SingleSheetMultiParserPositionWriter(SheetWriter sheet, Map<String, RowParser> rowParsers) {
super(sheet);
ArgumentChecker.notNull(rowParsers, "rowParsers");
_parserMap = rowParsers;
// create virtual manageable portfolio
_currentNode = new ManageablePortfolioNode("Root");
_portfolio = new ManageablePortfolio("Portfolio", _currentNode);
_currentNode.setPortfolioId(_portfolio.getUniqueId());
_includeTrades = false;
}
public SingleSheetMultiParserPositionWriter(SheetWriter sheet,
Map<String, RowParser> rowParsers,
boolean includeTrades) {
this(sheet, rowParsers);
_includeTrades = includeTrades;
}
public SingleSheetMultiParserPositionWriter(SheetWriter sheet, String[] securityTypes) {
this(sheet, getParsers(securityTypes));
_includeTrades = false;
}
public SingleSheetMultiParserPositionWriter(SheetWriter sheet, String[] securityTypes, boolean includeTrades) {
this(sheet, securityTypes);
_includeTrades = includeTrades;
}
public SingleSheetMultiParserPositionWriter(SheetFormat sheetFormat, OutputStream outputStream,
Map<String, RowParser> rowParsers) {
this(SheetWriter.newSheetWriter(sheetFormat, outputStream, getColumns(rowParsers)), rowParsers);
_includeTrades = false;
}
public SingleSheetMultiParserPositionWriter(SheetFormat sheetFormat, OutputStream outputStream,
Map<String, RowParser> rowParsers, boolean includeTrades) {
this(sheetFormat, outputStream, rowParsers);
_includeTrades = includeTrades;
}
public SingleSheetMultiParserPositionWriter(SheetFormat sheetFormat,
OutputStream outputStream,
String[] securityTypes) {
this(SheetWriter.newSheetWriter(sheetFormat, outputStream, getColumns(getParsers(securityTypes))), getParsers(securityTypes));
_includeTrades = false;
}
public SingleSheetMultiParserPositionWriter(SheetFormat sheetFormat,
OutputStream outputStream,
String[] securityTypes,
boolean includeTrades) {
this(sheetFormat, outputStream, securityTypes);
_includeTrades = includeTrades;
}
public SingleSheetMultiParserPositionWriter(String filename, Map<String, RowParser> rowParsers) {
this(SheetWriter.newSheetWriter(filename, getColumns(rowParsers)), rowParsers);
_includeTrades = false;
}
public SingleSheetMultiParserPositionWriter(String filename, Map<String, RowParser> rowParsers, boolean includeTrades) {
this(filename, rowParsers);
_includeTrades = includeTrades;
}
public SingleSheetMultiParserPositionWriter(String filename, String[] securityTypes) {
this(filename, getParsers(securityTypes));
_includeTrades = false;
}
public SingleSheetMultiParserPositionWriter(String filename, String[] securityTypes, boolean includeTrades) {
this(filename, securityTypes);
_includeTrades = includeTrades;
}
@Override
public void addAttribute(String key, String value) {
// Not supported
}
private void writeSecurities(ManageableSecurity[] securities) {
String className = securities[0].getClass().toString();
className = className.substring(className.lastIndexOf('.') + 1).replace("Security", "");
if ((_currentParser = _parserMap.get(className)) != null) { //CSIGNORE
_currentRow.putAll(_currentParser.constructRow(securities));
}
}
@Override
public ObjectsPair<ManageablePosition, ManageableSecurity[]> writePosition(ManageablePosition position, ManageableSecurity[] securities) {
ArgumentChecker.notNull(position, "position");
ArgumentChecker.notNull(securities, "securities");
// Write securities
writeSecurities(securities);
// Write position
if (_currentParser != null) {
// List<ManageableTrade> trades = position.getTrades();
// if (trades.size() > 1) {
// s_logger.warn("Omitting extra trades: only one trade per position is currently supported");
// }
// if (trades.size() > 0) {
// _currentRow.putAll(_currentParser.constructRow(trades.get(0)));
// }
if (_includeTrades) {
// Write each trade as a separate row if the current position contains trades
if (position.getTrades().size() > 0) {
ManageablePosition subPosition = JodaBeanUtils.clone(position);
for (ManageableTrade trade : position.getTrades()) {
Map<String, String> tempRow = new HashMap<>();
tempRow.putAll(_currentRow);
tempRow.putAll(_currentParser.constructRow(trade));
// Set position quantity to its trade's quantity and write position
subPosition.setQuantity(trade.getQuantity());
tempRow.putAll(_currentParser.constructRow(subPosition));
// Flush out the current row with trade
if (!tempRow.isEmpty()) {
getSheet().writeNextRow(tempRow);
}
}
} else {
// Write position
_currentRow.putAll(_currentParser.constructRow(position));
// Flush out the current row (excluding trades)
if (!_currentRow.isEmpty()) {
getSheet().writeNextRow(_currentRow);
}
}
} else {
// Write position
_currentRow.putAll(_currentParser.constructRow(position));
// Export only the first trade of each position or none at all
if (!position.getTrades().isEmpty()) {
_currentRow.putAll(_currentParser.constructRow(position.getTrades().get(0)));
}
if (position.getTrades().size() > 1) {
s_logger.warn("Omitting extra trades: only one trade per position is supported in the current mode");
}
if (!_currentRow.isEmpty()) {
getSheet().writeNextRow(_currentRow);
}
}
}
// Empty the current row buffer
_currentRow = new HashMap<String, String>();
return ObjectsPair.of(position, securities);
}
private static Map<String, RowParser> getParsers(String[] securityTypes) {
Map<String, RowParser> rowParsers = new HashMap<String, RowParser>();
if (securityTypes != null) {
for (String s : securityTypes) {
JodaBeanRowParser parser = JodaBeanRowParser.newJodaBeanRowParser(s);
if (parser != null) {
rowParsers.put(s, parser);
}
}
}
return rowParsers;
}
private static String[] getColumns(Map<String, RowParser> rowParsers) {
Set<String> columns = new HashSet<String>();
for (RowParser rowParser : rowParsers.values()) {
// Combine columns from supplied row parsers
for (String column : rowParser.getColumns()) {
columns.add(column);
}
}
return columns.toArray(new String[columns.size()]);
}
@Override
public void setPath(String[] newPath) {
// Nothing to do here (a specialised subclass might add a 'path' column to store the current path for each row)
}
@Override
public String[] getCurrentPath() {
return new String[] {};
}
}