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