TimeSpanMap.java

  1. /* Copyright 2002-2017 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.utils;

  18. import java.util.Collections;
  19. import java.util.NavigableSet;
  20. import java.util.SortedSet;
  21. import java.util.TreeSet;

  22. import org.orekit.time.AbsoluteDate;
  23. import org.orekit.time.ChronologicalComparator;
  24. import org.orekit.time.TimeStamped;

  25. /** Container for objects that apply to spans of time.

  26.  * @param <T> Type of the data.

  27.  * @author Luc Maisonobe
  28.  * @since 7.1
  29.  */
  30. public class TimeSpanMap<T> {

  31.     /** Container for the data. */
  32.     private final NavigableSet<Transition<T>> data;

  33.     /** Create a map containing a single object, initially valid throughout the timeline.
  34.      * <p>
  35.      * The real validity of this first entry will be truncated as other
  36.      * entries are either {@link #addValidBefore(Object, AbsoluteDate)
  37.      * added before} it or {@link #addValidAfter(Object, AbsoluteDate)
  38.      * added after} it.
  39.      * </p>
  40.      * @param entry entry (initially valid throughout the timeline)
  41.      */
  42.     public TimeSpanMap(final T entry) {
  43.         data = new TreeSet<Transition<T>>(new ChronologicalComparator());
  44.         data.add(new Transition<T>(AbsoluteDate.J2000_EPOCH, entry, entry));
  45.     }

  46.     /** Add an entry valid before a limit date.
  47.      * <p>
  48.      * As an entry is valid, it truncates the validity of the neighboring
  49.      * entries already present in the map.
  50.      * </p>
  51.      * <p>
  52.      * The transition dates should be entered only once, either
  53.      * by a call to this method or by a call to {@link #addValidAfter(Object,
  54.      * AbsoluteDate)}. Repeating a transition date will lead to unexpected
  55.      * result and is not supported.
  56.      * </p>
  57.      * @param entry entry to add
  58.      * @param latestValidityDate date before which the entry is valid
  59.      * (sould be different from <em>all</em> dates already used for transitions)
  60.      */
  61.     public void addValidBefore(final T entry, final AbsoluteDate latestValidityDate) {

  62.         if (data.size() == 1) {
  63.             final Transition<T> single = data.first();
  64.             if (single.getBefore() == single.getAfter()) {
  65.                 // the single entry was a dummy one, without a real transition
  66.                 // we replace it entirely
  67.                 data.clear();
  68.                 data.add(new Transition<T>(latestValidityDate, entry, single.getAfter()));
  69.                 return;
  70.             }
  71.         }

  72.         final Transition<T> previous =
  73.                 data.floor(new Transition<T>(latestValidityDate, entry, null));
  74.         if (previous == null) {
  75.             // the new transition will be the first one
  76.             data.add(new Transition<T>(latestValidityDate, entry, data.first().getBefore()));
  77.         } else {
  78.             // the new transition will be after the previous one
  79.             data.remove(previous);
  80.             data.add(new Transition<T>(previous.date,      previous.getBefore(), entry));
  81.             data.add(new Transition<T>(latestValidityDate, entry,                previous.getAfter()));
  82.         }

  83.     }

  84.     /** Add an entry valid after a limit date.
  85.      * <p>
  86.      * As an entry is valid, it truncates the validity of the neighboring
  87.      * entries already present in the map.
  88.      * </p>
  89.      * <p>
  90.      * The transition dates should be entered only once, either
  91.      * by a call to this method or by a call to {@link #addValidBefore(Object,
  92.      * AbsoluteDate)}. Repeating a transition date will lead to unexpected
  93.      * result and is not supported.
  94.      * </p>
  95.      * @param entry entry to add
  96.      * @param earliestValidityDate date after which the entry is valid
  97.      * (sould be different from <em>all</em> dates already used for transitions)
  98.      */
  99.     public void addValidAfter(final T entry, final AbsoluteDate earliestValidityDate) {

  100.         if (data.size() == 1) {
  101.             final Transition<T> single = data.first();
  102.             if (single.getBefore() == single.getAfter()) {
  103.                 // the single entry was a dummy one, without a real transition
  104.                 // we replace it entirely
  105.                 data.clear();
  106.                 data.add(new Transition<T>(earliestValidityDate, single.getBefore(), entry));
  107.                 return;
  108.             }
  109.         }

  110.         final Transition<T> next =
  111.                 data.ceiling(new Transition<T>(earliestValidityDate, entry, null));
  112.         if (next == null) {
  113.             // the new transition will be the last one
  114.             data.add(new Transition<T>(earliestValidityDate, data.last().getAfter(), entry));
  115.         } else {
  116.             // the new transition will be before the next one
  117.             data.remove(next);
  118.             data.add(new Transition<T>(earliestValidityDate, next.getBefore(), entry));
  119.             data.add(new Transition<T>(next.date,            entry,            next.getAfter()));
  120.         }

  121.     }

  122.     /** Get the entry valid at a specified date.
  123.      * @param date date at which the entry must be valid
  124.      * @return valid entry at specified date
  125.      */
  126.     public T get(final AbsoluteDate date) {
  127.         final Transition<T> previous = data.floor(new Transition<T>(date, null, null));
  128.         if (previous == null) {
  129.             // there are no transition before the specified date
  130.             // return the first valid entry
  131.             return data.first().getBefore();
  132.         } else {
  133.             return previous.getAfter();
  134.         }
  135.     }

  136.     /** Get an unmodifiable view of the sorted transitions.
  137.      * @return unmodifiable view of the sorted transitions
  138.      */
  139.     public SortedSet<Transition<T>> getTransitions() {
  140.         return Collections.unmodifiableSortedSet(data);
  141.     }

  142.     /** Local class holding transition times. */
  143.     public static class Transition<S> implements TimeStamped {

  144.         /** Transition date. */
  145.         private final AbsoluteDate date;

  146.         /** Entry valid before the transition. */
  147.         private final S before;

  148.         /** Entry valid after the transition. */
  149.         private final S after;

  150.         /** Simple constructor.
  151.          * @param date transition date
  152.          * @param before entry valid before the transition
  153.          * @param after entry valid after the transition
  154.          */
  155.         private Transition(final AbsoluteDate date, final S before, final S after) {
  156.             this.date   = date;
  157.             this.before = before;
  158.             this.after  = after;
  159.         }

  160.         /** Get the transition date.
  161.          * @return transition date
  162.          */
  163.         @Override
  164.         public AbsoluteDate getDate() {
  165.             return date;
  166.         }

  167.         /** Get the entry valid before transition.
  168.          * @return entry valid before transition
  169.          */
  170.         public S getBefore() {
  171.             return before;
  172.         }

  173.         /** Get the entry valid after transition.
  174.          * @return entry valid after transition
  175.          */
  176.         public S getAfter() {
  177.             return after;
  178.         }

  179.     }

  180. }