@Override
  public UrlyBirdRoomOffer bookRoomOffer(final BookRoomCommand command) throws Exception {

    checkNotNull(command, "command");

    final RoomOffer clientRoomToBook = command.getRoomToBook();
    final int roomOfferIndex = clientRoomToBook.getIndex();

    long lock = NOT_LOCKED;
    try {
      lock = roomOfferDao.lock(roomOfferIndex);
      final RoomOffer dbRoomToBook = roomOfferDao.read(roomOfferIndex);

      checkStaleRoomData(clientRoomToBook, dbRoomToBook);

      if (!isRoomBookable.isSatisfiedBy(dbRoomToBook)) {
        throw new Exception("the room to book: " + clientRoomToBook + " is already booked");
      }

      final UrlyBirdRoomOffer bookedRoomOffer =
          factory.copyRoomOfferWithNewCustomer(clientRoomToBook, command.getCustomerId());
      roomOfferDao.update(bookedRoomOffer, lock);
      return bookedRoomOffer;
    } catch (final Exception e) {
      logger.throwing(getClass().getName(), "bookRoomOffer", e);
      throw new Exception(e);
    } finally {
      unlockQuietly(roomOfferIndex, lock);
    }
  }
  @Override
  public UrlyBirdRoomOffer createRoomOffer(final CreateRoomCommand command) throws Exception {

    checkNotNull(command, "command");

    final List<String> values = command.getValues();
    final Date date = factory.getBookableDateFromValues(values);
    if (!isOccupancyIn48Hours.isSatisfiedBy(date)) {
      throw new Exception(
          "the occupany of the new room is not in the next 48 hours, the room can not be added");
    }

    UrlyBirdRoomOffer roomOffer = null;
    try {
      roomOffer = roomOfferDao.create(values);
    } catch (final Exception e) {
      logger.throwing(getClass().getName(), "createRoomOffer", e);
      throw new Exception(e);
    }

    return roomOffer;
  }