001package jmri.jmris;
002
003import java.beans.PropertyChangeEvent;
004import java.beans.PropertyChangeListener;
005import java.io.IOException;
006import java.util.HashMap;
007import java.util.Map;
008import jmri.InstanceManager;
009import jmri.JmriException;
010import jmri.Light;
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014/**
015 * Abstract interface between the a JMRI Light and a network connection
016 *
017 * @author Paul Bender Copyright (C) 2010
018 * @author Randall Wood Copyright (C) 2013, 2014
019 */
020abstract public class AbstractLightServer {
021
022    private final HashMap<String, LightListener> lights;
023    private final static Logger log = LoggerFactory.getLogger(AbstractLightServer.class);
024
025    public AbstractLightServer() {
026        lights = new HashMap<>();
027    }
028
029    /*
030     * Protocol Specific Abstract Functions
031     */
032    abstract public void sendStatus(String lightName, int Status) throws IOException;
033
034    abstract public void sendErrorStatus(String lightName) throws IOException;
035
036    abstract public void parseStatus(String statusString) throws JmriException, IOException;
037
038    synchronized protected void addLightToList(String lightName) {
039        if (!lights.containsKey(lightName)) {
040            Light li = InstanceManager.lightManagerInstance().getLight(lightName);
041            if (li != null) {
042                lights.put(lightName, new LightListener(lightName));
043                li.addPropertyChangeListener(lights.get(lightName));
044            } else {
045                log.error("Failed to get light {}", lightName);
046            }
047        }
048    }
049
050    synchronized protected void removeLightFromList(String lightName) {
051        if (lights.containsKey(lightName)) {
052            Light li = InstanceManager.lightManagerInstance().getLight(lightName);
053            if (li != null) {
054                li.removePropertyChangeListener(lights.get(lightName));
055                lights.remove(lightName);
056            } else {
057                log.error("Failed to get light {}", lightName);
058            }
059        }
060    }
061
062    public Light initLight(String lightName)  throws IllegalArgumentException {
063        Light light = InstanceManager.lightManagerInstance().provideLight(lightName);
064        this.addLightToList(lightName);
065        return light;        
066    }
067
068    public void lightOff(String lightName) {
069        Light light;
070        // load address from switchAddrTextField
071        try {
072
073            addLightToList(lightName);
074            light = InstanceManager.lightManagerInstance().getLight(lightName);
075            if (light == null) {
076                log.error("Light {} is not available", lightName);
077            } else {
078                log.debug("about to command OFF");
079                // and set state to OFF
080                light.setState(Light.OFF);
081            }
082        } catch (Exception ex) {
083            log.error("light off", ex);
084        }
085    }
086
087    public void lightOn(String lightName) {
088        Light light;
089        // load address from switchAddrTextField
090        try {
091            addLightToList(lightName);
092            light = InstanceManager.lightManagerInstance().getLight(lightName);
093
094            if (light == null) {
095                log.error("Light {} is not available", lightName);
096            } else {
097                log.debug("about to command ON");
098                // and set state to ON
099                light.setState(Light.ON);
100            }
101        } catch (Exception ex) {
102            log.error("light on", ex);
103        }
104    }
105
106    public void dispose() {
107        for (Map.Entry<String, LightListener> light : this.lights.entrySet()) {
108            Light li = InstanceManager.lightManagerInstance().getLight(light.getKey());
109            if (li != null) {
110                li.removePropertyChangeListener(light.getValue());
111            }
112        }
113        this.lights.clear();
114    }
115
116    class LightListener implements PropertyChangeListener {
117
118        LightListener(String lightName) {
119            name = lightName;
120            light = InstanceManager.lightManagerInstance().getLight(lightName);
121        }
122
123        // update state as state of light changes
124        @Override
125        public void propertyChange(PropertyChangeEvent e) {
126            // If the Commanded State changes, show transition state as "<inconsistent>"
127            if (e.getPropertyName().equals("KnownState")) {
128                int now = ((Integer) e.getNewValue()).intValue();
129                try {
130                    sendStatus(name, now);
131                } catch (IOException ie) {
132                    log.debug("Error Sending Status");
133                    // if we get an error, de-register
134                    light.removePropertyChangeListener(this);
135                    removeLightFromList(name);
136                }
137            }
138        }
139        Light light = null;
140        String name = null;
141    }
142}