package it.polimi.ingsw.gc14; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * A {@link LinkedHashMap} 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. * * @param the type of keys maintained by this map. * @param the type of mapped values. */ public class LimitedMap implements Map { private final ConcurrentHashMap 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 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 m) { m.forEach(this::put); } @Override public void clear() { map.clear(); } @Override public Set keySet() { return map.keySet(); } @Override public Collection values() { return map.values(); } @Override public Set> 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; } /** * Returns the current size limit of this map. * * @return the current limit. */ public int getLimit() { return limit; } /** * Sets a new action to execute when the map size reaches or exceeds the limit. * * @param action the new action to set. */ public void setAction(Runnable action) { this.action = action; } }