public void addCopies(Set<BookCopy> bookCopiesSet) throws BookStoreException {
    int ISBN, numCopies;

    if (bookCopiesSet == null) {
      throw new BookStoreException(BookStoreConstants.NULL_INPUT);
    }
    try {
      bsLock.updateLock().lock();
      for (BookCopy bookCopy : bookCopiesSet) {
        ISBN = bookCopy.getISBN();
        numCopies = bookCopy.getNumCopies();
        if (BookStoreUtility.isInvalidISBN(ISBN))
          throw new BookStoreException(BookStoreConstants.ISBN + ISBN + BookStoreConstants.INVALID);
        if (!bookMap.containsKey(ISBN))
          throw new BookStoreException(BookStoreConstants.ISBN + ISBN + BookStoreConstants.INVALID);
        if (BookStoreUtility.isInvalidNoCopies(numCopies))
          throw new BookStoreException(
              BookStoreConstants.NUM_COPIES + numCopies + BookStoreConstants.INVALID);
      }
      bsLock.writeLock().lock();
      BookStoreBook book;
      // Update the number of copies
      for (BookCopy bookCopy : bookCopiesSet) {
        ISBN = bookCopy.getISBN();
        numCopies = bookCopy.getNumCopies();
        book = bookMap.get(ISBN);
        book.addCopies(numCopies);
      }

    } finally {
      bsLock.writeLock().unlock();
      bsLock.updateLock().unlock();
    }
  }
 public void updateEditorPicks(Set<BookEditorPick> editorPicks) throws BookStoreException {
   // Check that all ISBNs that we add/remove are there first.
   if (editorPicks == null) {
     throw new BookStoreException(BookStoreConstants.NULL_INPUT);
   }
   int ISBNVal;
   try {
     bsLock.updateLock().lock();
     for (BookEditorPick editorPickArg : editorPicks) {
       ISBNVal = editorPickArg.getISBN();
       if (BookStoreUtility.isInvalidISBN(ISBNVal))
         throw new BookStoreException(
             BookStoreConstants.ISBN + ISBNVal + BookStoreConstants.INVALID);
       if (!bookMap.containsKey(ISBNVal))
         throw new BookStoreException(
             BookStoreConstants.ISBN + ISBNVal + BookStoreConstants.NOT_AVAILABLE);
     }
     bsLock.writeLock().lock();
     for (BookEditorPick editorPickArg : editorPicks) {
       bookMap.get(editorPickArg.getISBN()).setEditorPick(editorPickArg.isEditorPick());
     }
   } finally {
     bsLock.writeLock().unlock();
     bsLock.updateLock().unlock();
   }
   return;
 }
  public void buyBooks(Set<BookCopy> bookCopiesToBuy) throws BookStoreException {
    if (bookCopiesToBuy == null) {
      throw new BookStoreException(BookStoreConstants.NULL_INPUT);
    }
    // Check that all ISBNs that we buy are there first.
    int ISBN;
    BookStoreBook book;
    Boolean saleMiss = false;
    try {
      bsLock.updateLock().lock();
      for (BookCopy bookCopyToBuy : bookCopiesToBuy) {
        ISBN = bookCopyToBuy.getISBN();
        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);
        book = bookMap.get(ISBN);
        if (!book.areCopiesInStore(bookCopyToBuy.getNumCopies())) {
          book.addSaleMiss(); // If we cannot sell the copies of the
          // book
          // its a miss
          saleMiss = true;
        }
      }

      // We throw exception now since we want to see how many books in the
      // order incurred misses which is used by books in demand
      if (saleMiss)
        throw new BookStoreException(BookStoreConstants.BOOK + BookStoreConstants.NOT_AVAILABLE);
      bsLock.writeLock().lock();
      // Then make purchase
      for (BookCopy bookCopyToBuy : bookCopiesToBuy) {
        book = bookMap.get(bookCopyToBuy.getISBN());
        book.buyCopies(bookCopyToBuy.getNumCopies());
      }
    } finally {
      bsLock.writeLock().unlock();
      bsLock.updateLock().unlock();
    }
    return;
  }
 @Override
 public List<StockBook> getBooksInDemand() throws BookStoreException {
   // TODO Auto-generated method stub
   bsLock.updateLock().lock();
   List<StockBook> listBooksInDemand = new ArrayList<StockBook>();
   Collection<BookStoreBook> books = bookMap.values();
   if (books.isEmpty()) {
     throw new BookStoreException("No books in the bookstore");
   }
   try {
     for (BookStoreBook book : books) {
       if (book.hadSaleMiss()) {
         listBooksInDemand.add(book.immutableStockBook());
       }
     }
   } finally {
     bsLock.updateLock().unlock();
   }
   return listBooksInDemand;
 }
  @Override
  public void rateBooks(Set<BookRating> bookRating) throws BookStoreException {
    // TODO Auto-generated method stub
    // lock update lock, only allow read
    bsLock.updateLock().lock();
    try {
      /* Check if the input is valid */
      if (bookRating == null) throw new BookStoreException(BookStoreConstants.NULL_INPUT);

      int ISBN, rating;
      BookStoreBook book;
      for (BookRating br : bookRating) {
        ISBN = br.getISBN();
        rating = br.getRating();
        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);
        if (BookStoreUtility.isInvalidRating(rating))
          throw new BookStoreException(
              BookStoreConstants.RATING + rating + BookStoreConstants.INVALID);
      }

      try {
        bsLock.writeLock().lock(); // upgrade to write lock
        /* Inputs are valid so, ready to rate the books change */
        for (BookRating br : bookRating) {
          book = bookMap.get(br.getISBN());
          book.addRating(br.getRating());
        }
      } finally {
        bsLock.writeLock().unlock(); // downgrade to update lock
      }

    } finally {
      bsLock.updateLock().unlock();
    }

    return;
  }
  public void addBooks(Set<StockBook> bookSet) throws BookStoreException {

    if (bookSet == null) {
      throw new BookStoreException(BookStoreConstants.NULL_INPUT);
    }
    try {
      // Check if all are there
      bsLock.updateLock().lock();
      for (StockBook book : bookSet) {
        int ISBN = book.getISBN();
        String bookTitle = book.getTitle();
        String bookAuthor = book.getAuthor();
        int noCopies = book.getNumCopies();
        float bookPrice = book.getPrice();
        if (BookStoreUtility.isInvalidISBN(ISBN)
            || BookStoreUtility.isEmpty(bookTitle)
            || BookStoreUtility.isEmpty(bookAuthor)
            || BookStoreUtility.isInvalidNoCopies(noCopies)
            || bookPrice < 0.0) {
          throw new BookStoreException(
              BookStoreConstants.BOOK + book.toString() + BookStoreConstants.INVALID);
        } else if (bookMap.containsKey(ISBN)) {
          throw new BookStoreException(
              BookStoreConstants.ISBN + ISBN + BookStoreConstants.DUPLICATED);
        }
      }
      bsLock.writeLock().lock();
      for (StockBook book : bookSet) {
        int ISBN = book.getISBN();
        bookMap.put(ISBN, new BookStoreBook(book));
      }
    } finally {
      bsLock.writeLock().unlock();
      bsLock.updateLock().unlock();
    }
    return;
  }