001package jmri.server.json.throttle;
002
003import com.fasterxml.jackson.databind.ObjectMapper;
004import java.util.ArrayList;
005import java.util.Collection;
006import java.util.HashMap;
007import java.util.List;
008import jmri.DccLocoAddress;
009import jmri.InstanceManager;
010import jmri.InstanceManagerAutoDefault;
011import jmri.ThrottleListener;
012import jmri.ThrottleManager;
013
014/**
015 * Manager for {@link jmri.server.json.throttle.JsonThrottle} objects. A manager
016 * is needed since multiple JsonThrottle objects may be controlling the same
017 * {@link jmri.DccLocoAddress}.
018 *
019 * @author Randall Wood Copyright 2016, 2018
020 */
021public class JsonThrottleManager implements InstanceManagerAutoDefault {
022
023    private final HashMap<DccLocoAddress, JsonThrottle> throttles = new HashMap<>();
024    private final HashMap<JsonThrottle, ArrayList<JsonThrottleSocketService>> services = new HashMap<>();
025    private final ObjectMapper mapper = new ObjectMapper();
026
027    public JsonThrottleManager() {
028        // do nothing
029    }
030
031    // Synchronized throughout: notifyThrottleFound() is now deferred to the
032    // EDT (see AbstractThrottleManager), so that deferred callback and a
033    // thread handling a fresh JSON request can touch these maps at the
034    // same time. getThrottles() returns a copy since callers iterate it.
035    public synchronized Collection<JsonThrottle> getThrottles() {
036        return new ArrayList<>(this.throttles.values());
037    }
038
039    public synchronized void put(DccLocoAddress address, JsonThrottle throttle) {
040        this.throttles.put(address, throttle);
041    }
042
043    public synchronized void put(JsonThrottle throttle, JsonThrottleSocketService service) {
044        this.services.computeIfAbsent(throttle, v -> new ArrayList<>()).add(service);
045    }
046
047    public synchronized boolean containsKey(DccLocoAddress address) {
048        return this.throttles.containsKey(address);
049    }
050
051    public synchronized JsonThrottle get(DccLocoAddress address) {
052        return this.throttles.get(address);
053    }
054
055    public synchronized void remove(DccLocoAddress address) {
056        this.throttles.remove(address);
057    }
058
059    public synchronized List<JsonThrottleSocketService> getServers(JsonThrottle throttle) {
060        return this.services.computeIfAbsent(throttle, v -> new ArrayList<>());
061    }
062
063    public synchronized void remove(JsonThrottle throttle, JsonThrottleSocketService server) {
064        this.getServers(throttle).remove(server);
065    }
066
067    public ObjectMapper getObjectMapper() {
068        return this.mapper;
069    }
070
071    public boolean canBeLongAddress(int asInt) {
072        return InstanceManager.getDefault(ThrottleManager.class).canBeLongAddress(asInt);
073    }
074
075    public boolean canBeShortAddress(int asInt) {
076        return InstanceManager.getDefault(ThrottleManager.class).canBeShortAddress(asInt);
077    }
078
079    public boolean requestThrottle(DccLocoAddress address, ThrottleListener listener) {
080        return InstanceManager.getDefault(ThrottleManager.class).requestThrottle(address, listener, false);
081    }
082
083    public boolean requestThrottle(jmri.BasicRosterEntry rosterEntry, ThrottleListener listener) {
084        return InstanceManager.getDefault(ThrottleManager.class).requestThrottle(rosterEntry, listener, false);
085    }
086
087    // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(JsonThrottleManager.class);
088}