diff --git a/src/main/java/gov/usgs/earthquake/nshmp/netcdf/data/NetcdfShape.java b/src/main/java/gov/usgs/earthquake/nshmp/netcdf/data/NetcdfShape.java index 632de5c87c400353264b900a85162704e9258afb..698207bf4ae2a9d5c1c4cd5b24ad11ac491a8633 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/netcdf/data/NetcdfShape.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/netcdf/data/NetcdfShape.java @@ -1,8 +1,13 @@ package gov.usgs.earthquake.nshmp.netcdf.data; -import java.util.Arrays; +import static com.google.common.base.Preconditions.checkState; + +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Optional; /** * Create NetCDF shapes and keep track of indices. @@ -17,26 +22,91 @@ public class NetcdfShape { indexMap = builder.indexMap; } - public int[] buildShape(IndexMap... sizes) { - int[] shape = new int[indexMap.size()]; - Arrays.fill(shape, 0); - - Arrays.stream(sizes).forEach(size -> { - shape[indexMap.get(size.indexKey)] = size.size; - }); + /** + * Returns builder to build a NetCDF shape. + */ + public static Builder builder() { + return new Builder(); + } - return shape; + /** + * Returns a builder to build an array shape for NetCDF origin and shapes. + */ + public BuildShape buildShape() { + return new BuildShape(); } - public static Builder builder() { - return new Builder(); + public class BuildShape { + List<KeySize> keySizes; + Optional<Integer> pad = Optional.empty(); + boolean reduce = false; + + private BuildShape() { + keySizes = new ArrayList<>(); + } + + /** + * Add key and associated size for shape. + * + * @param key The key + * @param size The size + */ + public BuildShape add(IndexKey key, int size) { + checkState(indexMap.containsKey(key), String.format("Key [%s] not found in shape", key)); + keySizes.add(new KeySize(key, size)); + return this; + } + + /** + * Change to padding value of 0. + * + * Not used if reducing shape. + * + * @param value The value to pad the array shape + */ + public BuildShape pad(int value) { + pad = Optional.of(value); + return this; + } + + /** + * Reduce the array to only added keys in builder. + */ + public BuildShape reduce() { + reduce = true; + return this; + } + + /** + * Returns the shape array. + */ + public int[] build() { + if (reduce) { + var reducePad = -1; + return build(reducePad).stream() + .mapToInt(Integer::intValue) + .filter(val -> val != reducePad) + .toArray(); + } else { + return build(pad.orElse(0)).stream().mapToInt(Integer::intValue).toArray(); + } + } + + private List<Integer> build(int pad) { + var shape = new ArrayList<>(Collections.nCopies(indexMap.size(), pad)); + keySizes.forEach(keySize -> { + shape.set(indexMap.get(keySize.indexKey), keySize.size); + }); + + return shape; + } } - public static class IndexMap { + public static class KeySize { public final IndexKey indexKey; public final int size; - public IndexMap(IndexKey indexKey, int size) { + private KeySize(IndexKey indexKey, int size) { this.indexKey = indexKey; this.size = size; }