package io.pivotal.web.controller; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.TreeSet; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import io.pivotal.web.domain.CompanyInfo; import io.pivotal.web.domain.Order; import io.pivotal.web.domain.Quote; import io.pivotal.web.domain.Search; import io.pivotal.web.service.MarketService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ExceptionHandler; 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.client.HttpServerErrorException; import org.springframework.web.servlet.ModelAndView; @Controller public class TradeController { private static final Logger logger = LoggerFactory .getLogger(TradeController.class); @Autowired private MarketService marketService; @RequestMapping(value = "/trade", method = RequestMethod.GET) public String showTrade(Model model) { logger.debug("/trade.GET"); model.addAttribute("search", new Search()); //check if user is logged in! Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { String currentUserName = authentication.getName(); logger.debug("User logged in: " + currentUserName); model.addAttribute("order", new Order()); //TODO: add account summary? try { model.addAttribute("portfolio",marketService.getPortfolio(currentUserName)); } catch (HttpServerErrorException e) { model.addAttribute("portfolioRetrievalError",e.getMessage()); } } return "trade"; } @RequestMapping(value = "/trade", method = RequestMethod.POST) public String showTrade(Model model, @ModelAttribute("search") Search search) { logger.debug("/trade.POST - symbol: " + search.getName()); model.addAttribute("search", search); if (search.getName() == null || search.getName().equals("") ) { model.addAttribute("quotes", new ArrayList<Quote>()); } else { List<Quote> newQuotes = getQuotes(search.getName()); model.addAttribute("quotes", newQuotes); } //check if user is logged in! Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { String currentUserName = authentication.getName(); logger.debug("User logged in: " + currentUserName); model.addAttribute("order", new Order()); //TODO: add portfolio and account summary. try { model.addAttribute("portfolio",marketService.getPortfolio(currentUserName)); } catch (HttpServerErrorException e) { model.addAttribute("portfolioRetrievalError",e.getMessage()); } } return "trade"; } @RequestMapping(value = "/order", method = RequestMethod.POST) public String buy(Model model, @ModelAttribute("order") Order order) { model.addAttribute("search", new Search()); // buy the order after setting attributes not set by the UI. //check if user is logged in! Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { String currentUserName = authentication.getName(); logger.debug("/order ORDER: " + order); order.setAccountId(currentUserName); order.setCompletionDate(new Date()); Order result = marketService.sendOrder(order); model.addAttribute("savedOrder", result); model.addAttribute("order", new Order()); try { model.addAttribute("portfolio",marketService.getPortfolio(currentUserName)); } catch (HttpServerErrorException e) { model.addAttribute("portfolioRetrievalError",e.getMessage()); } } else { //should never get here!!! } return "trade"; } private List<Quote> getQuotes(String companyName) { logger.debug("Fetching quotes for companies that have: " + companyName + " in name or symbol"); List<CompanyInfo> companies = marketService.getCompanies(companyName); /* * Sleuth currently doesn't work with parallelStreams */ //get district companyinfos and get their respective quotes in parallel. //List<Quote> result = companies.stream().collect(Collectors.toCollection( // () -> new TreeSet<CompanyInfo>((p1, p2) -> p1.getSymbol().compareTo(p2.getSymbol())) // )).parallelStream().map(n -> getQuote(n.getSymbol())).collect(Collectors.toList()); List<Quote> result = companies.stream(). collect(Collectors.toCollection(() -> new TreeSet<>((p1, p2) -> p1.getSymbol().compareTo(p2.getSymbol())))).stream(). map(n -> getQuote(n.getSymbol()).get(0)). collect(Collectors.toList()); List<Quote> quotes = result.parallelStream().filter(n -> n.getStatus().startsWith("SUCCESS")).collect(Collectors.toList()); return quotes; } private List<Quote> getQuote(String symbol) { return marketService.getQuotes(symbol); } @ExceptionHandler({ Exception.class }) public ModelAndView error(HttpServletRequest req, Exception exception) { logger.debug("Handling error: " + exception); logger.warn("Exception:", exception); ModelAndView model = new ModelAndView(); model.addObject("errorCode", exception.getMessage()); model.addObject("errorMessage", exception); model.setViewName("error"); return model; } }