DefaultIndexerModule.java
/*
* DefaultIndexerModule
*/
package gov.usgs.earthquake.indexer;
import gov.usgs.earthquake.distribution.ContinuableListenerException;
import gov.usgs.earthquake.distribution.SignatureVerifier;
import gov.usgs.earthquake.geoserve.ANSSRegionsFactory;
import gov.usgs.earthquake.product.Product;
import gov.usgs.earthquake.qdm.Point;
import gov.usgs.earthquake.qdm.Regions;
import gov.usgs.util.Config;
import gov.usgs.util.DefaultConfigurable;
import gov.usgs.util.StringUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* Default implementation of the IndexerModule interface, implements ANSS
* Authoritative Region logic.
*
* Provides a basic level of support for any type of product. Creates a
* ProductSummary using the ProductSummary(product) constructor, which copies
* all properties, and links from the product.
*/
public class DefaultIndexerModule extends DefaultConfigurable implements IndexerModule {
private static final Logger LOGGER = Logger.getLogger(DefaultIndexerModule.class.getName());
/** Property for ignoreRegions */
public static final String IGNORE_REGIONS_PROPERTY = "ignoreRegions";
/** Initial preferred weight. */
public static final long DEFAULT_PREFERRED_WEIGHT = 1;
/** Weight added when product source is same as event source. */
public static final long SAME_SOURCE_WEIGHT = 5;
/** Weight added when product author is in its authoritative region. */
public static final long AUTHORITATIVE_WEIGHT = 100;
/** Weight added when product refers to an authoritative event. */
public static final long AUTHORITATIVE_EVENT_WEIGHT = 50;
/** Weight added when product author has an authoritative region. */
public static final long ANSS_CONTRIBUTOR_WEIGHT = 1;
/** Weight added when product author is NEIC. */
public static final long NEIC_CONTRIBUTOR_WEIGHT = 2;
/** Signature verifier, configured by indexer. */
private SignatureVerifier signatureVerifier = new SignatureVerifier();
private List<String> ignoreRegions = new ArrayList<String>();
@Override
public void configure(final Config config) throws Exception {
final String ignore = config.getProperty(IGNORE_REGIONS_PROPERTY);
if (ignore != null) {
ignoreRegions.addAll(StringUtils.split(ignore, ","));
LOGGER.config("[" + getName() + "] ignore regions = " + ignore);
}
}
/**
* Create a ProductSummary from a Product.
*
* Uses the ProductSummary(Product) constructor, which copies product
* information. Checks whether product is within its authoritative region, and
* if so boosts preferredWeight by AUTHORITATIVE_WEIGHT.
*
* @param product the product to summarize.
* @return ProductSummary for Product object.
*/
public ProductSummary getProductSummary(final Product product) throws Exception {
ProductSummary summary = new ProductSummary(product);
// allow sender to assign preferredWeight if we add them to the keychain
String preferredWeight = product.getProperties().get("preferredWeight");
if (preferredWeight != null && signatureVerifier.verifySignature(product)) {
LOGGER.fine("Signature verified, using sender assigned preferredWeight " + preferredWeight);
summary.setPreferredWeight(Long.valueOf(preferredWeight));
} else {
summary.setPreferredWeight(getPreferredWeight(summary));
}
return summary;
}
/**
* Calculate the preferred weight for a product summary.
*
* This method is called after creating a product summary, but before returning
* the created summary. It's return value is used to assign the product summary
* preferred weight.
*
* Within each type of product, the summary with the largest preferred weight is
* considered preferred.
*
* @param summary the summary to calculate a preferred weight.
* @return the absolute preferred weight.
* @throws Exception if error occurs
*/
protected long getPreferredWeight(final ProductSummary summary) throws Exception {
long preferredWeight = DEFAULT_PREFERRED_WEIGHT;
final String source = summary.getId().getSource();
final String eventSource = summary.getEventSource();
// check ignore regions here for subclasses that use this method.
if (ignoreRegions.contains(source)) {
// source gets no region boost
return preferredWeight;
}
final Regions regions = ANSSRegionsFactory.getFactory().getRegions();
if (regions == null) {
throw new ContinuableListenerException("Unable to load ANSS Authoritative Regions");
}
final BigDecimal latitude = summary.getEventLatitude();
final BigDecimal longitude = summary.getEventLongitude();
Point location = null;
if (latitude != null && longitude != null) {
location = new Point(longitude.doubleValue(), latitude.doubleValue());
}
// authoritative check
if (location != null) {
if (regions.isAuthor(source, location)) {
// based on product source, who authored this product.
preferredWeight += AUTHORITATIVE_WEIGHT;
}
if (eventSource != null && regions.isAuthor(eventSource, location)) {
// based on event source, which event this product is about
preferredWeight += AUTHORITATIVE_EVENT_WEIGHT;
}
}
// anss source check
if (regions.isValidnetID(source)) {
preferredWeight += ANSS_CONTRIBUTOR_WEIGHT;
}
// neic source check
if (regions.isDefaultNetID(source)) {
preferredWeight += NEIC_CONTRIBUTOR_WEIGHT;
}
// same source check
if (eventSource != null && eventSource.equalsIgnoreCase(source)) {
preferredWeight += SAME_SOURCE_WEIGHT;
}
return preferredWeight;
}
/**
* Remove "internal-" prefix and "-scenario" suffix from product type".
*
* @param type product type.
* @return base product type (without any known prefix or suffix).
*/
public String getBaseProductType(String type) {
if (type.startsWith("internal-")) {
type = type.replace("internal-", "");
}
if (type.endsWith("-scenario")) {
type = type.replace("-scenario", "");
}
return type;
}
/** @return ignoreRegions */
public List<String> getIgnoreRegions() {
return ignoreRegions;
}
/**
* This module provides a default level of support for any type of product.
*
* @param product the product to test.
* @return IndexerModule.LEVEL_DEFAULT.
*/
public int getSupportLevel(final Product product) {
return IndexerModule.LEVEL_DEFAULT;
}
/** @return signatureVerifier */
public SignatureVerifier getSignatureVerifier() {
return signatureVerifier;
}
/** @param signatureVerifier to set */
public void setSignatureVerifier(SignatureVerifier signatureVerifier) {
this.signatureVerifier = signatureVerifier;
}
}