/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.bbg;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import org.apache.kahadb.util.ByteArrayInputStream;
import org.fudgemsg.FudgeContext;
import org.fudgemsg.FudgeMsg;
import org.fudgemsg.mapping.FudgeSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.bbg.model.SecurityMasterRequestMessage;
import com.opengamma.bbg.model.SecurityMasterRequestMessage.MessageType;
import com.opengamma.bbg.model.SecurityMasterResponseMessage;
import com.opengamma.core.change.ChangeManager;
import com.opengamma.core.change.DummyChangeManager;
import com.opengamma.core.security.AbstractSecuritySource;
import com.opengamma.core.security.Security;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.transport.ByteArrayMessageReceiver;
import com.opengamma.transport.ByteArrayRequestSender;
import com.opengamma.util.ArgumentChecker;
/**
* Provides remote access to the {@link BloombergSecuritySource}.
*/
/**
* Provides remote access to the security master.
*/
public class RemoteBloombergSecuritySource extends AbstractSecuritySource implements SecuritySource {
// TODO: Needs better javadoc to explain why class is needed
/** Logger. */
private static Logger s_logger = LoggerFactory.getLogger(RemoteBloombergSecuritySource.class);
/**
* The request sender.
*/
private final ByteArrayRequestSender _byteArrayRequestSender;
/**
* The fudge context.
*/
private final FudgeContext _fudgeContext;
/**
* Creates an instance.
*
* @param byteArrayRequestSender the sender
*/
public RemoteBloombergSecuritySource(ByteArrayRequestSender byteArrayRequestSender) {
this(byteArrayRequestSender, new FudgeContext());
}
/**
* Creates an instance.
*
* @param byteArrayRequestSender the sender
* @param fudgeContext the context, not null
*/
public RemoteBloombergSecuritySource(ByteArrayRequestSender byteArrayRequestSender, FudgeContext fudgeContext) {
ArgumentChecker.notNull(byteArrayRequestSender, "byteArrayRequestSender");
ArgumentChecker.notNull(fudgeContext, "fudgeContext");
_byteArrayRequestSender = byteArrayRequestSender;
_fudgeContext = fudgeContext;
}
//-------------------------------------------------------------------------
/**
* Gets the sender.
*
* @return the sender
*/
public ByteArrayRequestSender getByteArrayRequestSender() {
return _byteArrayRequestSender;
}
/**
* Gets the Fudge context.
*
* @return the Fudge context
*/
public FudgeContext getFudgeContext() {
return _fudgeContext;
}
@Override
public Collection<Security> get(ExternalIdBundle secKey) {
ArgumentChecker.notNull(secKey, "security key");
RemoteSecurityMasterReceiver receiver = new RemoteSecurityMasterReceiver();
s_logger.debug("sending getSecurities for {} to remote securityMaster", secKey);
SecurityMasterRequestMessage requestMessage = new SecurityMasterRequestMessage();
requestMessage.setMessageType(MessageType.GET_SECURITIES_BY_KEY);
requestMessage.setSecKey(secKey);
FudgeMsg fudgeMsg = requestMessage.toFudgeMsg(new FudgeSerializer(_fudgeContext));
_byteArrayRequestSender.sendRequest(_fudgeContext.toByteArray(fudgeMsg), receiver);
try {
receiver.getLatch().await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
s_logger.info("InterruptedException, request cannot be serviced right now");
throw new OpenGammaRuntimeException("Unable to getSecurities because of InterruptedException", e);
}
byte[] data = receiver.getMessage();
SecurityMasterResponseMessage response = toSecurityMasterResponseMessage(data);
return response.getSecurities();
}
@Override
public Collection<Security> get(ExternalIdBundle bundle, VersionCorrection versionCorrection) {
return get(bundle);
}
@Override
public Security getSingle(ExternalIdBundle secKey) {
ArgumentChecker.notNull(secKey, "security key");
RemoteSecurityMasterReceiver receiver = new RemoteSecurityMasterReceiver();
s_logger.debug("sending getSecurity for {} to remote securityMaster", secKey);
SecurityMasterRequestMessage requestMessage = new SecurityMasterRequestMessage();
requestMessage.setMessageType(MessageType.GET_SECURITY_BY_KEY);
requestMessage.setSecKey(secKey);
FudgeMsg fudgeMsg = requestMessage.toFudgeMsg(new FudgeSerializer(_fudgeContext));
_byteArrayRequestSender.sendRequest(_fudgeContext.toByteArray(fudgeMsg), receiver);
try {
receiver.getLatch().await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
s_logger.info("InterruptedException, request cannot be serviced right now");
throw new OpenGammaRuntimeException("Unable to getSecurity because of InterruptedException", e);
}
byte[] data = receiver.getMessage();
SecurityMasterResponseMessage response = toSecurityMasterResponseMessage(data);
return response.getSecurity();
}
@Override
public Security getSingle(ExternalIdBundle bundle, VersionCorrection versionCorrection) {
return getSingle(bundle);
}
@Override
public Security get(UniqueId uid) {
ArgumentChecker.notNull(uid, "unique identifier");
RemoteSecurityMasterReceiver receiver = new RemoteSecurityMasterReceiver();
s_logger.debug("sending getSecurity for {} to remote securityMaster", uid);
SecurityMasterRequestMessage requestMessage = new SecurityMasterRequestMessage();
requestMessage.setMessageType(MessageType.GET_SECURITY_BY_IDENTITY);
requestMessage.setUniqueId(uid);
FudgeMsg fudgeMsg = requestMessage.toFudgeMsg(new FudgeSerializer(_fudgeContext));
_byteArrayRequestSender.sendRequest(_fudgeContext.toByteArray(fudgeMsg), receiver);
try {
receiver.getLatch().await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
s_logger.info("InterruptedException, request cannot be serviced right now");
throw new OpenGammaRuntimeException("Unable to getSecurity because of InterruptedException", e);
}
byte[] data = receiver.getMessage();
SecurityMasterResponseMessage response = toSecurityMasterResponseMessage(data);
return response.getSecurity();
}
@Override
public Security get(ObjectId objectId, VersionCorrection versionCorrection) {
// This is wrong
return get(objectId.atLatestVersion());
}
//-------------------------------------------------------------------------
@Override
public ChangeManager changeManager() {
return DummyChangeManager.INSTANCE;
}
//-------------------------------------------------------------------------
public Set<String> getOptionChain(ExternalId identifier) {
ArgumentChecker.notNull(identifier, "identifier");
RemoteSecurityMasterReceiver receiver = new RemoteSecurityMasterReceiver();
s_logger.debug("sending getSecurity for {} to remote securityMaster", identifier);
SecurityMasterRequestMessage requestMessage = new SecurityMasterRequestMessage();
requestMessage.setMessageType(MessageType.GET_OPTION_CHAIN);
requestMessage.setSecKey(ExternalIdBundle.of(identifier));
FudgeMsg fudgeMsg = requestMessage.toFudgeMsg(new FudgeSerializer(_fudgeContext));
_byteArrayRequestSender.sendRequest(_fudgeContext.toByteArray(fudgeMsg), receiver);
try {
receiver.getLatch().await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
s_logger.info("InterruptedException, request cannot be serviced right now");
throw new OpenGammaRuntimeException("Unable to getOptionChain because of InterruptedException", e);
}
byte[] data = receiver.getMessage();
SecurityMasterResponseMessage response = toSecurityMasterResponseMessage(data);
return response.getOptionChain();
}
// @Override
// public Collection<Security> getAllBondsOfIssuerType(String issuerType) {
// ArgumentChecker.notNull(issuerType, "issuer type");
// RemoteSecurityMasterReceiver receiver = new RemoteSecurityMasterReceiver();
// s_logger.debug("sending getAllBondsOfIssuerType for {} to remote securityMaster", issuerType);
// SecurityMasterRequestMessage requestMessage = new SecurityMasterRequestMessage();
// requestMessage.setMessageType(MessageType.GET_SECURITIES_BY_BOND_ISSUER_TYPE);
// requestMessage.setBondIssuerType(issuerType);
// FudgeFieldContainer fudgeMsg = requestMessage.toFudgeMsg(_fudgeContext);
// _byteArrayRequestSender.sendRequest(_fudgeContext.toByteArray(fudgeMsg), receiver);
// try {
// receiver.getLatch().await();
// } catch (InterruptedException e) {
// Thread.currentThread().interrupt();
// s_logger.info("InterruptedException, request cannot be serviced right now");
// throw new OpenGammaRuntimeException("Unable to getSecurities because of InterruptedException", e);
// }
// byte[] data = receiver.getMessage();
// SecurityMasterResponseMessage response = toSecurityMasterResponseMessage(data);
// return response.getSecurities();
//
// }
/**
* @param data the input data
* @return the response
*/
protected SecurityMasterResponseMessage toSecurityMasterResponseMessage(byte[] data) {
return _fudgeContext.readObject(SecurityMasterResponseMessage.class, new ByteArrayInputStream(data));
}
private final class RemoteSecurityMasterReceiver implements ByteArrayMessageReceiver {
private final CountDownLatch _latch = new CountDownLatch(1);
private byte[] _message;
@Override
public void messageReceived(byte[] message) {
_message = message;
_latch.countDown();
}
/**
* @return the message
*/
public byte[] getMessage() {
return _message;
}
/**
* @return the latch
*/
public CountDownLatch getLatch() {
return _latch;
}
}
@Override
public Map<UniqueId, Security> get(Collection<UniqueId> uniqueIds) {
throw new UnsupportedOperationException("Bulk loading of security not supported yet!");
}
}