DefaultIndexerListener.java

  1. package gov.usgs.earthquake.indexer;

  2. import gov.usgs.earthquake.indexer.IndexerChange.IndexerChangeType;
  3. import gov.usgs.earthquake.product.AbstractListener;
  4. import gov.usgs.earthquake.product.ProductId;
  5. import gov.usgs.earthquake.util.CompareUtil;
  6. import gov.usgs.util.Config;

  7. import java.util.Iterator;
  8. import java.util.List;
  9. import java.util.logging.Logger;

  10. /**
  11.  * DefaultIndexerListener provides a starting point from which all
  12.  * IndexerListeners may extend.
  13.  *
  14.  * As a child-class of the AbstractListener, this may be configured with all of
  15.  * the parent parameters and also accepts the following:
  16.  *
  17.  * <dl>
  18.  * <dt>command</dt>
  19.  * <dd>(Required) The command to execute. This must be an executable command and
  20.  * may include arguments. Any product-specific arguments are appended at the end
  21.  * of command.</dd>
  22.  *
  23.  * <dt>storage</dt>
  24.  * <dd>(Required) A directory used to store all products. Each product is
  25.  * extracted into a separate directory within this directory and is referenced
  26.  * by the --directory=/path/to/directory argument when command is executed.</dd>
  27.  *
  28.  * <dt>processUnassociated</dt>
  29.  * <dd>(Optional, Default = false) Whether or not to process unassociated
  30.  * products. Valid values are "true" and "false".</dd>
  31.  *
  32.  * <dt>processPreferredOnly</dt>
  33.  * <dd>(Optional, Default = false) Whether or not to process only preferred
  34.  * products of the type accepted by this listener. Valid values are "true" and
  35.  * "false".</dd>
  36.  *
  37.  * <dt>ignoreArchive</dt>
  38.  * <dd>(Optional, Default = false) Whether or not to ignore EVENT_ARCHIVED and
  39.  * PRODUCT_ARCHIVED indexer events. Value values are "true" and "false".</dd>
  40.  *
  41.  * </dl>
  42.  */
  43. public class DefaultIndexerListener extends AbstractListener implements
  44.         IndexerListener {
  45.     /** Logging object. */
  46.     private static final Logger LOGGER = Logger
  47.             .getLogger(DefaultIndexerListener.class.getName());

  48.     /** Property for process preferred only */
  49.     public static final String PROCESS_PREFERRED_ONLY_PROPERTY = "processPreferredOnly";
  50.     /** Default state of process preferred only */
  51.     public static final String PROCESS_PREFERRED_ONLY_DEFAULT = "false";

  52.     /** Property for process unassociated */
  53.     public static final String PROCESS_UNASSOCIATED_PROPERTY = "processUnassociated";
  54.     /** Default state of process unassociated */
  55.     public static final String PROCESS_UNASSOCIATED_DEFAULT = "true";

  56.     /** Property for process only when event change */
  57.     public static final String PROCESS_ONLY_WHEN_EVENT_CHANGE_PROPERTY = "processOnlyWhenEventChanged";
  58.     /** Default state of process only when event change */
  59.     public static final String PROCESS_ONLY_WHEN_EVENT_CHANGE_DEFAULT = "false";

  60.     /** Property for Ignore archive */
  61.     public static final String IGNORE_ARCHIVE_PROPERTY = "ignoreArchive";
  62.     /** Default state of ignore archive */
  63.     public static final String IGNORE_ARCHIVE_DEFAULT = "true";

  64.     /** Whether or not to process only preferred products. */
  65.     private boolean processOnlyPreferredProducts = false;

  66.     /** Whether or not to process unassociated products. */
  67.     private boolean processUnassociatedProducts = true;

  68.     /**
  69.      * Whether or not to process updates that don't change preferred event
  70.      * parameters.
  71.      */
  72.     private boolean processOnlyWhenEventChanged = false;

  73.     /** Whether or not to process archive events. */
  74.     private boolean ignoreArchive = false;

  75.     @Override
  76.     public void onIndexerEvent(IndexerEvent event) throws Exception {
  77.         StringBuffer buf = new StringBuffer();
  78.         Iterator<IndexerChange> changes = event.getIndexerChanges().iterator();
  79.         while (changes.hasNext()) {
  80.             IndexerChange change = changes.next();
  81.             buf.append("\n").append(change.getType().toString()).append(" ");
  82.             if (change.getOriginalEvent() == null) {
  83.                 buf.append("null");
  84.             } else {
  85.                 buf.append(change.getOriginalEvent().getEventId());
  86.             }
  87.             buf.append(" => ");
  88.             if (change.getNewEvent() == null) {
  89.                 buf.append("null");
  90.             } else {
  91.                 buf.append(change.getNewEvent().getEventId());
  92.             }
  93.         }
  94.         LOGGER.info(buf.toString());
  95.     }

  96.     /**
  97.      * @param change
  98.      *            the indexer event that has occurred
  99.      * @return whether this external indexer listener handles this product type
  100.      * @throws Exception if error occurs
  101.      */
  102.     public boolean accept(IndexerEvent change) throws Exception {
  103.         String productType = null;

  104.         if (change.getSummary() != null) {
  105.             ProductId productId = change.getSummary().getId();

  106.             productType = productId.getType();

  107.             // use default notification listener first
  108.             if (!super.accept(productId)) {
  109.                 return false;
  110.             }
  111.         }

  112.         List<Event> events = change.getEvents();
  113.         if (!processUnassociatedProducts && events.size() == 0) {
  114.             LOGGER.fine("[" + getName() + "] product is unassociated");
  115.             return false;
  116.         }

  117.         if (processOnlyPreferredProducts && events.size() > 0) {
  118.             // check if preferred for any event
  119.             boolean isPreferred = false;

  120.             // can only be a preferred product if a summary associated
  121.             if (productType != null) {
  122.                 Iterator<Event> iter = events.iterator();
  123.                 while (iter.hasNext()) {
  124.                     Event event = iter.next();
  125.                     ProductSummary preferred = event
  126.                             .getPreferredProduct(productType);
  127.                     if (preferred != null && preferred.getId().equals(
  128.                             change.getSummary().getId())) {
  129.                         // it is the most preferred product for this event
  130.                         isPreferred = true;
  131.                         break;
  132.                     }
  133.                 }
  134.             }

  135.             if (!isPreferred) {
  136.                 LOGGER.fine("[" + getName()
  137.                         + "] product is not preferred in any event");
  138.                 return false;
  139.             }
  140.         }

  141.         // accept by default
  142.         return true;
  143.     }

  144.     /**
  145.      * Returns a boolean based on if the preferred event params have changed
  146.      * Returns false if change is an archive indexer
  147.      * @param event an IndexerEvent
  148.      * @param change and IndexerChange
  149.      * @return boolean
  150.      * @throws Exception if error occurs
  151.      */
  152.     public boolean accept(IndexerEvent event, IndexerChange change)
  153.             throws Exception {
  154.         // check whether this is an archive indexer change
  155.         if (ignoreArchive
  156.                 && (change.getType() == IndexerChangeType.PRODUCT_ARCHIVED
  157.                 || change.getType() == IndexerChangeType.EVENT_ARCHIVED)) {
  158.             return false;
  159.         }

  160.         // see if preferred event parameters have changed
  161.         if (processOnlyWhenEventChanged) {
  162.             Event originalEvent = change.getOriginalEvent();
  163.             Event newEvent = change.getNewEvent();
  164.             if (originalEvent != null && newEvent != null) {
  165.                 EventSummary originalEventSummary = originalEvent.getEventSummary();
  166.                 EventSummary newEventSummary = newEvent.getEventSummary();
  167.                 if (CompareUtil.nullSafeCompare(
  168.                         originalEventSummary.getMagnitude(),
  169.                         newEventSummary.getMagnitude()) != 0) {
  170.                     // magnitude changed
  171.                 } else if (CompareUtil.nullSafeCompare(
  172.                         originalEventSummary.getLatitude(),
  173.                         newEventSummary.getLatitude()) != 0) {
  174.                     // latitude changed
  175.                 } else if (CompareUtil.nullSafeCompare(
  176.                         originalEventSummary.getLongitude(),
  177.                         newEventSummary.getLongitude()) != 0) {
  178.                     // longitude changed
  179.                 } else if (CompareUtil.nullSafeCompare(
  180.                         originalEventSummary.getDepth(),
  181.                         newEventSummary.getDepth()) != 0) {
  182.                     // depth changed
  183.                 } else if (CompareUtil.nullSafeCompare(
  184.                         originalEventSummary.getTime(),
  185.                         newEventSummary.getTime()) != 0) {
  186.                     // time changed
  187.                 } else if (originalEventSummary.isDeleted() != newEventSummary.isDeleted()) {
  188.                     // status changed
  189.                 } else {
  190.                     // preferred event parameters haven't changed
  191.                     return false;
  192.                 }
  193.             }
  194.         }

  195.         // accept changes by default
  196.         return true;
  197.     }

  198.     public void configure(Config config) throws Exception {
  199.         super.configure(config);

  200.         processOnlyPreferredProducts = Boolean.valueOf(config
  201.                 .getProperty(PROCESS_PREFERRED_ONLY_PROPERTY,
  202.                         PROCESS_PREFERRED_ONLY_DEFAULT));
  203.         LOGGER.config("[" + getName() + "] process only preferred products = "
  204.                 + processOnlyPreferredProducts);

  205.         processUnassociatedProducts = Boolean.valueOf(config.getProperty(
  206.                 PROCESS_UNASSOCIATED_PROPERTY, PROCESS_UNASSOCIATED_DEFAULT));
  207.         LOGGER.config("[" + getName() + "] process unassociated products = "
  208.                 + processUnassociatedProducts);

  209.         processOnlyWhenEventChanged = Boolean.valueOf(config.getProperty(
  210.                 PROCESS_ONLY_WHEN_EVENT_CHANGE_PROPERTY,
  211.                 PROCESS_ONLY_WHEN_EVENT_CHANGE_DEFAULT));
  212.         LOGGER.config("[" + getName() + "] process only when event changed = "
  213.                 + processOnlyWhenEventChanged);

  214.         ignoreArchive = Boolean.valueOf(config.getProperty(
  215.                 IGNORE_ARCHIVE_PROPERTY, IGNORE_ARCHIVE_DEFAULT));
  216.         LOGGER.config("[" + getName() + "] ignore archive changes = "
  217.                 + ignoreArchive);
  218.     }

  219.     /**
  220.      * @return whether only preferred products are processed
  221.      */
  222.     public boolean getProcessOnlyPreferredProducts() {
  223.         return processOnlyPreferredProducts;
  224.     }

  225.     /**
  226.      * @param processOnlyPreferredProducts
  227.      *            whether to process ony preferred products
  228.      */
  229.     public void setProcessOnlyPreferredProducts(
  230.             final boolean processOnlyPreferredProducts) {
  231.         this.processOnlyPreferredProducts = processOnlyPreferredProducts;
  232.     }

  233.     /** @param processUnassociatedProducts to set */
  234.     public void setProcessUnassociatedProducts(
  235.             final boolean processUnassociatedProducts) {
  236.         this.processUnassociatedProducts = processUnassociatedProducts;
  237.     }

  238.     /** @return boolean processUnassociatedProducts */
  239.     public boolean getProcessUnassociatedProducts() {
  240.         return processUnassociatedProducts;
  241.     }

  242.     /** @return boolean processOnlyWhenEventChanged */
  243.     public boolean isProcessOnlyWhenEventChanged() {
  244.         return processOnlyWhenEventChanged;
  245.     }

  246.     /** @param processOnlyWhenEventChanged to set */
  247.     public void setProcessOnlyWhenEventChanged(
  248.             boolean processOnlyWhenEventChanged) {
  249.         this.processOnlyWhenEventChanged = processOnlyWhenEventChanged;
  250.     }

  251.     /** @return ignoreArchive */
  252.     public boolean isIgnoreArchive() {
  253.         return ignoreArchive;
  254.     }

  255.     /** @param ignoreArchive to set */
  256.     public void setIgnoreArchive(boolean ignoreArchive) {
  257.         this.ignoreArchive = ignoreArchive;
  258.     }
  259. }