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.Turnout; 012import org.slf4j.Logger; 013import org.slf4j.LoggerFactory; 014 015/** 016 * Abstract interface between the a JMRI turnout and a network connection 017 * 018 * @author Paul Bender Copyright (C) 2010-2013 019 * @author Randall Wood Copyright (C) 2013 020 */ 021abstract public class AbstractTurnoutServer { 022 023 protected final HashMap<String, TurnoutListener> turnouts; 024 private final static Logger log = LoggerFactory.getLogger(AbstractTurnoutServer.class); 025 026 public AbstractTurnoutServer(){ 027 turnouts = new HashMap<>(); 028 } 029 030 /* 031 * Protocol Specific Abstract Functions 032 */ 033 abstract public void sendStatus(String turnoutName, int Status) throws IOException; 034 035 abstract public void sendErrorStatus(String turnoutName) throws IOException; 036 037 abstract public void parseStatus(String statusString) throws JmriException, IOException; 038 039 synchronized protected void addTurnoutToList(String turnoutName) { 040 if (!turnouts.containsKey(turnoutName)) { 041 Turnout t = InstanceManager.turnoutManagerInstance().getTurnout(turnoutName); 042 if(t!=null) { 043 TurnoutListener tl = new TurnoutListener(turnoutName); 044 t.addPropertyChangeListener(tl); 045 turnouts.put(turnoutName, tl); 046 } 047 } 048 } 049 050 synchronized protected void removeTurnoutFromList(String turnoutName) { 051 if (turnouts.containsKey(turnoutName)) { 052 Turnout t = InstanceManager.turnoutManagerInstance().getTurnout(turnoutName); 053 if(t!=null) { 054 t.removePropertyChangeListener(turnouts.get(turnoutName)); 055 turnouts.remove(turnoutName); 056 } 057 } 058 } 059 060 public Turnout initTurnout(String turnoutName) throws IllegalArgumentException { 061 Turnout turnout = InstanceManager.turnoutManagerInstance().provideTurnout(turnoutName); 062 this.addTurnoutToList(turnoutName); 063 return turnout; 064 } 065 066 public void closeTurnout(String turnoutName) { 067 // load address from switchAddrTextField 068 try { 069 if (!turnouts.containsKey(turnoutName)) { 070 // enforce that initTurnout must be called before moving a 071 // turnout 072 sendErrorStatus(turnoutName); 073 return; 074 } 075 Turnout turnout = InstanceManager.turnoutManagerInstance().getTurnout(turnoutName); 076 if (turnout == null) { 077 log.error("Turnout {} is not available", turnoutName); 078 } else { 079 log.debug("about to command CLOSED"); 080 // and set commanded state to CLOSED 081 turnout.setCommandedState(Turnout.CLOSED); 082 } 083 } catch (IOException ex) { 084 log.error("Error closing turnout", ex); 085 } 086 } 087 088 public void throwTurnout(String turnoutName) { 089 // load address from switchAddrTextField 090 try { 091 Turnout turnout = InstanceManager.turnoutManagerInstance().getTurnout(turnoutName); 092 if (!turnouts.containsKey(turnoutName)) { 093 // enforce that initTurnout must be called before moving a 094 // turnout 095 sendErrorStatus(turnoutName); 096 return; 097 } 098 099 if (turnout == null) { 100 log.error("Turnout {} is not available", turnoutName); 101 } else { 102 if (log.isDebugEnabled()) { 103 log.debug("about to command THROWN"); 104 } 105 // and set commanded state to THROWN 106 turnout.setCommandedState(Turnout.THROWN); 107 } 108 } catch (IOException ex) { 109 log.error("Error throwing turnout", ex); 110 } 111 } 112 113 public void dispose() { 114 for (Map.Entry<String, TurnoutListener> turnout : this.turnouts.entrySet()) { 115 Turnout t = InstanceManager.turnoutManagerInstance().getTurnout(turnout.getKey()); 116 if(t!=null) { 117 t.removePropertyChangeListener(turnout.getValue()); 118 } 119 } 120 this.turnouts.clear(); 121 } 122 123 protected TurnoutListener getListener(String turnoutName) { 124 if (!turnouts.containsKey(turnoutName)) { 125 return new TurnoutListener(turnoutName); 126 } else { 127 return turnouts.get(turnoutName); 128 } 129 } 130 131 protected class TurnoutListener implements PropertyChangeListener { 132 133 protected TurnoutListener(String turnoutName) { 134 name = turnoutName; 135 turnout = InstanceManager.turnoutManagerInstance().getTurnout(turnoutName); 136 } 137 138 // update state as state of turnout changes 139 @Override 140 public void propertyChange(PropertyChangeEvent e) { 141 // If the Commanded State changes, show transition state as "<inconsistent>" 142 if (e.getPropertyName().equals("KnownState")) { 143 int now = ((Integer) e.getNewValue()).intValue(); 144 try { 145 sendStatus(name, now); 146 } catch (IOException ie) { 147 log.debug("Error Sending Status"); 148 // if we get an error, de-register 149 turnout.removePropertyChangeListener(this); 150 removeTurnoutFromList(name); 151 } 152 } 153 } 154 String name = null; 155 Turnout turnout = null; 156 } 157}