View Javadoc
1   package org.djutils.event.collection;
2   
3   import java.io.Serializable;
4   import java.util.Collection;
5   import java.util.Map;
6   import java.util.Set;
7   
8   import org.djutils.event.EventType;
9   import org.djutils.event.LocalEventProducer;
10  import org.djutils.exceptions.Throw;
11  import org.djutils.metadata.MetaData;
12  import org.djutils.metadata.ObjectDescriptor;
13  
14  /**
15   * The Event producing map provides a map to which one can subscribe interest in entry changes. This class does not keep track
16   * of changes which take place indirectly. One is for example not notified on <code>map.iterator.remove()</code>. A listener
17   * must subscribe to the iterator, key set, etc. individually.
18   * <p>
19   * Copyright (c) 2002-2024 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
20   * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
21   * distributed under a three-clause BSD-style license, which can be found at
22   * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>. This class was
23   * originally part of the DSOL project, see <a href="https://simulation.tudelft.nl/dsol/manual" target="_blank">
24   * https://simulation.tudelft.nl/dsol/manual</a>.
25   * </p>
26   * @author <a href="https://www.linkedin.com/in/peterhmjacobs">Peter Jacobs </a>
27   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
28   * @param <K> the key type
29   * @param <V> the value type
30   */
31  public class EventProducingMap<K, V> extends LocalEventProducer implements Map<K, V>, Serializable
32  {
33      /** The default serial version UID for serializable classes. */
34      private static final long serialVersionUID = 20191230L;
35  
36      /** OBJECT_ADDED_EVENT is fired on new entries. */
37      public static final EventType OBJECT_ADDED_EVENT =
38              new EventType("OBJECT_ADDED_EVENT", new MetaData("Size of the map after add", "Size of the map",
39                      new ObjectDescriptor("Size of the map after add", "Size of the map", Integer.class)));
40  
41      /** OBJECT_REMOVED_EVENT is fired on removal of entries. */
42      public static final EventType OBJECT_REMOVED_EVENT =
43              new EventType("OBJECT_REMOVED_EVENT", new MetaData("Size of the map after remove", "Size of the map",
44                      new ObjectDescriptor("Size of the map after remove", "Size of the map", Integer.class)));
45  
46      /** OBJECT_CHANGED_EVENT is fired on change of one or more entries. */
47      public static final EventType OBJECT_CHANGED_EVENT =
48              new EventType("OBJECT_CHANGED_EVENT", new MetaData("Size of the map after change", "Size of the map",
49                      new ObjectDescriptor("Size of the map after change", "Size of the map", Integer.class)));
50  
51      /** the wrapped map. */
52      private final Map<K, V> wrappedMap;
53  
54      /**
55       * constructs a new EventProducingMap.
56       * @param wrappedMap Map&lt;K,V&gt;; the embedded map.
57       */
58      public EventProducingMap(final Map<K, V> wrappedMap)
59      {
60          Throw.whenNull(wrappedMap, "wrappedMap cannot be null");
61          this.wrappedMap = wrappedMap;
62      }
63  
64      @Override
65      public int size()
66      {
67          return this.wrappedMap.size();
68      }
69  
70      @Override
71      public boolean isEmpty()
72      {
73          return this.wrappedMap.isEmpty();
74      }
75  
76      @Override
77      public boolean containsKey(final Object key)
78      {
79          return this.wrappedMap.containsKey(key);
80      }
81  
82      @Override
83      public boolean containsValue(final Object value)
84      {
85          return this.wrappedMap.containsValue(value);
86      }
87  
88      @Override
89      public V get(final Object key)
90      {
91          return this.wrappedMap.get(key);
92      }
93  
94      @Override
95      public V put(final K key, final V value)
96      {
97          int nr = this.wrappedMap.size();
98          V result = this.wrappedMap.put(key, value);
99          if (nr != this.wrappedMap.size())
100         {
101             fireEvent(OBJECT_ADDED_EVENT, this.wrappedMap.size());
102         }
103         else
104         {
105             fireEvent(OBJECT_CHANGED_EVENT, this.wrappedMap.size());
106         }
107         return result;
108     }
109 
110     @Override
111     public V remove(final Object key)
112     {
113         int nr = this.wrappedMap.size();
114         V result = this.wrappedMap.remove(key);
115         if (nr != this.wrappedMap.size())
116         {
117             fireEvent(OBJECT_REMOVED_EVENT, this.wrappedMap.size());
118         }
119         return result;
120     }
121 
122     @Override
123     public void putAll(final Map<? extends K, ? extends V> map)
124     {
125         int nr = this.wrappedMap.size();
126         this.wrappedMap.putAll(map);
127         if (nr != this.wrappedMap.size())
128         {
129             fireEvent(OBJECT_ADDED_EVENT, this.wrappedMap.size());
130         }
131         else
132         {
133             if (!map.isEmpty())
134             {
135                 fireEvent(OBJECT_CHANGED_EVENT, this.wrappedMap.size());
136             }
137         }
138     }
139 
140     @Override
141     public void clear()
142     {
143         int nr = this.wrappedMap.size();
144         this.wrappedMap.clear();
145         if (nr != this.wrappedMap.size())
146         {
147             fireEvent(OBJECT_REMOVED_EVENT, this.wrappedMap.size());
148         }
149     }
150 
151     @Override
152     public Set<K> keySet()
153     {
154         return this.wrappedMap.keySet();
155     }
156 
157     @Override
158     public Collection<V> values()
159     {
160         return this.wrappedMap.values();
161     }
162 
163     @Override
164     public Set<Map.Entry<K, V>> entrySet()
165     {
166         return this.wrappedMap.entrySet();
167     }
168 
169 }