View Javadoc
1   package org.opentrafficsim.core.perception.collections;
2   
3   import java.util.Collection;
4   import java.util.Collections;
5   import java.util.HashSet;
6   import java.util.Iterator;
7   import java.util.Set;
8   
9   import org.djunits.value.vdouble.scalar.Time;
10  import org.opentrafficsim.core.perception.AbstractHistorical;
11  import org.opentrafficsim.core.perception.HistoryManager;
12  import org.opentrafficsim.core.perception.collections.AbstractHistoricalCollection.EventCollection;
13  
14  /**
15   * Collection-valued historical state. The current collection is always maintained, and past states of the collection are
16   * obtained by applying the events between now and the requested time in reverse.<br>
17   * <br>
18   * This implementation is suitable for sets, as add and remove events to retrieve historical states are only created if indeed
19   * the underlying collection is changed. {@code Set} introduces no new methods relative to {@code Collection}.<br>
20   * <br>
21   * The {@code Iterator} returned by this class does not support the {@code remove()} method.
22   * <p>
23   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
24   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
25   * <p>
26   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 1 jan. 2018 <br>
27   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
28   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
29   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
30   * @param <E> element type
31   * @param <C> collection type
32   */
33  public abstract class AbstractHistoricalCollection<E, C extends Collection<E>>
34          extends AbstractHistorical<E, EventCollection<E, C>> implements HistoricalCollection<E>
35  {
36  
37      /** Current collection. */
38      private final C current;
39  
40      /**
41       * Constructor.
42       * @param historyManager HistoryManager; history manager
43       * @param collection C; initial collection
44       */
45      protected AbstractHistoricalCollection(final HistoryManager historyManager, final C collection)
46      {
47          super(historyManager);
48          this.current = collection;
49      }
50  
51      /**
52       * Returns the internal collection.
53       * @return C; internal collection
54       */
55      protected final C getCollection()
56      {
57          return this.current;
58      }
59  
60      /**
61       * Fill collection with the current collection.
62       * @param collection C; collection to fill
63       * @return C; input collection filled
64       */
65      protected final C fill(final C collection)
66      {
67          collection.addAll(this.current);
68          return collection;
69      }
70  
71      /**
72       * Fill collection with the collection at the given simulation time.
73       * @param time Time; time
74       * @param collection C; collection to fill
75       * @return C; input collection filled
76       */
77      protected final C fill(final Time time, final C collection)
78      {
79          // copy all current elements and decrement per event
80          collection.addAll(this.current);
81          for (EventCollection<E, C> event : getEvents(time))
82          {
83              event.restore(collection);
84          }
85          return collection;
86      }
87  
88      // Altering Collection methods
89  
90      /** {@inheritDoc} */
91      @Override
92      public boolean add(final E value)
93      {
94          boolean added = getCollection().add(value);
95          if (added)
96          {
97              addEvent(new AddEvent<>(now().si, value));
98          }
99          return added;
100     }
101 
102     /** {@inheritDoc} */
103     @Override
104     public boolean addAll(final Collection<? extends E> c)
105     {
106         boolean changed = false;
107         for (E value : c)
108         {
109             changed |= add(value);
110         }
111         return changed;
112     }
113 
114     /** {@inheritDoc} */
115     @Override
116     public void clear()
117     {
118         new HashSet<>(this.current).forEach(this::remove);
119     }
120 
121     /** {@inheritDoc} */
122     @Override
123     @SuppressWarnings("unchecked")
124     public boolean remove(final Object value)
125     {
126         boolean removed = getCollection().remove(value);
127         if (removed)
128         {
129             addEvent(new RemoveEvent<>(now().si, (E) value)); // contains, so safe cast
130         }
131         return removed;
132     }
133 
134     /** {@inheritDoc} */
135     @Override
136     public boolean removeAll(final Collection<?> c)
137     {
138         boolean changed = false;
139         for (Object value : c)
140         {
141             changed |= remove(value);
142         }
143         return changed;
144     }
145 
146     /** {@inheritDoc} */
147     @Override
148     public boolean retainAll(final Collection<?> c)
149     {
150         boolean changed = false;
151         Set<E> values = new HashSet<>(this.current);
152         for (E value : values)
153         {
154             if (!c.contains(value))
155             {
156                 changed |= remove(value);
157             }
158         }
159         return changed;
160     }
161 
162     // Non-altering Collection methods
163 
164     /** {@inheritDoc} */
165     @Override
166     public int size()
167     {
168         return this.current.size();
169     }
170 
171     /** {@inheritDoc} */
172     @Override
173     public boolean isEmpty()
174     {
175         return this.current.isEmpty();
176     }
177 
178     /** {@inheritDoc} */
179     @Override
180     public boolean contains(final Object o)
181     {
182         return this.current.contains(o);
183     }
184 
185     /** {@inheritDoc} */
186     @Override
187     public Iterator<E> iterator()
188     {
189         return Collections.unmodifiableCollection(this.current).iterator();
190     }
191 
192     /** {@inheritDoc} */
193     @Override
194     public Object[] toArray()
195     {
196         return this.current.toArray();
197     }
198 
199     /** {@inheritDoc} */
200     @Override
201     public <T> T[] toArray(final T[] a)
202     {
203         return this.current.toArray(a);
204     }
205 
206     /** {@inheritDoc} */
207     @Override
208     public boolean containsAll(final Collection<?> c)
209     {
210         return this.current.containsAll(c);
211     }
212 
213     // Events
214 
215     /**
216      * Abstract super class for events that add or remove a value from the collection.
217      * <p>
218      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
219      * <br>
220      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
221      * <p>
222      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 1 jan. 2018 <br>
223      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
224      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
225      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
226      * @param <E> element type
227      * @param <C> collection type
228      */
229     public abstract static class EventCollection<E, C extends Collection<E>> extends AbstractHistorical.EventValue<E>
230     {
231 
232         /**
233          * Constructor.
234          * @param time double; time of event
235          * @param value E; value of event
236          */
237         public EventCollection(final double time, final E value)
238         {
239             super(time, value);
240         }
241 
242         /**
243          * Restores the collection to the state of before the event.
244          * @param collection C; collection to restore
245          */
246         public abstract void restore(C collection);
247 
248         /** {@inheritDoc} */
249         @Override
250         public String toString()
251         {
252             return "EventCollection []";
253         }
254 
255     }
256 
257     /**
258      * Event for adding value to the collection.
259      * <p>
260      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
261      * <br>
262      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
263      * <p>
264      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 1 jan. 2018 <br>
265      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
266      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
267      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
268      * @param <E> element type
269      * @param <C> collection type
270      */
271     public static class AddEvent<E, C extends Collection<E>> extends EventCollection<E, C>
272     {
273 
274         /**
275          * Constructor.
276          * @param time double; time of event
277          * @param value E; value of event
278          */
279         public AddEvent(final double time, final E value)
280         {
281             super(time, value);
282         }
283 
284         /** {@inheritDoc} */
285         @Override
286         public void restore(final C collection)
287         {
288             collection.remove(getValue()); // events are only created upon effective addition, so we can remove it
289         }
290 
291         /** {@inheritDoc} */
292         @Override
293         public String toString()
294         {
295             return "AddEvent []";
296         }
297 
298     }
299 
300     /**
301      * Event for removing value from the collection.
302      * <p>
303      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
304      * <br>
305      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
306      * <p>
307      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 1 jan. 2018 <br>
308      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
309      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
310      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
311      * @param <E> element type
312      * @param <C> collection type
313      */
314     public static class RemoveEvent<E, C extends Collection<E>> extends EventCollection<E, C>
315     {
316 
317         /**
318          * Constructor.
319          * @param time double; time of event
320          * @param value E; value of event
321          */
322         public RemoveEvent(final double time, final E value)
323         {
324             super(time, value);
325         }
326 
327         /** {@inheritDoc} */
328         @Override
329         public void restore(final C collection)
330         {
331             collection.add(getValue()); // events are only created upon effective removal, so we can add it
332         }
333 
334         /** {@inheritDoc} */
335         @Override
336         public String toString()
337         {
338             return "RemoveEvent []";
339         }
340 
341     }
342 
343 }