public List<Book> getBooks(Set<Integer> isbnSet) throws BookStoreException {
    if (isbnSet == null) {
      throw new BookStoreException(BookStoreConstants.NULL_INPUT);
    }
    List<Book> listBooks = new ArrayList<Book>();
    try {
      bsLock.readLock().lock();
      // Check that all ISBNs that we rate are there first.
      for (Integer ISBN : isbnSet) {
        if (BookStoreUtility.isInvalidISBN(ISBN))
          throw new BookStoreException(BookStoreConstants.ISBN + ISBN + BookStoreConstants.INVALID);
        if (!bookMap.containsKey(ISBN))
          throw new BookStoreException(
              BookStoreConstants.ISBN + ISBN + BookStoreConstants.NOT_AVAILABLE);
      }

      // Get the books
      for (Integer ISBN : isbnSet) {
        listBooks.add(bookMap.get(ISBN).immutableBook());
      }
    } finally {
      bsLock.readLock().unlock();
    }
    return listBooks;
  }
 public List<StockBook> getBooks() {
   List<StockBook> listBooks = new ArrayList<StockBook>();
   try {
     bsLock.readLock().lock();
     Collection<BookStoreBook> bookMapValues = bookMap.values();
     for (BookStoreBook book : bookMapValues) {
       listBooks.add(book.immutableStockBook());
     }
   } finally {
     bsLock.readLock().unlock();
   }
   return listBooks;
 }
  @Override
  public List<Book> getTopRatedBooks(int numBooks) throws BookStoreException {
    // TODO Auto-generated method stub
    // No negative number
    if (numBooks <= 0) {
      throw new BookStoreException("numBooks = " + numBooks + ", but it must be positive");
    }
    Collection<BookStoreBook> books = bookMap.values();
    if (books.isEmpty()) {
      throw new BookStoreException("No books in the bookstore");
    }

    List<BookStoreBook> listRatedBooks = new ArrayList<BookStoreBook>();
    List<Book> listTopRatedBooks = new ArrayList<Book>();
    try {
      bsLock.readLock().lock(); // block other from writing data
      // we only count the book has a rating
      for (BookStoreBook book : books) {
        if (book.getAverageRating() > 0) listRatedBooks.add(book);
      }

      Comparator<BookStoreBook> comparator =
          new Comparator<BookStoreBook>() {
            public int compare(BookStoreBook book1, BookStoreBook book2) {
              return Float.compare(
                  book2.getAverageRating(), book1.getAverageRating()); // get right order of books
            }
          };

      Collections.sort(listRatedBooks, comparator);

      for (BookStoreBook book : listRatedBooks) {
        listTopRatedBooks.add(book.immutableStockBook());
        if (listTopRatedBooks.size() == numBooks) break;
      }
    } finally {
      bsLock.readLock().unlock();
    }

    // return the certain amount of books by its rating
    return listTopRatedBooks;
  }
  public List<Book> getEditorPicks(int numBooks) throws BookStoreException {
    if (numBooks < 0) {
      throw new BookStoreException("numBooks = " + numBooks + ", but it must be positive");
    }

    List<BookStoreBook> listAllEditorPicks = new ArrayList<BookStoreBook>();
    List<Book> listEditorPicks = new ArrayList<Book>();
    try {
      bsLock.readLock().lock();
      Iterator<Entry<Integer, BookStoreBook>> it = bookMap.entrySet().iterator();
      BookStoreBook book;
      // Get all books that are editor picks
      while (it.hasNext()) {
        Entry<Integer, BookStoreBook> pair = (Entry<Integer, BookStoreBook>) it.next();
        book = (BookStoreBook) pair.getValue();
        if (book.isEditorPick()) {
          listAllEditorPicks.add(book);
        }
      }
      // Find numBooks random indices of books that will be picked
      Random rand = new Random();
      Set<Integer> tobePicked = new HashSet<Integer>();
      int rangePicks = listAllEditorPicks.size();
      if (rangePicks < numBooks) {
        throw new BookStoreException("Only " + rangePicks + " editor picks are available.");
      }
      int randNum;
      while (tobePicked.size() < numBooks) {
        randNum = rand.nextInt(rangePicks);
        tobePicked.add(randNum);
      }
      // Get the numBooks random books
      for (Integer index : tobePicked) {
        book = listAllEditorPicks.get(index);
        listEditorPicks.add(book.immutableBook());
      }
    } finally {
      bsLock.readLock().unlock();
    }
    return listEditorPicks;
  }