All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.ft.point.SortingStationPointFeatureCache Maven / Gradle / Ivy

The newest version!
package ucar.nc2.ft.point;

import java.io.File;
import java.io.IOException;
import java.util.*;

import com.google.common.base.Preconditions;
import ucar.nc2.constants.FeatureType;
import ucar.nc2.ft.FeatureDatasetFactoryManager;
import ucar.nc2.ft.FeatureDatasetPoint;
import ucar.nc2.ft.NoFactoryFoundException;
import ucar.nc2.ft.PointFeatureIterator;
import ucar.nc2.units.DateUnit;

/**
 *
 * @author cwardgar
 * @since 2014/08/21
 */
// This class ought to be a PointFeatureCollection, by extending PointCollectionImpl.
// However, we do not have the timeUnit and altUnits that the constructor requires. Does it really need
// that info? Can't it calculate it from one of its features? That interface may need to be re-thought.
public class SortingStationPointFeatureCache {
    public static final Comparator stationNameComparator = (pointFeat1, pointFeat2) ->
            pointFeat1.getStation().getName().compareTo(pointFeat2.getStation().getName());

    private final SortedMap> inMemCache;

    private volatile StationFeatureCopyFactory stationFeatCopyFactory;

    public SortingStationPointFeatureCache() {
        this(stationNameComparator);
    }

    // We're going to init stationFeatCopyFactory using the first feat that's add()ed.
    public SortingStationPointFeatureCache(Comparator comp) {
        this.inMemCache = new TreeMap<>(Preconditions.checkNotNull(comp, "comp == null"));
        // stationFeatCopyFactory remains null.
    }

    public SortingStationPointFeatureCache(
            Comparator comp, StationPointFeature proto, DateUnit dateUnit) throws IOException {
        this.inMemCache = new TreeMap<>(Preconditions.checkNotNull(comp, "comp == null"));

        if (proto != null && dateUnit != null) {
            this.stationFeatCopyFactory = new StationFeatureCopyFactory(proto);
        }
    }

    public void add(StationPointFeature feat) throws IOException {
        Preconditions.checkNotNull(feat, "feat == null");
        StationPointFeature featCopy = getStationFeatureCopyFactory(feat).deepCopy(feat);

        List bucket = inMemCache.get(featCopy);
        if (bucket == null) {
            bucket = new LinkedList<>();
            inMemCache.put(featCopy, bucket);
        }

        bucket.add(featCopy);
    }

    public void addAll(File datasetFile) throws NoFactoryFoundException, IOException {
        try (FeatureDatasetPoint fdPoint = (FeatureDatasetPoint) FeatureDatasetFactoryManager.open(
                FeatureType.STATION, datasetFile.getAbsolutePath(), null, new Formatter())) {
            addAll(fdPoint);
        }
    }

    // fdPoint remains open.
    public void addAll(FeatureDatasetPoint fdPoint) throws IOException {
        try (PointFeatureIterator pointFeatIter =
                new FlattenedDatasetPointCollection(fdPoint).getPointFeatureIterator()) {
            while (pointFeatIter.hasNext()) {
                StationPointFeature pointFeat = (StationPointFeature) pointFeatIter.next();
                add(pointFeat);
            }
        }
    }

    // Double-check idiom for lazy initialization of instance fields. See Effective Java 2nd Ed, p. 283.
    private StationFeatureCopyFactory getStationFeatureCopyFactory(StationPointFeature proto) throws IOException {
        if (stationFeatCopyFactory == null) {
            synchronized (this) {
                if (stationFeatCopyFactory == null) {
                    stationFeatCopyFactory = createStationFeatureCopyFactory(proto);
                }
            }
        }

        assert stationFeatCopyFactory != null : "We screwed this up.";
        return stationFeatCopyFactory;
    }

    private StationFeatureCopyFactory createStationFeatureCopyFactory(StationPointFeature proto) throws IOException {
        return new StationFeatureCopyFactory(proto);
    }

    // TODO: Once this method is called, prohibit any further additions to cache.
    public PointFeatureIterator getPointFeatureIterator() throws IOException {
        return new PointIteratorAdapter(new Iter());
    }

    private class Iter implements Iterator {
        private final Iterator> bucketsIter;
        private Iterator featsIter;

        public Iter() {
            this.bucketsIter = inMemCache.values().iterator();
        }

        @Override
        public boolean hasNext() {  // Method is idempotent.
            while (featsIter == null || !featsIter.hasNext()) {
                if (!bucketsIter.hasNext()) {
                    return false;
                } else {
                    featsIter = bucketsIter.next().iterator();
                }
            }

            assert featsIter != null && featsIter.hasNext();
            return true;
        }

        @Override
        public StationPointFeature next() {
            if (!hasNext()) {  // Don't rely on user to call this.
                throw new NoSuchElementException("There are no more elements.");
            } else {
                return featsIter.next();
            }
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("Operation not supported by this iterator.");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy