@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 List<RoomOffer> findRoomOffer(final FindRoomCommand command) throws Exception {

    checkNotNull(command, "command");

    // TODO this could give stale data
    try {
      if (command.isAnd()) {
        return new ArrayList<RoomOffer>(
            roomOfferDao.find(
                Arrays.asList(
                    command.getHotel(), command.getLocation(), null, null, null, null, null)));

      } else {
        final ArrayList<UrlyBirdRoomOffer> matchingHotels =
            new ArrayList<UrlyBirdRoomOffer>(
                roomOfferDao.find(
                    Arrays.asList(command.getHotel(), null, null, null, null, null, null)));
        final ArrayList<UrlyBirdRoomOffer> matchingLocations =
            new ArrayList<UrlyBirdRoomOffer>(
                roomOfferDao.find(
                    Arrays.asList(null, command.getLocation(), null, null, null, null, null)));

        final Set<UrlyBirdRoomOffer> union = new HashSet<UrlyBirdRoomOffer>();
        union.addAll(matchingHotels);
        union.addAll(matchingLocations);
        return new ArrayList<RoomOffer>(union);
      }
    } catch (final Exception e) {
      logger.throwing(getClass().getName(), "findRoomOffer", e);
      throw new Exception(e);
    }
  }
  @Override
  public UrlyBirdRoomOffer updateRoomOffer(final UpdateRoomCommand command) throws Exception {

    checkNotNull(command, "command");

    long lock = NOT_LOCKED;
    final List<String> values = command.getNewValues();
    final RoomOffer clientRoomToUpdate = command.getRoomToUpdate();
    final int index = clientRoomToUpdate.getIndex();
    try {
      lock = roomOfferDao.lock(index);

      final RoomOffer dbRoomToUpdate = roomOfferDao.read(index);
      checkStaleRoomData(clientRoomToUpdate, dbRoomToUpdate);

      final UrlyBirdRoomOffer updatedRoomOffer = factory.createRoomOffer(values, index);

      roomOfferDao.update(updatedRoomOffer, lock);
      return updatedRoomOffer;
    } catch (final Exception e) {
      logger.throwing(getClass().getName(), "updateRoomOffer", e);
      throw new Exception(e);
    } finally {
      unlockQuietly(index, lock);
    }
  }
 public void updateUser(User user) {
   try {
     User u = sao.read(user.getUsername());
     u.setPassword(user.getPassword());
     u.setAccessLevel(user.getAccessLevel());
     sao.update(user);
   } catch (DataAccessException e) {
     System.out.println("(User Model) Unable to update product ");
     e.printStackTrace();
   }
 }
 public void removeUser(String username) {
   try {
     sao.delete(username);
   } catch (DataAccessException e) {
     System.out.println("(User Model) Unable to delete product");
   }
 }
 public void addUser(User u) {
   try {
     sao.create(u);
   } catch (DataAccessException e) {
     System.out.println("(User Model) Unable to create user");
     e.printStackTrace();
   }
 }
  /**
   * Unlocks the room at the given index with the given lock without throwing any checked
   * exceptions. The checked exceptions could not reasonably be handled at this layer. This method
   * is inspired by commons-io closeQuietly().
   *
   * @param index the index of the room to unlock.
   * @param lock the lock the room was locked with.
   */
  private void unlockQuietly(final int index, final long lock) {

    if (lock == NOT_LOCKED) {
      return;
    }

    try {
      roomOfferDao.unlock(index, lock);
    } catch (final suncertify.db.SecurityException e) {
      logger.throwing(getClass().getName(), "unlockQuietly", e);
    } catch (final RecordNotFoundException e) {
      logger.throwing(getClass().getName(), "unlockQuietly", e);
    }
  }
  @Override
  public int deleteRoomOffer(final DeleteRoomCommand command) throws Exception {

    checkNotNull(command, "command");

    final RoomOffer clientRoomToDelete = command.getRoomOfferToDelete();
    final int index = clientRoomToDelete.getIndex();
    long lock = NOT_LOCKED;
    try {
      lock = roomOfferDao.lock(index);
      final RoomOffer dbRoomToDelete = roomOfferDao.read(index);

      checkStaleRoomData(clientRoomToDelete, dbRoomToDelete);

      roomOfferDao.delete(index, lock);
      return index;
    } catch (final Exception e) {
      logger.throwing(getClass().getName(), "deleteRoomOffer", e);
      throw new Exception(e);
    } finally {
      unlockQuietly(index, 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;
  }
 public HashMap<String, User> getUsers() {
   return sao.hashList();
 }