All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.byu.hbll.box.client.AbstractHttpBoxClient Maven / Gradle / Ivy

The newest version!
package edu.byu.hbll.box.client;

import edu.byu.hbll.box.BoxDocument;
import edu.byu.hbll.box.BoxQuery;
import edu.byu.hbll.box.QueryResult;
import edu.byu.hbll.box.internal.core.DocumentIterable;
import edu.byu.hbll.box.internal.util.BoxUriBuilder;
import edu.byu.hbll.json.ObjectMapperFactory;
import edu.byu.hbll.json.UncheckedObjectMapper;
import edu.byu.hbll.misc.BatchIterable.Batch;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.URI;
import java.util.List;
import java.util.Objects;
import lombok.Data;

/**
 * A client for communicating with Box through it's web api.
 *
 * @author Charles Draper
 */
public abstract class AbstractHttpBoxClient implements BoxClient {

  private static final UncheckedObjectMapper mapper = ObjectMapperFactory.newUnchecked();
  private static final int MAX_URI_LENGTH = 2048;
  private static final int ID_PARAM_OVERHEAD = "&id=".length();

  private URI uri;

  /**
   * Creates a new client.
   *
   * @param uri the base uri of the box source (eg, http://localhost:8080/app/box)
   */
  public AbstractHttpBoxClient(URI uri) {
    this.uri = Objects.requireNonNull(uri);
  }

  @Override
  public QueryResult collect(BoxQuery query) {
    if (query.isIdQuery()) {
      BoxQuery batchQuery = new BoxQuery(query).clearIds();
      QueryResult result = new QueryResult();

      for (List batch :
          Batch.of(query.getIds())
              .capacity(MAX_URI_LENGTH - getBaseUriLength(batchQuery))
              .scale(i -> i.length() + ID_PARAM_OVERHEAD)) {
        batchQuery.clearIds().addIds(batch);
        result.addAll(retrieve(batchQuery));
      }

      return result;
    } else {
      return retrieve(query);
    }
  }

  @Override
  public Iterable find(BoxQuery query) {
    return new DocumentIterable(query, q -> retrieve(q));
  }

  /**
   * Returns the base uri for the box.
   *
   * @return the uri
   */
  public URI getUri() {
    return uri;
  }

  /**
   * Queries the upstream box client for documents.
   *
   * @param query the query to run
   * @return the result of the query
   */
  private QueryResult retrieve(BoxQuery query) {
    URI uri = BoxUriBuilder.buildQuery(this.uri, query);

    try (InputStream input = send(uri)) {
      QueryResponse response = mapper.readValue(input, QueryResponse.class);
      QueryResult result = new QueryResult(response.documents);
      result.setNextCursor(response.nextCursor);
      return result;
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }

  /**
   * Returns the length of the uri based on the given id query, but without ids. Note this is
   * designed for id type queries.
   *
   * @param query the original box query
   * @return the length of the resulting uri for the box query
   */
  private int getBaseUriLength(BoxQuery query) {
    BoxQuery lengthQuery = new BoxQuery(query).clearIds().addId("");
    return BoxUriBuilder.buildQuery(this.uri, lengthQuery).toString().length() - ID_PARAM_OVERHEAD;
  }

  /**
   * Sends the request to the Box server and returns the response as an input stream. This can be
   * overridden by subclasses that require different HTTP clients. The input stream will be closed
   * here.
   *
   * @param uri the full uri to send to box for the query
   * @return the response body as an {@link InputStream}
   */
  protected abstract InputStream send(URI uri);

  /** Represents an http response from a box documents enpoint. */
  @Data
  public static class QueryResponse {
    private List documents;
    private long nextCursor;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy