/**
   * Deletes a topic, including all of its messages and TopicUsers
   *
   * @param topic The topic to delete
   * @param userRequestingDeletion The user who requested the topic be deleted
   * @throws AccessDeniedException
   */
  public void deleteTopic(JMSTopic topic, JMSUser userRequestingDeletion)
      throws AccessDeniedException {
    if (userRequestingDeletion.equals(topic.getOwner())) {
      // If the topic does not contain null fields
      if (isValidTopic(topic)) {
        try {
          Transaction transaction = TransactionHelper.getTransaction(10000l);

          space.takeIfExists(topic, transaction, 3000l);

          deleteAllTopicUsers(topic, transaction);
          MessageService.getMessageService().deleteAllTopicMessages(topic, transaction);

          // Writes a JMSTopicDeleted object so listeners know the
          // topic
          // has been removed
          space.write(new JMSTopicDeleted(topic), transaction, 1000l * 60l);

          transaction.commit();
        } catch (Exception e) {
          e.printStackTrace();
        }
      } else {
        System.err.println(
            "Attempted to delete topic with on or more null fields.  "
                + "Due to how JavaSpaces work, this will delete one at random and is not allowed.");
      }
    } else {
      throw new AccessDeniedException("Only the topic's owner can delete the topic");
    }
  }
  /**
   * Removes a given user from a given topic
   *
   * @param topic The topic to remove the user from
   * @param user The user to remove from the topic
   */
  public void removeTopicUser(JMSTopic topic, JMSUser user) {
    try {
      Transaction transaction = TransactionHelper.getTransaction();

      boolean removed = false;
      JMSTopicUser template = new JMSTopicUser(topic, user);

      // If the space is in a bad state and has duplicate users in a
      // topic, this while loop ensures they are all removed
      while (space.takeIfExists(template, transaction, 1000) != null) {
        removed = true;
      }

      // Put a JMSTopicUserRemoved object in the space so listeners can
      // pick them up and remove them from other user's lists
      if (removed) {
        JMSTopicUserRemoved removedTopicUser =
            new JMSTopicUserRemoved(template.getTopic(), template.getUser());

        // Writes the JMSTopicUserRemoved with a 60 second lease, so
        // listeners have 60 seconds to act on it
        space.write(removedTopicUser, transaction, 1000l * 60l);
      }

      transaction.commit();
    } catch (RemoteException
        | UnusableEntryException
        | TransactionException
        | InterruptedException e) {
      System.err.println(
          "Failed to remove user from topic.  "
              + "User ID: '"
              + user.getId().toString()
              + "' && Topic ID: '"
              + topic.getId().toString()
              + "'");
      e.printStackTrace();
    }
  }