001package jmri.jmrix.configurexml;
002
003import jmri.jmrix.SerialPortAdapter;
004import org.jdom2.Element;
005import org.slf4j.Logger;
006import org.slf4j.LoggerFactory;
007
008/**
009 * Abstract base (and partial implementation) for classes persisting the status
010 * of serial port adapters.
011 *
012 * @author Bob Jacobsen Copyright (c) 2003
013 */
014abstract public class AbstractSerialConnectionConfigXml extends AbstractConnectionConfigXml {
015
016    public AbstractSerialConnectionConfigXml() {
017    }
018
019    protected SerialPortAdapter adapter;
020
021    protected void getInstance(Object object) {
022        getInstance(); // over-ridden during migration
023    }
024
025    /**
026     * Default implementation for storing the static contents of the serial port
027     * implementation.
028     *
029     * @param object Object to store, of type AbstractSerialConnectionConfig
030     * @return Element containing the complete info
031     */
032    @Override
033    public Element store(Object object) {
034        getInstance(object);
035        Element e = new Element("connection");
036
037        if (adapter == null) {
038            log.warn("No adapter found while saving serial port configuration {}", object.toString());
039            return null;
040        }
041
042        // many of the following are required by the DTD; failing to include
043        // them makes the XML file unreadable, but at least the next
044        // invocation of the program can then continue.
045        storeCommon(e, adapter);
046
047        if (adapter.getCurrentPortName() != null) {
048            e.setAttribute("port", adapter.getCurrentPortName());
049        } else {
050            e.setAttribute("port", Bundle.getMessage("noneSelected"));
051        }
052
053        if (adapter.getCurrentBaudRate() != null) {
054            e.setAttribute("speed", adapter.getCurrentBaudNumber()); // store by baud number, not by i18n combo display string
055        } else {
056            e.setAttribute("speed", Bundle.getMessage("noneSelected"));
057        }
058
059        setOutputInterval(adapter, e);
060
061        e.setAttribute("class", this.getClass().getName());
062
063        extendElement(e);
064
065        return e;
066    }
067
068    /**
069     * Customizable method if you need to add anything more.
070     *
071     * @param e Element being created, update as needed
072     */
073    @Override
074    protected void extendElement(Element e) {
075    }
076
077    @Override
078    public boolean load(Element shared, Element perNode) {
079        boolean result = true;
080        getInstance();
081        log.info("Starting to connect for \"{}\"", adapter.getSystemConnectionMemo()!=null ? adapter.getSystemConnectionMemo().getUserName() : "(Unknown Connection)");
082
083        // configure port name
084        String portName = perNode.getAttribute("port").getValue();
085        adapter.setPort(portName);
086        String baudNumber = perNode.getAttribute("speed").getValue(); // updated number string format since JMRI 4.16
087        adapter.configureBaudRateFromNumber(baudNumber);
088        loadCommon(shared, perNode, adapter);
089        // register, so can be picked up next time
090        register();
091        // try to open the port
092        if (adapter.getDisabled()) {
093            unpackElement(shared, perNode);
094            return result;
095        }
096
097        String status = adapter.openPort(portName, "JMRI app");
098        if (status != null) {
099            // indicates an error, return it
100            handleException(status, "opening connection", null, null, null);
101            // now force end to operation
102            log.debug("load failed");
103            return false;
104        }
105
106        // if successful so far, go ahead and configure
107        adapter.configure();
108
109        // once all the configure processing has happened, do any extra config
110
111        if (perNode.getAttribute("turnoutInterval") != null) { // migrate existing profile, defaults to 250 ms in memo
112            adapter.getSystemConnectionMemo().setOutputInterval(Integer.parseInt(perNode.getAttribute("turnoutInterval").getValue()));
113        }
114
115        unpackElement(shared, perNode);
116        return result;
117    }
118
119    /**
120     * Update static data from XML file.
121     *
122     * @param element Top level Element to unpack.
123     */
124    @Override
125    public void load(Element element, Object o) {
126        log.error("method with two args invoked");
127    }
128
129    @Override
130    protected void dispose() {
131        if (adapter != null) {
132            adapter.dispose();
133        }
134    }
135
136    // initialize logging
137    private static final Logger log = LoggerFactory.getLogger(AbstractSerialConnectionConfigXml.class);
138
139}