Coverage Summary for Class: LimitedMap (it.polimi.ingsw.gc14)

Class Class, % Method, % Branch, % Line, %
LimitedMap 0% (0/1) 0% (0/15) 0% (0/10) 0% (0/27)


 package it.polimi.ingsw.gc14;
 
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * A {@link ConcurrentHashMap}-backed map with a configurable size limit and an associated action.
  * When the number of elements reaches or exceeds the limit, the specified action is automatically triggered.
  * This implementation is thread-safe for {@code put}; callers that need compound operations must synchronize externally.
  *
  * @param <K> the type of keys maintained by this map.
  * @param <V> the type of mapped values.
  */
 public class LimitedMap<K, V> implements Map<K, V> {
     /** The underlying thread-safe hash map storing all key-value pairs. */
     private final ConcurrentHashMap<K, V> map = new ConcurrentHashMap<>();
 
     /**
      * The maximum number of elements allowed in the map before the action is triggered.
      */
     private volatile int limit;
 
     /**
      * The action to execute when the map size reaches or exceeds the limit.
      */
     private volatile Runnable action;
 
     /**
      * Creates a new {@code LimitedMap} with the specified limit and action.
      *
      * @param limit  the maximum number of elements before the action is triggered.
      * @param action the action to execute when the limit is reached.
      */
     public LimitedMap(int limit, Runnable action) {
         this.limit = limit;
         this.action = action;
     }
 
     /**
      * Associates the specified value with the specified key in this map.
      * If the map size reaches or exceeds the limit after the insertion, the configured action is triggered.
      *
      * @param key   the key with which the specified value is to be associated.
      * @param value the value to be associated with the specified key.
      * @return the previous value associated with the key, or {@code null} if there was no mapping.
      */
     @Override
     public synchronized V put(K key, V value) {
         boolean added = true;
         if (map.size() == limit) {
             if (!map.containsKey(key))
                 return null;
             added = false;
         }
         V result = map.put(key, value);
         if (map.size() >= limit && added) {
             action.run();
         }
         return result;
     }
 
     @Override
     public synchronized V remove(Object key) { return map.remove(key); }
 
     @Override
     public V get(Object key) { return map.get(key); }
 
     @Override
     public boolean containsKey(Object key) { return map.containsKey(key); }
 
     @Override
     public boolean containsValue(Object value) { return map.containsValue(value); }
 
     @Override
     public int size() { return map.size(); }
 
     @Override
     public boolean isEmpty() { return map.isEmpty(); }
 
     @Override
     public void putAll(Map<? extends K, ? extends V> m) { m.forEach(this::put); }
 
     @Override
     public void clear() { map.clear(); }
 
     @Override
     public Set<K> keySet() { return map.keySet(); }
 
     @Override
     public Collection<V> values() { return map.values(); }
 
     @Override
     public Set<Entry<K, V>> entrySet() { return map.entrySet(); }
 
     /**
      * Sets a new size limit for this map.
      *
      * @param num the new limit.
      */
     public void setLimit(int num) { this.limit = num; }
 
     /**
      * Sets a new action to execute when the map size reaches or exceeds the limit.
      *
      * @param action the new action to set; must not be {@code null}.
      */
     public void setAction(Runnable action) {
         if (action == null) throw new IllegalArgumentException("action must not be null");
         this.action = action;
     }
 }