/** * This file is hereby placed into the Public Domain. This means anyone is * free to do whatever they wish with this file. */ package mil.nga.giat.process.elasticsearch; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import org.geotools.util.logging.Logging; public class NestedAggGeoHashGrid extends GeoHashGrid { private final static Logger LOGGER = Logging.getLogger(NestedAggGeoHashGrid.class); public final static int NESTED_KEY_INDEX = 0; public final static int METRIC_KEY_INDEX = 1; public final static int VALUE_KEY_INDEX = 2; public final static int SELECTION_STRATEGY_INDEX = 3; public final static int RASTER_STRATEGY_INDEX = 4; public final static int TERMS_MAP_INDEX = 5; public final static String SELECT_LARGEST = "largest"; public final static String SELECT_SMALLEST = "smallest"; public final static String RASTER_FROM_VALUE = "value"; public final static String RASTER_FROM_KEY = "key"; public final static String DEFAULT_AGG_KEY = "nested"; public final static String DEFAULT_METRIC_KEY = ""; private String nestedAggKey = DEFAULT_AGG_KEY; private String metricKey = DEFAULT_METRIC_KEY; private String valueKey = GeoHashGrid.VALUE_KEY; private String selectionStrategy = SELECT_LARGEST; private String rasterStrategy = RASTER_FROM_VALUE; private Map<String, Integer> termsMap = null; @Override public void setParams(List<String> params) { if (null != params) { if (params.size() < 5) { LOGGER.warning("Parameters list does not contain required length; you provided " + params.size() + ", expecting: 5 or more"); throw new IllegalArgumentException(); } nestedAggKey = params.get(NESTED_KEY_INDEX); metricKey = params.get(METRIC_KEY_INDEX); valueKey = params.get(VALUE_KEY_INDEX); switch (params.get(SELECTION_STRATEGY_INDEX)) { case SELECT_SMALLEST: selectionStrategy = params.get(SELECTION_STRATEGY_INDEX); break; case SELECT_LARGEST: selectionStrategy = params.get(SELECTION_STRATEGY_INDEX); break; default: LOGGER.warning("Unexpected buckets selection strategy parameter; you provided " + params.get(SELECTION_STRATEGY_INDEX) + ", defaulting to: " + selectionStrategy); } switch (params.get(RASTER_STRATEGY_INDEX)) { case RASTER_FROM_VALUE: rasterStrategy = params.get(RASTER_STRATEGY_INDEX); break; case RASTER_FROM_KEY: rasterStrategy = params.get(RASTER_STRATEGY_INDEX); break; default: LOGGER.warning("Unexpected raster strategy parameter; you provided " + params.get(RASTER_STRATEGY_INDEX) + ", defaulting to: " + rasterStrategy); } if (rasterStrategy.equals(RASTER_FROM_KEY) && params.size() >= 6) { termsMap = new HashMap<String, Integer>(); String[] terms = params.get(TERMS_MAP_INDEX).split(";"); for (int i=0; i<terms.length; i++) { String[] keyValueSplit = terms[i].split(":"); if (keyValueSplit.length != 2) { LOGGER.warning("Term " + terms[i] + " does not contain required format <key>:<value>"); throw new IllegalArgumentException(); } termsMap.put(keyValueSplit[0], new Integer(keyValueSplit[1])); } } } } @Override public Number computeCellValue(Map<String,Object> geogridBucket) { List<Map<String,Object>> aggBuckets = super.pluckAggBuckets(geogridBucket, nestedAggKey); Number rasterValue = 0; switch (selectionStrategy) { case SELECT_SMALLEST: rasterValue = selectSmallest(aggBuckets); break; case SELECT_LARGEST: rasterValue = selectLargest(aggBuckets); break; } return rasterValue; } protected Number selectLargest(List<Map<String,Object>> buckets) { String largestKey = pluckBucketName(buckets.get(0)); Number largestValue = super.pluckMetricValue(buckets.get(0), metricKey, valueKey); for (Map<String,Object> bucket : buckets) { Number value = super.pluckMetricValue(bucket, metricKey, valueKey); if (value.doubleValue() > largestValue.doubleValue()) { largestKey = super.pluckBucketName(bucket); largestValue = value; } } return bucketToRaster(largestKey, largestValue); } protected Number selectSmallest(List<Map<String,Object>> buckets) { String smallestKey = pluckBucketName(buckets.get(0)); Number smallestValue = super.pluckMetricValue(buckets.get(0), metricKey, valueKey); for (Map<String,Object> bucket : buckets) { Number value = super.pluckMetricValue(bucket, metricKey, valueKey); if (value.doubleValue() < smallestValue.doubleValue()) { smallestKey = super.pluckBucketName(bucket); smallestValue = value; } } return bucketToRaster(smallestKey, smallestValue); } protected Number bucketToRaster(String key, Number value) { Number rasterValue = value; if (rasterStrategy.equals(RASTER_FROM_KEY)) { if (null != termsMap) { if (termsMap.containsKey(key)) { rasterValue = termsMap.get(key); } else { LOGGER.warning("Cannot convert key (String) to raster value, mapping does not contain key " + key + ". Add key to terms_map argument to resolve."); throw new IllegalArgumentException(); } } else { try { rasterValue = Double.valueOf(key); } catch (NumberFormatException nfe) { LOGGER.warning("Cannot convert key (String) to raster value, key, " + key + ", is not a number. Use terms_map argument to map Strings to Numbers."); throw new IllegalArgumentException(); } } } return rasterValue; } public String getNestedAggKey() { return nestedAggKey; } public String getMetricKey() { return metricKey; } public String getValueKey() { return valueKey; } public String getSelectionStrategy() { return selectionStrategy; } public String getRasterStrategy() { return rasterStrategy; } public Map<String, Integer> getTermsMap() { return termsMap; } }