001package apps.configurexml;
002
003import apps.CreateButtonModel;
004
005import jmri.util.startup.StartupActionsManager;
006
007import java.lang.reflect.InvocationTargetException;
008
009import jmri.InstanceManager;
010import jmri.SystemConnectionMemo;
011import jmri.jmrix.swing.SystemConnectionAction;
012
013import org.jdom2.Attribute;
014import org.jdom2.Element;
015
016/**
017 * Handle XML persistence of CreateButtonModel objects.
018 *
019 * @author Bob Jacobsen Copyright: Copyright (c) 2003
020 * @see apps.startup.CreateButtonModelFactory
021 */
022public class CreateButtonModelXml extends jmri.configurexml.AbstractXmlAdapter {
023
024    public CreateButtonModelXml() {
025    }
026
027    /**
028     * Default implementation for storing the model contents
029     *
030     * @param o Object to store, of type CreateButtonModel
031     * @return Element containing the complete info
032     */
033    @Override
034    public Element store(Object o) {
035        Element element = new Element("perform");
036        CreateButtonModel g = (CreateButtonModel) o;
037
038        element.setAttribute("name", g.getClassName());
039        element.setAttribute("type", "Button");
040        element.setAttribute("enabled", g.isEnabled() ? "yes" : "no");
041        element.setAttribute("class", this.getClass().getName());
042        Element property = new Element("property"); // NOI18N
043        property.setAttribute("name", "systemPrefix"); // NOI18N
044        property.setAttribute("value", g.getSystemPrefix());
045        element.addContent(property);
046        return element;
047    }
048
049    /**
050     * Object should be loaded after basic GUI constructed
051     *
052     * @return true to defer loading
053     * @see jmri.configurexml.AbstractXmlAdapter#loadDeferred()
054     * @see jmri.configurexml.XmlAdapter#loadDeferred()
055     */
056    @Override
057    public boolean loadDeferred() {
058        return true;
059    }
060
061    @Override
062    public boolean load(Element shared, Element perNode) {
063        boolean result = true;
064        String className = shared.getAttribute("name").getValue();
065        CreateButtonModel model = new CreateButtonModel();
066
067        Attribute enabled = shared.getAttribute("enabled");
068        if (enabled != null) {
069            model.setEnabled("yes".equals(enabled.getValue()));
070        } else {
071            model.setEnabled(true);
072        }
073
074        model.setClassName(className);
075        shared.getChildren("property").forEach(child -> { // NOI18N
076            String value = child.getAttributeValue("value"); // NOI18N
077            if (child.getAttributeValue("name").equals("systemPrefix") // NOI18N
078                    && value != null) {
079                // handle the situation where the model expects a system prefix
080                // but was not saved with one in a pre-4.19.7 JMRI instance
081                // TODO: at some point (June 2022 release?) change entire
082                // try/catch block to just "model.setSystemPrefix(value);"
083                try {
084                    Class<?> ac = Class.forName(className);
085                    if (value.isEmpty() && SystemConnectionAction.class.isAssignableFrom(ac)) {
086                        SystemConnectionAction<?> a = (SystemConnectionAction<?>) ac.getConstructor().newInstance();
087                        InstanceManager.getList(SystemConnectionMemo.class)
088                                .forEach(memo -> a.getSystemConnectionMemoClasses().stream()
089                                .filter(mc -> memo.getClass().isAssignableFrom(mc))
090                                .forEach(mc -> model.setSystemPrefix(memo.getSystemPrefix())));
091                    } else {
092                        model.setSystemPrefix(value);
093                    }
094                } catch (ClassNotFoundException
095                        | InstantiationException
096                        | IllegalAccessException
097                        | IllegalArgumentException
098                        | InvocationTargetException
099                        | NoSuchMethodException
100                        | SecurityException ex) {
101                    // ignore to allow manager to handle later
102                    log.warn("While trying to do {}, encountered exception", className, ex);
103                }
104            }
105        });
106        InstanceManager.getDefault(StartupActionsManager.class).addAction(model);
107        return result;
108    }
109
110    /**
111     * Update static data from XML file
112     *
113     * @param element Top level Element to unpack.
114     * @param o       ignored
115     */
116    @Override
117    public void load(Element element, Object o) {
118        log.error("Unexpected call of load(Element, Object)");
119    }
120
121    // initialize logging
122    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CreateButtonModelXml.class);
123
124}