package mil.nga.giat.geowave.format.geotools.raster;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.converters.DoubleConverter;
import mil.nga.giat.geowave.adapter.raster.adapter.RasterDataAdapter;
import mil.nga.giat.geowave.adapter.raster.adapter.merge.RasterTileMergeStrategy;
import mil.nga.giat.geowave.core.ingest.spi.IngestFormatOptionProvider;
public class RasterOptionProvider implements
IngestFormatOptionProvider
{
// for now, default to no merging
private static final RasterTileMergeStrategy DEFAULT_MERGE_STRATEGY = null;
private final static Logger LOGGER = LoggerFactory.getLogger(RasterOptionProvider.class);
private static Map<String, RasterMergeStrategyProviderSpi> registeredMergeStrategies = null;
@Parameter(names = "--pyramid", description = "Build an image pyramid on ingest for quick reduced resolution query")
private final boolean buildPyramid = false;
@Parameter(names = "--crs", description = "A CRS override for the provided raster file")
private final String crs = null;
@Parameter(names = "--histogram", description = "Build a histogram of samples per band on ingest for performing band equalization")
private final boolean buildHistogream = false;
@Parameter(names = "--tileSize", description = "Optional parameter to set the tile size stored (default is 256)")
private final int tileSize = RasterDataAdapter.DEFAULT_TILE_SIZE;
@Parameter(names = "--coverage", description = "Optional parameter to set the coverage name (default is the file name)")
private final String coverageName = null;
@Parameter(names = "--nodata", variableArity = true, description = "Optional parameter to set 'no data' values, if 1 value is giving it is applied for each band, if multiple are given then the first totalNoDataValues/totalBands are applied to the first band and so on, so each band can have multiple differing 'no data' values if needed", converter = DoubleConverter.class)
private final List<Double> nodata = new ArrayList<>();
@Parameter(names = "--separateBands", description = "Optional parameter to separate each band into its own coverage name. By default the coverage name will have '_Bn' appended to it where `n` is the band's index.")
private final boolean separateBands = false;
@Parameter(names = "--mergeStrategy", description = "Optional parameter to choose a tile merge strategy used for mosaic. Default behavior will be `none`. Alternatively 'no-data' will mosaic the most recent tile over previous tiles, except where there are no data values.")
private final String mergeStrategy = NoMergeStrategyProvider.NAME;
public RasterOptionProvider() {}
public boolean isBuildPyramid() {
return buildPyramid;
}
public int getTileSize() {
return tileSize;
}
public boolean isSeparateBands() {
return separateBands;
}
public String getCrs() {
return crs;
}
public String getCoverageName() {
if ((coverageName == null) || coverageName.trim().isEmpty()) {
return null;
}
return coverageName;
}
public boolean isBuildHistogream() {
return buildHistogream;
}
public double[][] getNodata(
final int numBands ) {
if (nodata.isEmpty() || (numBands <= 0)) {
return null;
}
final double[][] retVal = new double[numBands][];
final int nodataPerBand = nodata.size() / numBands;
if (nodataPerBand <= 1) {
for (int b = 0; b < numBands; b++) {
retVal[b] = new double[] {
nodata.get(Math.min(
b,
nodata.size() - 1))
};
}
}
else {
for (int b = 0; b < retVal.length; b++) {
retVal[b] = new double[nodataPerBand];
for (int i = 0; i < nodataPerBand; i++) {
retVal[b][i] = nodata.get((b * nodataPerBand) + i);
}
}
}
return retVal;
}
public RasterTileMergeStrategy<?> getMergeStrategy() {
final Map<String, RasterMergeStrategyProviderSpi> internalMergeStrategies = getRegisteredMergeStrategies();
if ((mergeStrategy == null) || mergeStrategy.trim().isEmpty()) {
LOGGER.warn("Merge Strategy not found");
return DEFAULT_MERGE_STRATEGY;
}
final RasterMergeStrategyProviderSpi provider = internalMergeStrategies.get(mergeStrategy);
if (provider == null) {
LOGGER.warn("Merge Strategy Provider not found for '" + mergeStrategy + "'");
return DEFAULT_MERGE_STRATEGY;
}
return provider.getStrategy();
}
private synchronized Map<String, RasterMergeStrategyProviderSpi> getRegisteredMergeStrategies() {
if (registeredMergeStrategies == null) {
registeredMergeStrategies = new HashMap<String, RasterMergeStrategyProviderSpi>();
final ServiceLoader<RasterMergeStrategyProviderSpi> converters = ServiceLoader
.load(RasterMergeStrategyProviderSpi.class);
final Iterator<RasterMergeStrategyProviderSpi> it = converters.iterator();
while (it.hasNext()) {
final RasterMergeStrategyProviderSpi converter = it.next();
registeredMergeStrategies.put(
converter.getName(),
converter);
}
}
return registeredMergeStrategies;
}
}