/**
   * Get an array of all the collections that the current SWORD context will allow deposit onto in
   * the given DSpace context
   *
   * <p>The user may submit to a community if the following conditions are met:
   *
   * <p>IF: the authenticated user is an administrator AND: (the on-behalf-of user is an
   * administrator OR the on-behalf-of user is authorised to READ OR the on-behalf-of user is null)
   * OR IF: the authenticated user is authorised to READ AND: (the on-behalf-of user is an
   * administrator OR the on-behalf-of user is authorised to READ OR the on-behalf-of user is null)
   *
   * @param community
   * @return the array of allowed collections
   * @throws DSpaceSwordException
   */
  public List<Community> getCommunities(SwordContext swordContext, Community community)
      throws DSpaceSwordException {
    // a community is allowed if the following conditions are met
    //
    // - the authenticated user is an administrator
    // -- the on-behalf-of user is an administrator
    // -- the on-behalf-of user is authorised to READ
    // -- the on-behalf-of user is null
    // - the authenticated user is authorised to READ
    // -- the on-behalf-of user is an administrator
    // -- the on-behalf-of user is authorised to READ
    // -- the on-behalf-of user is null
    try {
      Community[] comms = community.getSubcommunities();
      List<Community> allowed = new ArrayList<Community>();

      for (int i = 0; i < comms.length; i++) {
        boolean authAllowed = false;
        boolean oboAllowed = false;

        // check for obo null
        if (swordContext.getOnBehalfOf() == null) {
          oboAllowed = true;
        }

        // look up the READ policy on the community.  This will include determining if the user is
        // an administrator
        // so we do not need to check that separately
        if (!authAllowed) {
          authAllowed =
              AuthorizeManager.authorizeActionBoolean(
                  swordContext.getAuthenticatorContext(), comms[i], Constants.READ);
        }

        // if we have not already determined that the obo user is ok to submit, look up the READ
        // policy on the
        // community.  THis will include determining if the user is an administrator.
        if (!oboAllowed) {
          oboAllowed =
              AuthorizeManager.authorizeActionBoolean(
                  swordContext.getOnBehalfOfContext(), comms[i], Constants.READ);
        }

        // final check to see if we are allowed to READ
        if (authAllowed && oboAllowed) {
          allowed.add(comms[i]);
        }
      }
      return allowed;

    } catch (SQLException e) {
      log.error("Caught exception: ", e);
      throw new DSpaceSwordException(e);
    }
  }
 /**
  * Is the given onBehalfOf user DSpace administrator? This translates as asking the question of
  * whether the given eperson is a member of the special DSpace group Administrator, with id 1
  *
  * @param swordContext
  * @return true if administrator, false if not
  * @throws java.sql.SQLException
  */
 public boolean isOnBehalfOfAdmin(SwordContext swordContext) throws DSpaceSwordException {
   EPerson onBehalfOf = swordContext.getOnBehalfOf();
   try {
     if (onBehalfOf != null) {
       return AuthorizeManager.isAdmin(swordContext.getOnBehalfOfContext());
     }
     return false;
   } catch (SQLException e) {
     log.error("Caught exception: ", e);
     throw new DSpaceSwordException(e);
   }
 }
  /**
   * Get an array of all the collections that the current SWORD context will allow deposit onto in
   * the given DSpace context
   *
   * <p>IF: the authenticated user is an administrator AND: (the on-behalf-of user is an
   * administrator OR the on-behalf-of user is authorised to ADD OR the on-behalf-of user is null)
   * OR IF: the authenticated user is authorised to ADD AND: (the on-behalf-of user is an
   * administrator OR the on-behalf-of user is authorised to ADD OR the on-behalf-of user is null)
   *
   * @param swordContext
   * @return the array of allowed collections
   * @throws DSpaceSwordException
   */
  public List<org.dspace.content.Collection> getAllowedCollections(
      SwordContext swordContext, Community community) throws DSpaceSwordException {
    // a collection is allowed if the following conditions are met
    //
    // - the authenticated user is an administrator
    // -- the on-behalf-of user is an administrator
    // -- the on-behalf-of user is authorised to ADD
    // -- the on-behalf-of user is null
    // - the authenticated user is authorised to ADD
    // -- the on-behalf-of user is an administrator
    // -- the on-behalf-of user is authorised to ADD
    // -- the on-behalf-of user is null

    try {
      // get the context of the authenticated user
      Context authContext = swordContext.getAuthenticatorContext();

      // short cut by obtaining the collections to which the authenticated user can submit
      org.dspace.content.Collection[] cols =
          org.dspace.content.Collection.findAuthorized(authContext, community, Constants.ADD);
      List<org.dspace.content.Collection> allowed = new ArrayList<org.dspace.content.Collection>();

      // now find out if the obo user is allowed to submit to any of these collections
      for (int i = 0; i < cols.length; i++) {
        boolean oboAllowed = false;

        // check for obo null
        if (swordContext.getOnBehalfOf() == null) {
          oboAllowed = true;
        }

        // if we have not already determined that the obo user is ok to submit, look up the READ
        // policy on the
        // community.  THis will include determining if the user is an administrator.
        if (!oboAllowed) {
          oboAllowed =
              AuthorizeManager.authorizeActionBoolean(
                  swordContext.getOnBehalfOfContext(), cols[i], Constants.ADD);
        }

        // final check to see if we are allowed to READ
        if (oboAllowed) {
          allowed.add(cols[i]);
        }
      }
      return allowed;

    } catch (SQLException e) {
      log.error("Caught exception: ", e);
      throw new DSpaceSwordException(e);
    }
  }
  public boolean canSubmitTo(SwordContext swordContext, Item item) throws DSpaceSwordException {
    // a context can submit to an item if the following are satisfied
    //
    // 1/ the primary authenticating user is authenticated (which is implicit
    //      in there being a context in the first place)
    // 2/ If an On-Behalf-Of request, the On-Behalf-Of user is authorised to
    //      carry out the action and the authenticating user is in the list
    //      of allowed mediaters
    // 3/ If not an On-Behalf-Of request, the authenticating user is authorised
    //      to carry out the action

    try {
      boolean isObo = swordContext.getOnBehalfOf() != null;
      Context allowContext = null;
      if (isObo) {
        // we need to find out if the authenticated user is permitted to mediate
        if (!this.allowedToMediate(swordContext.getAuthenticatorContext())) {
          return false;
        }
        allowContext = swordContext.getOnBehalfOfContext();
      } else {
        allowContext = swordContext.getAuthenticatorContext();
      }

      // we now need to check whether the selected context that we are authorising
      // has the appropriate permissions
      boolean write = AuthorizeManager.authorizeActionBoolean(allowContext, item, Constants.WRITE);

      Bundle[] bundles = item.getBundles("ORIGINAL");
      boolean add = false;
      if (bundles.length == 0) {
        add = AuthorizeManager.authorizeActionBoolean(allowContext, item, Constants.ADD);
      } else {
        for (int i = 0; i < bundles.length; i++) {
          add = AuthorizeManager.authorizeActionBoolean(allowContext, bundles[i], Constants.ADD);
          if (!add) {
            break;
          }
        }
      }

      boolean allowed = write && add;
      return allowed;
    } catch (SQLException e) {
      log.error("Caught exception: ", e);
      throw new DSpaceSwordException(e);
    }
  }
  /**
   * Can the current SWORD Context permit deposit into the given collection in the given DSpace
   * Context
   *
   * <p>IF: the authenticated user is an administrator AND: (the on-behalf-of user is an
   * administrator OR the on-behalf-of user is authorised to ADD OR the on-behalf-of user is null)
   * OR IF: the authenticated user is authorised to ADD AND: (the on-behalf-of user is an
   * administrator OR the on-behalf-of user is authorised to ADD OR the on-behalf-of user is null)
   *
   * @param swordContext
   * @param collection
   * @return
   * @throws DSpaceSwordException
   */
  public boolean canSubmitTo(SwordContext swordContext, org.dspace.content.Collection collection)
      throws DSpaceSwordException {
    // a user can submit to a collection in the following conditions:
    //
    // - the authenticated user is an administrator
    // -- the on-behalf-of user is an administrator
    // -- the on-behalf-of user is authorised to ADD/in the submission group
    // -- the on-behalf-of user is null
    // - the authenticated user is authorised to ADD/in the submission group
    // -- the on-behalf-of user is an administrator
    // -- the on-behalf-of user is authorised to ADD/in the submission group
    // -- the on-behalf-of user is null

    try {
      boolean authAllowed = false;
      boolean oboAllowed = false;

      // check for obo null
      if (swordContext.getOnBehalfOf() == null) {
        oboAllowed = true;
      }

      // look up the READ policy on the collection.  This will include determining if the user is an
      // administrator
      // so we do not need to check that separately
      if (!authAllowed) {
        authAllowed =
            AuthorizeManager.authorizeActionBoolean(
                swordContext.getAuthenticatorContext(), collection, Constants.ADD);
      }

      // if we have not already determined that the obo user is ok to submit, look up the READ
      // policy on the
      // community.  THis will include determining if the user is an administrator.
      if (!oboAllowed) {
        oboAllowed =
            AuthorizeManager.authorizeActionBoolean(
                swordContext.getOnBehalfOfContext(), collection, Constants.ADD);
      }

      // final check to see if we are allowed to READ
      return (authAllowed && oboAllowed);

    } catch (SQLException e) {
      log.error("Caught exception: ", e);
      throw new DSpaceSwordException(e);
    }
  }
  /**
   * Get a list of all the items that the current SWORD context will allow deposit onto in the given
   * DSpace context
   *
   * <p>IF: the authenticated user is an administrator AND: (the on-behalf-of user is an
   * administrator OR the on-behalf-of user is authorised to WRITE on the item and ADD on the
   * ORIGINAL bundle OR the on-behalf-of user is null) OR IF: the authenticated user is authorised
   * to WRITE on the item and ADD on the ORIGINAL bundle AND: (the on-behalf-of user is an
   * administrator OR the on-behalf-of user is authorised to WRITE on the item and ADD on the
   * ORIGINAL bundle OR the on-behalf-of user is null)
   *
   * @param swordContext
   * @return the array of allowed collections
   * @throws DSpaceSwordException
   */
  public List<Item> getAllowedItems(
      SwordContext swordContext, org.dspace.content.Collection collection)
      throws DSpaceSwordException {
    // an item is allowed if the following conditions are met
    //
    // - the authenticated user is an administrator
    // -- the on-behalf-of user is an administrator
    // -- the on-behalf-of user is authorised to WRITE on the item and ADD on the ORIGINAL bundle
    // -- the on-behalf-of user is null
    // - the authenticated user is authorised to WRITE on the item and ADD on the ORIGINAL bundle
    // -- the on-behalf-of user is an administrator
    // -- the on-behalf-of user is authorised to WRITE on the item and ADD on the ORIGINAL bundle
    // -- the on-behalf-of user is null

    try {
      List<Item> allowed = new ArrayList<Item>();
      ItemIterator ii = collection.getItems();

      while (ii.hasNext()) {
        Item item = ii.next();

        boolean authAllowed = false;
        boolean oboAllowed = false;

        // check for obo null
        if (swordContext.getOnBehalfOf() == null) {
          oboAllowed = true;
        }

        // get the "ORIGINAL" bundle(s)
        Bundle[] bundles = item.getBundles("ORIGINAL");

        // look up the READ policy on the community.  This will include determining if the user is
        // an administrator
        // so we do not need to check that separately
        if (!authAllowed) {
          boolean write =
              AuthorizeManager.authorizeActionBoolean(
                  swordContext.getAuthenticatorContext(), item, Constants.WRITE);

          boolean add = false;
          if (bundles.length == 0) {
            add =
                AuthorizeManager.authorizeActionBoolean(
                    swordContext.getAuthenticatorContext(), item, Constants.ADD);
          } else {
            for (int i = 0; i < bundles.length; i++) {
              add =
                  AuthorizeManager.authorizeActionBoolean(
                      swordContext.getAuthenticatorContext(), bundles[i], Constants.ADD);
              if (!add) {
                break;
              }
            }
          }

          authAllowed = write && add;
        }

        // if we have not already determined that the obo user is ok to submit, look up the READ
        // policy on the
        // community.  THis will include determining if the user is an administrator.
        if (!oboAllowed) {
          boolean write =
              AuthorizeManager.authorizeActionBoolean(
                  swordContext.getOnBehalfOfContext(), item, Constants.WRITE);

          boolean add = false;
          if (bundles.length == 0) {
            add =
                AuthorizeManager.authorizeActionBoolean(
                    swordContext.getAuthenticatorContext(), item, Constants.ADD);
          } else {
            for (int i = 0; i < bundles.length; i++) {
              add =
                  AuthorizeManager.authorizeActionBoolean(
                      swordContext.getAuthenticatorContext(), bundles[i], Constants.ADD);
              if (!add) {
                break;
              }
            }
          }

          oboAllowed = write && add;
        }

        // final check to see if we are allowed to READ
        if (authAllowed && oboAllowed) {
          allowed.add(item);
        }
      }

      return allowed;
    } catch (SQLException e) {
      throw new DSpaceSwordException(e);
    }
  }