IndexerEvent.java

/*
 * IndexerEvent
 */
package gov.usgs.earthquake.indexer;

import gov.usgs.earthquake.product.Product;

import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
 * A description of a change to a ProductIndex.
 *
 * IndexerEvents are created by the Indexer, and sent to IndexerListeners.
 */
public class IndexerEvent extends EventObject {

	/** Serialization ID. */
	private static final long serialVersionUID = 1L;

	/** The index that was changed. */
	private ProductIndex index;

	/** The product that triggered this change. */
	private ProductSummary summary;

	/**
	 * A Vector object is used here because it provides synchronized
	 * (thread-safe) access to its elements. This is important since this event
	 * will be sent asynchronously to many listeners (potentially).
	 */
	private Vector<IndexerChange> indexerChanges = null;

	/**
	 * Construct a new IndexerEvent.
	 *
	 * @param source
	 *            the indexer that made the change.
	 */
	public IndexerEvent(final Indexer source) {
		super(source);
		// Initial capacity = 5, capacity increment = 5;
		this.indexerChanges = new Vector<IndexerChange>(5, 5);
	}

	/** @return Indexer */
	public Indexer getIndexer() {
		return (Indexer) getSource();
	}

	/** @return Product Index */
	public ProductIndex getIndex() {
		return this.index;
	}

	/** @param index to set */
	public void setIndex(ProductIndex index) {
		this.index = index;
	}

	/** @return product summary */
	public ProductSummary getSummary() {
		return this.summary;
	}

	/** @param summary to add */
	public void setSummary(ProductSummary summary) {
		this.summary = summary;
	}

	/** @param change to add */
	public void addIndexerChange(IndexerChange change) {
		if (change != null) {
			this.indexerChanges.add(change);
		}
	}

	/** @param changes list of changes to add */
	public void addIndexerChanges(List<IndexerChange> changes) {
		if (changes == null) {
			return;
		}

		Iterator<IndexerChange> iterator = changes.iterator();
		while (iterator.hasNext()) {
			addIndexerChange(iterator.next());
		}
	}

	/** @return vector of Indexer Changes */
	public Vector<IndexerChange> getIndexerChanges() {
		return this.indexerChanges;
	}

	/**
	 * Convenience method to retrieve Product from Indexer storage.
	 *
	 * @return Product object corresponding to ProductSummary.
	 * @throws Exception if error occurs
	 */
	public Product getProduct() throws Exception {
		if (summary == null) {
			return null;
		}
		return getIndexer().getProductStorage().getProduct(summary.getId());
	}

	/**
	 * Retrieve a distinct list of events that were changed as part of this
	 * IndexerEvent.
	 *
	 * @return list of events
	 */
	public List<Event> getEvents() {
		// map from eventid to event
		Map<Long, Event> events = new HashMap<Long, Event>();

		// iterate over all changes, and place new event into map.

		// more recent changes occur later in list, and thus only the
		// latest update to an event will appear (if the event was
		// changed more than once).
		Iterator<IndexerChange> iter = indexerChanges.iterator();
		while (iter.hasNext()) {
			IndexerChange change = iter.next();
			Event event = change.getNewEvent();
			if (event != null) {
				// not an UNASSOCIATED_PRODUCT, which doesn't have an associated
				// event
				events.put(event.getIndexId(), event);
			}
		}

		// extract distinct events from map
		return new LinkedList<Event>(events.values());
	}

}