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}