@Override
  protected StationHelper createStationHelper() throws IOException {
    TimedCollection.Dataset td = dataCollection.getPrototype();
    if (td == null) throw new RuntimeException("No datasets in the collection");

    Formatter errlog = new Formatter();
    try (FeatureDatasetPoint openDataset =
        (FeatureDatasetPoint)
            FeatureDatasetFactoryManager.open(
                FeatureType.STATION, td.getLocation(), null, errlog)) {
      StationHelper stationHelper = new StationHelper();

      List<FeatureCollection> fcList = openDataset.getPointFeatureCollectionList();
      StationTimeSeriesCollectionImpl openCollection =
          (StationTimeSeriesCollectionImpl) fcList.get(0);
      List<Station> stns = openCollection.getStations();

      for (Station s : stns) {
        StationTimeSeriesFeature stnFeature = openCollection.getStationFeature(s);
        stationHelper.addStation(
            new CompositeStationFeature(
                s, timeUnit, altUnits, stnFeature.getFeatureData(), this.dataCollection));
      }

      dataVariables = openDataset.getDataVariables();
      globalAttributes = openDataset.getGlobalAttributes();

      return stationHelper;
    }
  }
 protected CompositeStationCollection(
     String name, DateUnit timeUnit, String altUnits, TimedCollection dataCollection)
     throws IOException {
   super(name, timeUnit, altUnits);
   this.dataCollection = dataCollection;
   TimedCollection.Dataset td = dataCollection.getPrototype();
   if (td == null) throw new RuntimeException("No datasets in the collection");
 }
 @Override
 public PointFeatureCollection flatten(
     List<String> stations, CalendarDateRange dateRange, List<VariableSimpleIF> varList)
     throws IOException {
   TimedCollection subsetCollection =
       (dateRange != null) ? dataCollection.subset(dateRange) : dataCollection;
   return new CompositeStationCollectionFlattened(
       getName(), getTimeUnit(), getAltUnits(), stations, dateRange, varList, subsetCollection);
 }
  @Override
  public PointFeatureCollection flatten(LatLonRect boundingBox, CalendarDateRange dateRange)
      throws IOException {
    TimedCollection subsetCollection =
        (dateRange != null) ? dataCollection.subset(dateRange) : dataCollection;
    return new CompositeStationCollectionFlattened(
        getName(), getTimeUnit(), getAltUnits(), boundingBox, dateRange, subsetCollection);

    // return flatten(stationHelper.getStations(boundingBox), dateRange, null);
  }
 CompositeStationFeature(
     Station s,
     DateUnit timeUnit,
     String altUnits,
     StructureData sdata,
     TimedCollection collForFeature) {
   super(s, timeUnit, altUnits, -1);
   setCalendarDateRange(collForFeature.getDateRange());
   this.sdata = sdata;
   this.collForFeature = collForFeature;
 }
    @Override
    public StationTimeSeriesFeature subset(CalendarDateRange dateRange) throws IOException {
      if (dateRange == null) return this;

      // Extract the collection members that intersect dateRange. For example, if we have:
      //     collForFeature == CollectionManager{
      //         Dataset{location='foo_20141015.nc', dateRange=2014-10-15T00:00:00Z -
      // 2014-10-16T00:00:00Z}
      //         Dataset{location='foo_20141016.nc', dateRange=2014-10-16T00:00:00Z -
      // 2014-10-17T00:00:00Z}
      //         Dataset{location='foo_20141017.nc', dateRange=2014-10-17T00:00:00Z -
      // 2014-10-18T00:00:00Z}
      //         Dataset{location='foo_20141018.nc', dateRange=2014-10-18T00:00:00Z -
      // 2014-10-19T00:00:00Z}
      //     }
      // and we want to subset it with:
      //     dateRange == 2014-10-16T12:00:00Z - 2014-10-17T12:00:00Z
      // the result will be:
      //     collectionSubset == CollectionManager{
      //         Dataset{location='foo_20141016.nc', dateRange=2014-10-16T00:00:00Z -
      // 2014-10-17T00:00:00Z}
      //         Dataset{location='foo_20141017.nc', dateRange=2014-10-17T00:00:00Z -
      // 2014-10-18T00:00:00Z}
      //     }
      TimedCollection collectionSubset = collForFeature.subset(dateRange);

      // Create a new CompositeStationFeature from the subsetted collection.
      CompositeStationFeature compStnFeatSubset =
          new CompositeStationFeature(s, getTimeUnit(), getAltUnits(), sdata, collectionSubset);

      // We're not done yet! While compStnFeatSubset has been limited to only include datasets that
      // intersect dateRange,
      // it'll often be the case that those datasets contain some times that we don't want. In the
      // example above,
      // we only want:
      //     dateRange == 2014-10-16T12:00:00Z - 2014-10-17T12:00:00Z
      // but the range of compStnFeatSubset is:
      //     2014-10-16T00:00:00Z - 2014-10-18T00:00:00Z
      // We don't want the first or last 12 hours! So, wrap in a StationFeatureSubset to do
      // per-feature filtering.
      // Note that the TimedCollection.subset() call above is still worth doing, as it limits the
      // number of features
      // we must iterate over.
      return new StationFeatureSubset(compStnFeatSubset, dateRange);
    }
 @Override
 public CalendarDateRange update() throws IOException {
   return dataCollection.update();
 }