package ucar.coord;
import thredds.featurecollection.FeatureCollectionConfig;
import ucar.nc2.grib.TimeCoord;
import java.util.*;
/**
* Create the overall coordinate across the same variable in different partitions
* The CoordinateBuilders create unique sets of Coordinates.
* The CoordinateND result is then the cross-product of those Coordinates.
*
* This is a builder helper class, the result is obtained from List<Coordinate> finish().
*
* So if theres a lot of missing records in that cross-product, we may have the variable wrong (?),
* or our assumption that the data comprises a multidim array may be wrong
*
* @author John
* @since 12/10/13
*/
public class CoordinateUnionizer {
static private org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CoordinateUnionizer.class);
FeatureCollectionConfig.GribIntvFilter intvFilter;
int varId;
public CoordinateUnionizer(int varId, FeatureCollectionConfig.GribIntvFilter intvFilter) {
this.intvFilter = intvFilter;
this.varId = varId;
}
List<Coordinate> unionCoords = new ArrayList<>();
CoordinateBuilder runtimeBuilder ;
CoordinateBuilder timeBuilder;
CoordinateBuilder timeIntvBuilder;
CoordinateBuilder vertBuilder;
CoordinateBuilder ensBuilder;
CoordinateTime2DUnionizer time2DBuilder;
public void addCoords(List<Coordinate> coords) {
Coordinate runtime = null;
for (Coordinate coord : coords) {
switch (coord.getType()) {
case runtime:
CoordinateRuntime rtime = (CoordinateRuntime) coord;
if (runtimeBuilder == null) runtimeBuilder = new CoordinateRuntime.Builder2(rtime.getTimeUnits());
runtimeBuilder.addAll(coord);
runtime = coord;
break;
case time:
CoordinateTime time = (CoordinateTime) coord;
if (timeBuilder == null) timeBuilder = new CoordinateTime.Builder2(coord.getCode(), time.getTimeUnit(), time.getRefDate());
timeBuilder.addAll(coord);
break;
case timeIntv:
CoordinateTimeIntv timeIntv = (CoordinateTimeIntv) coord;
if (timeIntvBuilder == null) timeIntvBuilder = new CoordinateTimeIntv.Builder2(null, coord.getCode(), timeIntv.getTimeUnit(), timeIntv.getRefDate());
timeIntvBuilder.addAll(intervalFilter((CoordinateTimeIntv)coord));
break;
case time2D:
CoordinateTime2D time2D = (CoordinateTime2D) coord;
if (time2DBuilder == null) time2DBuilder = new CoordinateTime2DUnionizer(time2D.isTimeInterval(), time2D.getTimeUnit(), coord.getCode(), false);
time2DBuilder.addAll(time2D);
// debug
CoordinateRuntime runtimeFrom2D = time2D.getRuntimeCoordinate();
if (!runtimeFrom2D.equals(runtime))
logger.warn("HEY CoordinateUnionizer runtimes not equal");
break;
case ens:
if (ensBuilder == null) ensBuilder = new CoordinateEns.Builder2(coord.getCode());
ensBuilder.addAll(coord);
break;
case vert:
CoordinateVert vertCoord = (CoordinateVert) coord;
if (vertBuilder == null) vertBuilder = new CoordinateVert.Builder2(coord.getCode(), vertCoord.getVertUnit());
vertBuilder.addAll(coord);
break;
}
}
}
private List<TimeCoord.Tinv> intervalFilter(CoordinateTimeIntv coord) {
if (intvFilter == null) return coord.getTimeIntervals();
List<TimeCoord.Tinv> result = new ArrayList<>();
for (TimeCoord.Tinv tinv : coord.getTimeIntervals()) {
if (intvFilter.filterOk(varId, tinv.getIntervalSize(), 0))
result.add(tinv);
}
return result;
}
public List<Coordinate> finish() {
if (runtimeBuilder != null)
unionCoords.add(runtimeBuilder.finish());
else
logger.warn("HEY CoordinateUnionizer missing runtime");
if (timeBuilder != null)
unionCoords.add(timeBuilder.finish());
else if (timeIntvBuilder != null)
unionCoords.add(timeIntvBuilder.finish());
else if (time2DBuilder != null)
unionCoords.add(time2DBuilder.finish());
else
logger.warn("HEY CoordinateUnionizer missing time");
if (ensBuilder != null) // ens must come before vert to preserve order
unionCoords.add(ensBuilder.finish());
if (vertBuilder != null)
unionCoords.add(vertBuilder.finish());
// result = new CoordinateND<>(unionCoords);
return unionCoords;
}
}