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 for (int k = 0; k < editors.size(); k++) { 091 LayoutEditor panel = editors.get(k); 092 List<Object> nxpair = p.getSourceList(panel); 093 094 java.util.Collections.sort(nxpair, new Comparator<Object>(){ 095 @Override 096 public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString() ); } 097 }); 098 Element panelElem = new Element("layoutPanel"); // NOI18N 099 panelElem.setAttribute("name", panel.getLayoutName()); // NOI18N 100 for (int j = 0; j < nxpair.size(); j++) { 101 Object key = nxpair.get(j); 102 Element source = new Element("source"); // NOI18N 103 String type = ""; 104 String item = ""; 105 106 if (key instanceof SignalMast) { 107 type = "signalMast"; // NOI18N 108 item = ((SignalMast) key).getDisplayName(); 109 } else if (key instanceof Sensor) { 110 type = "sensor"; // NOI18N 111 item = ((Sensor) key).getDisplayName(); 112 } else if (key instanceof SignalHead) { 113 type = "signalHead"; // NOI18N 114 item = ((SignalHead) key).getDisplayName(); 115 } 116 117 source.setAttribute("type", type); // NOI18N 118 source.setAttribute("item", item); // NOI18N 119 120 List<Object> a = p.getDestinationList(key, panel); 121 java.util.Collections.sort(a, new Comparator<Object>(){ 122 @Override 123 public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString() ); } 124 }); 125 126 for (int i = 0; i < a.size(); i++) { 127 Object keyDest = a.get(i); 128 String typeDest = ""; 129 String itemDest = ""; 130 if (keyDest instanceof SignalMast) { 131 typeDest = "signalMast"; // NOI18N 132 itemDest = ((SignalMast) keyDest).getDisplayName(); 133 } else if (keyDest instanceof Sensor) { 134 typeDest = "sensor"; // NOI18N 135 itemDest = ((Sensor) keyDest).getDisplayName(); 136 } else if (keyDest instanceof SignalHead) { 137 typeDest = "signalHead"; // NOI18N 138 itemDest = ((SignalHead) keyDest).getDisplayName(); 139 } 140 Element dest = new Element("destination"); // NOI18N 141 dest.setAttribute("type", typeDest); // NOI18N 142 dest.setAttribute("item", itemDest); // NOI18N 143 if (!p.isUniDirection(key, panel, keyDest)) { 144 dest.setAttribute("uniDirection", "no"); // NOI18N 145 } 146 if (!p.isEnabled(key, panel, keyDest)) { 147 dest.setAttribute("enabled", "no"); // NOI18N 148 } 149 int nxType = p.getEntryExitType(key, panel, keyDest); 150 switch (nxType) { 151 case 0x01: 152 dest.setAttribute("nxType", "signalmastlogic"); // NOI18N 153 break; 154 case 0x02: 155 dest.setAttribute("nxType", "fullinterlocking"); // NOI18N 156 break; 157 case 0x00: 158 default: 159 dest.setAttribute("nxType", "turnoutsetting"); // NOI18N 160 break; 161 } 162 if (p.getUniqueId(key, panel, keyDest) != null) { 163 dest.setAttribute("uniqueid", p.getUniqueId(key, panel, keyDest)); // NOI18N 164 } 165 source.addContent(dest); 166 } 167 panelElem.addContent(source); 168 } 169 element.addContent(panelElem); 170 } 171 return element; 172 } 173 174 /** 175 * Define attribute for an element that is to be stored. 176 * 177 * @param messages Storage element 178 */ 179 public void setStoreElementClass(Element messages) { 180 messages.setAttribute("class", "jmri.jmrit.entryexit.configurexml.EntryExitPairsXml"); // NOI18N 181 } 182 183 /** 184 * Load, starting with the layoutBlock element, then all the value-icon 185 * pairs. 186 * 187 * @param shared Top level Element to unpack 188 * @param perNode ignored in this application 189 * @return true if loaded without errors; false otherwise 190 */ 191 @Override 192 public boolean load(Element shared, Element perNode) { 193 // create the objects 194 EntryExitPairs eep = InstanceManager.getDefault(EntryExitPairs.class); 195 String nodeText; 196 197 nodeText = shared.getChildText("cleardown"); 198 if (nodeText != null) eep.setClearDownOption(Integer.parseInt(nodeText)); 199 200 nodeText = shared.getChildText("overlap"); 201 if (nodeText != null) eep.setOverlapOption(Integer.parseInt(nodeText)); 202 203 nodeText = shared.getChildText("memorycleardelay"); 204 if (nodeText != null) eep.setMemoryClearDelay(Integer.parseInt(nodeText)); 205 206 nodeText = shared.getChildText("memoryname"); 207 if (nodeText != null) eep.setMemoryOption(nodeText); 208 209 // get attributes 210 ConfigureManager cm = InstanceManager.getNullableDefault(jmri.ConfigureManager.class); 211 List<Object> loadedPanel; 212 if (cm != null) { 213 loadedPanel = cm.getInstanceList(LayoutEditor.class); 214 } else { 215 log.error("Failed getting optional default config manager"); // NOI18N 216 loadedPanel = new ArrayList<>(); 217 } 218 219 if (shared.getChild("dispatcherintegration") != null && shared.getChild("dispatcherintegration").getText().equals("yes")) { // NOI18N 220 eep.setDispatcherIntegration(true); 221 } 222 223 if (shared.getChild("colourwhilesetting") != null) { 224 try { 225 eep.setSettingRouteColor(ColorUtil.stringToColor(shared.getChild("colourwhilesetting").getText())); // NOI18N 226 } catch (IllegalArgumentException e) { 227 eep.setSettingRouteColor(Color.BLACK); 228 log.error("Invalid color {}; using black", shared.getChild("colourwhilesetting").getText()); 229 } 230 int settingTimer = 2000; 231 try { 232 settingTimer = Integer.parseInt(shared.getChild("settingTimer").getText()); // NOI18N 233 } catch (NumberFormatException e) { 234 log.error("Error in converting timer to int {}", shared.getChild("settingTimer")); // NOI18N 235 } 236 eep.setSettingTimer(settingTimer); 237 } 238 239 if (shared.getChild("abssignalmode") != null && shared.getChild("abssignalmode").getText().equals("yes")) { // NOI18N 240 eep.setAbsSignalMode(true); 241 } 242 243 List<Element> panelList = shared.getChildren("layoutPanel"); // NOI18N 244 for (int k = 0; k < panelList.size(); k++) { 245 String panelName = panelList.get(k).getAttribute("name").getValue(); // NOI18N 246 LayoutEditor panel = null; 247 for (int i = 0; i < loadedPanel.size(); i++) { 248 LayoutEditor tmp = (LayoutEditor) loadedPanel.get(i); 249 if (tmp.getLayoutName().equals(panelName)) { 250 panel = tmp; 251 break; 252 } 253 } 254 if (panel != null) { 255 List<Element> sourceList = panelList.get(k).getChildren("source"); // NOI18N 256 for (int i = 0; i < sourceList.size(); i++) { 257 String sourceType = sourceList.get(i).getAttribute("type").getValue(); // NOI18N 258 String sourceItem = sourceList.get(i).getAttribute("item").getValue(); // NOI18N 259 NamedBean source = null; 260 switch (sourceType) { 261 case "signalMast": // NOI18N 262 source = InstanceManager.getDefault(SignalMastManager.class).getSignalMast(sourceItem); 263 break; 264 case "sensor": // NOI18N 265 source = InstanceManager.getDefault(SensorManager.class).getSensor(sourceItem); 266 break; 267 case "signalHead": // NOI18N 268 source = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(sourceItem); 269 break; 270 default: 271 break; 272 } 273 274 //These two could be subbed off. 275 List<Element> destinationList = sourceList.get(i).getChildren("destination"); // NOI18N 276 if (destinationList.size() > 0) { 277 eep.addNXSourcePoint(source, panel); 278 } 279 for (int j = 0; j < destinationList.size(); j++) { 280 String id = null; 281 if (destinationList.get(j).getAttribute("uniqueid") != null) { // NOI18N 282 id = destinationList.get(j).getAttribute("uniqueid").getValue(); // NOI18N 283 if (!id.startsWith("IN:")) { // NOI18N 284 id = "IN:" + id; // NOI18N 285 } 286 } 287 String destType = destinationList.get(j).getAttribute("type").getValue(); // NOI18N 288 String destItem = destinationList.get(j).getAttribute("item").getValue(); // NOI18N 289 NamedBean dest = null; 290 switch (destType) { 291 case "signalMast": // NOI18N 292 dest = InstanceManager.getDefault(SignalMastManager.class).getSignalMast(destItem); 293 break; 294 case "sensor": // NOI18N 295 dest = InstanceManager.getDefault(SensorManager.class).getSensor(destItem); 296 break; 297 case "signalHead": // NOI18N 298 dest = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(destItem); 299 break; 300 default: 301 break; 302 } 303 try { 304 eep.addNXDestination(source, dest, panel, id); 305 } catch (java.lang.NullPointerException e) { 306 log.error("An error occurred while trying to add a point"); // NOI18N 307 } 308 if ((destinationList.get(j).getAttribute("uniDirection") != null) && (destinationList.get(j).getAttribute("uniDirection").getValue().equals("no"))) { // NOI18N 309 eep.setUniDirection(source, panel, dest, false); 310 } 311 if ((destinationList.get(j).getAttribute("enabled") != null) && (destinationList.get(j).getAttribute("enabled").getValue().equals("no"))) { // NOI18N 312 eep.setEnabled(source, panel, dest, false); 313 } 314 if (destinationList.get(j).getAttribute("nxType") != null) { // NOI18N 315 String nxType = destinationList.get(j).getAttribute("nxType").getValue(); // NOI18N 316 switch (nxType) { 317 case "turnoutsetting": // NOI18N 318 eep.setEntryExitType(source, panel, dest, 0x00); 319 break; 320 case "signalmastlogic": // NOI18N 321 eep.setEntryExitType(source, panel, dest, 0x01); 322 break; 323 case "fullinterlocking": // NOI18N 324 eep.setEntryExitType(source, panel, dest, 0x02); 325 break; 326 default: 327 break; 328 } 329 330 } 331 } 332 } 333 } else { 334 log.error("Panel has not been loaded"); // NOI18N 335 } 336 } 337 return true; 338 } 339 340 @Override 341 public int loadOrder() { 342 return InstanceManager.getDefault(EntryExitPairs.class).getXMLOrder(); 343 } 344 345 private final static Logger log = LoggerFactory.getLogger(EntryExitPairsXml.class); 346}