001package jmri.jmrit.entryexit.configurexml; 002 003import java.awt.Color; 004import java.util.ArrayList; 005import java.util.List; 006import java.util.Comparator; 007import jmri.ConfigureManager; 008import jmri.InstanceManager; 009import jmri.NamedBean; 010import jmri.Sensor; 011import jmri.SensorManager; 012import jmri.SignalHead; 013import jmri.SignalHeadManager; 014import jmri.SignalMast; 015import jmri.SignalMastManager; 016import jmri.configurexml.AbstractXmlAdapter; 017import jmri.jmrit.display.layoutEditor.LayoutEditor; 018import jmri.jmrit.entryexit.EntryExitPairs; 019import jmri.util.ColorUtil; 020import org.jdom2.Element; 021import org.slf4j.Logger; 022import org.slf4j.LoggerFactory; 023 024/** 025 * This module handles configuration for the Entry Exit pairs used in 026 * interlocking on a Layout Editor Panel. 027 * 028 * @author Kevin Dickerson Copyright (c) 2007 029 */ 030public class EntryExitPairsXml extends AbstractXmlAdapter { 031 032 public EntryExitPairsXml() { 033 } 034 035 /** 036 * Default implementation for storing the contents of a PositionablePoint. 037 * 038 * @param o Object to store, of type PositionablePoint 039 * @return Element containing the complete info 040 */ 041 @Override 042 public Element store(Object o) { 043 EntryExitPairs p = (EntryExitPairs) o; 044 Element element = new Element("entryexitpairs"); // NOI18N 045 setStoreElementClass(element); 046 List<LayoutEditor> editors = p.getSourcePanelList(); 047 if (editors.isEmpty()) { 048 return null; //return element; // <== don't store empty (unused) element 049 } 050 051 java.util.Collections.sort(editors, new Comparator<LayoutEditor>(){ 052 @Override 053 public int compare(LayoutEditor o1, LayoutEditor o2) { return o1.toString().compareTo(o2.toString() ); } 054 }); 055 056 int clearDown = p.getClearDownOption(); 057 if (clearDown > 0) { 058 element.addContent(new Element("cleardown").addContent("" + clearDown)); // NOI18N 059 } 060 061 int overLap = p.getOverlapOption(); 062 if (overLap > 0) { 063 element.addContent(new Element("overlap").addContent("" + overLap)); // NOI18N 064 } 065 066 int memoryClearDelay = p.getMemoryClearDelay(); 067 if (memoryClearDelay > 0) { 068 element.addContent(new Element("memorycleardelay").addContent("" + memoryClearDelay)); // NOI18N 069 } 070 071 String memoryName = p.getMemoryOption(); 072 if (!memoryName.isEmpty()) { 073 element.addContent(new Element("memoryname").addContent(memoryName)); // NOI18N 074 } 075 076 if (p.getDispatcherIntegration()) { 077 element.addContent(new Element("dispatcherintegration").addContent("yes")); // NOI18N 078 } 079 080 if (p.useDifferentColorWhenSetting()) { 081 element.addContent(new Element("colourwhilesetting") 082 .addContent(ColorUtil.colorToColorName(p.getSettingRouteColor()))); // NOI18N 083 element.addContent(new Element("settingTimer").addContent("" + p.getSettingTimer())); // NOI18N 084 } 085 086 if (p.isAbsSignalMode()) { 087 element.addContent(new Element("abssignalmode").addContent("yes")); // NOI18N 088 } 089 090 if (p.isQuietFail()) { 091 element.addContent(new Element("quietfail").addContent("yes")); // NOI18N 092 } 093 094 if (p.isSkipGuiFix()) { 095 element.addContent(new Element("skipguifix").addContent("yes")); // NOI18N 096 } 097 098 for (int k = 0; k < editors.size(); k++) { 099 LayoutEditor panel = editors.get(k); 100 List<Object> nxpair = p.getSourceList(panel); 101 102 java.util.Collections.sort(nxpair, new Comparator<Object>(){ 103 @Override 104 public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString() ); } 105 }); 106 Element panelElem = new Element("layoutPanel"); // NOI18N 107 panelElem.setAttribute("name", panel.getLayoutName()); // NOI18N 108 for (int j = 0; j < nxpair.size(); j++) { 109 Object key = nxpair.get(j); 110 Element source = new Element("source"); // NOI18N 111 String type = ""; 112 String item = ""; 113 114 if (key instanceof SignalMast) { 115 type = "signalMast"; // NOI18N 116 item = ((SignalMast) key).getDisplayName(); 117 } else if (key instanceof Sensor) { 118 type = "sensor"; // NOI18N 119 item = ((Sensor) key).getDisplayName(); 120 } else if (key instanceof SignalHead) { 121 type = "signalHead"; // NOI18N 122 item = ((SignalHead) key).getDisplayName(); 123 } 124 125 source.setAttribute("type", type); // NOI18N 126 source.setAttribute("item", item); // NOI18N 127 128 List<Object> a = p.getDestinationList(key, panel); 129 java.util.Collections.sort(a, new Comparator<Object>(){ 130 @Override 131 public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString() ); } 132 }); 133 134 for (int i = 0; i < a.size(); i++) { 135 Object keyDest = a.get(i); 136 String typeDest = ""; 137 String itemDest = ""; 138 if (keyDest instanceof SignalMast) { 139 typeDest = "signalMast"; // NOI18N 140 itemDest = ((SignalMast) keyDest).getDisplayName(); 141 } else if (keyDest instanceof Sensor) { 142 typeDest = "sensor"; // NOI18N 143 itemDest = ((Sensor) keyDest).getDisplayName(); 144 } else if (keyDest instanceof SignalHead) { 145 typeDest = "signalHead"; // NOI18N 146 itemDest = ((SignalHead) keyDest).getDisplayName(); 147 } 148 Element dest = new Element("destination"); // NOI18N 149 dest.setAttribute("type", typeDest); // NOI18N 150 dest.setAttribute("item", itemDest); // NOI18N 151 if (!p.isUniDirection(key, panel, keyDest)) { 152 dest.setAttribute("uniDirection", "no"); // NOI18N 153 } 154 if (!p.isEnabled(key, panel, keyDest)) { 155 dest.setAttribute("enabled", "no"); // NOI18N 156 } 157 int nxType = p.getEntryExitType(key, panel, keyDest); 158 switch (nxType) { 159 case 0x01: 160 dest.setAttribute("nxType", "signalmastlogic"); // NOI18N 161 break; 162 case 0x02: 163 dest.setAttribute("nxType", "fullinterlocking"); // NOI18N 164 break; 165 case 0x00: 166 default: 167 dest.setAttribute("nxType", "turnoutsetting"); // NOI18N 168 break; 169 } 170 if (p.getUniqueId(key, panel, keyDest) != null) { 171 dest.setAttribute("uniqueid", p.getUniqueId(key, panel, keyDest)); // NOI18N 172 } 173 source.addContent(dest); 174 } 175 panelElem.addContent(source); 176 } 177 element.addContent(panelElem); 178 } 179 return element; 180 } 181 182 /** 183 * Define attribute for an element that is to be stored. 184 * 185 * @param messages Storage element 186 */ 187 public void setStoreElementClass(Element messages) { 188 messages.setAttribute("class", "jmri.jmrit.entryexit.configurexml.EntryExitPairsXml"); // NOI18N 189 } 190 191 /** 192 * Load, starting with the layoutBlock element, then all the value-icon 193 * pairs. 194 * 195 * @param shared Top level Element to unpack 196 * @param perNode ignored in this application 197 * @return true if loaded without errors; false otherwise 198 */ 199 @Override 200 public boolean load(Element shared, Element perNode) { 201 // create the objects 202 EntryExitPairs eep = InstanceManager.getDefault(EntryExitPairs.class); 203 String nodeText; 204 205 nodeText = shared.getChildText("cleardown"); 206 if (nodeText != null) eep.setClearDownOption(Integer.parseInt(nodeText)); 207 208 nodeText = shared.getChildText("overlap"); 209 if (nodeText != null) eep.setOverlapOption(Integer.parseInt(nodeText)); 210 211 nodeText = shared.getChildText("memorycleardelay"); 212 if (nodeText != null) eep.setMemoryClearDelay(Integer.parseInt(nodeText)); 213 214 nodeText = shared.getChildText("memoryname"); 215 if (nodeText != null) eep.setMemoryOption(nodeText); 216 217 // get attributes 218 ConfigureManager cm = InstanceManager.getNullableDefault(jmri.ConfigureManager.class); 219 List<Object> loadedPanel; 220 if (cm != null) { 221 loadedPanel = cm.getInstanceList(LayoutEditor.class); 222 } else { 223 log.error("Failed getting optional default config manager"); // NOI18N 224 loadedPanel = new ArrayList<>(); 225 } 226 227 if (shared.getChild("dispatcherintegration") != null && shared.getChild("dispatcherintegration").getText().equals("yes")) { // NOI18N 228 eep.setDispatcherIntegration(true); 229 } 230 231 if (shared.getChild("colourwhilesetting") != null) { 232 try { 233 eep.setSettingRouteColor(ColorUtil.stringToColor(shared.getChild("colourwhilesetting").getText())); // NOI18N 234 } catch (IllegalArgumentException e) { 235 eep.setSettingRouteColor(Color.BLACK); 236 log.error("Invalid color {}; using black", shared.getChild("colourwhilesetting").getText()); 237 } 238 int settingTimer = 2000; 239 try { 240 settingTimer = Integer.parseInt(shared.getChild("settingTimer").getText()); // NOI18N 241 } catch (NumberFormatException e) { 242 log.error("Error in converting timer to int {}", shared.getChild("settingTimer")); // NOI18N 243 } 244 eep.setSettingTimer(settingTimer); 245 } 246 247 if (shared.getChild("abssignalmode") != null && shared.getChild("abssignalmode").getText().equals("yes")) { // NOI18N 248 eep.setAbsSignalMode(true); 249 } 250 251 if (shared.getChild("quietfail") != null && shared.getChild("quietfail").getText().equals("yes")) { // NOI18N 252 eep.setQuietFail(true); 253 } 254 255 if (shared.getChild("skipguifix") != null && shared.getChild("skipguifix").getText().equals("yes")) { // NOI18N 256 eep.setSkipGuiFix(true); 257 } 258 259 List<Element> panelList = shared.getChildren("layoutPanel"); // NOI18N 260 for (int k = 0; k < panelList.size(); k++) { 261 String panelName = panelList.get(k).getAttribute("name").getValue(); // NOI18N 262 LayoutEditor panel = null; 263 for (int i = 0; i < loadedPanel.size(); i++) { 264 LayoutEditor tmp = (LayoutEditor) loadedPanel.get(i); 265 if (tmp.getLayoutName().equals(panelName)) { 266 panel = tmp; 267 break; 268 } 269 } 270 if (panel != null) { 271 List<Element> sourceList = panelList.get(k).getChildren("source"); // NOI18N 272 for (int i = 0; i < sourceList.size(); i++) { 273 String sourceType = sourceList.get(i).getAttribute("type").getValue(); // NOI18N 274 String sourceItem = sourceList.get(i).getAttribute("item").getValue(); // NOI18N 275 NamedBean source = null; 276 switch (sourceType) { 277 case "signalMast": // NOI18N 278 source = InstanceManager.getDefault(SignalMastManager.class).getSignalMast(sourceItem); 279 break; 280 case "sensor": // NOI18N 281 source = InstanceManager.getDefault(SensorManager.class).getSensor(sourceItem); 282 break; 283 case "signalHead": // NOI18N 284 source = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(sourceItem); 285 break; 286 default: 287 break; 288 } 289 290 //These two could be subbed off. 291 List<Element> destinationList = sourceList.get(i).getChildren("destination"); // NOI18N 292 if (destinationList.size() > 0) { 293 eep.addNXSourcePoint(source, panel); 294 } 295 for (int j = 0; j < destinationList.size(); j++) { 296 String id = null; 297 if (destinationList.get(j).getAttribute("uniqueid") != null) { // NOI18N 298 id = destinationList.get(j).getAttribute("uniqueid").getValue(); // NOI18N 299 if (!id.startsWith("IN:")) { // NOI18N 300 id = "IN:" + id; // NOI18N 301 } 302 } 303 String destType = destinationList.get(j).getAttribute("type").getValue(); // NOI18N 304 String destItem = destinationList.get(j).getAttribute("item").getValue(); // NOI18N 305 NamedBean dest = null; 306 switch (destType) { 307 case "signalMast": // NOI18N 308 dest = InstanceManager.getDefault(SignalMastManager.class).getSignalMast(destItem); 309 break; 310 case "sensor": // NOI18N 311 dest = InstanceManager.getDefault(SensorManager.class).getSensor(destItem); 312 break; 313 case "signalHead": // NOI18N 314 dest = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(destItem); 315 break; 316 default: 317 break; 318 } 319 try { 320 eep.addNXDestination(source, dest, panel, id); 321 } catch (java.lang.NullPointerException e) { 322 log.error("An error occurred while trying to add a point"); // NOI18N 323 } 324 if ((destinationList.get(j).getAttribute("uniDirection") != null) && (destinationList.get(j).getAttribute("uniDirection").getValue().equals("no"))) { // NOI18N 325 eep.setUniDirection(source, panel, dest, false); 326 } 327 if ((destinationList.get(j).getAttribute("enabled") != null) && (destinationList.get(j).getAttribute("enabled").getValue().equals("no"))) { // NOI18N 328 eep.setEnabled(source, panel, dest, false); 329 } 330 if (destinationList.get(j).getAttribute("nxType") != null) { // NOI18N 331 String nxType = destinationList.get(j).getAttribute("nxType").getValue(); // NOI18N 332 switch (nxType) { 333 case "turnoutsetting": // NOI18N 334 eep.setEntryExitType(source, panel, dest, 0x00); 335 break; 336 case "signalmastlogic": // NOI18N 337 eep.setEntryExitType(source, panel, dest, 0x01); 338 break; 339 case "fullinterlocking": // NOI18N 340 eep.setEntryExitType(source, panel, dest, 0x02); 341 break; 342 default: 343 break; 344 } 345 346 } 347 } 348 } 349 } else { 350 log.error("Panel has not been loaded"); // NOI18N 351 } 352 } 353 return true; 354 } 355 356 @Override 357 public int loadOrder() { 358 return InstanceManager.getDefault(EntryExitPairs.class).getXMLOrder(); 359 } 360 361 private final static Logger log = LoggerFactory.getLogger(EntryExitPairsXml.class); 362}