@GET
  @Path("/{bitstream_id}")
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public Bitstream getBitstream(
      @PathParam("bitstream_id") Integer bitstream_id, @QueryParam("expand") String expand) {
    org.dspace.core.Context context = null;
    try {
      context = new org.dspace.core.Context();

      org.dspace.content.Bitstream bitstream =
          org.dspace.content.Bitstream.find(context, bitstream_id);

      if (AuthorizeManager.authorizeActionBoolean(
          context, bitstream, org.dspace.core.Constants.READ)) {
        return new org.dspace.rest.common.Bitstream(bitstream, expand);
      } else {
        throw new WebApplicationException(Response.Status.UNAUTHORIZED);
      }
    } catch (SQLException e) {
      log.error(e.getMessage());
      throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
    } finally {
      if (context != null) {
        try {
          context.complete();
        } catch (SQLException e) {
          log.error(e.getMessage() + " occurred while trying to close");
        }
      }
    }
  }
  @GET
  @Path("/{bitstream_id}/retrieve")
  public javax.ws.rs.core.Response getFile(
      @PathParam("bitstream_id") final Integer bitstream_id,
      @QueryParam("userIP") String user_ip,
      @QueryParam("userAgent") String user_agent,
      @QueryParam("xforwarderfor") String xforwarderfor,
      @Context HttpHeaders headers,
      @Context HttpServletRequest request) {
    org.dspace.core.Context context = null;
    try {
      context = new org.dspace.core.Context();

      org.dspace.content.Bitstream bitstream =
          org.dspace.content.Bitstream.find(context, bitstream_id);
      if (AuthorizeManager.authorizeActionBoolean(
          context, bitstream, org.dspace.core.Constants.READ)) {
        if (writeStatistics) {
          writeStats(context, bitstream_id, user_ip, user_agent, xforwarderfor, headers, request);
        }

        return Response.ok(bitstream.retrieve()).type(bitstream.getFormat().getMIMEType()).build();
      } else {
        throw new WebApplicationException(Response.Status.UNAUTHORIZED);
      }

    } catch (IOException e) {
      log.error(e.getMessage());
      throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
    } catch (SQLException e) {
      log.error(e.getMessage());
      throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
    } catch (AuthorizeException e) {
      log.error(e.getMessage());
      throw new WebApplicationException(Response.Status.UNAUTHORIZED);
    } finally {
      if (context != null) {
        try {
          context.complete();
        } catch (SQLException e) {
          log.error(e.getMessage() + " occurred while trying to close");
        }
      }
    }
  }
  /**
   * Return instance of collection with passed id. You can add more properties through expand
   * parameter.
   *
   * @param expand String in which is what you want to add to returned instance of collection.
   *     Options are: "all", "parentCommunityList", "parentCommunity", "items", "license" and
   *     "logo". If you want to use multiple options, it must be separated by commas.
   * @param limit Limit value for items in list in collection. Default value is 100.
   * @param offset Offset of start index in list of items of collection. Default value is 0.
   * @param filters Comma separated list of Item Filters to use to evaluate against the items in a
   *     collection
   * @param query_field List of metadata fields to evaluate in a metadata query. Each list value is
   *     used in conjunction with a query_op and query_field.
   * @param query_op List of metadata operators to use in a metadata query. Each list value is used
   *     in conjunction with a query_field and query_field.
   * @param query_val List of metadata values to evaluate in a metadata query. Each list value is
   *     used in conjunction with a query_value and query_op.
   * @param collSel List of collections to query.
   * @param headers If you want to access to collection under logged user into context. In headers
   *     must be set header "rest-dspace-token" with passed token from login method.
   * @return Return instance of collection. It can also return status code NOT_FOUND(404) if id of
   *     collection is incorrect or status code UNATHORIZED(401) if user has no permission to read
   *     collection.
   * @throws WebApplicationException It is thrown when was problem with database reading
   *     (SQLException) or problem with creating context(ContextException). It is thrown by
   *     NOT_FOUND and UNATHORIZED status codes, too.
   */
  @GET
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public org.dspace.rest.common.ItemFilter getItemQuery(
      @QueryParam("expand") String expand,
      @QueryParam("limit") @DefaultValue("100") Integer limit,
      @QueryParam("offset") @DefaultValue("0") Integer offset,
      @QueryParam("userIP") String user_ip,
      @QueryParam("userAgent") String user_agent,
      @QueryParam("xforwarderfor") String xforwarderfor,
      @QueryParam("filters") @DefaultValue("is_item,all_filters") String filters,
      @QueryParam("query_field[]") @DefaultValue("dc.title") List<String> query_field,
      @QueryParam("query_op[]") @DefaultValue("exists") List<String> query_op,
      @QueryParam("query_val[]") @DefaultValue("") List<String> query_val,
      @QueryParam("collSel[]") @DefaultValue("") List<String> collSel,
      @Context HttpHeaders headers,
      @Context HttpServletRequest request) {
    org.dspace.core.Context context = null;
    ItemFilterSet itemFilterSet = new ItemFilterSet(filters, true);
    ItemFilter result = itemFilterSet.getAllFiltersFilter();
    try {
      context = createContext(getUser(headers));
      if (!configurationService.getBooleanProperty("rest.reporting-authenticate", true)) {
        context.turnOffAuthorisationSystem();
      }

      int index = Math.min(query_field.size(), Math.min(query_op.size(), query_val.size()));
      List<ItemFilterQuery> itemFilterQueries = new ArrayList<ItemFilterQuery>();
      for (int i = 0; i < index; i++) {
        itemFilterQueries.add(
            new ItemFilterQuery(query_field.get(i), query_op.get(i), query_val.get(i)));
      }

      String regexClause = configurationService.getProperty("rest.regex-clause");
      if (regexClause == null) {
        regexClause = "";
      }

      List<UUID> uuids = getUuidsFromStrings(collSel);
      List<List<MetadataField>> listFieldList = getMetadataFieldsList(context, query_field);

      Iterator<org.dspace.content.Item> childItems =
          itemService.findByMetadataQuery(
              context, listFieldList, query_op, query_val, uuids, regexClause, offset, limit);

      int count = itemFilterSet.processSaveItems(context, childItems, true, expand);
      writeStats(
          siteService.findSite(context),
          UsageEvent.Action.VIEW,
          user_ip,
          user_agent,
          xforwarderfor,
          headers,
          request,
          context);
      result.annotateQuery(query_field, query_op, query_val);
      result.setUnfilteredItemCount(count);
      context.complete();
    } catch (IOException e) {
      processException(e.getMessage(), context);
    } catch (SQLException e) {
      processException(e.getMessage(), context);
    } catch (AuthorizeException e) {
      processException(e.getMessage(), context);
    } catch (ContextException e) {
      processException("Unauthorized filtered item query. " + e.getMessage(), context);
    } finally {
      processFinally(context);
    }
    return result;
  }