/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.amqp.rabbit.stocks.web;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.PriorityBlockingQueue;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.stocks.domain.Quote;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
import org.springframework.amqp.rabbit.stocks.gateway.StockServiceGateway;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author Dave Syer
*
*/
@Controller
public class QuoteController {
private static Log logger = LogFactory.getLog(QuoteController.class);
private StockServiceGateway stockServiceGateway;
private ConcurrentMap<String, TradeResponse> responses = new ConcurrentHashMap<String, TradeResponse>();
private Queue<Quote> quotes = new PriorityBlockingQueue<Quote>(100, new QuoteComparator());
private long timeout = 30000; // 30 seconds of data
public void setStockServiceGateway(StockServiceGateway stockServiceGateway) {
this.stockServiceGateway = stockServiceGateway;
}
public void handleTrade(TradeResponse response) {
logger.info("Client received: " + response);
String key = response.getRequestId();
responses.putIfAbsent(key, response);
Collection<TradeResponse> queue = new ArrayList<TradeResponse>(responses.values());
long timestamp = System.currentTimeMillis() - timeout;
for (Iterator<TradeResponse> iterator = queue.iterator(); iterator.hasNext();) {
TradeResponse tradeResponse = iterator.next();
if (tradeResponse.getTimestamp() < timestamp) {
responses.remove(tradeResponse.getRequestId());
}
}
}
public void handleQuote(Quote message) {
logger.info("Client received: " + message);
long timestamp = System.currentTimeMillis() - timeout;
for (Iterator<Quote> iterator = quotes.iterator(); iterator.hasNext();) {
Quote quote = iterator.next();
if (quote.getTimestamp() < timestamp) {
iterator.remove();
}
}
quotes.add(message);
}
@RequestMapping("/quotes")
@ResponseBody
public List<Quote> quotes(@RequestParam(required = false) Long timestamp) {
if (timestamp == null) {
timestamp = 0L;
}
ArrayList<Quote> list = new ArrayList<Quote>();
for (Quote quote : quotes) {
if (quote.getTimestamp() > timestamp) {
list.add(quote);
}
}
Collections.reverse(list);
return list;
}
@RequestMapping(value = "/trade", method = RequestMethod.POST)
@ResponseBody
public TradeRequest trade(@ModelAttribute TradeRequest tradeRequest) {
String ticker = tradeRequest.getTicker();
Long quantity = tradeRequest.getQuantity();
if (quantity == null || quantity <= 0 || !StringUtils.hasText(ticker)) {
// error
return tradeRequest;
} else {
// Fake rest of request while UI is basic
tradeRequest.setAccountName("ACCT-123");
tradeRequest.setBuyRequest(true);
tradeRequest.setOrderType("MARKET");
tradeRequest.setRequestId("REQ-1");
tradeRequest.setUserName("Joe Trader");
tradeRequest.setUserName("Joe");
stockServiceGateway.send(tradeRequest);
}
return tradeRequest;
}
@RequestMapping(value = "/trade", method = RequestMethod.GET)
@ResponseBody
public TradeResponse response(@RequestParam String requestId) {
TradeResponse result = responses.get(requestId);
return result;
}
private static class QuoteComparator implements Comparator<Quote> {
public int compare(Quote o1, Quote o2) {
return new Long(o1.getTimestamp() - o2.getTimestamp()).intValue();
}
}
}