ObjectProductHandler.java

/*
 * ObjectProductHandler
 */
package gov.usgs.earthquake.product.io;

import gov.usgs.earthquake.product.Content;
import gov.usgs.earthquake.product.ByteContent;
import gov.usgs.earthquake.product.FileContent;
import gov.usgs.earthquake.product.URLContent;
import gov.usgs.util.CryptoUtils.Version;
import gov.usgs.earthquake.product.Product;
import gov.usgs.earthquake.product.ProductId;
import gov.usgs.earthquake.product.ProductSignature;

import java.net.URI;

import java.util.List;
import java.util.Map;
import java.util.LinkedList;

/**
 * Convert ProductSource events into a java Product object.
 *
 * ObjectProductHandlers are not designed to handle multiple products
 * simultaneously and separate objects must be created for each unique product
 * id.
 *
 * The static method ObjectProductHandler.getProduct(ProductInput) should
 * usually be used instead of constructing objects manually.
 */
public class ObjectProductHandler implements ProductHandler {

  /** The Product being created. */
  private Product product = null;

  /** Whether onEndProduct has been called yet. */
  private boolean complete = false;

  /** Empty constructor */
  public ObjectProductHandler() {
  }

  /**
   * @return the product object that was created.
   * @throws Exception if error occurs
   */
  public Product getProduct() throws Exception {
    if (product == null) {
      throw new IllegalArgumentException("Called getProduct before onBeginProduct");
    } else if (!complete) {
      throw new IllegalArgumentException("Called getProduct before onEndProduct");
    }

    return product;
  }

  public void onBeginProduct(final ProductId id, final String status) throws Exception {
    if (product != null) {
      throw new IllegalArgumentException("Called onBeginProduct after onBeginProduct");
    } else if (complete) {
      throw new IllegalArgumentException("Called onBeginProduct after onEndProduct");
    }

    product = new Product(id, status);
  }

  public void onContent(final ProductId id, final String path, final Content content) throws Exception {
    if (product == null) {
      throw new IllegalArgumentException("Called onContent before onBeginProduct");
    } else if (complete) {
      throw new IllegalArgumentException("Called onContent after onEndProduct");
    } else if (!product.getId().equals(id)) {
      throw new IllegalArgumentException("ProductIds do not match");
    }

    // System.err.println("onContent(" + id.toString() + ", " + path + ", "
    // + content.toString() + ")");

    if (content instanceof FileContent || content instanceof ByteContent || content instanceof URLContent) {
      // these types of content do not need to be read immediately
      product.getContents().put(path, content);
    } else {
      // new ByteContent reads stream into byte array
      product.getContents().put(path, new ByteContent(content));
    }

  }

  public void onEndProduct(final ProductId id) throws Exception {
    // System.err.println("onEndProduct(" + id.toString() + ")");

    complete = true;
  }

  public void onLink(final ProductId id, final String relation, final URI href) throws Exception {
    if (product == null) {
      throw new IllegalArgumentException("Called onLink before onBeginProduct");
    } else if (complete) {
      throw new IllegalArgumentException("Called onLink after onEndProduct");
    } else if (!product.getId().equals(id)) {
      throw new IllegalArgumentException("ProductIds do not match");
    }

    // get list of links for relation
    List<URI> links = product.getLinks().get(relation);
    if (links == null) {
      // create if doesn't already exist
      links = new LinkedList<URI>();
      product.getLinks().put(relation, links);
    }

    // add if doesn't already contain
    if (!links.contains(href)) {
      links.add(href);
    }
  }

  public void onProperty(final ProductId id, final String name, final String value) throws Exception {
    if (product == null) {
      throw new IllegalArgumentException("Called onProperty before onBeginProduct");
    } else if (complete) {
      throw new IllegalArgumentException("Called onProperty after onEndProduct");
    } else if (!product.getId().equals(id)) {
      throw new IllegalArgumentException("ProductIds do not match");
    }

    // System.err.println("onProperty(" + id.toString() + ", " + name + ", "
    // + value + ")");
    product.getProperties().put(name, value);
  }

  public void onSignatureVersion(final ProductId id, final Version version) throws Exception {
    if (product == null) {
      throw new IllegalArgumentException("Called onSignature before onBeginProduct");
    } else if (complete) {
      throw new IllegalArgumentException("Called onSignature after onEndProduct");
    } else if (!product.getId().equals(id)) {
      throw new IllegalArgumentException("ProductIds do not match");
    }

    product.setSignatureVersion(version);
  }

  public void onSignature(final ProductId id, final String signature) throws Exception {
    if (product == null) {
      throw new IllegalArgumentException("Called onSignature before onBeginProduct");
    } else if (complete) {
      throw new IllegalArgumentException("Called onSignature after onEndProduct");
    } else if (!product.getId().equals(id)) {
      throw new IllegalArgumentException("ProductIds do not match");
    }

    product.setSignature(signature);
  }

  public void onSignatureHistory(final ProductId id, final List<ProductSignature> signatureHistory)
      throws Exception {
    if (product == null) {
      throw new IllegalArgumentException("Called onSignature before onBeginProduct");
    } else if (complete) {
      throw new IllegalArgumentException("Called onSignature after onEndProduct");
    } else if (!product.getId().equals(id)) {
      throw new IllegalArgumentException("ProductIds do not match");
    }
    product.setSignatureHistory(signatureHistory);
  }

  /**
   * Convenience method to get a Product object from a ProductInput.
   *
   * @param in the ProductInput to read.
   * @return the Product read, or null if errors occur.
   * @throws Exception if error occurs
   */
  public static Product getProduct(final ProductSource in) throws Exception {
    ObjectProductHandler out = new ObjectProductHandler();
    try {
      in.streamTo(out);
    } finally {
      in.close();
    }
    return out.getProduct();
  }

  /**
   * Free any resources associated with this handler.
   */
  @Override
  public void close() {
    // this.product = null;
  }

}