001package jmri.jmrix.configurexml;
002
003import jmri.jmrix.NetworkPortAdapter;
004import org.jdom2.Element;
005import org.slf4j.Logger;
006import org.slf4j.LoggerFactory;
007
008import javax.annotation.Nonnull;
009
010/**
011 * Abstract base (and partial implementation) for classes persisting the status
012 * of Network port adapters.
013 *
014 * @author Bob Jacobsen, Copyright (c) 2003
015 */
016abstract public class AbstractNetworkConnectionConfigXml extends AbstractConnectionConfigXml {
017
018    public AbstractNetworkConnectionConfigXml() {
019    }
020
021    protected NetworkPortAdapter adapter;
022
023    protected void getInstance(Object object) {
024        getInstance(); // over-ridden during migration
025    }
026
027    /**
028     * Default implementation for storing the static contents of the Network
029     * port implementation.
030     *
031     * @param o Object to store, of type PositionableLabel
032     * @return Element containing the complete info
033     */
034    @Override
035    public Element store(Object o) {
036        getInstance(o);
037
038        Element e = new Element("connection");
039        // many of the following are required by the DTD; failing to include
040        // them makes the XML file unreadable, but at least the next
041        // invocation of the program can then continue.
042
043        storeCommon(e, adapter);
044
045        if (adapter.getMdnsConfigure()) {
046            // if we are using mDNS for configuration, only save
047            // the hostname if it was specified.
048            if (adapter.getHostName() != null && !adapter.getHostName().equals("")) {
049                e.setAttribute("address", adapter.getHostName());
050            }
051
052            e.setAttribute("mdnsConfigure", "true");
053            if (adapter.getAdvertisementName() != null) {
054                e.setAttribute("advertisementName", adapter.getAdvertisementName());
055            }
056            if (adapter.getServiceType() != null) {
057                e.setAttribute("serviceType", adapter.getServiceType());
058            }
059
060        } else {
061            e.setAttribute("mdnsConfigure", "false");
062
063            // require a value for the address if we are not using mDNS.
064            if (adapter.getHostName() != null) {
065                e.setAttribute("address", adapter.getHostName());
066            } else {
067                e.setAttribute("address", Bundle.getMessage("noneSelected"));
068            }
069
070            // write the port only if we are not using automatic configuration.
071            if (adapter.getPort() != 0) {
072                e.setAttribute("port", "" + adapter.getPort());
073            } else {
074                e.setAttribute("port", Bundle.getMessage("noneSelected"));
075            }
076        }
077
078        setOutputInterval(adapter, e);
079
080        e.setAttribute("class", this.getClass().getName());
081
082        extendElement(e);
083
084        return e;
085    }
086
087    /**
088     * Customizable method if you need to add anything more.
089     *
090     * @param e Element being created, update as needed
091     */
092    @Override
093    protected void extendElement(Element e) {
094    }
095
096    @Override
097    public boolean load(@Nonnull Element shared, Element perNode) {
098        boolean result = true;
099        getInstance();
100
101        boolean mdnsConfig = false;
102        try {
103            mdnsConfig = (shared.getAttribute("mdnsConfigure").getValue().equals("true"));
104        } catch (NullPointerException ex) {  // considered normal if the attributes are not present
105        }
106        adapter.setMdnsConfigure(mdnsConfig);
107
108        if (mdnsConfig) {
109
110            // configure host name
111            try {
112                String hostName = shared.getAttribute("address").getValue();
113                // the hostname is optional when mDNS is being used.
114                adapter.setHostName(hostName);
115            } catch (NullPointerException ex) {  // considered normal if the attributes are not present
116            }
117
118            // configure the Service Type
119            try {
120                String serviceType = shared.getAttribute("serviceType").getValue();
121                // the Service Type is optional when mDNS is being used.
122                adapter.setServiceType(serviceType);
123            } catch (NullPointerException ex) {  // considered normal if the attributes are not present
124            }
125
126            // configure the advertisement name
127            try {
128                String advertisementName = shared.getAttribute("advertisementName").getValue();
129                // the Advertisement Name is optional when mDNS is being used.
130                adapter.setAdvertisementName(advertisementName);
131            } catch (NullPointerException ex) {  // considered normal if the attributes are not present
132            }
133
134            // get the host IP and port number
135            // via mdns
136            adapter.autoConfigure();
137
138        } else {
139            // get the host name and port number via parameters.
140
141            // configure host name
142            String hostName = null;
143            try {
144                hostName = shared.getAttribute("address").getValue();
145            } catch (NullPointerException ex) {  // considered normal if the attributes are not present
146            }
147            adapter.setHostName(hostName);
148
149            try {
150                int port = shared.getAttribute("port").getIntValue();
151                adapter.setPort(port);
152            } catch (org.jdom2.DataConversionException ex) {
153                log.warn("Could not parse port attribute: {}", shared.getAttribute("port"));
154            } catch (NullPointerException ex) {  // considered normal if the attributes are not present
155            }
156        }
157
158        loadCommon(shared, perNode, adapter);
159        // register, so can be picked up next time
160        register();
161
162        if (adapter.getDisabled()) {
163            unpackElement(shared, perNode);
164            return result;
165        }
166        try {
167            log.trace("start adapter.connect()");
168            adapter.connect();
169        } catch (Exception ex) {
170            log.debug("Caught exception in adapter.connect", ex);
171            handleException(ex.getMessage(), "opening connection", null, null, ex);
172            return false;
173        }
174
175        // if successful so far, go ahead and configure
176        log.trace("start adapter.configure()");
177        adapter.configure();
178
179        // once all the configure processing has happened, do any
180        // extra config
181        log.trace("start unpackElement");
182
183        if (perNode.getAttribute("turnoutInterval") != null) { // migrate existing profile, defaults to 250 ms in memo
184            adapter.getSystemConnectionMemo().setOutputInterval(Integer.parseInt(perNode.getAttribute("turnoutInterval").getValue()));
185        }
186
187        unpackElement(shared, perNode);
188        return result;
189    }
190
191    /**
192     * Update static data from XML file.
193     *
194     * @param element Top level Element to unpack.
195     */
196    @Override
197    public void load(Element element, Object o) {
198        log.error("method with two args invoked");
199    }
200
201    @Override
202    protected void dispose() {
203        adapter.dispose();
204    }
205
206    // initialize logging
207    private final static Logger log = LoggerFactory.getLogger(AbstractNetworkConnectionConfigXml.class);
208
209}