001package jmri.managers.configurexml; 002 003import java.awt.GraphicsEnvironment; 004 005import java.util.List; 006import java.util.SortedSet; 007 008import jmri.ConfigureManager; 009import jmri.InstanceManager; 010import jmri.Logix; 011import jmri.LogixManager; 012import jmri.managers.DefaultLogixManager; 013import jmri.util.swing.JmriJOptionPane; 014 015import org.jdom2.Element; 016 017/** 018 * Provides the functionality for configuring LogixManagers. 019 * 020 * @author Dave Duchamp Copyright (c) 2007 021 */ 022public class DefaultLogixManagerXml extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML { 023 024 public DefaultLogixManagerXml() { 025 } 026 027 /** 028 * Default implementation for storing the contents of a LogixManager. 029 * 030 * @param o Object to store, of type LogixManager 031 * @return Element containing the complete info 032 */ 033 @Override 034 public Element store(Object o) { 035 Element logixs = new Element("logixs"); 036 setStoreElementClass(logixs); 037 LogixManager lxm = (LogixManager) o; 038 if (lxm != null) { 039 SortedSet<Logix> logixList = lxm.getNamedBeanSet(); 040 // don't return an element if there are no Logix to include 041 if (logixList.isEmpty()) { 042 return null; 043 } 044 // store the Logix 045 for (Logix x : logixList) { 046 String xName = x.getSystemName(); 047 log.debug("Logix system name is {}", xName); // NOI18N 048 boolean enabled = x.getEnabled(); 049 050 Element elem = new Element("logix"); // NOI18N 051 elem.addContent(new Element("systemName").addContent(xName)); // NOI18N 052 053 // As a work-around for backward compatibility, store systemName and username as attribute. 054 // TODO Remove this in e.g. JMRI 4.11.1 and then update all the loadref comparison files 055 String uName = x.getUserName(); 056 if ((uName != null) && !uName.isEmpty()) { 057 elem.setAttribute("userName", uName); // NOI18N 058 } 059 060 // store common part 061 storeCommon(x, elem); 062 063 if (enabled) { 064 elem.setAttribute("enabled", "yes"); // NOI18N 065 } else { 066 elem.setAttribute("enabled", "no"); // NOI18N 067 } 068 // save child Conditionals 069 int numConditionals = x.getNumConditionals(); 070 if (numConditionals > 0) { 071 String cSysName = ""; 072 Element cElem = null; 073 for (int k = 0; k < numConditionals; k++) { 074 cSysName = x.getConditionalByNumberOrder(k); 075 cElem = new Element("logixConditional"); // NOI18N 076 cElem.setAttribute("systemName", cSysName); // NOI18N 077 cElem.setAttribute("order", Integer.toString(k)); // NOI18N 078 elem.addContent(cElem); 079 } 080 } 081 logixs.addContent(elem); 082 } 083 } 084 return (logixs); 085 } 086 087 /** 088 * Subclass provides implementation to create the correct top element, 089 * including the type information. Default implementation is to use the 090 * local class here. 091 * 092 * @param logixs The top-level element being created 093 */ 094 public void setStoreElementClass(Element logixs) { 095 logixs.setAttribute("class", this.getClass().getName()); // NOI18N 096 } 097 098 @Override 099 public void load(Element element, Object o) { 100 log.error("Invalid method called"); // NOI18N 101 } 102 103 /** 104 * Create a LogixManager object of the correct class, then register and fill 105 * it. 106 * 107 * @param sharedLogix Shared top level Element to unpack. 108 * @param perNodeLogix Per-node top level Element to unpack. 109 * @return true if successful 110 */ 111 @Override 112 public boolean load(Element sharedLogix, Element perNodeLogix) { 113 // create the master object 114 replaceLogixManager(); 115 // load individual sharedLogix 116 loadLogixs(sharedLogix); 117 return true; 118 } 119 120 /** 121 * Utility method to load the individual Logix objects. If there's no 122 * additional info needed for a specific logix type, invoke this with the 123 * parent of the set of Logix elements. 124 * 125 * @param logixs Element containing the Logix elements to load. 126 */ 127 public void loadLogixs(Element logixs) { 128 List<Element> logixList = logixs.getChildren("logix"); // NOI18N 129 log.debug("Found {} Logixs", logixList.size()); // NOI18N 130 LogixManager lxm = InstanceManager.getDefault(jmri.LogixManager.class); 131 132 String systemNamePrefix = lxm.getSystemNamePrefix(); 133 int namesChanged = 0; 134 135 for (Element elem : logixList) { 136 String sysName = getSystemName(elem); 137 if (sysName == null) { 138 log.warn("unexpected null in systemName {}", elem); // NOI18N 139 break; 140 } 141 142 if (!sysName.startsWith(systemNamePrefix)) { 143 String old = sysName; 144 sysName = systemNamePrefix + ":" + sysName; 145 log.warn("Converting Logix system name from {} to {}", old, sysName); 146 namesChanged++; 147 } 148 149 String userName = getUserName(elem); 150 log.debug("create logix: ({})({})", sysName, // NOI18N 151 (userName == null ? "<null>" : userName)); // NOI18N 152 153 String yesno = ""; 154 if (elem.getAttribute("enabled") != null) { // NOI18N 155 yesno = elem.getAttribute("enabled").getValue(); // NOI18N 156 } 157 158 Logix x = lxm.createNewLogix(sysName, userName); 159 if (x != null) { 160 // load common part 161 loadCommon(x, elem); 162 163 // set enabled/disabled if attribute was present 164 if ((yesno != null) && (!yesno.equals(""))) { 165 if (yesno.equals("yes")) { // NOI18N 166 x.setEnabled(true); 167 } else if (yesno.equals("no")) { // NOI18N 168 x.setEnabled(false); 169 } 170 } 171 // load conditionals, if there are any 172 List<Element> logixConditionalList = elem.getChildren("logixConditional"); // NOI18N 173 // add conditionals 174 for (Element lxcond : logixConditionalList) { 175 String cSysName = getAttributeString(lxcond, "systemName"); 176 if (cSysName == null) { 177 log.warn("unexpected null in systemName {} {}", // NOI18N 178 lxcond, lxcond.getAttributes()); 179 break; 180 } 181 182 // Fix conditional name if necessary 183 if (!cSysName.startsWith(systemNamePrefix)) { 184 cSysName = systemNamePrefix + ":" + cSysName; 185 } 186 187 int cOrder = Integer.parseInt(lxcond 188 .getAttribute("order").getValue()); // NOI18N 189 // add the conditional to logix 190 x.addConditional(cSysName, cOrder); 191 } 192 } 193 } 194 195 if (namesChanged > 0) { 196 // TODO: replace the System property check with an in-application mechanism 197 // for notifying users of multiple changes that can be silenced as part of 198 // normal operations 199 if (!GraphicsEnvironment.isHeadless() && !Boolean.getBoolean("jmri.test.no-dialogs")) { 200 JmriJOptionPane.showMessageDialog(null, 201 Bundle.getMessage(namesChanged > 1 ? "LogixManager.SystemNamesChanged.Message" : "LogixManager.SystemNameChanged.Message", namesChanged), 202 Bundle.getMessage("Manager.SystemNamesChanged.Title", namesChanged, lxm.getBeanTypeHandled(namesChanged > 1)), 203 JmriJOptionPane.WARNING_MESSAGE); 204 } 205 log.warn("System names for {} Logixs changed; this may have operational impacts.", namesChanged); 206 } 207 } 208 209 /** 210 * Replace the current LogixManager, if there is one, with one newly created 211 * during a load operation. This is skipped if they are of the same absolute 212 * type. 213 */ 214 protected void replaceLogixManager() { 215 if (InstanceManager.getDefault(jmri.LogixManager.class).getClass().getName() 216 .equals(DefaultLogixManager.class.getName())) { 217 return; 218 } 219 // if old manager exists, remove it from configuration process 220 if (InstanceManager.getNullableDefault(jmri.LogixManager.class) != null) { 221 ConfigureManager cmOD = InstanceManager.getNullableDefault(jmri.ConfigureManager.class); 222 if (cmOD != null) { 223 cmOD.deregister(InstanceManager.getDefault(jmri.LogixManager.class)); 224 } 225 } 226 227 // register new one with InstanceManager 228 DefaultLogixManager pManager = InstanceManager.getDefault(DefaultLogixManager.class); 229 InstanceManager.store(pManager, LogixManager.class); 230 // register new one for configuration 231 ConfigureManager cmOD = InstanceManager.getNullableDefault(jmri.ConfigureManager.class); 232 if (cmOD != null) { 233 cmOD.registerConfig(pManager, jmri.Manager.LOGIXS); 234 } 235 } 236 237 @Override 238 public int loadOrder() { 239 return InstanceManager.getDefault(jmri.LogixManager.class).getXMLOrder(); 240 } 241 242 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultLogixManagerXml.class); 243 244}