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

org.gedcomx.rs.client.util.PagedFeedIterator Maven / Gradle / Ivy

There is a newer version: 2.180.0
Show newest version
/**
 * Copyright Intellectual Reserve, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.gedcomx.rs.client.util;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import org.gedcomx.atom.Feed;
import org.gedcomx.common.URI;
import org.gedcomx.links.Link;

import javax.ws.rs.core.MediaType;
import java.util.*;

/**
 * A paged {@link org.gedcomx.atom.Feed feed} iterator.
 *
 * The HTTP GET requests can be customized by using a custom {@link WebResourceProvider} and/or adding {@link WebResourceBuilderExtension}s.
 *
 * @see Paged Feeds
 */
public class PagedFeedIterator implements Iterator {
  /**
   * The default {@link WebResourceProvider} which simply calls {@link com.sun.jersey.api.client.Client#resource(String)}.
   */
  public static WebResourceProvider DEFAULT_WEB_RESOURCE_PROVIDER = new WebResourceProvider() {
    @Override
    public WebResource provide(Client client, URI uri) {
      return client.resource(uri.toURI());
    }
  };
  private final List extensions = new ArrayList();
  private Client client;
  private WebResourceProvider webResourceProvider = DEFAULT_WEB_RESOURCE_PROVIDER;
  private URI first = null;
  private URI last = null;
  private URI previous = null;
  private URI next = null;

  private PagedFeedIterator(URI uri) {
    next = uri;
  }

  private PagedFeedIterator(Feed feed) {
    loadHRefsFromFeed(feed);
  }

  /**
   * Creates a new paged feed iterator using the specified URI.
   *
   * @param uri the {@link org.gedcomx.common.URI} to use to get the initial (next) paged feed document and from which
   *            future values of first, last, previous, and next hypertext references will be acquired.
   * @return a new {@link PagedFeedIterator}
   */
  public static PagedFeedIterator fromUri(URI uri) {
    return new PagedFeedIterator(uri);
  }

  /**
   * Creates a new paged feed iterator using the specified {@link org.gedcomx.atom.Feed}.
   *
   * @param feed the feed document from which the initial first, last, previous, and next hypertext references will be
   *             acquired.
   * @return a new {@link PagedFeedIterator}
   */
  public static PagedFeedIterator fromFeed(Feed feed) {
    return new PagedFeedIterator(feed);
  }

  /**
   * Gets the hypertext reference from the specified {@link org.gedcomx.atom.Feed} for the specified rel link.
   *
   * @param feed the source feed document
   * @param rel  the desired rel
   * @return the hypertext reference, if it exists; otherwise {@code null}
   */
  public static URI getLinkRelHref(Feed feed, String rel) {
    Link link = feed.getLink(rel);
    return link == null ? null : link.getHref();
  }

  public List getWebResourceBuilderExtensions() {
    return Collections.unmodifiableList(this.extensions);
  }

  /**
   * Adds a {@link WebResourceBuilderExtension} in order to add cookies, header values, etc. to the paged feed document
   * GET request.
   *
   * @param extension the extension to add
   */
  public synchronized void addWebResourceBuilderExtension(WebResourceBuilderExtension extension) {
    this.extensions.add(extension);
  }

  /**
   * Removes a {@link WebResourceBuilderExtension}.
   *
   * @param extension the extension to remove
   */
  public synchronized void removeWebResourceBuilderExtension(WebResourceBuilderExtension extension) {
    this.extensions.remove(extension);
  }

  public synchronized void clearWebResourceBuilderExtensions() {
    this.extensions.clear();
  }

  /**
   * Adds a {@link WebResourceBuilderExtension} in order to add cookies, header values, etc. to the paged feed document
   * GET request.
   *
   * @param extension the extension
   * @return a reference to this {@link PagedFeedIterator} for fluent configuration chaining
   */
  public PagedFeedIterator withWebResourceBuilderExtension(WebResourceBuilderExtension extension) {
    addWebResourceBuilderExtension(extension);
    return this;
  }

  /**
   * Gets the {@link com.sun.jersey.api.client.Client} being used to get paged feed documents.
   *
   * @return the {@link com.sun.jersey.api.client.Client} being used to get paged feed documents.
   */
  public Client getClient() {
    if (client == null) {
      withClient(Client.create());
    }
    return client;
  }

  /**
   * Sets the {@link com.sun.jersey.api.client.Client} to use to get paged feed documents.
   *
   * @param client the {@link com.sun.jersey.api.client.Client} to use to get paged feed documents.
   */
  public synchronized void setClient(Client client) {
    this.client = client;
  }

