@Override
 @Transactional(propagation = Propagation.REQUIRED)
 public BookEntity getBookById(int bookId) throws ForbiddenException, NoSuchEntityException {
   BookEntity book = bookDao.getNotNull(bookId);
   bookAvailabilityService.isBookAvailable(book);
   return book;
 }
 @Override
 @Transactional
 public Boolean deleteBookToAuthor(int bookId, int authorId)
     throws NoSuchEntityException, ForbiddenException {
   bookAvailabilityService.canDeleteRelationshipToAuthor(bookDao.getNotNull(bookId), authorId);
   return bookAuthorDao.delete(bookId, authorId);
 }
 @Override
 @Transactional
 public Boolean deleteBookToKeyword(int bookId, int authorId)
     throws NoSuchEntityException, ForbiddenException {
   bookAvailabilityService.isCurrentUsersBook(bookDao.getNotNull(bookId));
   return bookKeywordDao.delete(bookId, authorId);
 }
 @Override
 @Transactional(propagation = Propagation.REQUIRED)
 public Boolean deleteBook(int bookId) throws NoSuchEntityException, ForbiddenException {
   BookEntity book = bookDao.getNotNull(bookId);
   bookAvailabilityService.isBookAvailable(book);
   book.setStatus(BookStatusesEnum.DELETED);
   return bookDao.update(book).getStatus().equals(BookStatusesEnum.DELETED);
 }
 @Override
 @Transactional(propagation = Propagation.REQUIRED)
 public Integer update(BookEntity book)
     throws ValidationException, IllegalDatabaseStateException, ForbiddenException,
         NoSuchEntityException, AuthRequiredException {
   bookAvailabilityService.isCurrentUsersBook(book);
   BookEntity bookEntity = bookDao.update(book);
   return bookEntity.getId();
 }
 private Boolean setStatusAndUpdate(Collection<BookEntity> to, BookStatusesEnum statuses)
     throws ForbiddenException {
   for (BookEntity bookEntity : to) {
     bookAvailabilityService.isStatusChangeAvailable(bookEntity, statuses);
     bookEntity.setStatus(statuses);
     if (!bookDao.update(bookEntity).getStatus().equals(statuses)) {
       return false;
     }
   }
   return true;
 }
 @Override
 public Number countBooksForCatalog(SubCategoryEntity subCategoryEntity, BookStatusesEnum status)
     throws ForbiddenException, AuthRequiredException {
   bookAvailabilityService.areBooksWithStatusAvailable(status);
   if (subCategoryEntity == null) {
     throw new IllegalArgumentException();
   }
   Collection<Integer> integers = Sets.newHashSet();
   integers.add(subCategoryEntity.getId());
   return bookDao.countBySubCategories(integers, status);
 }
 @Override
 public Number countBooksWithLanguage(LanguageEntity languageEntity, BookStatusesEnum status)
     throws ForbiddenException, AuthRequiredException {
   bookAvailabilityService.areBooksWithStatusAvailable(status);
   if (languageEntity == null) {
     return bookDao.countBooks(status);
   }
   Collection<Integer> integers = Sets.newHashSet();
   integers.add(languageEntity.getId());
   return bookDao.countBySubCategories(integers, status);
 }
 @Override
 @Transactional
 public boolean changeStatus(int id, BookStatusesEnum status)
     throws NoSuchEntityException, ForbiddenException, WrongStatusException {
   if (status == null) throw new WrongStatusException();
   BookEntity book = bookDao.getNotNull(id);
   bookAvailabilityService.isStatusChangeAvailable(book, status);
   book.setStatus(status);
   if (status == BookStatusesEnum.ACTIVE) book.setDateChanged(new Date());
   book = bookDao.update(book);
   return book != null;
 }
 @Override
 public Number countBooksForCatalog(
     Set<String> categories, Set<String> subcategories, BookStatusesEnum status)
     throws ForbiddenException, AuthRequiredException {
   bookAvailabilityService.areBooksWithStatusAvailable(status);
   if (CollectionUtils.isEmpty(categories) && CollectionUtils.isEmpty(subcategories)) {
     return bookDao.countBooks(status);
   }
   Collection<Integer> integers =
       subcategoryDao.collectSubcategoryIdsByPriority(categories, subcategories);
   return bookDao.countBySubCategories(integers, status);
 }
 @Override
 public Number countBooksForCatalog(CategoryEntity categoryEntity, BookStatusesEnum status)
     throws ForbiddenException, AuthRequiredException {
   bookAvailabilityService.areBooksWithStatusAvailable(status);
   if (categoryEntity == null) {
     return bookDao.countBooks(status);
   }
   Collection<Integer> integers = Sets.newHashSet();
   if (CollectionUtils.isNotEmpty(categoryEntity.getSubcategories())) {
     for (SubCategoryEntity sce : categoryEntity.getSubcategories()) integers.add(sce.getId());
   }
   return bookDao.countBySubCategories(integers, status);
 }
  @Override
  @Transactional(propagation = Propagation.REQUIRED)
  public List<BookEntity> getBooks(int offset, int limit, BookStatusesEnum status)
      throws NoSuchEntityException, NotSupportedFieldException, ForbiddenException,
          AuthRequiredException {
    bookAvailabilityService.areBooksWithStatusAvailable(status);
    List<BookEntity> books = bookDao.getBooksWithStatuses(offset, limit, status);

    if (CollectionUtils.isEmpty(books)) {
      throw new NoSuchEntityException(
          BookEntity.class.getName(),
          String.format("offset %d, limit %d, status %s", offset, limit, status));
    }
    return books;
  }
 @Override
 @Transactional(propagation = Propagation.REQUIRED)
 public Set<BookOnPortalEntity> getBookPortals(int bookId) throws NoSuchEntityException {
   BookEntity book = bookDao.getNotNull(bookId);
   try {
     bookAvailabilityService.isCurrentUsersBook(book);
     return book.getBookPortals();
   } catch (ForbiddenException e) {
     if (book.getBookPortals() == null || book.getBookPortals().size() == 0) return null;
     Set<BookOnPortalEntity> list = new HashSet<BookOnPortalEntity>();
     for (BookOnPortalEntity portal : book.getBookPortals())
       if (BookPortalStatusEnum.ACTIVE.equals(portal.getStatus())) list.add(portal);
     return list;
   }
 }
 @Override
 public List<BookEntity> getBooksForCatalog(
     int offset,
     int limit,
     Set<String> categories,
     Set<String> subcategories,
     BookStatusesEnum status)
     throws NotSupportedFieldException, NoSuchEntityException, ForbiddenException,
         AuthRequiredException {
   bookAvailabilityService.areBooksWithStatusAvailable(status);
   if (CollectionUtils.isEmpty(categories) && CollectionUtils.isEmpty(subcategories)) {
     return getBooks(offset, limit, status);
   }
   Collection<Integer> integers =
       subcategoryDao.collectSubcategoryIdsByPriority(categories, subcategories);
   return bookDao.getBySubCategories(offset, limit, integers, status);
 }
 @Override
 @Transactional(propagation = Propagation.REQUIRED)
 public List<BookEntity> getBooksByIds(
     Iterable<Integer> ids, int count, BookStatusesEnum statusEnum)
     throws NotSupportedFieldException, NoSuchEntityException, ForbiddenException {
   if (ids == null || !ids.iterator().hasNext()) return Lists.newArrayList();
   List<Criterion> criterions = Lists.newArrayList();
   if (statusEnum != null) {
     criterions.add(Restrictions.eq("status", statusEnum));
   } else {
     criterions.add(Restrictions.eq("status", BookStatusesEnum.ACTIVE));
   }
   criterions.add(Restrictions.in("id", Lists.newArrayList(ids)));
   List<BookEntity> res = bookDao.get(0, count, criterions);
   if (sessionUtils.isUserWithAnotherRole(RolesEnum.admin)) {
     if (statusEnum != null && !BookStatusesEnum.ACTIVE.equals(statusEnum)) {
       bookAvailabilityService.areBooksAvailable(res);
     }
   }
   return res;
 }