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    @Override
063    @SuppressFBWarnings(value = "UW_UNCOND_WAIT", justification="false postive, guarded by while statement")
064    public void configureManagers() {
065        while(!configured){
066           // wait for the managers to be configured.
067           synchronized(this){
068              try {
069                  this.wait();
070              } catch(java.lang.InterruptedException ie){
071                // just catch the error and re-check our condition.
072              }
073           }
074        }
075        register();
076        log.debug("Manager configuration complete for bus {}", _bus );
077    }
078
079    /**
080     * package protected function to get the bus associated with this memo.
081     *
082     * @return integer bus number
083     */
084    int getBus() {
085        return _bus;
086    }
087
088    /**
089     * Provides access to the Programmer for this particular connection.
090     * <p>
091     * NOTE: Programmer defaults to null
092     * @return programmer manager.
093     */
094    public SRCPProgrammerManager getProgrammerManager() {
095        return (SRCPProgrammerManager)get(GlobalProgrammerManager.class);
096    }
097
098    public void setProgrammerManager(SRCPProgrammerManager p) {
099        store(p,GlobalProgrammerManager.class);
100    }
101
102    /*
103     * Provides access to the Throttle Manager for this particular connection.
104     * NOTE: Throttle Manager defaults to null
105     */
106    public ThrottleManager getThrottleManager() {
107        return get(ThrottleManager.class);
108    }
109
110    public void setThrottleManager(ThrottleManager t) {
111        store(t,ThrottleManager.class);
112    }
113
114    /*
115     * Provides access to the Clock Control for this particular connection.
116     * NOTE: May return null if the Clock Control has not been set.
117     */
118    public ClockControl getClockControl() {
119        return get(ClockControl.class);
120    }
121
122    public void setClockControl(ClockControl t) {
123        store(t,ClockControl.class);
124        InstanceManager.store(t, ClockControl.class);
125        InstanceManager.setDefault(ClockControl.class, t);
126    }
127
128    /*
129     * Provides access to the PowerManager for this particular connection.
130     */
131    public PowerManager getPowerManager() {
132        return get(PowerManager.class);
133    }
134
135    public void setPowerManager(PowerManager p) {
136        store(p,PowerManager.class);
137    }
138
139    /*
140     * Provides access to the SensorManager for this particular connection.
141     */
142    public SensorManager getSensorManager() {
143        return get(SensorManager.class);
144    }
145
146    public void setSensorManager(SensorManager s) {
147        store(s,SensorManager.class);
148    }
149
150    /*
151     * Provides access to the TurnoutManager for this particular connection.
152     * NOTE: TurnoutManager defaults to NULL
153     */
154    public TurnoutManager getTurnoutManager() {
155        return get(TurnoutManager.class);
156    }
157
158    public void setTurnoutManager(TurnoutManager t) {
159        store(t,TurnoutManager.class);
160    }
161
162    @Override
163    protected ResourceBundle getActionModelResourceBundle() {
164        return ResourceBundle.getBundle("jmri.jmrix.srcp.SrcpActionListBundle");
165    }
166
167    @Override
168    public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) {
169        return new NamedBeanComparator<>();
170    }
171
172    @Override
173    public void dispose() {
174        if (et != null) {
175            et = null;
176        }
177        InstanceManager.deregister(this, SRCPBusConnectionMemo.class);
178        if (cf != null) {
179            InstanceManager.deregister(cf, jmri.jmrix.swing.ComponentFactory.class);
180        }
181        super.dispose();
182    }
183
184    // functions for the SRCP Listener interface.
185    @Override
186    public void message(SRCPMessage m) {
187    }
188
189    @Override
190    public void reply(SRCPReply m) {
191    }
192
193    @Override
194    @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "NN_NAKED_NOTIFY", justification="Notify passing reply event, not state")
195    public void reply(jmri.jmrix.srcp.parser.SimpleNode n) {
196        log.debug("SimpleNode Reply called with {}", n.toString());
197        reply(new SRCPReply(n));
198        if (n.jjtGetChild(1) instanceof ASTinfo) {
199            jmri.jmrix.srcp.parser.SimpleNode infonode
200                    = (jmri.jmrix.srcp.parser.SimpleNode) n.jjtGetChild(1);
201            if (!((String) ((SimpleNode) (infonode.jjtGetChild(0))).jjtGetValue()).equals("" + _bus)) {
202                return; // not for this bus.
203            }          // Look for description information for this bus, and configure the
204            // managers for this bus.
205            if (infonode.jjtGetChild(1) instanceof jmri.jmrix.srcp.parser.ASTdescription) {
206                SimpleNode descnode = (SimpleNode) infonode.jjtGetChild(1);
207                for (int i = 0; i < descnode.jjtGetNumChildren(); i++) {
208                    jmri.jmrix.srcp.parser.SimpleNode child
209                            = (jmri.jmrix.srcp.parser.SimpleNode) descnode.jjtGetChild(i);
210                    log.debug("child node type {} value {}", child.toString(), child.jjtGetValue());
211                    if (child instanceof jmri.jmrix.srcp.parser.ASTdevicegroup) {
212                        String DeviceType = (String) child.jjtGetValue();
213                        switch (DeviceType) {
214                            case "FB":
215                                setSensorManager(new SRCPSensorManager(this));
216                                InstanceManager.setSensorManager(getSensorManager());
217                                break;
218                            case "GA":
219                                setTurnoutManager(new SRCPTurnoutManager(this));
220                                InstanceManager.setTurnoutManager(getTurnoutManager());
221                                break;
222                            case "SM":
223                                setProgrammerManager(new SRCPProgrammerManager(new SRCPProgrammer(this), this));
224                                InstanceManager.store(getProgrammerManager(), GlobalProgrammerManager.class);
225                                break;
226                            case "POWER":
227                                setPowerManager(new SRCPPowerManager(this, _bus));
228                                InstanceManager.store(getPowerManager(), PowerManager.class);
229                                break;
230                            case "GL":
231                                setThrottleManager(new SRCPThrottleManager(this));
232                                InstanceManager.setThrottleManager(getThrottleManager());
233                                break;
234                            case "TIME":
235                                setClockControl(new SRCPClockControl(this));
236                                break;
237                            default:
238                                log.warn("unexpected DeviceType");
239                                break;
240                        }
241                    }
242                }
243                configured = true;
244                synchronized(this) {
245                    this.notifyAll(); // wake up any thread that called configureManagers().
246                }
247            }
248        }
249    }
250
251    private final static Logger log = LoggerFactory.getLogger(SRCPBusConnectionMemo.class);
252
253}