package org.marketcetera.marketdata.core.rpc;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.xml.bind.JAXBException;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.marketcetera.event.Event;
import org.marketcetera.marketdata.Capability;
import org.marketcetera.marketdata.Content;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.AllEventsRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.AllEventsResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.AvailableCapabilityRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.AvailableCapabilityResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.CancelRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.CancelResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.EventsRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.EventsResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.HeartbeatRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.HeartbeatResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.LastUpdateRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.LastUpdateResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.LoginRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.LoginResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.LogoutRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.LogoutResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.MarketDataRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.MarketDataResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.SnapshotPageRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.SnapshotPageResponse;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.SnapshotRequest;
import org.marketcetera.marketdata.core.rpc.RpcMarketdata.SnapshotResponse;
import org.marketcetera.marketdata.core.webservice.PageRequest;
import org.marketcetera.trade.Instrument;
import org.marketcetera.util.log.SLF4JLoggerProxy;
import org.marketcetera.util.misc.ClassVersion;
import org.marketcetera.util.rpc.RpcCredentials;
import org.marketcetera.util.rpc.RpcServerServices;
import org.marketcetera.util.rpc.RpcServiceSpec;
import org.marketcetera.util.ws.tags.SessionId;
import com.google.protobuf.BlockingService;
import com.google.protobuf.RpcController;
import com.google.protobuf.ServiceException;
/* $License$ */
/**
* Provides market data RPC server-side services.
*
* @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a>
* @version $Id: MarketDataRpcService.java 16901 2014-05-11 16:14:11Z colin $
* @since 2.4.0
*/
@ClassVersion("$Id: MarketDataRpcService.java 16901 2014-05-11 16:14:11Z colin $")
public class MarketDataRpcService<SessionClazz>
implements RpcServiceSpec<SessionClazz>,RpcMarketDataService.BlockingInterface
{
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#login(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.LoginRequest)
*/
@Override
public LoginResponse login(RpcController inController,
LoginRequest inRequest)
throws ServiceException
{
SLF4JLoggerProxy.debug(this,
"{} received authentication request for {}", //$NON-NLS-1$
DESCRIPTION,
inRequest.getUsername());
RpcMarketdata.LoginResponse.Builder responseBuilder = RpcMarketdata.LoginResponse.newBuilder();
try {
SessionId sessionId = serverServices.login(new RpcCredentials(inRequest.getUsername(),
inRequest.getPassword(),
inRequest.getAppId(),
inRequest.getClientId(),
inRequest.getVersionId(),
new Locale(inRequest.getLocale().getLanguage(),
inRequest.getLocale().getCountry(),
inRequest.getLocale().getVariant())));
return responseBuilder.setSessionId(sessionId.getValue()).build();
} catch (Exception e) {
return responseBuilder.setFailed(true).setMessage(e.getMessage()==null?"":e.getMessage()==null?"":e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#logout(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.LogoutRequest)
*/
@Override
public LogoutResponse logout(RpcController inController,
LogoutRequest inRequest)
throws ServiceException
{
SLF4JLoggerProxy.debug(this,
"{} received logout request for {}", //$NON-NLS-1$
DESCRIPTION,
inRequest.getSessionId());
RpcMarketdata.LogoutResponse.Builder responseBuilder = RpcMarketdata.LogoutResponse.newBuilder();
try {
serverServices.logout(inRequest.getSessionId());
return responseBuilder.build();
} catch (Exception e) {
return responseBuilder.setFailed(true).setMessage(e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#heartbeat(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.HeartbeatRequest)
*/
@Override
public HeartbeatResponse heartbeat(RpcController inController,
HeartbeatRequest inRequest)
throws ServiceException
{
RpcMarketdata.HeartbeatResponse.Builder responseBuilder = RpcMarketdata.HeartbeatResponse.newBuilder();
try {
return responseBuilder.setId(inRequest.getId()).build();
} catch (Exception e) {
return responseBuilder.setFailed(true).setMessage(e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#request(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.MarketDataRequest)
*/
@Override
public MarketDataResponse request(RpcController inController,
MarketDataRequest inRequest)
throws ServiceException
{
RpcMarketdata.MarketDataResponse.Builder responseBuilder = RpcMarketdata.MarketDataResponse.newBuilder();
try {
serverServices.validateAndReturnSession(inRequest.getSessionId());
return responseBuilder.setId(serviceAdapter.request(org.marketcetera.marketdata.MarketDataRequestBuilder.newRequestFromString(inRequest.getRequest()),
inRequest.getStreamEvents())).build();
} catch (Exception e) {
return responseBuilder.setFailed(true).setId(-1).setMessage(ExceptionUtils.getRootCauseMessage(e)).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#getLastUpdate(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.LastUpdateRequest)
*/
@Override
public LastUpdateResponse getLastUpdate(RpcController inController,
LastUpdateRequest inRequest)
throws ServiceException
{
RpcMarketdata.LastUpdateResponse.Builder responseBuilder = RpcMarketdata.LastUpdateResponse.newBuilder();
try {
serverServices.validateAndReturnSession(inRequest.getSessionId());
return responseBuilder.setTimestamp(serviceAdapter.getLastUpdate(inRequest.getId())).build();
} catch (Exception e) {
return responseBuilder.setFailed(true).setTimestamp(-1).setMessage(e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#cancel(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.CancelRequest)
*/
@Override
public CancelResponse cancel(RpcController inController,
CancelRequest inRequest)
throws ServiceException
{
RpcMarketdata.CancelResponse.Builder responseBuilder = RpcMarketdata.CancelResponse.newBuilder();
try {
serverServices.validateAndReturnSession(inRequest.getSessionId());
serviceAdapter.cancel(inRequest.getId());
return responseBuilder.build();
} catch (Exception e) {
return responseBuilder.setFailed(true).setMessage(e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#getEvents(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.EventsRequest)
*/
@Override
public EventsResponse getEvents(RpcController inController,
EventsRequest inRequest)
throws ServiceException
{
RpcMarketdata.EventsResponse.Builder responseBuilder = RpcMarketdata.EventsResponse.newBuilder();
try {
serverServices.validateAndReturnSession(inRequest.getSessionId());
Deque<Event> events = serviceAdapter.getEvents(inRequest.getId());
responseBuilder.setId(inRequest.getId());
for(Event event : events) {
responseBuilder.addPayload(serverServices.marshal(event));
}
return responseBuilder.build();
} catch (Exception e) {
return responseBuilder.setId(-1).setFailed(true).setMessage(e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#getAllEvents(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.AllEventsRequest)
*/
@Override
public AllEventsResponse getAllEvents(RpcController inController,
AllEventsRequest inRequest)
throws ServiceException
{
RpcMarketdata.AllEventsResponse.Builder responseBuilder = RpcMarketdata.AllEventsResponse.newBuilder();
try {
serverServices.validateAndReturnSession(inRequest.getSessionId());
Map<Long,LinkedList<Event>> events = serviceAdapter.getAllEvents(inRequest.getIdList());
for(Map.Entry<Long,LinkedList<Event>> entry : events.entrySet()) {
RpcMarketdata.EventsResponse.Builder entryBuilder = RpcMarketdata.EventsResponse.newBuilder().setId(entry.getKey());
for(Event event : entry.getValue()) {
entryBuilder.addPayload(serverServices.marshal(event));
}
responseBuilder.addEvents(entryBuilder.build());
}
return responseBuilder.build();
} catch (Exception e) {
return responseBuilder.setFailed(true).setMessage(e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#getSnapshot(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.SnapshotRequest)
*/
@Override
public SnapshotResponse getSnapshot(RpcController inController,
SnapshotRequest inRequest)
throws ServiceException
{
RpcMarketdata.SnapshotResponse.Builder responseBuilder = RpcMarketdata.SnapshotResponse.newBuilder();
try {
serverServices.validateAndReturnSession(inRequest.getSessionId());
Instrument instrument = serverServices.unmarshall(inRequest.getInstrument().getPayload());
Content content = Content.valueOf(inRequest.getContent().name());
String provider = null;
if(inRequest.hasProvider()) {
provider = inRequest.getProvider();
}
Deque<Event> events = serviceAdapter.getSnapshot(instrument,
content,
provider);
for(Event event : events) {
responseBuilder.addPayload(serverServices.marshal(event));
}
return responseBuilder.build();
} catch (Exception e) {
return responseBuilder.setFailed(true).setMessage(e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#getSnapshotPage(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.SnapshotPageRequest)
*/
@Override
public SnapshotPageResponse getSnapshotPage(RpcController inController,
SnapshotPageRequest inRequest)
throws ServiceException
{
RpcMarketdata.SnapshotPageResponse.Builder responseBuilder = RpcMarketdata.SnapshotPageResponse.newBuilder();
try {
serverServices.validateAndReturnSession(inRequest.getSessionId());
Instrument instrument = serverServices.unmarshall(inRequest.getInstrument().getPayload());
Content content = Content.valueOf(inRequest.getContent().name());
String provider = null;
if(inRequest.hasProvider()) {
provider = inRequest.getProvider();
}
Deque<Event> events = serviceAdapter.getSnapshotPage(instrument,
content,
provider,
new PageRequest(inRequest.getPage().getPage(),
inRequest.getPage().getSize()));
for(Event event : events) {
responseBuilder.addPayload(serverServices.marshal(event));
}
return responseBuilder.build();
} catch (JAXBException e) {
return responseBuilder.setFailed(true).setMessage(e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.marketdata.core.rpc.RpcMarketdata.RpcMarketDataService.BlockingInterface#getAvailableCapability(com.google.protobuf.RpcController, org.marketcetera.marketdata.core.rpc.RpcMarketdata.AvailableCapabilityRequest)
*/
@Override
public AvailableCapabilityResponse getAvailableCapability(RpcController inController,
AvailableCapabilityRequest inRequest)
throws ServiceException
{
RpcMarketdata.AvailableCapabilityResponse.Builder responseBuilder = RpcMarketdata.AvailableCapabilityResponse.newBuilder();
try {
serverServices.validateAndReturnSession(inRequest.getSessionId());
Set<Capability> events = serviceAdapter.getAvailableCapability();
for(Capability event : events) {
responseBuilder.addCapability(RpcMarketdata.ContentAndCapability.valueOf(event.name()));
}
return responseBuilder.build();
} catch (Exception e) {
return responseBuilder.setFailed(true).setMessage(e.getMessage()==null?"":e.getMessage()).build();
}
}
/* (non-Javadoc)
* @see org.marketcetera.util.rpc.RpcServiceSpec#getDescription()
*/
@Override
public String getDescription()
{
return DESCRIPTION;
}
/* (non-Javadoc)
* @see org.marketcetera.util.rpc.RpcServiceSpec#generateService()
*/
@Override
public BlockingService generateService()
{
return RpcMarketDataService.newReflectiveBlockingService(this);
}
/* (non-Javadoc)
* @see org.marketcetera.util.rpc.RpcServiceSpec#setRpcServerServices(org.marketcetera.util.rpc.RpcServerServices)
*/
@Override
public void setRpcServerServices(RpcServerServices<SessionClazz> inServerServices)
{
serverServices = inServerServices;
}
/**
* Validates this object.
*
* @throws IllegalArgumentException if a validation error occurs
*/
@PostConstruct
public void validate()
{
Validate.notNull(serviceAdapter);
}
/**
* Get the serviceAdapter value.
*
* @return a <code>MarketDataServiceAdapter</code> value
*/
public MarketDataServiceAdapter getServiceAdapter()
{
return serviceAdapter;
}
/**
* Sets the serviceAdapter value.
*
* @param inServiceAdapter a <code>MarketDataServiceAdapter</code> value
*/
public void setServiceAdapter(MarketDataServiceAdapter inServiceAdapter)
{
serviceAdapter = inServiceAdapter;
}
/**
* provides a link to the service provider for market data services
*/
private MarketDataServiceAdapter serviceAdapter;
/**
* provides RPC Server services
*/
private RpcServerServices<SessionClazz> serverServices;
/**
* description of the service
*/
private static final String DESCRIPTION = "MATP Marketdata RPC Service"; //$NON-NLS-1$
}