  /**
   * Sets the {@link com.sun.jersey.api.client.Client} to use to get paged feed documents.
   *
   * @param client the {@link com.sun.jersey.api.client.Client} to use to get paged feed documents.
   * @return a reference to this {@link PagedFeedIterator} for fluent configuration chaining
   */
  public PagedFeedIterator withClient(Client client) {
    setClient(client);
    return this;
  }

  /**
   * Gets the {@link WebResourceProvider}.
   *
   * @return the {@link WebResourceProvider}.
   * @see #DEFAULT_WEB_RESOURCE_PROVIDER
   */
  public WebResourceProvider getWebResourceProvider() {
    return webResourceProvider;
  }

  /**
   * Sets the {@link WebResourceProvider}.
   *
   * @param webResourceProvider the desired {@link WebResourceProvider}.
   * @see #DEFAULT_WEB_RESOURCE_PROVIDER
   */
  public void setWebResourceProvider(WebResourceProvider webResourceProvider) {
    this.webResourceProvider = webResourceProvider;
  }

  /**
   * Sets the {@link WebResourceProvider}.
   *
   * @param webResourceProvider the desired {@link WebResourceProvider}.
   * @return a reference to this {@link PagedFeedIterator} for fluent configuration chaining
   * @see #DEFAULT_WEB_RESOURCE_PROVIDER
   */
  public PagedFeedIterator withWebResourceProvider(WebResourceProvider webResourceProvider) {
    setWebResourceProvider(webResourceProvider);
    return this;
  }

  public boolean hasFirst() {
    return first != null;
  }

  public URI firstHRef() {
    return first;
  }

  public Feed first() {
    if (!hasFirst()) {
      throw new NoSuchElementException();
    }
    return getFeed(first);
  }

  public URI lastHRef() {
    return last;
  }

  public boolean hasLast() {
    return last != null;
  }

  public Feed last() {
    if (!hasLast()) {
      throw new NoSuchElementException();
    }
    return getFeed(last);
  }

  public URI previousHRef() {
    return previous;
  }

  public boolean hasPrevious() {
    return previous != null;
  }

  public Feed previous() {
    if (!hasPrevious()) {
      throw new NoSuchElementException();
    }
    return getFeed(previous);
  }

  public URI nextHRef() {
    return next;
  }

  @Override
  public boolean hasNext() {
    return next != null;
  }

  @Override
  public Feed next() {
    if (!hasNext()) {
      throw new NoSuchElementException();
    }
    return getFeed(next);
  }

  @Override
  public void remove() {
    throw new UnsupportedOperationException();
  }

  private void loadHRefsFromFeed(Feed feed) {
    first = getLinkRelHref(feed, "first");
    last = getLinkRelHref(feed, "last");
    previous = getLinkRelHref(feed, "previous");
    next = getLinkRelHref(feed, "next");
  }

  private synchronized Feed getFeed(URI uri) {
    WebResource.Builder builder = webResourceProvider.provide(getClient(), uri)
        .accept(MediaType.APPLICATION_ATOM_XML_TYPE);
    for (WebResourceBuilderExtension extension : this.extensions) {
      builder = extension.extend(builder);
    }
    ClientResponse clientResponse = builder.get(ClientResponse.class);
    ClientResponse.Status status = clientResponse.getClientResponseStatus();
    switch (status) {
      case OK:
        Feed feed = clientResponse.getEntity(Feed.class);
        loadHRefsFromFeed(feed);
        return feed;
      case NO_CONTENT:
        return null;
      default:
        throw new IllegalStateException(status.toString());
    }
  }

  /**
   * Interface for providing {@link com.sun.jersey.api.client.WebResource}s to use for fetching paged feed documents.
   */
  public static interface WebResourceProvider {
    /**
     * Provide the {@link com.sun.jersey.api.client.WebResource} to use for fetching a paged feed document.
     *
     * @param client the configured client to use
     * @param uri    the specified {@link org.gedcomx.common.URI} for the first, last, previous, and/or next paged feed
     *               document
     * @return a {@link com.sun.jersey.api.client.WebResource} for acquiring the desired paged feed document
     */
    WebResource provide(Client client, URI uri);
  }

  /**
   * Interface for extending HTTP GET requests (e.g. add cookies, header values, etc.).
   */
  public static interface WebResourceBuilderExtension {
    /**
     * Extends a {@link com.sun.jersey.api.client.WebResource.Builder}.
     *
     * @param builder the base {@link com.sun.jersey.api.client.WebResource.Builder}
     * @return the extended {@link com.sun.jersey.api.client.WebResource.Builder}
     */
    WebResource.Builder extend(WebResource.Builder builder);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy