ucar.nc2.ft.point.StationTimeSeriesCollectionImpl Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.nc2.ft.point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import ucar.nc2.VariableSimpleIF;
import ucar.nc2.constants.FeatureType;
import ucar.nc2.ft.PointFeature;
import ucar.nc2.ft.PointFeatureCollection;
import ucar.nc2.ft.PointFeatureCollectionIterator;
import ucar.nc2.ft.StationTimeSeriesFeature;
import ucar.nc2.ft.StationTimeSeriesFeatureCollection;
import ucar.nc2.time.CalendarDateRange;
import ucar.nc2.time.CalendarDateUnit;
import ucar.nc2.util.IOIterator;
import ucar.unidata.geoloc.LatLonRect;
/**
* Abstract superclass for implementations of StationFeatureCollection.
* Subclass must supply createStationHelper, may need to override getPointFeatureCollectionIterator().
*
* @author caron
* @since Feb 5, 2008
*/
public abstract class StationTimeSeriesCollectionImpl extends PointFeatureCCImpl implements StationTimeSeriesFeatureCollection {
private volatile StationHelper stationHelper;
public StationTimeSeriesCollectionImpl(String name, CalendarDateUnit timeUnit, String altUnits) {
super(name, timeUnit, altUnits, FeatureType.STATION);
}
// Double-check idiom for lazy initialization of instance fields. See Effective Java 2nd Ed, p. 283.
protected StationHelper getStationHelper() {
if (stationHelper == null) {
synchronized (this) {
if (stationHelper == null) {
try {
stationHelper = createStationHelper();
} catch (IOException e) {
// The methods that will call getStationHelper() aren't declared to throw IOException, so we must
// wrap it in an unchecked exception.
throw new RuntimeException(e);
}
}
}
}
assert stationHelper != null : "stationHelper is null for StationTimeSeriesCollectionImpl"+getName();
return stationHelper;
}
// Allow StationHelper to be lazily initialized.
protected abstract StationHelper createStationHelper() throws IOException;
@Override
public LatLonRect getBoundingBox() {
return getStationHelper().getBoundingBox();
}
@Override
public List getStationFeatures() throws IOException {
return getStationHelper().getStationFeatures();
}
@Override
public List getStationFeatures(List stnNames) {
return getStationHelper().getStationFeaturesFromNames(stnNames);
}
@Override
public List getStationFeatures(ucar.unidata.geoloc.LatLonRect boundingBox) throws IOException {
return getStationHelper().getStationFeatures(boundingBox);
}
@Override
public StationFeature findStationFeature(String name) {
return getStationHelper().getStation(name);
}
@Override
public StationTimeSeriesFeature getStationTimeSeriesFeature(StationFeature s) {
return (StationTimeSeriesFeature) s; // LOOK
}
////////////////////////////////////////////////////////////////
// subset
@Override
public StationTimeSeriesFeatureCollection subset(ucar.unidata.geoloc.LatLonRect boundingBox) throws IOException {
return subset( getStationFeatures(boundingBox));
}
@Override
public StationTimeSeriesFeatureCollection subset(LatLonRect boundingBox, CalendarDateRange dateRange) throws IOException {
return subset(getStationFeatures(boundingBox), dateRange);
}
@Override
public StationTimeSeriesFeatureCollection subset(List stations) throws IOException {
return new StationSubset(this, stations);
}
@Override
public StationTimeSeriesFeatureCollection subset(List stnsWanted, CalendarDateRange dateRange) throws IOException {
if (dateRange == null)
return subset(stnsWanted);
List subsetStations = new ArrayList<>();
for (StationFeature sf : stnsWanted) {
StationTimeSeriesFeature stsf = (StationTimeSeriesFeature) sf; // LOOK
StationTimeSeriesFeature subset = stsf.subset(dateRange);
subsetStations.add(subset);
}
return new StationSubset(this, subsetStations);
}
@Override
public StationTimeSeriesFeatureCollection subsetFeatures(List stationsFeatures) throws IOException {
return new StationSubset(this, stationsFeatures);
}
private static class StationSubset extends StationTimeSeriesCollectionImpl {
private final List stations;
StationSubset(StationTimeSeriesCollectionImpl from, List stations) {
super(from.getName(), from.getTimeUnit(), from.getAltUnits());
this.stations = stations;
}
@Override
protected StationHelper createStationHelper() throws IOException {
StationHelper stationHelper = new StationHelper();
stationHelper.setStations(stations);
return stationHelper;
}
@Override
public List getStationFeatures() throws IOException {
return getStationHelper().getStationFeatures();
}
}
///////////////////////////////
// flatten
// might need to override for efficiency
@Override
public PointFeatureCollection flatten(List stationNames, CalendarDateRange dateRange, List varList) throws IOException {
if ((stationNames == null) || (stationNames.size() == 0))
return new StationTimeSeriesCollectionFlattened(this, dateRange);
List subsetStations = getStationHelper().getStationFeaturesFromNames(stationNames);
return new StationTimeSeriesCollectionFlattened(new StationSubset(this, subsetStations), dateRange);
}
@Override
public PointFeatureCollection flatten(LatLonRect boundingBox, CalendarDateRange dateRange) throws IOException {
if (boundingBox == null)
return new StationTimeSeriesCollectionFlattened(this, dateRange);
List subsetStations = getStationHelper().getStationFeatures(boundingBox);
return new StationTimeSeriesCollectionFlattened(new StationSubset(this, subsetStations), dateRange);
}
@Override
public StationFeature getStationFeature(PointFeature flatPointFeature) throws IOException {
if (flatPointFeature instanceof StationFeatureHas) {
return ((StationFeatureHas)flatPointFeature).getStationFeature();
}
return null;
}
/////////////////////////////////////////////////////////////////////////////////////
@Override
public Iterator iterator() {
try {
PointFeatureCollectionIterator pfIterator = getPointFeatureCollectionIterator();
return new CollectionIteratorAdapter<>(pfIterator);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public IOIterator getCollectionIterator() throws IOException {
return new StationIterator();
}
@Override
public PointFeatureCollectionIterator getPointFeatureCollectionIterator() throws IOException {
return new StationIterator();
}
// note this assumes that a StationFeature is-a PointFeatureCollection (meaning is-a StationTimeSeriesFeature) (see the cast in next())
// subclasses must override if thats not true
// note that subset() may have made a subset of stationHelper
private class StationIterator implements PointFeatureCollectionIterator, IOIterator {
Iterator stationIter;
DsgCollectionImpl prev;
CollectionInfo calcInfo;
public StationIterator() {
stationIter = getStationHelper().getStationFeatures().iterator();
CollectionInfo info = getInfo();
if (!info.isComplete())
calcInfo = info;
}
@Override
public boolean hasNext() throws IOException {
if (prev != null && calcInfo != null)
calcInfo.extend(prev.getInfo());
boolean more = stationIter.hasNext();
if (!more && calcInfo != null) calcInfo.setComplete();
return more;
}
@Override
public PointFeatureCollection next() throws IOException {
PointFeatureCollection result = (PointFeatureCollection) stationIter.next(); // LOOK
prev = (DsgCollectionImpl) result; // common for Station and StationProfile
return result;
}
}
/////////////////////////////////////////////////////////////////////////////////////
// deprecated
protected PointFeatureCollectionIterator localIterator;
@Override
public boolean hasNext() throws IOException {
if (localIterator == null) resetIteration();
return localIterator.hasNext();
}
@Override
public void finish() {
if (localIterator != null)
localIterator.close();
}
@Override
public StationTimeSeriesFeature next() throws IOException {
return (StationTimeSeriesFeature) localIterator.next();
}
@Override
public void resetIteration() throws IOException {
localIterator = getPointFeatureCollectionIterator();
}
}