001package jmri.managers.configurexml; 002 003import java.util.Hashtable; 004import java.util.List; 005import jmri.Block; 006import jmri.InstanceManager; 007import jmri.NamedBeanHandle; 008import jmri.Section; 009import jmri.Sensor; 010import jmri.SignalMast; 011import jmri.SignalMastLogic; 012import jmri.SignalMastLogicManager; 013import jmri.SignalMastManager; 014import jmri.Turnout; 015import org.jdom2.Element; 016import org.slf4j.Logger; 017import org.slf4j.LoggerFactory; 018 019/** 020 * 021 * @author kevin 022 */ 023public class DefaultSignalMastLogicManagerXml extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML { 024 025 public DefaultSignalMastLogicManagerXml() { 026 } 027 028 protected jmri.NamedBeanHandleManager nbhm = jmri.InstanceManager.getDefault(jmri.NamedBeanHandleManager.class); 029 030 @Override 031 public Element store(Object o) { 032 Element signalMastLogic = new Element("signalmastlogics"); 033 setStoreElementClass(signalMastLogic); 034 SignalMastLogicManager smlm = (SignalMastLogicManager) o; 035 signalMastLogic.addContent(new Element("logicDelay").addContent(Long.toString(smlm.getSignalLogicDelay()))); 036 List<SignalMastLogic> smll = smlm.getSignalMastLogicList(); 037 for (SignalMastLogic sml : smll) { 038 039 List<SignalMast> destinations = sml.getDestinationList(); 040 041 // write in consistent order 042 java.util.Comparator<SignalMast> comparator = new jmri.util.NamedBeanComparator<>(); 043 java.util.Collections.sort(destinations, comparator); 044 045 if (destinations.isEmpty()) { 046 log.warn("Empty SML for source mast {} skipped", sml.getSourceMast().getDisplayName()); 047 continue; 048 } 049 Element source = new Element("signalmastlogic"); 050 source.setAttribute("source", sml.getSourceMast().getDisplayName());// added purely to make human reading of the xml easier 051 source.addContent(new Element("sourceSignalMast").addContent(sml.getSourceMast().getDisplayName())); 052 for (SignalMast dest : destinations) { 053 if (sml.getStoreState(dest) != SignalMastLogic.STORENONE) { 054 Element elem = new Element("destinationMast"); 055 elem.setAttribute("destination", dest.getDisplayName()); // added purely to make human reading of the xml easier 056 elem.addContent(new Element("destinationSignalMast").addContent(dest.getDisplayName())); 057 elem.addContent(new Element("comment").addContent(sml.getComment(dest))); 058 if (sml.isEnabled(dest)) { 059 elem.addContent(new Element("enabled").addContent("yes")); 060 } else { 061 elem.addContent(new Element("enabled").addContent("no")); 062 } 063 064 if (sml.allowAutoMaticSignalMastGeneration(dest)) { 065 elem.addContent(new Element("allowAutoMaticSignalMastGeneration").addContent("yes")); 066 } else { 067 elem.addContent(new Element("allowAutoMaticSignalMastGeneration").addContent("no")); 068 } 069 070 if (sml.useLayoutEditor(dest)) { 071 elem.addContent(new Element("useLayoutEditor").addContent("yes")); 072 } else { 073 elem.addContent(new Element("useLayoutEditor").addContent("no")); 074 } 075 076 if (sml.useLayoutEditorTurnouts(dest)) { 077 elem.addContent(new Element("useLayoutEditorTurnouts").addContent("yes")); 078 } else { 079 elem.addContent(new Element("useLayoutEditorTurnouts").addContent("no")); 080 } 081 082 if (sml.useLayoutEditorBlocks(dest)) { 083 elem.addContent(new Element("useLayoutEditorBlocks").addContent("yes")); 084 } else { 085 elem.addContent(new Element("useLayoutEditorBlocks").addContent("no")); 086 } 087 088 if (sml.getAssociatedSection(dest) != null) { 089 elem.addContent(new Element("associatedSection").addContent(sml.getAssociatedSection(dest).getDisplayName())); 090 } 091 if (sml.isTurnoutLockAllowed(dest)) { 092 elem.addContent(new Element("lockTurnouts").addContent("yes")); 093 } else { 094 elem.addContent(new Element("lockTurnouts").addContent("no")); 095 } 096 097 if (sml.getStoreState(dest) == SignalMastLogic.STOREALL) { 098 List<Block> blocks = sml.getBlocks(dest); 099 100 // write in consistent order 101 java.util.Comparator<Block> blockComp = new jmri.util.NamedBeanComparator<>(); 102 java.util.Collections.sort(blocks, blockComp); 103 104 if (blocks.size() > 0) { 105 Element blockElement = new Element("blocks"); 106 for (Block bl : blocks) { 107 Element bloc = new Element("block"); 108 bloc.addContent(new Element("blockName").addContent(bl.getDisplayName())); 109 String blkState = "anyState"; 110 if (sml.getBlockState(bl, dest) == Block.OCCUPIED) { 111 blkState = "occupied"; 112 } else if (sml.getBlockState(bl, dest) == Block.UNOCCUPIED) { 113 blkState = "unoccupied"; 114 } 115 bloc.addContent(new Element("blockState").addContent(blkState)); 116 blockElement.addContent(bloc); 117 } 118 elem.addContent(blockElement); 119 } 120 121 List<NamedBeanHandle<Turnout>> turnouts = sml.getNamedTurnouts(dest); 122 123 // write in consistent order 124 java.util.Comparator<NamedBeanHandle<Turnout>> turnoutComp = new jmri.util.NamedBeanHandleComparator<>(); 125 java.util.Collections.sort(turnouts, turnoutComp); 126 127 if (turnouts.size() > 0) { 128 Element turnoutElement = new Element("turnouts"); 129 for (NamedBeanHandle<Turnout> t : turnouts) { 130 Element turn = new Element("turnout"); 131 turn.addContent(new Element("turnoutName").addContent(t.getName())); 132 String turnState = "thrown"; 133 if (sml.getTurnoutState(t.getBean(), dest) == Turnout.CLOSED) { 134 turnState = "closed"; 135 } 136 turn.addContent(new Element("turnoutState").addContent(turnState)); 137 turnoutElement.addContent(turn); 138 } 139 elem.addContent(turnoutElement); 140 } 141 142 List<NamedBeanHandle<Sensor>> sensors = sml.getNamedSensors(dest); 143 144 // write in consistent order 145 java.util.Comparator<NamedBeanHandle<Sensor>> sensorsComp = new jmri.util.NamedBeanHandleComparator<>(); 146 java.util.Collections.sort(sensors, sensorsComp); 147 148 if (sensors.size() > 0) { 149 Element sensorElement = new Element("sensors"); 150 for (NamedBeanHandle<Sensor> s : sensors) { 151 Element sensor = new Element("sensor"); 152 sensor.addContent(new Element("sensorName").addContent(s.getName())); 153 String sensorState = "inActive"; 154 if (sml.getSensorState(s.getBean(), dest) == Sensor.ACTIVE) { 155 sensorState = "active"; 156 } 157 sensor.addContent(new Element("sensorState").addContent(sensorState)); 158 sensorElement.addContent(sensor); 159 } 160 elem.addContent(sensorElement); 161 } 162 163 List<SignalMast> masts = sml.getSignalMasts(dest); 164 165 // write in consistent order 166 java.util.Comparator<SignalMast> mastComp = new jmri.util.NamedBeanComparator<>(); 167 java.util.Collections.sort(masts, mastComp); 168 169 if (masts.size() > 0) { 170 Element mastElement = new Element("masts"); 171 for (SignalMast sm : masts) { 172 Element mast = new Element("mast"); 173 mast.addContent(new Element("mastName").addContent(sm.getDisplayName())); 174 mast.addContent(new Element("mastState").addContent(sml.getSignalMastState(sm, dest))); 175 mastElement.addContent(mast); 176 } 177 elem.addContent(mastElement); 178 } 179 } 180 source.addContent(elem); 181 } 182 } 183 signalMastLogic.addContent(source); 184 } 185 return signalMastLogic; 186 } 187 188 public void setStoreElementClass(Element signalMastLogic) { 189 signalMastLogic.setAttribute("class", "jmri.managers.configurexml.DefaultSignalMastLogicManagerXml"); 190 } 191 192 @Override 193 public void load(Element element, Object o) { 194 log.error("Invalid method called"); 195 } 196 197 @Override 198 public boolean load(Element shared, Element perNode) { 199 // load individual Transits 200 return loadSignalMastLogic(shared); 201 } 202 203 public boolean loadSignalMastLogic(Element signalMastLogic) { 204 List<Element> logicList = signalMastLogic.getChildren("signalmastlogic"); 205 log.debug("Found {} signal mast logics", logicList.size()); 206 207 SignalMastManager sm = InstanceManager.getDefault(jmri.SignalMastManager.class); 208 SignalMastLogicManager smlm = InstanceManager.getDefault(jmri.SignalMastLogicManager.class); 209 try { 210 String logicDelay = signalMastLogic.getChild("logicDelay").getText(); 211 smlm.setSignalLogicDelay(Integer.parseInt(logicDelay)); 212 } catch (java.lang.NullPointerException e) { 213 //Considered normal if it doesn't exists 214 } 215 boolean loadOk = true; 216 for (Element sml : logicList) { 217 String source = sml.getChild("sourceSignalMast").getText(); 218 SignalMast sourceMast = sm.getSignalMast(source); 219 if (sourceMast != null) { 220 SignalMastLogic logic = smlm.newSignalMastLogic(sourceMast); 221 List<Element> destList = sml.getChildren("destinationMast"); 222 for (Element d : destList) { 223 String destination = d.getChild("destinationSignalMast").getText(); 224 SignalMast dest = sm.getSignalMast(destination); 225 if (dest != null) { 226 logic.setDestinationMast(dest); 227 if (d.getChild("comment") != null) { 228 logic.setComment(d.getChild("comment").getText(), dest); 229 } 230 if (d.getChild("enabled") != null) { 231 if (d.getChild("enabled").getText().equals("yes")) { 232 logic.setEnabled(dest); 233 } else { 234 logic.setDisabled(dest); 235 } 236 } 237 238 if (d.getChild("allowAutoMaticSignalMastGeneration") != null) { 239 if (d.getChild("allowAutoMaticSignalMastGeneration").getText().equals("no")) { 240 logic.allowAutoMaticSignalMastGeneration(false, dest); 241 } else { 242 logic.allowAutoMaticSignalMastGeneration(true, dest); 243 } 244 } 245 246 boolean useLayoutEditorTurnout = true; 247 boolean useLayoutEditorBlock = true; 248 if (d.getChild("useLayoutEditorTurnouts") != null) { 249 if (d.getChild("useLayoutEditorTurnouts").getText().equals("no")) { 250 useLayoutEditorTurnout = false; 251 } 252 } 253 254 if (d.getChild("useLayoutEditorBlocks") != null) { 255 if (d.getChild("useLayoutEditorBlocks").getText().equals("no")) { 256 useLayoutEditorBlock = false; 257 } 258 } 259 try { 260 logic.useLayoutEditorDetails(useLayoutEditorTurnout, useLayoutEditorBlock, dest); 261 } catch (jmri.JmriException ex) { 262 log.error("use LayoutEditor details failed"); 263 } 264 265 if (d.getChild("useLayoutEditor") != null) { 266 try { 267 if (d.getChild("useLayoutEditor").getText().equals("yes")) { 268 logic.useLayoutEditor(true, dest); 269 } else { 270 logic.useLayoutEditor(false, dest); 271 } 272 } catch (jmri.JmriException e) { 273 //Considered normal if layout editor hasn't yet been set up. 274 } 275 } 276 277 if (d.getChild("associatedSection") != null) { 278 Section sect = InstanceManager.getDefault(jmri.SectionManager.class).getSection(d.getChild("associatedSection").getText()); 279 logic.setAssociatedSection(sect, dest); 280 } 281 282 Element turnoutElem = d.getChild("turnouts"); 283 if (turnoutElem != null) { 284 List<Element> turnoutList = turnoutElem.getChildren("turnout"); 285 if (turnoutList.size() > 0) { 286 Hashtable<NamedBeanHandle<Turnout>, Integer> list = new Hashtable<>(); 287 for (Element t : turnoutList) { 288 String turnout = t.getChild("turnoutName").getText(); 289 String state = t.getChild("turnoutState").getText(); 290 int value = Turnout.CLOSED; 291 if (state.equals("thrown")) { 292 value = Turnout.THROWN; 293 } 294 Turnout turn = InstanceManager.turnoutManagerInstance().getTurnout(turnout); 295 if (turn != null) { 296 NamedBeanHandle<Turnout> namedTurnout = nbhm.getNamedBeanHandle(turnout, turn); 297 list.put(namedTurnout, value); 298 } 299 log.debug("Unable to add Turnout {} as it does not exist in the panel file", turnout); 300 } 301 logic.setTurnouts(list, dest); 302 } 303 } 304 Element sensorElem = d.getChild("sensors"); 305 if (sensorElem != null) { 306 List<Element> sensorList = sensorElem.getChildren("sensor"); 307 if (sensorList.size() > 0) { 308 Hashtable<NamedBeanHandle<Sensor>, Integer> list = new Hashtable<>(); 309 for (Element sl : sensorList) { 310 String sensorName = sl.getChild("sensorName").getText(); 311 String state = sl.getChild("sensorState").getText(); 312 int value = Sensor.INACTIVE; 313 if (state.equals("active")) { 314 value = Sensor.ACTIVE; 315 } 316 317 Sensor sen = InstanceManager.sensorManagerInstance().getSensor(sensorName); 318 if (sen != null) { 319 NamedBeanHandle<Sensor> namedSensor = nbhm.getNamedBeanHandle(sensorName, sen); 320 list.put(namedSensor, value); 321 } 322 log.debug("Unable to add sensor {} as it does not exist in the panel file", sensorName); 323 } 324 logic.setSensors(list, dest); 325 } 326 } 327 Element blockElem = d.getChild("blocks"); 328 if (blockElem != null) { 329 List<Element> blockList = blockElem.getChildren("block"); 330 if (blockList.size() > 0) { 331 Hashtable<Block, Integer> list = new Hashtable<>(); 332 for (Element b : blockList) { 333 String block = b.getChild("blockName").getText(); 334 String state = b.getChild("blockState").getText(); 335 int value = 0x03; 336 if (state.equals("occupied")) { 337 value = Block.OCCUPIED; 338 } else if (state.equals("unoccupied")) { 339 value = Block.UNOCCUPIED; 340 } 341 342 Block blk = InstanceManager.getDefault(jmri.BlockManager.class).getBlock(block); 343 if (blk != null) { 344 list.put(blk, value); 345 } 346 log.debug("Unable to add Block {} as it does not exist in the panel file", block); 347 } 348 logic.setBlocks(list, dest); 349 } 350 } 351 Element mastElem = d.getChild("masts"); 352 if (mastElem != null) { 353 List<Element> mastList = mastElem.getChildren("mast"); 354 if (mastList.size() > 0) { 355 Hashtable<SignalMast, String> list = new Hashtable<>(); 356 for (Element m : mastList) { 357 String mast = m.getChild("mastName").getText(); 358 String state = m.getChild("mastState").getText(); 359 SignalMast mst = InstanceManager.getDefault(jmri.SignalMastManager.class).getSignalMast(mast); 360 if (mst != null) { 361 list.put(mst, state); 362 } 363 log.debug("Unable to add Signal Mast {} as it does not exist in the panel file", mast); 364 } 365 logic.setMasts(list, dest); 366 } 367 } 368 } else { 369 log.error("Destination Mast {} not found, logic not loaded", destination); 370 loadOk = false; 371 } 372 } 373 } else { 374 log.error("Source Mast {} Not found, logic not loaded", source); 375 loadOk = false; 376 } 377 } 378 smlm.initialise(); 379 return loadOk; 380 } 381 382 @Override 383 public int loadOrder() { 384 return InstanceManager.getDefault(jmri.SignalMastLogicManager.class).getXMLOrder(); 385 } 386 387 private final static Logger log = LoggerFactory.getLogger(DefaultSignalMastLogicManagerXml.class); 388 389}