001package jmri.jmrix.srcp;
002
003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
004
005import java.util.Comparator;
006import java.util.ResourceBundle;
007
008import jmri.*;
009import jmri.jmrix.ConfiguringSystemConnectionMemo;
010import jmri.jmrix.DefaultSystemConnectionMemo;
011import jmri.jmrix.srcp.parser.ASTinfo;
012import jmri.jmrix.srcp.parser.SimpleNode;
013import jmri.util.NamedBeanComparator;
014
015import org.slf4j.Logger;
016import org.slf4j.LoggerFactory;
017
018/**
019 * Lightweight class to denote that a system is active, and provide general
020 * information.
021 * <p>
022 * Objects of specific subtypes are registered in the instance manager to
023 * activate their particular system.
024 *
025 * @author Bob Jacobsen Copyright (C) 2010
026 */
027public class SRCPBusConnectionMemo extends DefaultSystemConnectionMemo implements SRCPListener, ConfiguringSystemConnectionMemo {
028
029    private int _bus = 0;
030    private boolean configured = false;
031
032    public SRCPBusConnectionMemo(SRCPTrafficController et, String Prefix, int bus) {
033        super(Prefix + bus, "SRCP:" + bus);
034        this.et = et;
035        _bus = bus;
036        log.debug("Created SRCPBusConnectionMemo for bus {}", bus);
037        et.addSRCPListener(this);
038        et.sendSRCPMessage(new SRCPMessage("GET " + bus + " DESCRIPTION\n"), null);
039        configured = false;
040    }
041
042    private jmri.jmrix.swing.ComponentFactory cf = null;
043
044    /**
045     * Provides access to the TrafficController for this particular connection.
046     * @return SRCP Traffic Controller.
047     */
048    public SRCPTrafficController getTrafficController() {
049        return et;
050    }
051
052    public void setTrafficController(SRCPTrafficController et) {
053        this.et = et;
054    }
055
056    private SRCPTrafficController et;
057
058    /**
059     * Configure the common managers for Internal connections. This puts the
060     * common manager config in one place.
061     */
062    @SuppressFBWarnings(value = "UW_UNCOND_WAIT", justification="false postive, guarded by while statement")
063    public void configureManagers() {
064        while(!configured){
065           // wait for the managers to be configured.
066           synchronized(this){
067              try {
068                  this.wait();
069              } catch(java.lang.InterruptedException ie){
070                // just catch the error and re-check our condition.
071              }
072           }
073        }
074        register();
075        log.debug("Manager configuration complete for bus {}", _bus );
076    }
077
078    /**
079     * package protected function to get the bus associated with this memo.
080     *
081     * @return integer bus number
082     */
083    int getBus() {
084        return _bus;
085    }
086
087    /**
088     * Provides access to the Programmer for this particular connection.
089     * <p>
090     * NOTE: Programmer defaults to null
091     * @return programmer manager.
092     */
093    public SRCPProgrammerManager getProgrammerManager() {
094        return get(GlobalProgrammerManager.class);
095    }
096
097    public void setProgrammerManager(SRCPProgrammerManager p) {
098        store(p,GlobalProgrammerManager.class);
099    }
100
101    /*
102     * Provides access to the Throttle Manager for this particular connection.
103     * NOTE: Throttle Manager defaults to null
104     */
105    public ThrottleManager getThrottleManager() {
106        return get(ThrottleManager.class);
107    }
108
109    public void setThrottleManager(ThrottleManager t) {
110        store(t,ThrottleManager.class);
111    }
112
113    /*
114     * Provides access to the Clock Control for this particular connection.
115     * NOTE: May return null if the Clock Control has not been set.
116     */
117    public ClockControl getClockControl() {
118        return get(ClockControl.class);
119    }
120
121    public void setClockControl(ClockControl t) {
122        store(t,ClockControl.class);
123        InstanceManager.store(t, ClockControl.class);
124        InstanceManager.setDefault(ClockControl.class, t);
125    }
126
127    /*
128     * Provides access to the PowerManager for this particular connection.
129     */
130    public PowerManager getPowerManager() {
131        return get(PowerManager.class);
132    }
133
134    public void setPowerManager(PowerManager p) {
135        store(p,PowerManager.class);
136    }
137
138    /*
139     * Provides access to the SensorManager for this particular connection.
140     */
141    public SensorManager getSensorManager() {
142        return get(SensorManager.class);
143    }
144
145    public void setSensorManager(SensorManager s) {
146        store(s,SensorManager.class);
147    }
148
149    /*
150     * Provides access to the TurnoutManager for this particular connection.
151     * NOTE: TurnoutManager defaults to NULL
152     */
153    public TurnoutManager getTurnoutManager() {
154        return get(TurnoutManager.class);
155    }
156
157    public void setTurnoutManager(TurnoutManager t) {
158        store(t,TurnoutManager.class);
159    }
160
161    @Override
162    protected ResourceBundle getActionModelResourceBundle() {
163        return ResourceBundle.getBundle("jmri.jmrix.srcp.SrcpActionListBundle");
164    }
165
166    @Override
167    public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) {
168        return new NamedBeanComparator<>();
169    }
170
171    @Override
172    public void dispose() {
173        if (et != null) {
174            et = null;
175        }
176        InstanceManager.deregister(this, SRCPBusConnectionMemo.class);
177        if (cf != null) {
178            InstanceManager.deregister(cf, jmri.jmrix.swing.ComponentFactory.class);
179        }
180        super.dispose();
181    }
182
183    // functions for the SRCP Listener interface.
184    @Override
185    public void message(SRCPMessage m) {
186    }
187
188    @Override
189    public void reply(SRCPReply m) {
190    }
191
192    @Override
193    @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "NN_NAKED_NOTIFY", justification="Notify passing reply event, not state")
194    public void reply(jmri.jmrix.srcp.parser.SimpleNode n) {
195        log.debug("SimpleNode Reply called with {}", n.toString());
196        reply(new SRCPReply(n));
197        if (n.jjtGetChild(1) instanceof ASTinfo) {
198            jmri.jmrix.srcp.parser.SimpleNode infonode
199                    = (jmri.jmrix.srcp.parser.SimpleNode) n.jjtGetChild(1);
200            if (!((String) ((SimpleNode) (infonode.jjtGetChild(0))).jjtGetValue()).equals("" + _bus)) {
201                return; // not for this bus.
202            }          // Look for description information for this bus, and configure the
203            // managers for this bus.
204            if (infonode.jjtGetChild(1) instanceof jmri.jmrix.srcp.parser.ASTdescription) {
205                SimpleNode descnode = (SimpleNode) infonode.jjtGetChild(1);
206                for (int i = 0; i < descnode.jjtGetNumChildren(); i++) {
207                    jmri.jmrix.srcp.parser.SimpleNode child
208                            = (jmri.jmrix.srcp.parser.SimpleNode) descnode.jjtGetChild(i);
209                    log.debug("child node type {} value {}", child.toString(), child.jjtGetValue());
210                    if (child instanceof jmri.jmrix.srcp.parser.ASTdevicegroup) {
211                        String DeviceType = (String) child.jjtGetValue();
212                        switch (DeviceType) {
213                            case "FB":
214                                setSensorManager(new SRCPSensorManager(this));
215                                InstanceManager.setSensorManager(getSensorManager());
216                                break;
217                            case "GA":
218                                setTurnoutManager(new SRCPTurnoutManager(this));
219                                InstanceManager.setTurnoutManager(getTurnoutManager());
220                                break;
221                            case "SM":
222                                setProgrammerManager(new SRCPProgrammerManager(new SRCPProgrammer(this), this));
223                                InstanceManager.store(getProgrammerManager(), GlobalProgrammerManager.class);
224                                break;
225                            case "POWER":
226                                setPowerManager(new SRCPPowerManager(this, _bus));
227                                InstanceManager.store(getPowerManager(), PowerManager.class);
228                                break;
229                            case "GL":
230                                setThrottleManager(new SRCPThrottleManager(this));
231                                InstanceManager.setThrottleManager(getThrottleManager());
232                                break;
233                            case "TIME":
234                                setClockControl(new SRCPClockControl(this));
235                                break;
236                            default:
237                                log.warn("unexpected DeviceType");
238                                break;
239                        }
240                    }
241                }
242                configured = true;
243                synchronized(this) {
244                    this.notifyAll(); // wake up any thread that called configureManagers().
245                }
246            }
247        }
248    }
249
250    private final static Logger log = LoggerFactory.getLogger(SRCPBusConnectionMemo.class);
251
252}