001package jmri.jmrix.bidib.simulator;
002
003import java.io.DataInputStream;
004import java.io.DataOutputStream;
005import java.io.File;
006import java.util.Set;
007import jmri.util.FileUtil;
008
009import jmri.jmrix.bidib.BiDiBSerialPortController;
010import jmri.jmrix.bidib.BiDiBTrafficController;
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014import org.bidib.jbidibc.core.MessageListener;
015import org.bidib.jbidibc.core.NodeListener;
016import org.bidib.jbidibc.core.node.listener.TransferListener;
017import org.bidib.jbidibc.messages.ConnectionListener;
018import org.bidib.jbidibc.simulation.comm.SimulationBidib;
019import org.bidib.jbidibc.simulation.SimulationInterface;
020
021/**
022 * Provide access to a simulated BiDiB system.
023 *
024 * @author Paul Bender, Copyright (C) 2009-2010
025 * @author Eckart Meyer Copyright (C) 2019-2024
026 *
027 */
028public class BiDiBSimulatorAdapter extends BiDiBSerialPortController {
029
030    protected String simulationFile = "simulation.xml"; //default
031    protected String loadedSimulationFilename = null;
032    protected String absoluteSimulationFile = null;
033
034
035    public BiDiBSimulatorAdapter() {
036        //super(new BiDiBSystemConnectionMemo());
037//        log.debug("ctor BiDiBSimulatorAdapter");
038    }
039
040
041    public String getSimulationFile() {
042        return simulationFile;
043    }
044    
045    public void setSimulationFile(String f) {
046        if (loadedSimulationFilename == null) {
047            loadedSimulationFilename = f;
048        }
049        simulationFile = f;
050    }
051
052    // not sure if this is the recommended way yu check our additional field... but works, I think.
053    @Override
054    public boolean isDirty() {
055        log.debug("isDirty");
056        if (super.isDirty()) {
057            return true;
058        }
059        return (! simulationFile.equals(loadedSimulationFilename));
060    }
061
062    //is this ever called?
063    @Override
064    public boolean isRestartRequired() {
065        log.debug("isRestartRequired");
066        return super.isRestartRequired();
067    }
068    
069    
070    
071    /**
072     * {@inheritDoc}
073     */
074    @Override
075    public String getCurrentPortName() {
076        if (absoluteSimulationFile == null) {
077            return getSimulationFile();
078        }
079        else {
080            return absoluteSimulationFile;
081        }
082    }
083    
084    /**
085     * {@inheritDoc}
086     * 
087     * Get the "port name" in the format which is used by jbidibc - this is absolute path to the simulation XML file
088     * @return real port name
089     */
090    @Override
091    public String getRealPortName() {
092        File f = new File(FileUtil.getExternalFilename("profile:" + getSimulationFile()));
093        return f.getAbsolutePath();
094    }
095    
096//    @Override
097//    public void recover() {
098//        log.debug("recover called - ignored.");
099//        // nothing
100//    }
101//    
102//    /**
103//     * {@inheritDoc}
104//     */
105//    @Override
106//    public void connect() throws java.io.IOException {
107//        log.warn("connect called - ignored.");
108//        //openPort(mPort, "JMRI app");
109//    }
110
111    /**
112     * Here we do not really open something.
113     * 
114     * @param fileName name of simulation file
115     * @param appName not used
116     * @return error string, null if no error
117     */
118    @Override
119    public String openPort(String fileName, String appName) {
120        // NOT USED AND NOT CALLED! Would be normally called by ConnectConfigXml
121        // we can't do anything meaningfull here. Even the existance of a file can't
122        // be checked since the seachpath is a secret of the jbidibc library... (the SimulatorBidib)
123          log.debug("simulation openPort: {}", fileName);
124//        log.debug("user files path: {}", FileUtil.getUserFilesPath());
125//        log.debug("in profile: {}", FileUtil.getExternalFilename("profile:" + fileName));
126//        log.debug("in settings: {}", FileUtil.getExternalFilename("settings:" + fileName));
127//        Profile p = ProfileManager.getDefault().getActiveProfile();
128//        log.debug("active profile: path: {}, name: {}, uid: {}, id: {}", p.getPath(), p.getName(), p.getUniqueId(), p.getId());
129//        File f = new File(fileName);
130//        if (!f.exists()) {
131//            f = new File(FileUtil.getExternalFilename("profile:" + fileName));
132//        }
133//        if (!f.exists()) {
134//            f = new File(FileUtil.getExternalFilename("settings:" + fileName));
135//        }
136//        if (!f.exists()) {
137//            log.error("File not found: {}", fileName);
138//            return "File not found: " + fileName;
139//        }
140//        absoluteSimulationFile = f.getAbsolutePath();
141//        log.info("Simulation file used: {}", f.getAbsoluteFile());
142//        // open the port in XpressNet mode, check ability to set moderators
143//        //setPort(portName);
144//        //return "---- TEST ----";
145
146
147        return null; // normal operation
148    }
149
150
151    /**
152     * Set up all of the other objects to operate with a BiDiBSimulator
153     * connected to this port
154     */
155    @Override
156    public void configure() {
157        log.debug("configure");
158        MSG_RAW_LOGGER.debug("RAW> create BiDiB Instance");
159        
160        bidib = SimulationBidib.createInstance(getContext());
161        BiDiBTrafficController tc = new BiDiBTrafficController(bidib);
162        log.debug("memo: {}, bidib simulator: {}", this.getSystemConnectionMemo(), bidib);
163        this.getSystemConnectionMemo().setBiDiBTrafficController(tc);
164        context = tc.connnectPort(this); //must be done before configuring managers since they may need features from the device
165        opened = false;
166        if (context != null) {
167            opened = true;
168        }
169        else {
170            log.warn("Simulation cannot be opened: {} ({}})",
171                    getCurrentPortName(), getCurrentPortName());
172        }
173        this.getSystemConnectionMemo().configureManagers();
174    }
175
176    /**
177     * {@inheritDoc}
178     */
179    @Override
180    public void registerAllListeners(ConnectionListener connectionListener, Set<NodeListener> nodeListeners,
181                Set<MessageListener> messageListeners, Set<TransferListener> transferListeners) {
182        
183        SimulationInterface b = (SimulationInterface)bidib;
184        b.setConnectionListener(connectionListener);
185        b.registerListeners(nodeListeners, messageListeners, transferListeners);
186    }
187    
188    // base class methods for the BiDiBSerialPortController interface
189    // not used but must be implemented
190
191    /**
192     * {@inheritDoc}
193     */
194    @Override
195    public DataInputStream getInputStream() {
196//        log.trace("getInputStream - pin: {}", pin);
197//        if (pin == null) {
198//            log.error("getInputStream called before load(), stream not available");
199//            ConnectionStatus.instance().setConnectionState(getUserName(), getCurrentPortName(), ConnectionStatus.CONNECTION_DOWN);
200//        }
201//        return pin;
202        return null;
203    }
204
205    /**
206     * {@inheritDoc}
207     */
208    @Override
209    public DataOutputStream getOutputStream() {
210//        log.trace("getInputStream - pin: {}", pout);
211//        if (pout == null) {
212//            log.error("getOutputStream called before load(), stream not available");
213//            ConnectionStatus.instance().setConnectionState(getUserName(), getCurrentPortName(), ConnectionStatus.CONNECTION_DOWN);
214//        }
215//        return pout;
216        return null;
217    }
218
219    /**
220     * {@inheritDoc}
221     */
222    @Override
223    public boolean status() {
224        return opened;
225    }
226
227
228    private final static Logger log = LoggerFactory.getLogger(BiDiBSimulatorAdapter.class);
229    private static final Logger MSG_RAW_LOGGER = LoggerFactory.getLogger("RAW");
230
231}