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