/*
* Copyright (C) 2012 - present by Yann Le Tallec.
* Please see distribution for license.
*/
package com.assylias.jbloomberg;
import static com.assylias.jbloomberg.DateUtils.toOffsetDateTime;
import com.bloomberglp.blpapi.Datetime;
import com.bloomberglp.blpapi.Element;
import com.bloomberglp.blpapi.Name;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* A ResultParser to parse the responses received from the Bloomberg Session when sending a Historical Data request.
*
* This implementation is thread safe as the Bloomberg API might send results through more than one thread.
*/
final class IntradayBarResultParser extends AbstractResultParser<IntradayBarData> {
private final static Logger logger = LoggerFactory.getLogger(IntradayBarResultParser.class);
/**
* The various element names
*/
private static final Name BAR_DATA = new Name("barData");
private static final Name BAR_TICK_DATA = new Name("barTickData");
private final String security;
/**
* @param security the Bloomberg identifier of the security
*/
public IntradayBarResultParser(String security) {
this.security = security;
}
@Override
protected void addFieldError(String field) {
throw new UnsupportedOperationException("Intraday Bar Requests can't report a field exception");
}
@Override
protected IntradayBarData getRequestResult() {
return new IntradayBarData(security);
}
/**
* Only the fields we are interested in - the numEvents and value fields will be discarded
*/
private static enum BarTickDataElements {
TIME("time"),
OPEN("open"),
HIGH("high"),
LOW("low"),
CLOSE("close"),
VOLUME("volume"),
NUM_EVENTS("numEvents");
private final Name elementName;
private BarTickDataElements(String elementName) {
this.elementName = new Name(elementName);
}
private Name asName() {
return elementName;
}
}
@Override
protected void parseResponseNoResponseError(Element response) {
if (response.hasElement(BAR_DATA, true)) {
Element barData = response.getElement(BAR_DATA);
parseBarData(barData);
}
}
private void parseBarData(Element barData) {
if (barData.hasElement(BAR_TICK_DATA, true)) {
Element barTickDataArray = barData.getElement(BAR_TICK_DATA);
parseBarTickDataArray(barTickDataArray);
}
}
/**
* There should be no more error at this point and we can happily parse the interesting portion of the response
*
*/
private void parseBarTickDataArray(Element barTickDataArray) {
int countData = barTickDataArray.numValues();
for (int i = 0; i < countData; i++) {
Element fieldData = barTickDataArray.getValueAsElement(i);
Element field = fieldData.getElement(0);
if (!BarTickDataElements.TIME.asName().equals(field.name())) {
throw new AssertionError("Time field is supposed to be first but got: " + field.name());
}
Datetime dt = field.getValueAsDatetime();
for (int j = 1; j < fieldData.numElements(); j++) {
field = fieldData.getElement(j);
addField(toOffsetDateTime(dt), field);
}
}
}
}