001package jmri.jmrit.logixng.implementation.configurexml; 002 003import java.lang.reflect.Constructor; 004import java.lang.reflect.InvocationTargetException; 005import java.util.HashMap; 006import java.util.List; 007import java.util.Map; 008 009import jmri.ConfigureManager; 010import jmri.InstanceManager; 011import jmri.configurexml.JmriConfigureXmlException; 012import jmri.jmrit.logixng.*; 013import jmri.jmrit.logixng.implementation.DefaultNamedTableManager; 014import jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML; 015import jmri.util.ThreadingUtil; 016 017import org.jdom2.Element; 018 019/** 020 * Provides the functionality for configuring DefaultNamedTableManager 021 * 022 * @author Dave Duchamp Copyright (c) 2007 023 * @author Daniel Bergqvist Copyright (c) 2018 024 */ 025public class DefaultNamedTableManagerXml extends AbstractManagerXml { 026 027 private final Map<String, Class<?>> xmlClasses = new HashMap<>(); 028 029 public DefaultNamedTableManagerXml() { 030 } 031 032 /** 033 * Default implementation for storing the contents of a NamedTableManager 034 * 035 * @param o Object to store, of type LogixManager 036 * @return Element containing the complete info 037 */ 038 @Override 039 public Element store(Object o) { 040 Element tables = new Element("LogixNGTables"); 041 setStoreElementClass(tables); 042 DefaultNamedTableManager tm = (DefaultNamedTableManager) o; 043 if (tm != null) { 044 if (tm.getNamedBeanSet().isEmpty()) return null; 045 for (NamedTable table : tm.getNamedBeanSet()) { 046 log.debug("table system name is {}", table.getSystemName()); // NOI18N 047 try { 048 Element e = jmri.configurexml.ConfigXmlManager.elementFromObject(table); 049 if (e != null) { 050 tables.addContent(e); 051 } 052 } catch (RuntimeException e) { 053 log.error("Error storing table: {}", e, e); 054 } 055 } 056 } 057 return (tables); 058 } 059 060 /** 061 * Subclass provides implementation to create the correct top element, 062 * including the type information. Default implementation is to use the 063 * local class here. 064 * 065 * @param expressions The top-level element being created 066 */ 067 public void setStoreElementClass(Element expressions) { 068 expressions.setAttribute("class", this.getClass().getName()); // NOI18N 069 } 070 071 /** 072 * Create a NamedTableManager object of the correct class, then 073 * register and fill it. 074 * 075 * @param sharedExpression Shared top level Element to unpack. 076 * @param perNodeExpression Per-node top level Element to unpack. 077 * @return true if successful 078 */ 079 @Override 080 public boolean load(Element sharedExpression, Element perNodeExpression) { 081 // create the master object 082 replaceExpressionManager(); 083 // load individual sharedLogix 084 loadTables(sharedExpression); 085 return true; 086 } 087 088 /** 089 * Utility method to load the individual Logix objects. If there's no 090 * additional info needed for a specific logix type, invoke this with the 091 * parent of the set of Logix elements. 092 * 093 * @param expressions Element containing the Logix elements to load. 094 */ 095 public void loadTables(Element expressions) { 096 097 List<Element> expressionList = expressions.getChildren(); // NOI18N 098 log.debug("Found {} tables", expressionList.size() ); // NOI18N 099 100 for (int i = 0; i < expressionList.size(); i++) { 101 102 String className = expressionList.get(i).getAttribute("class").getValue(); 103// log.error("className: " + className); 104 105 Class<?> clazz = xmlClasses.get(className); 106 107 if (clazz == null) { 108 try { 109 clazz = Class.forName(className); 110 xmlClasses.put(className, clazz); 111 } catch (ClassNotFoundException ex) { 112 log.error("cannot load class {}", className, ex); 113 } 114 } 115 116 if (clazz != null) { 117 Constructor<?> c = null; 118 try { 119 c = clazz.getConstructor(); 120 } catch (NoSuchMethodException | SecurityException ex) { 121 log.error("cannot create constructor", ex); 122 } 123 124 if (c != null) { 125 try { 126 AbstractNamedBeanManagerConfigXML o = (AbstractNamedBeanManagerConfigXML)c.newInstance(); 127 o.load(expressionList.get(i), null); 128 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 129 log.error("cannot create object", ex); 130 } catch (JmriConfigureXmlException ex) { 131 log.error("cannot load action", ex); 132 } 133 } 134 } 135 } 136 } 137 138 /** 139 * Replace the current NamedTableManager, if there is one, with one newly created 140 * during a load operation. This is skipped if they are of the same absolute 141 * type. 142 */ 143 protected void replaceExpressionManager() { 144 if (InstanceManager.getDefault(NamedTableManager.class).getClass().getName() 145 .equals(DefaultNamedTableManager.class.getName())) { 146 return; 147 } 148 // if old manager exists, remove it from configuration process 149 if (InstanceManager.getNullableDefault(NamedTableManager.class) != null) { 150 ConfigureManager cmOD = InstanceManager.getNullableDefault(jmri.ConfigureManager.class); 151 if (cmOD != null) { 152 cmOD.deregister(InstanceManager.getDefault(NamedTableManager.class)); 153 } 154 155 } 156 157 ThreadingUtil.runOnGUI(() -> { 158 // register new one with InstanceManager 159 DefaultNamedTableManager pManager = DefaultNamedTableManager.instance(); 160 InstanceManager.store(pManager, NamedTableManager.class); 161 // register new one for configuration 162 ConfigureManager cmOD = InstanceManager.getNullableDefault(jmri.ConfigureManager.class); 163 if (cmOD != null) { 164 cmOD.registerConfig(pManager, jmri.Manager.LOGIXNG_TABLES); 165 } 166 }); 167 } 168 169 @Override 170 public int loadOrder() { 171 return InstanceManager.getDefault(NamedTableManager.class).getXMLOrder(); 172 } 173 174 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultNamedTableManagerXml.class); 175}