private synchronized void addToBook(BookSide side, Tradable trd) throws Exception {
    if (ProductService.getInstance().getMarketState().equals(MarketState.PREOPEN)) {
      switch (side) {
        case BUY:
          buySide.addToBook(trd);
          break;
        case SELL:
          sellSide.addToBook(trd);
          break;
      }
    } else {
      HashMap<String, FillMessage> allFills = null;

      switch (side) {
        case BUY:
          allFills = sellSide.tryTrade(trd);
          break;
        case SELL:
          allFills = buySide.tryTrade(trd);
          break;
      }

      if (allFills != null && !allFills.isEmpty()) {
        this.updateCurrentMarket();
        int difference = trd.getOriginalVolume() - trd.getRemainingVolume();
        Price lastSalePrice = this.determineLastSalePrice(allFills);
        LastSalePublisher.getInstance()
            .publishLastSale(this.productSymbol, lastSalePrice, difference);
      }

      if (trd.getRemainingVolume() > 0) {
        if (trd.getPrice().isMarket()) {
          CancelMessage cm =
              new CancelMessage(
                  trd.getUser(),
                  trd.getProduct(),
                  trd.getPrice(),
                  trd.getRemainingVolume(),
                  "Cancelled",
                  trd.getSide(),
                  trd.getId());

          MessagePublisher.getInstance().publishCancel(cm);
        } else {
          switch (side) {
            case BUY:
              buySide.addToBook(trd);
              break;
            case SELL:
              sellSide.addToBook(trd);
              break;
          }
        }
      }
    }
  }
  public synchronized void checkTooLateToCancel(String orderId) throws Exception {
    String message = "Too Late to Cancel";
    boolean containsOrder = false;

    for (Price p : oldEntries.keySet()) {
      for (Tradable t : oldEntries.get(p)) {
        if (t.getId().equals(orderId)) {
          CancelMessage cm =
              new CancelMessage(
                  t.getUser(),
                  t.getProduct(),
                  t.getPrice(),
                  t.getRemainingVolume(),
                  message,
                  t.getSide(),
                  t.getId());

          MessagePublisher.getInstance().publishCancel(cm);
          containsOrder = true;
        }
      }
    }

    if (containsOrder == false) throw new OrderNotFoundException("Order cannot be found.");
  }
  public synchronized void addOldEntry(Tradable t) throws InvalidTradableValue {
    if (!oldEntries.containsKey(t.getPrice())) {
      oldEntries.put(t.getPrice(), new ArrayList<Tradable>());
    }
    Tradable temp = t;

    temp.setCancelledVolume(t.getRemainingVolume());
    temp.setRemainingVolume(0);

    oldEntries.get(t.getPrice()).add(temp);
  }
  public synchronized void openMarket() throws Exception {
    Price bestBuyPrice = buySide.topOfBookPrice();
    Price bestSellPrice = sellSide.topOfBookPrice();

    if (bestBuyPrice != null && bestSellPrice != null) {
      while (bestBuyPrice.greaterOrEqual(bestSellPrice)
          || bestBuyPrice.isMarket()
          || bestSellPrice.isMarket()) {
        ArrayList<Tradable> topOfBuySide = buySide.getEntriesAtPrice(bestBuyPrice);
        ArrayList<Tradable> toRemove = new ArrayList<Tradable>();
        HashMap<String, FillMessage> allFills = null;

        for (Tradable t : topOfBuySide) {
          allFills = sellSide.tryTrade(t);
          if (t.getRemainingVolume() == 0) {
            toRemove.add(t);
          }
        }

        for (Tradable t : toRemove) {
          buySide.removeTradable(t);
        }
        updateCurrentMarket();

        Price lastSalePrice = this.determineLastSalePrice(allFills);
        int lastSaleVolume = this.determineLastSaleQuantity(allFills);

        LastSalePublisher.getInstance()
            .publishLastSale(productSymbol, lastSalePrice, lastSaleVolume);

        bestBuyPrice = buySide.topOfBookPrice();
        bestSellPrice = sellSide.topOfBookPrice();

        if (bestBuyPrice == null || bestSellPrice == null) break;
      }
    }
  }