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-2023
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        return null; // normal operation
146    }
147
148
149    /**
150     * Set up all of the other objects to operate with a BiDiBSimulator
151     * connected to this port
152     */
153    @Override
154    public void configure() {
155        log.debug("configure");
156        MSG_RAW_LOGGER.debug("RAW> create BiDiB Instance");
157        
158        bidib = SimulationBidib.createInstance(getContext());
159        BiDiBTrafficController tc = new BiDiBTrafficController(bidib);
160        context = tc.connnectPort(this); //must be done before configuring managers since they may need features from the device
161        log.debug("memo: {}, bidib simulator: {}", this.getSystemConnectionMemo(), bidib);
162        this.getSystemConnectionMemo().setBiDiBTrafficController(tc);
163        if (context != null) {
164            opened = true;
165        }
166        else {
167            opened = false;
168            log.warn("Simulation cannot be opened: {} ({}})",
169                    getCurrentPortName(), getCurrentPortName());
170        }
171        this.getSystemConnectionMemo().configureManagers();
172    }
173
174    /**
175     * {@inheritDoc}
176     */
177    @Override
178    public void registerAllListeners(ConnectionListener connectionListener, Set<NodeListener> nodeListeners,
179                Set<MessageListener> messageListeners, Set<TransferListener> transferListeners) {
180        
181        SimulationInterface b = (SimulationInterface)bidib;
182        b.setConnectionListener(connectionListener);
183        b.registerListeners(nodeListeners, messageListeners, transferListeners);
184    }
185    
186    // base class methods for the BiDiBSerialPortController interface
187    // not used but must be implemented
188
189    /**
190     * {@inheritDoc}
191     */
192    @Override
193    public DataInputStream getInputStream() {
194//        log.trace("getInputStream - pin: {}", pin);
195//        if (pin == null) {
196//            log.error("getInputStream called before load(), stream not available");
197//            ConnectionStatus.instance().setConnectionState(getUserName(), getCurrentPortName(), ConnectionStatus.CONNECTION_DOWN);
198//        }
199//        return pin;
200        return null;
201    }
202
203    /**
204     * {@inheritDoc}
205     */
206    @Override
207    public DataOutputStream getOutputStream() {
208//        log.trace("getInputStream - pin: {}", pout);
209//        if (pout == null) {
210//            log.error("getOutputStream called before load(), stream not available");
211//            ConnectionStatus.instance().setConnectionState(getUserName(), getCurrentPortName(), ConnectionStatus.CONNECTION_DOWN);
212//        }
213//        return pout;
214        return null;
215    }
216
217    /**
218     * {@inheritDoc}
219     */
220    @Override
221    public boolean status() {
222        return opened;
223    }
224
225
226    private final static Logger log = LoggerFactory.getLogger(BiDiBSimulatorAdapter.class);
227    private static final Logger MSG_RAW_LOGGER = LoggerFactory.getLogger("RAW");
228
229}