/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.bbg.livedata; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.fudgemsg.FudgeContext; import org.fudgemsg.FudgeMsg; import org.fudgemsg.MutableFudgeMsg; import org.fudgemsg.wire.FudgeMsgReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.bbg.referencedata.ReferenceData; import com.opengamma.bbg.referencedata.ReferenceDataProviderGetRequest; import com.opengamma.bbg.referencedata.ReferenceDataProviderGetResult; import com.opengamma.bbg.referencedata.impl.AbstractReferenceDataProvider; import com.opengamma.util.ArgumentChecker; /** * A reference data provider which uses reference data logged by {@link LoggingReferenceDataProvider} * as its source of data. Requests for data which is not in the log cannot be satisfied. */ public class LoggedReferenceDataProvider extends AbstractReferenceDataProvider { /** Logger. */ private static final Logger s_logger = LoggerFactory.getLogger(LoggedReferenceDataProvider.class); /** * The Fudge contxet. */ private final FudgeContext _fudgeContext; /** * The map of data by security key. */ private final Map<String, ? extends FudgeMsg> _data; /** * Creates an instance that reads from a file. * * @param fudgeContext the Fudge context, not null * @param inputFile the input file, not null */ public LoggedReferenceDataProvider(FudgeContext fudgeContext, File inputFile) { ArgumentChecker.notNull(fudgeContext, "fudgeContext"); ArgumentChecker.notNull(inputFile, "inputFile"); _fudgeContext = fudgeContext; _data = loadFile(fudgeContext, inputFile); //logAvailableData(dataMap); } /** * Loads the input file. * * @param fudgeContext the Fudge context, not null * @param inputFile the input file, not null */ private static Map<String, ? extends FudgeMsg> loadFile(FudgeContext fudgeContext, File inputFile) { Map<String, MutableFudgeMsg> dataMap = new ConcurrentHashMap<String, MutableFudgeMsg>(); FudgeMsgReader reader = null; try { FileInputStream fis = new FileInputStream(inputFile); reader = fudgeContext.createMessageReader(fis); while (reader.hasNext()) { FudgeMsg msg = reader.nextMessage(); LoggedReferenceData loggedData = fudgeContext.fromFudgeMsg(LoggedReferenceData.class, msg); addDataToMap(fudgeContext, dataMap, loggedData); } } catch (FileNotFoundException ex) { throw new OpenGammaRuntimeException("Cannot open " + inputFile + " for reading"); } finally { if (reader != null) { reader.close(); } } reflectTickersToBUIDs(dataMap); return dataMap; } /** * Add extra entries for BUIDs. * * @param dataMap the data map, not null */ private static void reflectTickersToBUIDs(final Map<String, MutableFudgeMsg> dataMap) { final Map<String, MutableFudgeMsg> extra = new HashMap<String, MutableFudgeMsg>(); for (Map.Entry<String, MutableFudgeMsg> entry : dataMap.entrySet()) { final String buid = entry.getValue().getString("ID_BB_UNIQUE"); if (buid != null) { extra.put("/buid/" + buid, entry.getValue()); } } dataMap.putAll(extra); } // private void logAvailableData(Map<String, MutableFudgeMsg> dataMap) { // if (!s_logger.isDebugEnabled()) { // return; // } // StringBuilder sb = new StringBuilder("The following recorded reference data is available:\n"); // for (Map.Entry<String, MutableFudgeMsg> dataEntry : dataMap.entrySet()) { // sb.append("\t").append(dataEntry.getKey()).append(": ").append(dataEntry.getValue()).append("\n"); // } // s_logger.debug(sb.toString()); // } /** * Add data to the map. * * @param fudgeContext the Fudge context, not null * @param dataMap the data map, not null * @param loggedData the logged data, not null */ private static void addDataToMap(FudgeContext fudgeContext, Map<String, MutableFudgeMsg> dataMap, LoggedReferenceData loggedData) { MutableFudgeMsg securityData = dataMap.get(loggedData.getSecurity()); if (securityData == null) { securityData = fudgeContext.newMessage(); dataMap.put(loggedData.getSecurity(), securityData); } if (securityData.hasField(loggedData.getField())) { s_logger.warn("Skipping duplicate field " + loggedData.getField() + " for security " + loggedData.getSecurity()); return; } securityData.add(loggedData.getField(), loggedData.getValue()); } //------------------------------------------------------------------------- @Override protected ReferenceDataProviderGetResult doBulkGet(ReferenceDataProviderGetRequest request) { ReferenceDataProviderGetResult result = new ReferenceDataProviderGetResult(); for (String identifier : request.getIdentifiers()) { // copy the requested fields across into a new message MutableFudgeMsg fieldData = _fudgeContext.newMessage(); FudgeMsg allFieldData = _data.get(identifier); if (allFieldData != null) { for (String fieldName : request.getFields()) { Object fieldValue = allFieldData.getValue(fieldName); fieldData.add(fieldName, fieldValue); } } ReferenceData refData = new ReferenceData(identifier, fieldData); result.addReferenceData(refData); } return result; } }