viper.api.time.MultipleRange.java Source code

Java tutorial

Introduction

Here is the source code for viper.api.time.MultipleRange.java

Source

/***************************************
 *            ViPER                    *
 *  The Video Processing               *
 *         Evaluation Resource         *
 *                                     *
 *  Distributed under the GPL license  *
 *        Terms available at gnu.org.  *
 *                                     *
 *  Copyright University of Maryland,  *
 *                      College Park.  *
 ***************************************/

package viper.api.time;

import java.util.*;

import org.apache.commons.collections.*;

import viper.api.*;
import edu.umd.cfar.lamp.viper.util.*;

/**
 * Acts as an aggregate of several TemporalRange objects.
 * It acts as if it were a list of arrays, where each array at time <i>t</i>
 * contains the value of the respective TemporalRange at time <i>t</i>. 
 * 
 * @author davidm
 * @since May 17, 2003
 */
public class MultipleRange implements TemporalRange {
    private static Integer ONE = new Integer(1);
    /**
     * The ranges that make up this multiplerange object.
     */
    public TemporalRange[] subs;

    /**
     * Creates a new MultipleRange using the given array as backing.
     * Note that it takes the reference to the array; it does not copy it.
     * 
     * @param subs The TemporalRanges to act as children to this aggregator
     */
    public MultipleRange(TemporalRange[] subs) {
        this.subs = subs;
    }

    /**
     * {@inheritDoc}
     */
    public void clear() {
        for (int i = 0; i < subs.length; i++) {
            subs[i].clear();
        }
    }

