@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;
    }
  }
  /**
   * Open a ucar.nc2.ft.PointFeatureCollection, write out in CF point format.
   *
   * @param fileIn open through TypedDatasetFactory.open(FeatureType.POINT, ..)
   * @param fileOut write to this netcdf-3 file
   * @param inMemory if true, read file into memory for efficiency
   * @return true on success
   * @throws IOException on read/write error
   */
  public static boolean rewritePointFeatureDataset(String fileIn, String fileOut, boolean inMemory)
      throws IOException {
    System.out.println(
        "Rewrite2 .nc files from " + fileIn + " to " + fileOut + " inMemory= " + inMemory);

    long start = System.currentTimeMillis();

    // do it in memory for speed
    NetcdfFile ncfile = inMemory ? NetcdfFile.openInMemory(fileIn) : NetcdfFile.open(fileIn);
    NetcdfDataset ncd = new NetcdfDataset(ncfile);

    Formatter errlog = new Formatter();
    FeatureDataset fd = FeatureDatasetFactoryManager.wrap(FeatureType.ANY_POINT, ncd, null, errlog);
    if (fd == null) return false;

    if (fd instanceof FeatureDatasetPoint) {
      writePointFeatureCollection((FeatureDatasetPoint) fd, fileOut);
      fd.close();
      long took = System.currentTimeMillis() - start;
      System.out.println(" that took " + (took - start) + " msecs");
      return true;
    }

    return false;
  }
      private PointFeatureIterator getNextIterator() throws IOException {
        if (!iter.hasNext()) return null;
        TimedCollection.Dataset td = iter.next();
        Formatter errlog = new Formatter();
        currentDataset =
            (FeatureDatasetPoint)
                FeatureDatasetFactoryManager.open(
                    FeatureType.STATION, td.getLocation(), null, errlog);
        List<FeatureCollection> fcList = currentDataset.getPointFeatureCollectionList();
        StationTimeSeriesFeatureCollection stnCollection =
            (StationTimeSeriesFeatureCollection) fcList.get(0);
        Station s = stnCollection.getStation(getName());
        if (s == null) {
          System.out.printf(
              "CompositeStationFeatureIterator dataset: %s missing station %s%n",
              td.getLocation(), getName());
          return getNextIterator();
        }

        StationTimeSeriesFeature stnFeature = stnCollection.getStationFeature(s);
        if (CompositeDatasetFactory.debug)
          System.out.printf(
              "CompositeStationFeatureIterator open dataset: %s for %s%n",
              td.getLocation(), s.getName());
        return stnFeature.getPointFeatureIterator(bufferSize);
      }
  private ThreddsDataFactory.Result openFeatureDataset(
      FeatureType wantFeatureType, InvAccess access, ucar.nc2.util.CancelTask task, Result result)
      throws IOException {
    result.featureType = wantFeatureType;
    result.accessUsed = access;

    // special handling for IMAGE
    if (result.featureType == FeatureType.IMAGE) {
      result.imageURL = access.getStandardUrlName();
      result.location = result.imageURL;
      return result;
    }

    if (access.getService().getServiceType() == ServiceType.CdmrFeature) {
      result.featureDataset =
          CdmrFeatureDataset.factory(wantFeatureType, access.getStandardUrlName());

    } else {

      // all other datatypes
      NetcdfDataset ncd = openDataset(access, true, task, result);
      if (null != ncd) {
        result.featureDataset =
            FeatureDatasetFactoryManager.wrap(result.featureType, ncd, task, result.errLog);
      }
    }

    if (null == result.featureDataset) result.fatalError = true;
    else {
      result.location = result.featureDataset.getLocation();
      if ((result.featureType == null) && (result.featureDataset != null))
        result.featureType = result.featureDataset.getFeatureType();
    }

    return result;
  }
  public ThreddsDataFactory.Result openFeatureDataset(
      FeatureType wantFeatureType,
      InvDataset invDataset,
      ucar.nc2.util.CancelTask task,
      Result result)
      throws IOException {

    result.featureType = invDataset.getDataType();
    if (result.featureType == null) result.featureType = wantFeatureType;

    // look for remote FeatureDataset
    if ((result.featureType != null) && result.featureType.isPointFeatureType()) {
      InvAccess access = findAccessByServiceType(invDataset.getAccess(), ServiceType.CdmrFeature);
      if (access != null) return openFeatureDataset(result.featureType, access, task, result);
    }

    // special handling for images
    if (result.featureType == FeatureType.IMAGE) {
      InvAccess access = getImageAccess(invDataset, task, result);
      if (access != null) {
        return openFeatureDataset(result.featureType, access, task, result);
      } else result.fatalError = true;
      return result;
    }

    // special handling for DQC
    InvAccess qc = invDataset.getAccess(ServiceType.QC);
    if (qc != null) {
      String dqc_location = qc.getStandardUrlName();

      if (result.featureType == FeatureType.STATION) {

        /* DqcFactory dqcFactory = new DqcFactory(true);
        QueryCapability dqc = dqcFactory.readXML(dqc_location);
        if (dqc.hasFatalError()) {
          result.errLog.append(dqc.getErrorMessages());
          result.fatalError = true;
        } */

        result.featureDataset =
            null; // LOOK FIX ucar.nc2.thredds.DqcStationObsDataset.factory(invDataset,
                  // dqc_location, result.errLog);
        result.fatalError = (result.featureDataset == null);

      } else {
        result.errLog.format("DQC must be station DQC, dataset = %s %n", invDataset.getName());
        result.fatalError = true;
      }

      return result;
    }

    NetcdfDataset ncd = openDataset(invDataset, true, task, result.errLog);
    if (null != ncd)
      result.featureDataset =
          FeatureDatasetFactoryManager.wrap(result.featureType, ncd, task, result.errLog);

    if (null == result.featureDataset) result.fatalError = true;
    else {
      result.location = result.featureDataset.getLocation();
      if ((result.featureType == null) && (result.featureDataset != null))
        result.featureType = result.featureDataset.getFeatureType();
    }

    return result;
  }