/**
   * Get an array of all the communities 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 swordContext
   * @return the array of allowed collections
   * @throws DSpaceSwordException
   */
  public List<Community> getAllowedCommunities(SwordContext swordContext)
      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 {
      // locate all the top level communities
      Context context = swordContext.getContext();
      List<Community> allowed = new ArrayList<Community>();
      Community[] comms = Community.findAllTop(context);
      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);
    }
  }
  public Statement getStatement(
      String stateIRI,
      Map<String, String> accept,
      AuthCredentials authCredentials,
      SwordConfiguration swordConfig)
      throws SwordServerException, SwordError, SwordAuthException {
    SwordContext sc = null;
    try {
      SwordConfigurationDSpace config = (SwordConfigurationDSpace) swordConfig;

      SwordAuthenticator auth = new SwordAuthenticator();
      sc = auth.authenticate(authCredentials);
      Context context = sc.getContext();

      if (log.isDebugEnabled()) {
        log.debug(LogManager.getHeader(context, "sword_get_statement", ""));
      }

      // log the request
      String un = authCredentials.getUsername() != null ? authCredentials.getUsername() : "NONE";
      String obo =
          authCredentials.getOnBehalfOf() != null ? authCredentials.getOnBehalfOf() : "NONE";
      log.info(
          LogManager.getHeader(
              context, "sword_get_statement", "username="******",on_behalf_of=" + obo));

      // first thing is to figure out what we're being asked to work on
      SwordUrlManager urlManager = config.getUrlManager(context, config);
      Item item = urlManager.getItem(context, stateIRI);
      if (item == null) {
        throw new SwordError(404);
      }

      // find out if we are allowed to read the item's statement
      AuthorizeManager.authorizeAction(context, item, Constants.READ);

      // find out, now we know what we're being asked for, whether this is allowed
      WorkflowManagerFactory.getInstance().retrieveStatement(context, item);

      String suffix = urlManager.getTypeSuffix(context, stateIRI);
      SwordStatementDisseminator disseminator = null;

      if (suffix != null) {
        Map<Float, List<String>> analysed = new HashMap<Float, List<String>>();
        List<String> list = new ArrayList<String>();
        list.add(suffix);
        analysed.put((float) 1.0, list);
        disseminator = SwordDisseminatorFactory.getStatementInstance(analysed);
      } else {
        // we rely on the content negotiation to do the work
        String acceptContentType = this.getHeader(accept, "Accept", null);

        // we extract from the Accept header the ordered list of content types
        TreeMap<Float, List<String>> analysed = this.analyseAccept(acceptContentType);

        // the meat of this is done by the package disseminator
        disseminator = SwordDisseminatorFactory.getStatementInstance(analysed);
      }

      Statement statement = disseminator.disseminate(context, item);
      return statement;
    } catch (AuthorizeException e) {
      throw new SwordAuthException();
    } catch (SQLException e) {
      throw new SwordServerException(e);
    } catch (DSpaceSwordException e) {
      throw new SwordServerException(e);
    } finally {
      if (sc != null) {
        sc.abort();
      }
    }
  }