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

com.yahoo.bard.webservice.util.IntervalUtils Maven / Gradle / Ivy

Go to download

Fili web service library provides core capabilities for RESTful aggregation navigation, query planning and metadata

There is a newer version: 1.1.13
Show newest version
// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms.
package com.yahoo.bard.webservice.util;

import com.yahoo.bard.webservice.config.SystemConfig;
import com.yahoo.bard.webservice.config.SystemConfigProvider;
import com.yahoo.bard.webservice.data.time.Granularity;
import com.yahoo.bard.webservice.data.time.StandardGranularityParser;
import com.yahoo.bard.webservice.data.time.TimeGrain;
import com.yahoo.bard.webservice.table.resolver.GranularityComparator;

import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.Interval;
import org.joda.time.base.AbstractInterval;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * Methods and Iterators which support interval slicing alignment and set operations.
 */
public class IntervalUtils {

    private static final GranularityComparator COMPARATOR = GranularityComparator.getInstance();

    public static final SystemConfig SYSTEM_CONFIG = SystemConfigProvider.getInstance();

    public static final String ALIGNMENT_EPOCH_STRING = SYSTEM_CONFIG.getStringProperty(
            SYSTEM_CONFIG.getPackageVariableName("alignment_epoch"),
            "1970-01-01T00:00:00Z"
    );

    public static final DateTime SYSTEM_ALIGNMENT_EPOCH = new DateTime(ALIGNMENT_EPOCH_STRING);

    /**
     * For a given interval, return a stream of the subintervals of it that are shared with at least one interval
     * in the collection of compare intervals.
     *
     * @param interval  The interval being matched
     * @param compareIntervals  The collection of intervals being matched against
     *
     * @return Every pairwise overlap
     */
    public static Stream getIntervalOverlaps(Interval interval, Collection compareIntervals) {
        return compareIntervals.stream().map(interval::overlap).filter(Objects::nonNull);
    }

    /**
     * Find all the interval overlaps between two collections of intervals.
     * 

* If the left set is null, return the right. This makes this usable in a reduce function. * * @param left The intervals being streamed over * @param right The intervals being tested against * * @return A set of intervals describing the time common to both sets */ public static Set getOverlappingSubintervals(Collection left, Collection right) { if (left == null) { return new LinkedHashSet<>(right); } // Each interval in left is matched against all intervals in the right, collecting overlaps return left.stream() .flatMap(leftElement -> getIntervalOverlaps(leftElement, right)) .collect(Collectors.toSet()); } /** * Find all the interval overlaps between two collections of intervals. *

* If the left set is null, return the right. This makes this usable in a reduce function. * * @param left The intervals being streamed over * @param right The intervals being tested against * * @return A set of intervals describing the time common to both sets */ public static Set getOverlappingSubintervals(Set left, Set right) { return getOverlappingSubintervals((Collection) left, (Collection) right); } /** * Simplify raw intervals and return a map of intervals (dividing them by the grain) to the ordinal of the interval. * * @param rawIntervals A collection of intervals to be split * @param grain The grain to split by. * * @return a map of simplified intervals split according to the grain to an integer that indicates their ordinal */ public static Map getSlicedIntervals( Collection rawIntervals, Granularity grain ) { Iterable requestIterable = grain.intervalsIterable(rawIntervals); AtomicInteger index = new AtomicInteger(0); return StreamSupport .stream(requestIterable.spliterator(), false) .collect( Collectors.toMap( Function.identity(), ignored -> new AtomicInteger(index.getAndIncrement()), (x, y) -> { throw new AssertionError(); }, LinkedHashMap::new ) ); } /** * Count the intervals after simplifying raw intervals and splitting by grain. * * @param rawIntervals A collection of intervals to be split * @param grain The grain to split by. * * @return a count of intervals as split by grain */ public static long countSlicedIntervals(Collection rawIntervals, Granularity grain) { Iterable requestIterable = grain.intervalsIterable(rawIntervals); return StreamSupport.stream(requestIterable.spliterator(), false) .count(); } /** * Collect all subintervals of an interval list of a grain bucketed size which are subintervals of another supply * list of intervals. * * @param supplyIntervals The interval collection to match bucketedIntervals against * @param bucketedIntervals The grain bucketed intervals to collect if they overlap the supply * @param granularity Grain at which to split the bucketingIntervals * * @return a simplified list of subintervals of the bucketedIntervals list */ public static SimplifiedIntervalList collectBucketedIntervalsIntersectingIntervalList( SimplifiedIntervalList supplyIntervals, SimplifiedIntervalList bucketedIntervals, Granularity granularity ) { // Stream the from intervals, split by grain Iterable bucketedIterable = granularity.intervalsIterable(bucketedIntervals); // Predicate to find buckets which overlap Predicate isIntersecting = new SimplifiedIntervalList.SkippingIntervalPredicate( supplyIntervals, AbstractInterval::overlaps, false ); return StreamSupport.stream(bucketedIterable.spliterator(), false) .filter(isIntersecting) .collect(SimplifiedIntervalList.getCollector()); } /** * Sum the length of the intervals in this collection. * * @param intervals A collection of time intervals * * @return The total duration of all the intervals */ public static long getTotalDuration(Collection intervals) { return new SimplifiedIntervalList(intervals).stream() .map(Interval::toDuration) .mapToLong(Duration::getMillis) .sum(); } /** * Return the first date time instant in this set of intervals if available. * * @param intervalSets A collection of intervals sets * * @return Return the earliest date time (if any) across all the intervals contained */ public static Optional firstMoment(Collection> intervalSets) { return intervalSets.stream().flatMap(Collection::stream) .map(Interval::getStart) .reduce(Utils::getMinValue); } /** * Find a valid timegrain for the interval based on the start and end date of the interval. * * @param interval The interval to find a timegrain for. * @return the valid timegrain spanned by the interval. */ public static Optional getTimeGrain(Interval interval) { return StandardGranularityParser.getDefaultGrainMap() .values() .stream() .filter(granularity -> granularity instanceof TimeGrain) .map(granularity -> (TimeGrain) granularity) .filter(timeGrain -> timeGrain.aligns(interval)) .filter(timeGrain -> interval.getStart().plus(timeGrain.getPeriod()).equals(interval.getEnd())) .findFirst(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy