001package jmri.jmrix.configurexml;
002
003import jmri.jmrix.UsbPortAdapter;
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 (non-serial) USB adapters.
011 * <p>
012 * IOW: if you're just using usb to access a serial buss on the other side then
013 * you should be using AbstractSerialConnectionConfigXml instead.
014 *
015 * @author Bob Jacobsen Copyright: Copyright (c) 2003
016 * @author George Warner Copyright: Copyright (c) 2017
017 */
018abstract public class AbstractUsbConnectionConfigXml extends AbstractConnectionConfigXml {
019
020    /**
021     * constructor
022     */
023    public AbstractUsbConnectionConfigXml() {
024    }
025
026    protected UsbPortAdapter adapter;
027
028    /**
029     * set the usb port adapter
030     *
031     * @param usbPortAdapter the usb port adapter to set
032     */
033    protected void setAdapter(UsbPortAdapter usbPortAdapter) {
034        log.debug("setAdapter({})", usbPortAdapter);
035        adapter = usbPortAdapter;
036    }
037
038    /**
039     * get the usb port adapter
040     *
041     * @return the usb port adapter
042     */
043    protected UsbPortAdapter getAdapter() {
044        log.debug("getAdapter()");
045        return adapter;
046    }
047
048    /**
049     * get instance
050     *
051     * @param object to get the instance of
052     */
053    protected abstract void getInstance(Object object);
054
055    /**
056     * {@inheritDoc}
057     */
058    @Override
059    public Element store(Object object) {
060        log.debug("store({})", object);
061        getInstance(object);
062        Element e = new Element("connection");
063
064        if (adapter == null) {
065            log.warn("No adapter found while saving usb port configuration {}", object.toString());
066            return null;
067        }
068
069        // many of the following are required by the DTD; failing to include
070        // them makes the XML file unreadable, but at least the next
071        // invocation of the program can then continue.
072        storeCommon(e, adapter);
073
074        if (adapter.getCurrentPortName() != null) {
075            e.setAttribute("port", adapter.getCurrentPortName());
076        } else {
077            e.setAttribute("port", Bundle.getMessage("noneSelected"));
078        }
079        if (adapter.getSerialNumber() != null) {
080            e.setAttribute("serialNumber", adapter.getSerialNumber());
081        }
082
083        e.setAttribute("class", this.getClass().getName());
084
085        extendElement(e);
086
087        return e;
088    }
089
090    /**
091     * {@inheritDoc}
092     */
093    @Override
094    protected void extendElement(Element e) {
095        log.debug("extendElement({})", e);
096    }
097
098    /**
099     * load from xml elements
100     *
101     * @param shared  element
102     * @param perNode element
103     * @return boolean true if successful
104     */
105    @Override
106    public boolean load(Element shared, Element perNode) {
107        log.debug("load({}, {})", shared, perNode);
108        boolean result = true;  // assume success (optimist!)
109
110        getInstance();
111        // configure port name
112        String portName = perNode.getAttributeValue("port");
113        String serialNumber = perNode.getAttributeValue("serialNumber");
114        if (serialNumber != null && serialNumber.isEmpty()) {
115            serialNumber = null;
116        }
117        adapter.setPort(portName);
118        adapter.setSerialNumber(serialNumber);
119
120        loadCommon(shared, perNode, adapter);
121
122        // register, so can be picked up next time
123        register();
124
125        // try to open the port
126        if (adapter.getDisabled()) {
127            unpackElement(shared, perNode);
128            return result;
129        }
130
131        String status = adapter.openPort(portName, serialNumber);
132        if (status != null) {
133            // indicates an error, return it
134            handleException(status, "opening connection", null, null, null);
135            // now force end to operation
136            log.debug("load failed");
137            return false;
138        }
139
140        // if successful so far, go ahead and configure
141        adapter.configure();
142
143        // once all the configure processing has happened, do any
144        // extra config
145        unpackElement(shared, perNode);
146        return result;
147    }
148
149    /**
150     * Update static data from XML file
151     *
152     * @param element Top level Element to unpack.
153     */
154    @Override
155    public void load(Element element, Object o) {
156        log.error("method with two args invoked");
157    }
158
159    @Override
160    protected void dispose() {
161        adapter.dispose();
162    }
163
164    // initialize logging
165    private static final Logger log
166            = LoggerFactory.getLogger(AbstractUsbConnectionConfigXml.class);
167}