AbstractHistoricalMap.java

  1. package org.opentrafficsim.core.perception.collections;

  2. import java.util.Collection;
  3. import java.util.Collections;
  4. import java.util.LinkedHashSet;
  5. import java.util.Map;
  6. import java.util.Objects;
  7. import java.util.Set;

  8. import org.djunits.value.vdouble.scalar.Time;
  9. import org.djutils.exceptions.Throw;
  10. import org.opentrafficsim.core.perception.AbstractHistorical;
  11. import org.opentrafficsim.core.perception.HistoryManager;
  12. import org.opentrafficsim.core.perception.collections.AbstractHistoricalMap.EventMap;

  13. /**
  14.  * Map-valued historical state. The current map is always maintained, and past states of the map are obtained by applying the
  15.  * events between now and the requested time in reverse.<br>
  16.  * <br>
  17.  * The set views returned by this class are unmodifiable.
  18.  * <p>
  19.  * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  20.  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  21.  * <p>
  22.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 1 feb. 2018 <br>
  23.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  24.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  25.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  26.  * @param <K> key type
  27.  * @param <V> value type
  28.  * @param <M> map type
  29.  */
  30. public abstract class AbstractHistoricalMap<K, V, M extends Map<K, V>> extends AbstractHistorical<K, EventMap<K, V, M>>
  31.         implements HistoricalMap<K, V>
  32. {

  33.     /** Current map. */
  34.     private final M current;

  35.     /**
  36.      * Constructor.
  37.      * @param historyManager HistoryManager; history manager
  38.      * @param map M; initial map
  39.      */
  40.     protected AbstractHistoricalMap(final HistoryManager historyManager, final M map)
  41.     {
  42.         super(historyManager);
  43.         Throw.when(!map.isEmpty(), IllegalArgumentException.class, "The initial map should be empty.");
  44.         this.current = map;
  45.     }

  46.     /**
  47.      * Returns the internal map.
  48.      * @return M; internal map
  49.      */
  50.     protected M getMap()
  51.     {
  52.         return this.current;
  53.     }

  54.     /**
  55.      * Fill map with the current map.
  56.      * @param map M; map to fill
  57.      * @return M; input map filled
  58.      */
  59.     protected M fill(final M map)
  60.     {
  61.         map.putAll(this.current);
  62.         return map;
  63.     }

  64.     /**
  65.      * Fill map with the map at the given simulation time.
  66.      * @param time Time; time
  67.      * @param map M; map to fill
  68.      * @return M; input map filled
  69.      */
  70.     protected M fill(final Time time, final M map)
  71.     {
  72.         // copy all current elements and decrement per event
  73.         map.putAll(this.current);
  74.         for (EventMap<K, V, M> event : getEvents(time))
  75.         {
  76.             event.restore(map);
  77.         }
  78.         return map;
  79.     }

  80.     // Altering Map methods

  81.     /** {@inheritDoc} */
  82.     @Override
  83.     public void clear()
  84.     {
  85.         new LinkedHashSet<>(this.current.keySet()).forEach(this::remove);
  86.     }

  87.     /** {@inheritDoc} */
  88.     @Override
  89.     public V put(final K key, final V value)
  90.     {
  91.         boolean contained = this.current.containsKey(key);
  92.         V previousValue = contained ? this.current.get(key) : null;
  93.         if (!contained || !Objects.equals(previousValue, value))
  94.         {
  95.             addEvent(new EventMap<>(now().si, key, contained, previousValue));
  96.             return this.current.put(key, value);
  97.         }
  98.         return previousValue;
  99.     }

  100.     /** {@inheritDoc} */
  101.     @Override
  102.     public void putAll(final Map<? extends K, ? extends V> m)
  103.     {
  104.         m.forEach(this::put);
  105.     }

  106.     /** {@inheritDoc} */
  107.     @Override
  108.     @SuppressWarnings("unchecked")
  109.     public V remove(final Object key)
  110.     {
  111.         boolean contained = this.current.containsKey(key);
  112.         if (contained)
  113.         {
  114.             V previousValue = this.current.get(key);
  115.             addEvent(new EventMap<>(now().si, (K) key, contained, previousValue)); // contains, so safe cast
  116.             return this.current.remove(key);
  117.         }
  118.         return null;
  119.     }

  120.     // Non-altering Map methods

  121.     /** {@inheritDoc} */
  122.     @Override
  123.     public int size()
  124.     {
  125.         return this.current.size();
  126.     }

  127.     /** {@inheritDoc} */
  128.     @Override
  129.     public boolean isEmpty()
  130.     {
  131.         return this.current.isEmpty();
  132.     }

  133.     /** {@inheritDoc} */
  134.     @Override
  135.     public boolean containsKey(final Object key)
  136.     {
  137.         return this.current.containsKey(key);
  138.     }

  139.     /** {@inheritDoc} */
  140.     @Override
  141.     public boolean containsValue(final Object value)
  142.     {
  143.         return this.current.containsValue(value);
  144.     }

  145.     /** {@inheritDoc} */
  146.     @Override
  147.     public V get(final Object key)
  148.     {
  149.         return this.current.get(key);
  150.     }

  151.     /** {@inheritDoc} */
  152.     @Override
  153.     public Set<K> keySet()
  154.     {
  155.         return Collections.unmodifiableSet(this.current.keySet());
  156.     }

  157.     /** {@inheritDoc} */
  158.     @Override
  159.     public Collection<V> values()
  160.     {
  161.         return Collections.unmodifiableCollection(this.current.values());
  162.     }

  163.     /** {@inheritDoc} */
  164.     @Override
  165.     public Set<Entry<K, V>> entrySet()
  166.     {
  167.         // need to ensure that the Entries themselves allow no alterations
  168.         return Collections.unmodifiableMap(this.current).entrySet();
  169.     }

  170.     // Events

  171.     /**
  172.      * Abstract super class for events that add or remove a value from the map.
  173.      * <p>
  174.      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
  175.      * <br>
  176.      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  177.      * <p>
  178.      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 1 jan. 2018 <br>
  179.      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  180.      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  181.      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  182.      * @param <K> key type
  183.      * @param <V> value type
  184.      * @param <M> map type
  185.      */
  186.     public static class EventMap<K, V, M extends Map<K, V>> extends AbstractHistorical.EventValue<K>
  187.     {

  188.         /** Whether the map contained the key prior to the event. */
  189.         private final boolean contained;

  190.         /** Previous value in the map. */
  191.         private final V previousValue;

  192.         /**
  193.          * Constructor.
  194.          * @param time double; time of event
  195.          * @param key K; key of event
  196.          * @param contained boolean; whether the map contained the key prior to the event
  197.          * @param previousValue V; previous value in the map
  198.          */
  199.         public EventMap(final double time, final K key, final boolean contained, final V previousValue)
  200.         {
  201.             super(time, key);
  202.             this.contained = contained;
  203.             this.previousValue = previousValue;
  204.         }

  205.         /**
  206.          * Restores the map to the state of before the event.
  207.          * @param map M; map to restore
  208.          */
  209.         public void restore(final M map)
  210.         {
  211.             if (this.contained)
  212.             {
  213.                 map.put(getValue(), this.previousValue); // event value = map key
  214.             }
  215.             else
  216.             {
  217.                 map.remove(getValue()); // event value = map key
  218.             }
  219.         }

  220.         /** {@inheritDoc} */
  221.         @Override
  222.         public String toString()
  223.         {
  224.             return "EventMap [contained=" + this.contained + ", previousValue=" + this.previousValue + "]";
  225.         }

  226.     }

  227. }