001package jmri.jmris; 002 003import java.beans.PropertyChangeEvent; 004import java.beans.PropertyChangeListener; 005import java.io.IOException; 006import java.util.HashMap; 007import java.util.Map; 008 009import jmri.InstanceManager; 010import jmri.JmriException; 011import jmri.SignalMast; 012import jmri.server.json.JsonException; 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016/** 017 * Abstract interface between a JMRI signal mast and a network connection 018 * 019 * @author Paul Bender Copyright (C) 2010 020 * 021 */ 022abstract public class AbstractSignalMastServer { 023 024 private final HashMap<String, SignalMastListener> signalMasts; 025 static private final Logger log = LoggerFactory.getLogger(AbstractSignalMastServer.class); 026 027 public AbstractSignalMastServer(){ 028 signalMasts = new HashMap<>(); 029 } 030 031 /* 032 * Protocol Specific Abstract Functions 033 */ 034 abstract public void sendStatus(String signalMast, String Status) throws IOException; 035 036 abstract public void sendErrorStatus(String signalMast) throws IOException; 037 038 abstract public void parseStatus(String statusString) throws JmriException, IOException, JsonException; 039 040 synchronized protected void addSignalMastToList(String signalMastName) { 041 if (!signalMasts.containsKey(signalMastName)) { 042 SignalMast sm = InstanceManager.getDefault(jmri.SignalMastManager.class).getSignalMast(signalMastName); 043 if(sm!=null) { 044 SignalMastListener sml = new SignalMastListener(signalMastName); 045 sm.addPropertyChangeListener(sml); 046 signalMasts.put(signalMastName, sml); 047 log.debug("Added listener to signalMast {}", signalMastName); 048 } 049 } 050 } 051 052 synchronized protected void removeSignalMastFromList(String signalMastName) { 053 if (signalMasts.containsKey(signalMastName)) { 054 SignalMast sm = InstanceManager.getDefault(jmri.SignalMastManager.class).getSignalMast(signalMastName); 055 if(sm!=null) { 056 sm.removePropertyChangeListener(signalMasts.get(signalMastName)); 057 signalMasts.remove(signalMastName); 058 } 059 } 060 } 061 062 protected void setSignalMastAspect(String signalMastName, String signalMastState) { 063 SignalMast signalMast; 064 try { 065 addSignalMastToList(signalMastName); 066 signalMast = InstanceManager.getDefault(jmri.SignalMastManager.class).getSignalMast(signalMastName); 067 if (signalMast == null) { 068 log.error("SignalMast {} is not available.", signalMastName); 069 } else { 070 String aspect = signalMast.getAspect(); 071 if ( aspect == null || !aspect.equals(signalMastState) || signalMast.getHeld()) { 072 if (signalMastState.equals("Held")) { 073 signalMast.setHeld(true); 074 } else { 075 if (signalMast.getHeld()) signalMast.setHeld(false); 076 signalMast.setAspect(signalMastState); 077 } 078 } else { 079 try { 080 sendStatus(signalMastName, signalMastState); 081 } catch (IOException ex) { 082 log.error("Error sending aspect ", ex); 083 } 084 } 085 } 086 } catch (Exception ex) { 087 log.error("Exception setting signalMast {} aspect:", signalMastName, ex); 088 } 089 } 090 091 public void dispose() { 092 for (Map.Entry<String, SignalMastListener> signalMast : this.signalMasts.entrySet()) { 093 SignalMast sm = InstanceManager.getDefault(jmri.SignalMastManager.class).getSignalMast(signalMast.getKey()); 094 if(sm != null) { 095 sm.removePropertyChangeListener(signalMast.getValue()); 096 } 097 } 098 this.signalMasts.clear(); 099 } 100 101 class SignalMastListener implements PropertyChangeListener { 102 103 String name = null; 104 SignalMast signalMast = null; 105 106 SignalMastListener(String signalMastName) { 107 name = signalMastName; 108 signalMast = InstanceManager.getDefault(jmri.SignalMastManager.class).getSignalMast(signalMastName); 109 } 110 111 // update state as state of signalMast changes 112 @Override 113 public void propertyChange(PropertyChangeEvent e) { 114 if (e.getPropertyName().equals("Aspect") || e.getPropertyName().equals("Held") || e.getPropertyName().equals("Lit")) { 115 SignalMast sm = (SignalMast) e.getSource(); 116 String state = sm.getAspect(); 117 if ((sm.getHeld()) && (sm.getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.HELD) != null)) { 118 state = "Held"; 119 } else if ((!sm.getLit()) && (sm.getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.DARK) != null)) { 120 state = "Dark"; 121 } 122 try { 123 sendStatus(name, state); 124 } catch (IOException ie) { 125 // if we get an error, de-register 126 if (log.isDebugEnabled()) { 127 log.debug("Unable to send status, removing listener from signalMast {}", name); 128 } 129 signalMast.removePropertyChangeListener(this); 130 removeSignalMastFromList(name); 131 } 132 } 133 } 134 } 135}