    /**
     * {@inheritDoc}
     */
    public boolean isFrameBased() {
        if (subs.length > 0) {
            return subs[0].isFrameBased();
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isTimeBased() {
        if (subs.length > 0) {
            return subs[0].isTimeBased();
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public Object clone() {
        TemporalRange[] c = new MultipleRange[subs.length];
        for (int i = 0; i < subs.length; i++) {
            c[i] = (TemporalRange) subs[i].clone();
        }
        return new MultipleRange(c);
    }

    /**
     * {@inheritDoc}
     */
    public boolean intersects(TemporalRange other) {
        for (int i = 0; i < subs.length; i++) {
            if (subs[i].intersects(other)) {
                return true;
            }
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public Interval getExtrema() {
        if (subs.length == 0) {
            return null;
        }
        Interval ex = null;
        for (int i = 0; i < subs.length; i++) {
            if (subs[i].isEmpty()) {
                continue;
            }
            Interval curr = subs[i].getExtrema();
            if (ex == null) {
                ex = curr;
            } else if (curr != null) {
                Comparable n_s = ex.getStart();
                Comparable n_e = ex.getEnd();
                boolean changed = false;
                if (ex.getStart().compareTo(curr.getStart()) > 0) {
                    changed = true;
                    n_s = curr.getStart();
                }
                if (ex.getEnd().compareTo(curr.getEnd()) < 0) {
                    changed = true;
                    n_e = curr.getEnd();
                }
                if (changed) {
                    ex = ex.change(n_s, n_e);
                }
            }
        }
        return ex;
    }

    /**
     * {@inheritDoc}
     */
    public boolean contains(Object o) {
        for (int i = 0; i < subs.length; i++) {
            if (subs[i].contains(o)) {
                return true;
            }
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public Object get(Comparable index) {
        Object[] r = new Object[subs.length];
        for (int i = 0; i < subs.length; i++) {
            r[i] = subs[i].get(index);
        }
        return r;
    }

    /**
     * {@inheritDoc}
     */
    public void set(Comparable start, Comparable stop, Object value) {
        Object[] r = (Object[]) value;
        for (int i = 0; i < subs.length; i++) {
            subs[i].set(start, stop, r[i]);
        }
    }

    /**
     * {@inheritDoc}
     */
    public boolean remove(Comparable start, Comparable stop) {
        boolean r = false;
        for (int i = 0; i < subs.length; i++) {
            r = r || subs[i].remove(start, stop);
        }
        return r;
    }

    /** @inheritDoc */
    public Iterator iterator(Interval i) {
        return new CropIteratorUtility(i).getIterator(iterator());
    }

    private static class IntersectsThisFilter implements ExceptIterator.ExceptFunctor {
        private Interval i;

        IntersectsThisFilter(Interval i) {
            super();
            this.i = i;
        }

        public boolean check(Object o) {
            Interval toCheck = (Interval) o;
            return i.intersects(toCheck);
        }

    }

    /**
     * {@inheritDoc}
     */
    public Iterator iterator() {
        return new MyIterator();
    }

    private class MyIterator implements Iterator {
        private Iterator[] iters;
        private Interval[] nexts;
        private Comparable n_s = null;
        private Comparable n_e = null;
        private boolean hn = false;

        MyIterator() {
            iters = new Iterator[subs.length];
            nexts = new Interval[subs.length];
            for (int i = 0; i < subs.length; i++) {
                iters[i] = subs[i].iterator();
                if (iters[i].hasNext()) {
                    nexts[i] = (Interval) iters[i].next();
                    hn = true;
                }
            }
            Interval r = getExtrema();
            if (r != null) {
                n_s = r.getStart();
                n_e = r.getEnd();
            }
        }

        /**
         * Gets the next interval in the range.
         * @return an interval
         */
        public Object next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            Object[] c = new Object[nexts.length];
            Comparable e = n_e;
            Comparable s = n_s;
            boolean found = false;
            while (!found && hasNext()) {
                hn = false;
                for (int i = 0; i < nexts.length; i++) {
                    // fill c with the values of each iter at frame s
                    // while searching for the next end frame e.
                    // if they are all null values, set s = e, e = n_e and continue
                    if (nexts[i] == null) {
                        // Iterator is empty
                        continue;
                    } else if (nexts[i].getEnd().compareTo(n_s) <= 0) {
                        // out of date iterator element. Go to the next one.
                        if (iters[i].hasNext()) {
                            nexts[i] = (Interval) iters[i].next();
                        } else {
                            nexts[i] = null;
                            continue;
                        }
                    }

                    if (nexts[i].contains(s)) {
                        if (nexts[i] instanceof DynamicValue) {
                            c[i] = ((DynamicValue) nexts[i]).getValue();
                        } else {
                            c[i] = ONE;
                        }
                        found = true;
                        if (nexts[i].getEnd().compareTo(e) < 0) {
                            e = nexts[i].getEnd();
                            hn = true;
                        }
                    } else {
                        // nexts[i] starts after the current frame
                        if (nexts[i].getStart().compareTo(e) < 0) {
                            // nexts[i] starts during [s,e)
                            e = nexts[i].getStart();
                            hn = true;
                        }
                    }
                }
                if (!found) {
                    s = e;
                    e = n_e;
                }
            }
            DynamicAttributeValue v = new TemporalObject((Instant) s, (Instant) e, c);
            n_s = e;
            return v;
        }

        /**
         * Tests to see if next will fail.
         * @return if next will succeed
         */
        public boolean hasNext() {
            return hn;
        }

        /**
         * Not implemented.
         */
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    /**
     * {@inheritDoc}
     */
    public boolean addAll(IntervalIndexList l) {
        Iterator iter = l.iterator();
        while (iter.hasNext()) {
            DynamicAttributeValue curr = (DynamicAttributeValue) iter.next();
            this.set(curr.getStart(), curr.getEnd(), curr.getValue());
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public IntervalIndexList subList(Comparable start, Comparable stop) {
        throw new UnsupportedOperationException();
    }

    private static final Comparator NULL_OR_INT_SORT = new Comparator() {
        public int compare(Object o1, Object o2) {
            // null == +inf
            if (o1 == o2) {
                return 0;
            } else if (o1 == null) {
                return Integer.MAX_VALUE;
            } else if (o2 == null) {
                return Integer.MIN_VALUE;
            } else {
                return ((Comparable) o1).compareTo((Comparable) o2);
            }
        }
    };

    private void fourSort(Comparable[] four) {
        Arrays.sort(four, NULL_OR_INT_SORT);
        int alpha = 0;
        int beta = 1;
        while (alpha < four.length - 1) {
            if (four[alpha] == null) {
                return;
            }
            while (four[alpha].equals(nullGet(four, beta))) {
                beta++;
            }
            four[++alpha] = nullGet(four, beta++);
        }
    }

    private Comparable nullGet(Comparable[] C, int index) {
        if (index < 0 || C.length <= index) {
            return null;
        } else {
            return C[index];
        }
    }

    private Comparable[] firstTwoEndsOrStartsBefore(Comparable c) {
        Comparable[] F = new Comparable[4];
        for (int i = 0; i < subs.length; i++) {
            F[2] = subs[i].firstBefore(c);
            if (F[2] == null) {
                continue;
            } else {
                F[3] = subs[i].endOf(F[2]);
                fourSort(F);
                if (F[3] != null && F[3].compareTo(c) < 0) {
                    F[0] = F[2];
                    F[1] = F[3];
                } else if (F[2] != null && F[2].compareTo(c) < 0) {
                    F[0] = F[1];
                    F[1] = F[2];
                }
            }
        }
        if (F[1] != null && F[1].compareTo(c) < 0)
            return new Comparable[] { F[0], F[1] };
        else if (F[0] != null && F[0].compareTo(c) < 0)
            return new Comparable[] { F[0] };
        else
            return new Comparable[0];
    }

    private Comparable[] firstTwoEndsOrStartsAfter(Comparable c) {
        Comparable[] F = new Comparable[4];
        for (int i = 0; i < subs.length; i++) {
            F[2] = subs[i].firstBefore(c);
            if (F[2] != null) {
                F[2] = subs[i].endOf(F[2]);
                if (F[2] != null && F[2].compareTo(c) <= 0) {
                    F[2] = null;
                }
            }
            F[3] = subs[i].firstAfter(c);
            fourSort(F);
        }
        if (F[1] != null && F[1].compareTo(c) >= 0)
            return new Comparable[] { F[0], F[1] };
        else if (F[0] != null && F[0].compareTo(c) >= 0)
            return new Comparable[] { F[0] };
        else
            return new Comparable[0];
    }

    /**
     * {@inheritDoc}
     */
    public Comparable firstBefore(Comparable c) {
        Comparable[] F = firstTwoEndsOrStartsBefore(c);
        for (int i = 0; i < F.length; i++) {
            if (F[i] != null && this.contains(F[i])) {
                return F[i];
            }
        }
        return null;
    }

    public Comparable firstBeforeOrAt(Comparable c) {
        return firstBefore(((Incrementable) c).next());
    }

    /**
     * {@inheritDoc}
     */
    public Comparable firstAfterOrAt(Comparable c) {
        return firstAfter(((Incrementable) c).previous());
    }

    /**
     * {@inheritDoc}
     */
    public Comparable firstAfter(Comparable c) {
        Comparable[] F = firstTwoEndsOrStartsAfter(c);
        for (int i = 0; i < F.length; i++) {
            if (F[i] != null && this.contains(F[i])) {
                return F[i];
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    public Comparable endOf(Comparable c) {
        if (c == null) {
            return null;
        }
        if (subs.length == 0) {
            return null;
        }
        Comparable eo = subs[0].endOf(c);
        for (int i = 1; i < subs.length; i++) {
            Comparable temp = subs[i].endOf(c);
            if ((eo == null) || (temp != null && eo.compareTo(temp) < 0)) {
                eo = temp;
            }
        }
        return eo;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isEmpty() {
        for (int i = 0; i < subs.length; i++) {
            if (!subs[i].isEmpty()) {
                return false;
            }
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public void map(Transformer c) {
        for (int i = 0; i < subs.length; i++) {
            subs[i].map(c);
        }
    }

    /**
     * Counts the number of contiguous, homogenous intervals.
     * @return the number of elements the iterator returns.
     */
    public int getContiguousIntervalCount() {
        int i = 0;
        Iterator iter = this.iterator();
        while (iter.hasNext()) {
            i++;
            iter.next();
        }
        return i;
    }

    /** @inheritDoc */
    public void shift(Instant amount) {
        for (int i = 0; i < subs.length; i++) {
            subs[i].shift(amount);
        }
    }
}