001package jmri.jmrit.ctc.configurexml; 002 003import java.util.*; 004 005import jmri.*; 006import jmri.jmrit.ctc.*; 007import jmri.jmrit.ctc.editor.code.*; 008import jmri.jmrit.ctc.ctcserialdata.*; 009 010import org.jdom2.Element; 011import org.slf4j.Logger; 012import org.slf4j.LoggerFactory; 013 014/** 015 * Provides the functionality for persistence of the CTC tool data. The data is stored 016 * in the PanelPro data xml file using the standard Load/Store process. 017 * 018 * @author Dave Sand Copyright (c) 2020 019 */ 020public class CtcManagerXml extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML { 021 CtcManager cm = InstanceManager.getDefault(CtcManager.class); 022 023 public CtcManagerXml() { 024 } 025 026 /** 027 * Implementation for storing the contents of the CTC configuration. 028 * 029 * @param o Object to store, of type CtcManager 030 * @return Element containing the complete info 031 */ 032 @Override 033 public Element store(Object o) { 034 Element ctcdata = new Element("ctcdata"); 035 setStoreElementClass(ctcdata); 036 037 ctcdata.addContent(storeProperties(cm)); 038 ctcdata.addContent(storeOtherData(cm)); 039 for (CodeButtonHandlerData cbhd : cm.getCTCSerialData().getCodeButtonHandlerDataArrayList()) { 040 Element cbhdElement = new Element("ctcCodeButtonData"); 041 042 cbhdElement.addContent(storeInt("UniqueID", cbhd._mUniqueID)); 043 cbhdElement.addContent(storeInt("SwitchNumber", cbhd._mSwitchNumber)); 044 cbhdElement.addContent(storeInt("SignalEtcNumber", cbhd._mSignalEtcNumber)); 045 cbhdElement.addContent(storeInt("GUIColumnNumber", cbhd._mGUIColumnNumber)); 046 047 // Code section 048 cbhdElement.addContent(storeSensor("CodeButtonInternalSensor", cbhd._mCodeButtonInternalSensor)); 049 cbhdElement.addContent(storeSensor("OSSectionOccupiedExternalSensor", cbhd._mOSSectionOccupiedExternalSensor)); 050 cbhdElement.addContent(storeSensor("OSSectionOccupiedExternalSensor2", cbhd._mOSSectionOccupiedExternalSensor2)); 051 cbhdElement.addContent(storeInt("OSSectionSwitchSlavedToUniqueID", cbhd._mOSSectionSwitchSlavedToUniqueID)); 052 cbhdElement.addContent(storeBoolean("GUIGeneratedAtLeastOnceAlready", cbhd._mGUIGeneratedAtLeastOnceAlready)); 053 cbhdElement.addContent(storeInt("CodeButtonDelayTime", cbhd._mCodeButtonDelayTime)); 054 055 // SIDI section 056 cbhdElement.addContent(storeBoolean("SIDI_Enabled", cbhd._mSIDI_Enabled)); 057 cbhdElement.addContent(storeSensor("SIDI_LeftInternalSensor", cbhd._mSIDI_LeftInternalSensor)); 058 cbhdElement.addContent(storeSensor("SIDI_NormalInternalSensor", cbhd._mSIDI_NormalInternalSensor)); 059 cbhdElement.addContent(storeSensor("SIDI_RightInternalSensor", cbhd._mSIDI_RightInternalSensor)); 060 cbhdElement.addContent(storeInt("SIDI_CodingTimeInMilliseconds", cbhd._mSIDI_CodingTimeInMilliseconds)); 061 cbhdElement.addContent(storeInt("SIDI_TimeLockingTimeInMilliseconds", cbhd._mSIDI_TimeLockingTimeInMilliseconds)); 062 cbhdElement.addContent(storeString("SIDI_TrafficDirection", cbhd._mSIDI_TrafficDirection.toString())); 063 cbhdElement.addContent(storeSignalList("SIDI_LeftRightTrafficSignals", cbhd._mSIDI_LeftRightTrafficSignals)); 064 cbhdElement.addContent(storeSignalList("SIDI_RightLeftTrafficSignals", cbhd._mSIDI_RightLeftTrafficSignals)); 065 066 // SIDL section 067 cbhdElement.addContent(storeBoolean("SIDL_Enabled", cbhd._mSIDL_Enabled)); 068 cbhdElement.addContent(storeSensor("SIDL_LeftInternalSensor", cbhd._mSIDL_LeftInternalSensor)); 069 cbhdElement.addContent(storeSensor("SIDL_NormalInternalSensor", cbhd._mSIDL_NormalInternalSensor)); 070 cbhdElement.addContent(storeSensor("SIDL_RightInternalSensor", cbhd._mSIDL_RightInternalSensor)); 071 072 // SWDI section 073 cbhdElement.addContent(storeBoolean("SWDI_Enabled", cbhd._mSWDI_Enabled)); 074 cbhdElement.addContent(storeSensor("SWDI_NormalInternalSensor", cbhd._mSWDI_NormalInternalSensor)); 075 cbhdElement.addContent(storeSensor("SWDI_ReversedInternalSensor", cbhd._mSWDI_ReversedInternalSensor)); 076 cbhdElement.addContent(storeTurnout("SWDI_ExternalTurnout", cbhd._mSWDI_ExternalTurnout)); 077 cbhdElement.addContent(storeInt("SWDI_CodingTimeInMilliseconds", cbhd._mSWDI_CodingTimeInMilliseconds)); 078 cbhdElement.addContent(storeBoolean("SWDI_FeedbackDifferent", cbhd._mSWDI_FeedbackDifferent)); 079 cbhdElement.addContent(storeInt("SWDI_GUITurnoutType", cbhd._mSWDI_GUITurnoutType.getInt())); 080 cbhdElement.addContent(storeBoolean("SWDI_GUITurnoutLeftHand", cbhd._mSWDI_GUITurnoutLeftHand)); 081 cbhdElement.addContent(storeBoolean("SWDI_GUICrossoverLeftHand", cbhd._mSWDI_GUICrossoverLeftHand)); 082 083 // SWDL section 084 cbhdElement.addContent(storeBoolean("SWDL_Enabled", cbhd._mSWDL_Enabled)); 085 cbhdElement.addContent(storeSensor("SWDL_InternalSensor", cbhd._mSWDL_InternalSensor)); 086 087 // CO section 088 cbhdElement.addContent(storeBoolean("CO_Enabled", cbhd._mCO_Enabled)); 089 cbhdElement.addContent(storeSensor("CO_CallOnToggleInternalSensor", cbhd._mCO_CallOnToggleInternalSensor)); 090 cbhdElement.addContent(storeCallOnList("CO_GroupingsList", cbhd._mCO_GroupingsList)); 091 092 // TRL section 093 cbhdElement.addContent(storeBoolean("TRL_Enabled", cbhd._mTRL_Enabled)); 094 cbhdElement.addContent(storeTRLRules("TRL_LeftRules", cbhd._mTRL_LeftTrafficLockingRules)); 095 cbhdElement.addContent(storeTRLRules("TRL_RightRules", cbhd._mTRL_RightTrafficLockingRules)); 096 097 // TUL section 098 cbhdElement.addContent(storeBoolean("TUL_Enabled", cbhd._mTUL_Enabled)); 099 cbhdElement.addContent(storeSensor("TUL_DispatcherInternalSensorLockToggle", cbhd._mTUL_DispatcherInternalSensorLockToggle)); 100 cbhdElement.addContent(storeTurnout("TUL_ExternalTurnout", cbhd._mTUL_ExternalTurnout)); 101 cbhdElement.addContent(storeBoolean("TUL_ExternalTurnoutFeedbackDifferent", cbhd._mTUL_ExternalTurnoutFeedbackDifferent)); 102 cbhdElement.addContent(storeSensor("TUL_DispatcherInternalSensorUnlockedIndicator", cbhd._mTUL_DispatcherInternalSensorUnlockedIndicator)); 103 cbhdElement.addContent(storeBoolean("TUL_NoDispatcherControlOfSwitch", cbhd._mTUL_NoDispatcherControlOfSwitch)); 104 cbhdElement.addContent(storeBoolean("TUL_ndcos_WhenLockedSwitchStateIsClosed", cbhd._mTUL_ndcos_WhenLockedSwitchStateIsClosed)); 105 cbhdElement.addContent(storeBoolean("TUL_GUI_IconsEnabled", cbhd._mTUL_GUI_IconsEnabled)); 106 cbhdElement.addContent(storeInt("TUL_LockImplementation", cbhd._mTUL_LockImplementation.getInt())); 107 cbhdElement.addContent(storeTULAdditionalTurnouts("TUL_AdditionalExternalTurnouts", cbhd)); 108 109 // IL section 110 cbhdElement.addContent(storeBoolean("IL_Enabled", cbhd._mIL_Enabled)); 111 cbhdElement.addContent(storeSignalList("IL_Signals", cbhd._mIL_Signals)); 112 113 ctcdata.addContent(cbhdElement); 114 } 115 116 return (ctcdata); 117 } 118 119 /** 120 * Subclass provides implementation to create the correct top element, 121 * including the type information. Default implementation is to use the 122 * local class here. 123 * 124 * @param ctcdata The top-level element being created 125 */ 126 public void setStoreElementClass(Element ctcdata) { 127 ctcdata.setAttribute("class", "jmri.jmrit.ctc.configurexml.CtcManagerXml"); 128 } 129 130 Element storeProperties(CtcManager cm) { 131 ProgramProperties pp = cm.getProgramProperties(); 132 133 Element properties = new Element("ctcProperties"); 134 properties.addContent(storeString("CodeButtonInternalSensorPattern", pp._mCodeButtonInternalSensorPattern)); 135 properties.addContent(storeInt("SIDI_CodingTimeInMilliseconds", pp._mSIDI_CodingTimeInMilliseconds)); 136 properties.addContent(storeString("SIDI_LeftInternalSensorPattern", pp._mSIDI_LeftInternalSensorPattern)); 137 properties.addContent(storeString("SIDI_NormalInternalSensorPattern", pp._mSIDI_NormalInternalSensorPattern)); 138 properties.addContent(storeString("SIDI_RightInternalSensorPattern", pp._mSIDI_RightInternalSensorPattern)); 139 properties.addContent(storeInt("SIDI_TimeLockingTimeInMilliseconds", pp._mSIDI_TimeLockingTimeInMilliseconds)); 140 properties.addContent(storeString("SIDL_LeftInternalSensorPattern", pp._mSIDL_LeftInternalSensorPattern)); 141 properties.addContent(storeString("SIDL_NormalInternalSensorPattern", pp._mSIDL_NormalInternalSensorPattern)); 142 properties.addContent(storeString("SIDL_RightInternalSensorPattern", pp._mSIDL_RightInternalSensorPattern)); 143 properties.addContent(storeInt("SWDI_CodingTimeInMilliseconds", pp._mSWDI_CodingTimeInMilliseconds)); 144 properties.addContent(storeString("SWDI_NormalInternalSensorPattern", pp._mSWDI_NormalInternalSensorPattern)); 145 properties.addContent(storeString("SWDI_ReversedInternalSensorPattern", pp._mSWDI_ReversedInternalSensorPattern)); 146 properties.addContent(storeString("SWDL_InternalSensorPattern", pp._mSWDL_InternalSensorPattern)); 147 properties.addContent(storeString("CO_CallOnToggleInternalSensorPattern", pp._mCO_CallOnToggleInternalSensorPattern)); 148 properties.addContent(storeString("TUL_DispatcherInternalSensorLockTogglePattern", pp._mTUL_DispatcherInternalSensorLockTogglePattern)); 149 properties.addContent(storeString("TUL_DispatcherInternalSensorUnlockedIndicatorPattern", pp._mTUL_DispatcherInternalSensorUnlockedIndicatorPattern)); 150 properties.addContent(storeInt("CodeButtonDelayTime", pp._mCodeButtonDelayTime)); 151 152 return properties; 153 } 154 155 Element storeOtherData(CtcManager cm) { 156 OtherData od = cm.getOtherData(); 157 158 Element otherData = new Element("ctcOtherData"); 159 160 otherData.addContent(storeString("CtcVersion", OtherData.CTC_VERSION)); 161 162// Fleeting: 163 otherData.addContent(storeSensor("FleetingToggleInternalSensor", od._mFleetingToggleInternalSensor)); 164 otherData.addContent(storeBoolean("DefaultFleetingEnabled", od._mDefaultFleetingEnabled)); 165 166// Global startup: 167 otherData.addContent(storeBoolean("TUL_EnabledAtStartup", od._mTUL_EnabledAtStartup)); 168 otherData.addContent(storeInt("SignalSystemType", od._mSignalSystemType.getInt())); 169 otherData.addContent(storeInt("TUL_SecondsToLockTurnouts", od._mTUL_SecondsToLockTurnouts)); 170 171// Next unique # for each created Column: 172 otherData.addContent(storeInt("NextUniqueNumber", od._mNextUniqueNumber)); 173 174// CTC Debugging: 175 otherData.addContent(storeSensor("CTCDebugSystemReloadInternalSensor", od._mCTCDebugSystemReloadInternalSensor)); 176 otherData.addContent(storeSensor("CTCDebug_TrafficLockingRuleTriggeredDisplayInternalSensor", od._mCTCDebug_TrafficLockingRuleTriggeredDisplayInternalSensor)); 177 178// GUI design: 179 otherData.addContent(storeInt("GUIDesign_NumberOfEmptyColumnsAtEnd", od._mGUIDesign_NumberOfEmptyColumnsAtEnd)); 180 otherData.addContent(storeInt("GUIDesign_CTCPanelType", od._mGUIDesign_CTCPanelType.getRadioGroupValue())); 181 otherData.addContent(storeBoolean("GUIDesign_BuilderPlate", od._mGUIDesign_BuilderPlate)); 182 otherData.addContent(storeInt("GUIDesign_SignalsOnPanel", od._mGUIDesign_SignalsOnPanel.getRadioGroupValue())); 183 otherData.addContent(storeBoolean("GUIDesign_FleetingToggleSwitch", od._mGUIDesign_FleetingToggleSwitch)); 184 otherData.addContent(storeBoolean("GUIDesign_AnalogClockEtc", od._mGUIDesign_AnalogClockEtc)); 185 otherData.addContent(storeBoolean("GUIDesign_ReloadCTCSystemButton", od._mGUIDesign_ReloadCTCSystemButton)); 186 otherData.addContent(storeBoolean("GUIDesign_CTCDebugOnToggle", od._mGUIDesign_CTCDebugOnToggle)); 187 otherData.addContent(storeBoolean("GUIDesign_CreateTrackPieces", od._mGUIDesign_CreateTrackPieces)); 188 otherData.addContent(storeInt("GUIDesign_VerticalSize", od._mGUIDesign_VerticalSize.getRadioGroupValue())); 189 otherData.addContent(storeBoolean("GUIDesign_OSSectionUnknownInconsistentRedBlink", od._mGUIDesign_OSSectionUnknownInconsistentRedBlink)); 190 otherData.addContent(storeBoolean("GUIDesign_TurnoutsOnPanel", od._mGUIDesign_TurnoutsOnPanel)); 191 192 return otherData; 193 } 194 195 // **** Create elements for simple objects **** 196 197 Element storeString(String elementName, String elementValue) { 198 Element element = new Element(elementName); 199 element.setText(elementValue); 200 return element; 201 } 202 203 Element storeInt(String elementName, int elementValue) { 204 Element element = new Element(elementName); 205 element.setText(String.valueOf(elementValue)); 206 return element; 207 } 208 209 Element storeBoolean(String elementName, boolean elementValue) { 210 Element element = new Element(elementName); 211 element.setText(elementValue == true ? "true" : "false"); 212 return element; 213 } 214 215 Element storeSensor(String elementName, NBHSensor sensor) { 216 Element element = new Element(elementName); 217 if (sensor != null) { 218 element.setText(sensor.getHandleName()); 219 } 220 return element; 221 } 222 223 Element storeSignal(String elementName, NBHSignal signal) { 224 Element element = new Element(elementName); 225 if (signal != null) { 226 element.setText(signal.getHandleName()); 227 } 228 return element; 229 } 230 231 Element storeTurnout(String elementName, NBHTurnout turnout) { 232 Element element = new Element(elementName); 233 if (turnout != null) { 234 element.setText(turnout.getHandleName()); 235 } 236 return element; 237 } 238 239 Element storeBlock(String elementName, NamedBeanHandle<Block> block) { 240 Element element = new Element(elementName); 241 if (block != null) { 242 element.setText(block.getName()); 243 } 244 return element; 245 } 246 247 // **** Create elements for ArrayList objects **** 248 249 Element storeSensorList(String elementName, List<NBHSensor> sensors) { 250 Element element = new Element(elementName); 251 sensors.forEach(sensor -> { 252 element.addContent(storeSensor("sensor", sensor)); 253 }); 254 return element; 255 } 256 257 Element storeSignalList(String elementName, List<NBHSignal> signals) { 258 Element element = new Element(elementName); 259 signals.forEach(signal -> { 260 element.addContent(storeSignal("signal", signal)); 261 }); 262 return element; 263 } 264 265 Element storeCallOnList(String elementName, List<CallOnData> callOnList) { 266 Element element = new Element(elementName); 267 callOnList.forEach(row -> { 268 Element groupEntry = new Element("CO_GroupEntry"); 269 groupEntry.addContent(storeSignal("ExternalSignal", row._mExternalSignal)); 270 groupEntry.addContent(storeString("SignalFacingDirection", row._mSignalFacingDirection)); 271 groupEntry.addContent(storeString("SignalAspectToDisplay", row._mSignalAspectToDisplay)); 272 groupEntry.addContent(storeSensor("CalledOnExternalSensor", row._mCalledOnExternalSensor)); 273 groupEntry.addContent(storeBlock("ExternalBlock", row._mExternalBlock)); 274 groupEntry.addContent(storeSensorList("SwitchIndicators", row._mSwitchIndicators)); 275 element.addContent(groupEntry); 276 }); 277 return element; 278 } 279 280 Element storeTRLRules(String elementName, List<TrafficLockingData> trlList) { 281 Element element = new Element(elementName); 282 trlList.forEach(row -> { 283 Element ruleEntry = new Element("TRL_TrafficLockingRule"); 284 ruleEntry.addContent(storeString("UserRuleNumber", row._mUserRuleNumber)); 285 ruleEntry.addContent(storeString("RuleEnabled", row._mRuleEnabled)); 286 ruleEntry.addContent(storeString("DestinationSignalOrComment", row._mDestinationSignalOrComment)); 287 288 ruleEntry.addContent(storeTRLSwitches("switches", row._mSwitchAlignments)); 289 290 ruleEntry.addContent(storeSensorList("OccupancyExternalSensors", row._mOccupancyExternalSensors)); 291 ruleEntry.addContent(storeSensorList("OptionalExternalSensors", row._mOptionalExternalSensors)); 292 element.addContent(ruleEntry); 293 }); 294 return element; 295 } 296 297 Element storeTRLSwitches(String elementName, List<TrafficLockingData.TRLSwitch> trlSwitches) { 298 Element element = new Element(elementName); 299 trlSwitches.forEach(trlSwitch -> { 300 Element elSwitch = new Element("switch"); 301 elSwitch.addContent(storeString("UserText", trlSwitch._mUserText)); 302 elSwitch.addContent(storeString("SwitchAlignment", trlSwitch._mSwitchAlignment)); 303 elSwitch.addContent(storeInt("UniqueID", trlSwitch._mUniqueID)); 304 element.addContent(elSwitch); 305 }); 306 return element; 307 } 308 309 Element storeTULAdditionalTurnouts(String elementName, CodeButtonHandlerData cbhd) { 310 Element element = new Element(elementName); 311 312 Element elementRow = createAdditionalTurnoutEntry(cbhd._mTUL_AdditionalExternalTurnout1, cbhd._mTUL_AdditionalExternalTurnout1FeedbackDifferent); 313 if (elementRow != null) element.addContent(elementRow); 314 elementRow = createAdditionalTurnoutEntry(cbhd._mTUL_AdditionalExternalTurnout2, cbhd._mTUL_AdditionalExternalTurnout2FeedbackDifferent); 315 if (elementRow != null) element.addContent(elementRow); 316 elementRow = createAdditionalTurnoutEntry(cbhd._mTUL_AdditionalExternalTurnout3, cbhd._mTUL_AdditionalExternalTurnout3FeedbackDifferent); 317 if (elementRow != null) element.addContent(elementRow); 318 319 return element; 320 } 321 322 Element createAdditionalTurnoutEntry(NBHTurnout turnout, boolean turnoutFeedback) { 323 Element element = null; 324 if (turnout.valid()) { 325 element = new Element("TUL_AdditionalExternalTurnoutEntry"); 326 element.addContent(storeTurnout("TUL_AdditionalExternalTurnout", turnout)); 327 element.addContent(storeBoolean("TUL_AdditionalExternalTurnoutFeedbackDifferent", turnoutFeedback)); 328 } 329 return element; 330 } 331 332 @Override 333 public void load(Element element, Object o) { 334 log.error("Invalid method called"); 335 } 336 337 /** 338 * Implementation for loading the contents of the CTC configuration. 339 * 340 * @param sharedCtcData Element to loaded. 341 * @param perNodeCtcData Element to loaded (same as sharedCtcData). 342 * @return true for successful load. 343 */ 344 @Override 345 public boolean load(Element sharedCtcData, Element perNodeCtcData) { 346 List<Element> ctcList = sharedCtcData.getChildren(); 347 348 for (Element lvl1 : ctcList) { 349 if (lvl1.getName().equals("ctcProperties")) { 350 loadProperties(cm, lvl1); 351 continue; 352 } 353 if (lvl1.getName().equals("ctcOtherData")) { 354 loadOtherData(cm, lvl1); 355 continue; 356 } 357 if (lvl1.getName().equals("ctcCodeButtonData")) { 358 // Create basic CodeButtonHandlerData 359 log.debug("------------- CBHD ------------"); 360 int _mUniqueID = loadInt(lvl1.getChild("UniqueID")); 361 int _mSwitchNumber = loadInt(lvl1.getChild("SwitchNumber")); 362 int _mSignalEtcNumber = loadInt(lvl1.getChild("SignalEtcNumber")); 363 int _mGUIColumnNumber = loadInt(lvl1.getChild("GUIColumnNumber")); 364 365 // Create a new CodeButtonHandlerData via CodeButtonHandlerDataRoutines which sets default values and empty NBH... objects 366 CodeButtonHandlerData cbhd = CodeButtonHandlerDataRoutines.createNewCodeButtonHandlerData( 367 _mUniqueID, _mSwitchNumber, _mSignalEtcNumber, _mGUIColumnNumber, cm.getProgramProperties()); 368 cm.getCTCSerialData().addCodeButtonHandlerData(cbhd); 369 370 log.debug("------------- Code ------------"); 371 372 // Code section 373 cbhd._mCodeButtonInternalSensor = loadSensor(lvl1.getChild("CodeButtonInternalSensor"), true); 374 cbhd._mOSSectionOccupiedExternalSensor = loadSensor(lvl1.getChild("OSSectionOccupiedExternalSensor"), false); 375 cbhd._mOSSectionOccupiedExternalSensor2 = loadSensor(lvl1.getChild("OSSectionOccupiedExternalSensor2"), false); 376 cbhd._mOSSectionSwitchSlavedToUniqueID = loadInt(lvl1.getChild("OSSectionSwitchSlavedToUniqueID")); 377 cbhd._mGUIGeneratedAtLeastOnceAlready = loadBoolean(lvl1.getChild("GUIGeneratedAtLeastOnceAlready")); 378 cbhd._mCodeButtonDelayTime = loadInt(lvl1.getChild("CodeButtonDelayTime")); 379 log.debug("------------- SIDI ------------"); 380 381 // SIDI section 382 cbhd._mSIDI_Enabled = loadBoolean(lvl1.getChild("SIDI_Enabled")); 383 cbhd._mSIDI_LeftInternalSensor = loadSensor(lvl1.getChild("SIDI_LeftInternalSensor"), true); 384 cbhd._mSIDI_NormalInternalSensor = loadSensor(lvl1.getChild("SIDI_NormalInternalSensor"), true); 385 cbhd._mSIDI_RightInternalSensor = loadSensor(lvl1.getChild("SIDI_RightInternalSensor"), true); 386 cbhd._mSIDI_CodingTimeInMilliseconds = loadInt(lvl1.getChild("SIDI_CodingTimeInMilliseconds")); 387 cbhd._mSIDI_TimeLockingTimeInMilliseconds = loadInt(lvl1.getChild("SIDI_TimeLockingTimeInMilliseconds")); 388 cbhd._mSIDI_TrafficDirection = CodeButtonHandlerData.TRAFFIC_DIRECTION.valueOf(loadString(lvl1.getChild("SIDI_TrafficDirection"))); 389 cbhd._mSIDI_LeftRightTrafficSignals = getSignalList(lvl1.getChild("SIDI_LeftRightTrafficSignals")); 390 cbhd._mSIDI_RightLeftTrafficSignals = getSignalList(lvl1.getChild("SIDI_RightLeftTrafficSignals")); 391 392 log.debug("------------- SIDL ------------"); 393 // SIDL section 394 cbhd._mSIDL_Enabled = loadBoolean(lvl1.getChild("SIDL_Enabled")); 395 cbhd._mSIDL_LeftInternalSensor = loadSensor(lvl1.getChild("SIDL_LeftInternalSensor"), true); 396 cbhd._mSIDL_NormalInternalSensor = loadSensor(lvl1.getChild("SIDL_NormalInternalSensor"), true); 397 cbhd._mSIDL_RightInternalSensor = loadSensor(lvl1.getChild("SIDL_RightInternalSensor"), true); 398 399 log.debug("------------- SWDI ------------"); 400 // SWDI section 401 cbhd._mSWDI_Enabled = loadBoolean(lvl1.getChild("SWDI_Enabled")); 402 cbhd._mSWDI_NormalInternalSensor = loadSensor(lvl1.getChild("SWDI_NormalInternalSensor"), true); 403 cbhd._mSWDI_ReversedInternalSensor = loadSensor(lvl1.getChild("SWDI_ReversedInternalSensor"), true); 404 cbhd._mSWDI_ExternalTurnout = loadTurnout(lvl1.getChild("SWDI_ExternalTurnout"), lvl1.getChild("SWDI_FeedbackDifferent")); 405 cbhd._mSWDI_CodingTimeInMilliseconds = loadInt(lvl1.getChild("SWDI_CodingTimeInMilliseconds")); 406 cbhd._mSWDI_FeedbackDifferent = loadBoolean(lvl1.getChild("SWDI_FeedbackDifferent")); 407 cbhd._mSWDI_GUITurnoutType = CodeButtonHandlerData.TURNOUT_TYPE.getTurnoutType(loadInt(lvl1.getChild("SWDI_GUITurnoutType"))); 408 cbhd._mSWDI_GUITurnoutLeftHand = loadBoolean(lvl1.getChild("SWDI_GUITurnoutLeftHand")); 409 cbhd._mSWDI_GUICrossoverLeftHand = loadBoolean(lvl1.getChild("SWDI_GUICrossoverLeftHand")); 410 411 log.debug("------------- SWDL ------------"); 412 // SWDL section 413 cbhd._mSWDL_Enabled = loadBoolean(lvl1.getChild("SWDL_Enabled")); 414 cbhd._mSWDL_InternalSensor = loadSensor(lvl1.getChild("SWDL_InternalSensor"), true); 415 416 log.debug("------------- CO ------------"); 417 // CO section 418 cbhd._mCO_Enabled = loadBoolean(lvl1.getChild("CO_Enabled")); 419 cbhd._mCO_CallOnToggleInternalSensor = loadSensor(lvl1.getChild("CO_CallOnToggleInternalSensor"), true); 420 cbhd._mCO_GroupingsList = getCallOnList(lvl1.getChild("CO_GroupingsList")); 421 422 log.debug("------------- TRL ------------"); 423 // TRL section 424 cbhd._mTRL_Enabled = loadBoolean(lvl1.getChild("TRL_Enabled")); 425 cbhd._mTRL_LeftTrafficLockingRules = getTrafficLocking(lvl1.getChild("TRL_LeftRules")); 426 cbhd._mTRL_RightTrafficLockingRules = getTrafficLocking(lvl1.getChild("TRL_RightRules")); 427 428 log.debug("------------- TUL ------------"); 429 // TUL section 430 cbhd._mTUL_Enabled = loadBoolean(lvl1.getChild("TUL_Enabled")); 431 cbhd._mTUL_DispatcherInternalSensorLockToggle = loadSensor(lvl1.getChild("TUL_DispatcherInternalSensorLockToggle"), true); 432 cbhd._mTUL_ExternalTurnout = loadTurnout(lvl1.getChild("TUL_ExternalTurnout"), lvl1.getChild("TUL_ExternalTurnoutFeedbackDifferent")); 433 cbhd._mTUL_ExternalTurnoutFeedbackDifferent = loadBoolean(lvl1.getChild("TUL_ExternalTurnoutFeedbackDifferent")); 434 cbhd._mTUL_DispatcherInternalSensorUnlockedIndicator = loadSensor(lvl1.getChild("TUL_DispatcherInternalSensorUnlockedIndicator"), true); 435 cbhd._mTUL_NoDispatcherControlOfSwitch = loadBoolean(lvl1.getChild("TUL_NoDispatcherControlOfSwitch")); 436 cbhd._mTUL_ndcos_WhenLockedSwitchStateIsClosed = loadBoolean(lvl1.getChild("TUL_ndcos_WhenLockedSwitchStateIsClosed")); 437 cbhd._mTUL_GUI_IconsEnabled = loadBoolean(lvl1.getChild("TUL_GUI_IconsEnabled")); 438 cbhd._mTUL_LockImplementation = CodeButtonHandlerData.LOCK_IMPLEMENTATION.getLockImplementation(loadInt(lvl1.getChild("TUL_LockImplementation"))); 439 loadAdditionalTurnouts(lvl1.getChild("TUL_AdditionalExternalTurnouts"), cbhd); 440 441 log.debug("------------- IL ------------"); 442 // IL section 443 cbhd._mIL_Enabled = loadBoolean(lvl1.getChild("IL_Enabled")); 444 cbhd._mIL_Signals = getSignalList(lvl1.getChild("IL_Signals")); 445 446// Debugging aid -- not active due to SpotBugs 447// log.info("CodeButtonHandlerData, {}/{}:", _mSwitchNumber, _mSignalEtcNumber); 448// List<Field> fields = Arrays.asList(CodeButtonHandlerData.class.getFields()); 449// fields.forEach(field -> { 450// try { 451// log.info(" CBHD: fld = {}, type = {}, val = {}", field.getName(), field.getType(), field.get(cbhd)); 452// } catch (Exception ex) { 453// log.info(" CBHD list exception: {}", ex.getMessage()); 454// } 455// }); 456 } 457 } 458 convertCallOnSensorNamesToNBHSensors(cm); 459 return true; 460 } 461 462 /** 463 * Load the ProgramProperties class. 464 * @param cm The CTC manager. 465 * @param el The "ctcProperties" element. 466 */ 467 void loadProperties(CtcManager cm, Element el) { 468 ProgramProperties pp = cm.getProgramProperties(); 469 470 pp._mCodeButtonInternalSensorPattern = loadString(el.getChild("CodeButtonInternalSensorPattern")); 471 pp._mSIDI_CodingTimeInMilliseconds = loadInt(el.getChild("SIDI_CodingTimeInMilliseconds")); 472 pp._mSIDI_LeftInternalSensorPattern = loadString(el.getChild("SIDI_LeftInternalSensorPattern")); 473 pp._mSIDI_NormalInternalSensorPattern = loadString(el.getChild("SIDI_NormalInternalSensorPattern")); 474 pp._mSIDI_RightInternalSensorPattern = loadString(el.getChild("SIDI_RightInternalSensorPattern")); 475 pp._mSIDI_TimeLockingTimeInMilliseconds = loadInt(el.getChild("SIDI_TimeLockingTimeInMilliseconds")); 476 pp._mSIDL_LeftInternalSensorPattern = loadString(el.getChild("SIDL_LeftInternalSensorPattern")); 477 pp._mSIDL_NormalInternalSensorPattern = loadString(el.getChild("SIDL_NormalInternalSensorPattern")); 478 pp._mSIDL_RightInternalSensorPattern = loadString(el.getChild("SIDL_RightInternalSensorPattern")); 479 pp._mSWDI_CodingTimeInMilliseconds = loadInt(el.getChild("SWDI_CodingTimeInMilliseconds")); 480 pp._mSWDI_NormalInternalSensorPattern = loadString(el.getChild("SWDI_NormalInternalSensorPattern")); 481 pp._mSWDI_ReversedInternalSensorPattern = loadString(el.getChild("SWDI_ReversedInternalSensorPattern")); 482 pp._mSWDL_InternalSensorPattern = loadString(el.getChild("SWDL_InternalSensorPattern")); 483 pp._mCO_CallOnToggleInternalSensorPattern = loadString(el.getChild("CO_CallOnToggleInternalSensorPattern")); 484 pp._mTUL_DispatcherInternalSensorLockTogglePattern = loadString(el.getChild("TUL_DispatcherInternalSensorLockTogglePattern")); 485 pp._mTUL_DispatcherInternalSensorUnlockedIndicatorPattern = loadString(el.getChild("TUL_DispatcherInternalSensorUnlockedIndicatorPattern")); 486 pp._mCodeButtonDelayTime = loadInt(el.getChild("CodeButtonDelayTime")); 487 488// Debugging aid -- not active due to SpotBugs 489// log.debug("ProgramProperties:"); 490// List<Field> fields = Arrays.asList(ProgramProperties.class.getFields()); 491// fields.forEach(field -> { 492// try { 493// log.info(" ProgramProperties: fld = {}, val = {}", field.getName(), field.get(pp)); 494// } catch (Exception ex) { 495// log.info(" ProgramProperties list exception: {}", ex.getMessage()); 496// } 497// }); 498 } 499 500 /** 501 * Load the OtherData class. 502 * @param cm The CTC manager. 503 * @param el The "ctcOtherData" element. 504 */ 505 void loadOtherData(CtcManager cm, Element el) { 506 OtherData od = cm.getOtherData(); 507 508 String xmlVersion = loadString(el.getChild("CtcVersion")); 509 xmlVersion = xmlVersion == null ? "v2.0" : xmlVersion; // v2.0 is the initial version 510 if (!xmlVersion.equals(OtherData.CTC_VERSION)) { 511 log.warn("Update from version {} to version {} required", xmlVersion, OtherData.CTC_VERSION); 512 } 513 514// Fleeting: 515 od._mFleetingToggleInternalSensor = loadSensor(el.getChild("FleetingToggleInternalSensor"), true); 516 od._mDefaultFleetingEnabled = loadBoolean(el.getChild("DefaultFleetingEnabled")); 517 518// Global startup: 519 od._mTUL_EnabledAtStartup = loadBoolean(el.getChild("TUL_EnabledAtStartup")); 520 od._mSignalSystemType = OtherData.SIGNAL_SYSTEM_TYPE.getSignalSystemType(loadInt(el.getChild("SignalSystemType"))); 521 od._mTUL_SecondsToLockTurnouts = loadInt(el.getChild("TUL_SecondsToLockTurnouts")); 522 523// Next unique # for each created Column: 524 od._mNextUniqueNumber = loadInt(el.getChild("NextUniqueNumber")); 525 526// CTC Debugging: 527 od._mCTCDebugSystemReloadInternalSensor = loadSensor(el.getChild("CTCDebugSystemReloadInternalSensor"), true); 528 od._mCTCDebug_TrafficLockingRuleTriggeredDisplayInternalSensor = loadSensor(el.getChild("CTCDebug_TrafficLockingRuleTriggeredDisplayInternalSensor"), true); 529 530// GUI design: 531 od._mGUIDesign_NumberOfEmptyColumnsAtEnd = loadInt(el.getChild("GUIDesign_NumberOfEmptyColumnsAtEnd")); 532 od._mGUIDesign_CTCPanelType = OtherData.CTC_PANEL_TYPE.getRadioGroupValue(loadInt(el.getChild("GUIDesign_CTCPanelType"))); 533 od._mGUIDesign_BuilderPlate = loadBoolean(el.getChild("GUIDesign_BuilderPlate")); 534 od._mGUIDesign_SignalsOnPanel = OtherData.SIGNALS_ON_PANEL.getRadioGroupValue(loadInt(el.getChild("GUIDesign_SignalsOnPanel"))); 535 od._mGUIDesign_FleetingToggleSwitch = loadBoolean(el.getChild("GUIDesign_FleetingToggleSwitch")); 536 od._mGUIDesign_AnalogClockEtc = loadBoolean(el.getChild("GUIDesign_AnalogClockEtc")); 537 od._mGUIDesign_ReloadCTCSystemButton = loadBoolean(el.getChild("GUIDesign_ReloadCTCSystemButton")); 538 od._mGUIDesign_CTCDebugOnToggle = loadBoolean(el.getChild("GUIDesign_CTCDebugOnToggle")); 539 od._mGUIDesign_CreateTrackPieces = loadBoolean(el.getChild("GUIDesign_CreateTrackPieces")); 540 od._mGUIDesign_VerticalSize = OtherData.VERTICAL_SIZE.getRadioGroupValue(loadInt(el.getChild("GUIDesign_VerticalSize"))); 541 od._mGUIDesign_OSSectionUnknownInconsistentRedBlink = loadBoolean(el.getChild("GUIDesign_OSSectionUnknownInconsistentRedBlink")); 542 od._mGUIDesign_TurnoutsOnPanel = loadBoolean(el.getChild("GUIDesign_TurnoutsOnPanel")); 543 544// Debugging aid -- not active due to SpotBugs 545// log.info("OtherData:"); 546// List<Field> fields = Arrays.asList(OtherData.class.getFields()); 547// fields.forEach(field -> { 548// try { 549// log.info(" OtherData: fld = {}, type = {}, val = {}", field.getName(), field.getType(), field.get(od)); 550// } catch (Exception ex) { 551// log.info(" OtherData list exception: {}", ex.getMessage()); 552// } 553// }); 554 } 555 556 // **** Load simple objects **** 557 558 String loadString(Element element) { 559 String newString = null; 560 if (element != null) { 561 newString = element.getValue(); 562 } 563 return newString; 564 } 565 566 int loadInt(Element element) { 567 int newInt = 0; 568 if (element != null) { 569 try { 570 newInt = Integer.parseInt(element.getValue()); 571 } catch (NumberFormatException ex) { 572 log.warn("loadInt format exception: element = {}, value = {}", element.getName(), element.getValue()); 573 } 574 } 575 return newInt; 576 } 577 578 boolean loadBoolean(Element element) { 579 boolean newBoolean = false; 580 if (element != null) { 581 newBoolean = element.getValue().equals("true") ? true : false; 582 } 583 return newBoolean; 584 } 585 586 NBHSensor loadSensor(Element element, boolean isInternal) { 587 NBHSensor sensor = null; 588 if (element != null && element.getValue() != null && !element.getValue().isEmpty()) { 589 String sensorName = element.getValue(); 590 sensor = cm.getNBHSensor(sensorName); 591 if (sensor == null) { 592 if (isInternal) { 593 sensor = new NBHSensor("CtcManagerXml", "create internal = ", sensorName, sensorName); 594 } else { 595 sensor = new NBHSensor("CtcManagerXml", "create standard = ", sensorName, sensorName, false); 596 } 597 } 598 } else { 599 sensor = new NBHSensor("CtcManagerXml", "", "Empty NBHSensor", "", true); 600 } 601 return sensor; 602 } 603 604 NBHSignal loadSignal(Element element) { 605 NBHSignal signal = null; 606 if (element != null && element.getValue() != null && !element.getValue().isEmpty()) { 607 String signalName = element.getValue(); 608 signal = cm.getNBHSignal(signalName); 609 if (signal == null) { 610 signal = new NBHSignal(element.getValue()); 611 } 612 } else { 613 signal = new NBHSignal(""); 614 } 615 return signal; 616 } 617 618 NBHTurnout loadTurnout(Element element, Element feedback) { 619 NBHTurnout turnout = null; 620 boolean feedBack = loadBoolean(feedback); 621 if (element != null && element.getValue() != null && !element.getValue().isEmpty()) { 622 String turnoutName = element.getValue(); 623 624 turnout = cm.getNBHTurnout(turnoutName); 625 if (turnout == null) { 626 turnout = new NBHTurnout("CtcManagerXml", "", element.getValue(), element.getValue(), feedBack); 627 } 628 } else { 629 turnout = new NBHTurnout("CtcManagerXml", "Empty NBHTurnout", ""); 630 } 631 return turnout; 632 } 633 634 NamedBeanHandle<Block> loadBlock(Element element) { 635 NamedBeanHandle<Block> blockHandle = null; 636 if (element != null && element.getValue() != null && !element.getValue().isEmpty()) { 637 blockHandle = cm.getBlock(element.getValue()); 638 if (blockHandle == null) { 639 Block block = InstanceManager.getDefault(BlockManager.class).getBlock(element.getValue()); 640 if (block != null) { 641 blockHandle = InstanceManager.getDefault(NamedBeanHandleManager.class).getNamedBeanHandle(element.getValue(), block); 642 cm.putBlock(element.getValue(), blockHandle); 643 } 644 } 645 } 646 return blockHandle; 647 } 648 649 // **** Load ArrayList objects **** 650 651 ArrayList<NBHSensor> getSensorList(Element element) { 652 ArrayList<NBHSensor> sensorList = new ArrayList<>(); 653 if (element != null) { 654 for (Element el : element.getChildren()) { 655 NBHSensor sensor = loadSensor(el, false); 656 sensorList.add(sensor); 657 } 658 } 659 return sensorList; 660 } 661 662 ArrayList<NBHSignal> getSignalList(Element element) { 663 ArrayList<NBHSignal> signalList = new ArrayList<>(); 664 if (element != null) { 665 for (Element el : element.getChildren()) { 666 NBHSignal signal = loadSignal(el); 667 signalList.add(signal); 668 } 669 } 670 return signalList; 671 } 672 673 ArrayList<CallOnData> getCallOnList(Element element) { 674 ArrayList<CallOnData> callOnList = new ArrayList<>(); 675 if (element != null) { 676 for (Element elCallOn : element.getChildren()) { 677 CallOnData cod = new CallOnData(); 678 cod._mExternalSignal = loadSignal(elCallOn.getChild("ExternalSignal")); 679 cod._mSignalFacingDirection = loadString(elCallOn.getChild("SignalFacingDirection")); 680 cod._mSignalAspectToDisplay = loadString(elCallOn.getChild("SignalAspectToDisplay")); 681 cod._mCalledOnExternalSensor = loadSensor(elCallOn.getChild("CalledOnExternalSensor"), false); 682 cod._mExternalBlock = loadBlock(elCallOn.getChild("ExternalBlock")); 683 cod._mSwitchIndicators = new ArrayList<>(); 684 cod._mSwitchIndicatorNames = getCallOnSensorNames(elCallOn.getChild("SwitchIndicators")); 685 callOnList.add(cod); 686 } 687 } 688 return callOnList; 689 } 690 691 ArrayList<String> getCallOnSensorNames(Element element) { 692 ArrayList<String> sensorList = new ArrayList<>(); 693 if (element != null) { 694 for (Element el : element.getChildren()) { 695 sensorList.add(el.getValue()); 696 } 697 } 698 return sensorList; 699 } 700 701 void convertCallOnSensorNamesToNBHSensors(CtcManager cm) { 702 for (CodeButtonHandlerData cbhd : cm.getCTCSerialData().getCodeButtonHandlerDataArrayList()) { 703 for (CallOnData cod : cbhd._mCO_GroupingsList) { 704 for (String sensorName : cod._mSwitchIndicatorNames) { 705 NBHSensor sensor = cm.getNBHSensor(sensorName); 706 if (sensor != null) { 707 cod._mSwitchIndicators.add(sensor); 708 } 709 } 710 } 711 } 712 } 713 714 ArrayList<TrafficLockingData> getTrafficLocking(Element element) { 715 ArrayList<TrafficLockingData> trlData = new ArrayList<>(); 716 if (element != null) { 717 for (Element elRule : element.getChildren()) { 718 TrafficLockingData trl = new TrafficLockingData(); 719 trl._mUserRuleNumber = loadString(elRule.getChild("UserRuleNumber")); 720 trl._mRuleEnabled = loadString(elRule.getChild("RuleEnabled")); 721 trl._mDestinationSignalOrComment = loadString(elRule.getChild("DestinationSignalOrComment")); 722 723 trl._mSwitchAlignments = getTRLSwitchList(elRule.getChild("switches")); 724 725 trl._mOccupancyExternalSensors = getSensorList(elRule.getChild("OccupancyExternalSensors")); 726 trl._mOptionalExternalSensors = getSensorList(elRule.getChild("OptionalExternalSensors")); 727 trlData.add(trl); 728 } 729 } 730 return trlData; 731 } 732 733 ArrayList<TrafficLockingData.TRLSwitch> getTRLSwitchList(Element element) { 734 ArrayList<TrafficLockingData.TRLSwitch> trlSwitches = new ArrayList<>(); 735 if (element != null) { 736 for (Element elSwitch : element.getChildren()) { 737 String userText = loadString(elSwitch.getChild("UserText")); 738 if (userText != null && !userText.isEmpty()) { 739 TrafficLockingData.TRLSwitch newSwitch = new TrafficLockingData.TRLSwitch( 740 userText, 741 loadString(elSwitch.getChild("SwitchAlignment")), 742 loadInt(elSwitch.getChild("UniqueID"))); 743 trlSwitches.add(newSwitch); 744 } 745 } 746 } 747 return trlSwitches; 748 } 749 750 void loadAdditionalTurnouts(Element element, CodeButtonHandlerData cbhd) { // TUL_AdditionalExternalTurnouts 751 if (element != null) { 752 int rowNumber = 0; 753 for (Element elTurnout : element.getChildren()) { // TUL_AdditionalExternalTurnoutEntry 754 rowNumber++; 755 NBHTurnout turnout = loadTurnout(elTurnout.getChild("TUL_AdditionalExternalTurnout"), elTurnout.getChild("TUL_AdditionalExternalTurnoutFeedbackDifferent")); 756 boolean feedback = loadBoolean(elTurnout.getChild("TUL_AdditionalExternalTurnoutFeedbackDifferent")); 757 758 if (rowNumber == 1) { 759 cbhd._mTUL_AdditionalExternalTurnout1 = turnout; 760 cbhd._mTUL_AdditionalExternalTurnout1FeedbackDifferent = feedback; 761 } 762 if (rowNumber == 2) { 763 cbhd._mTUL_AdditionalExternalTurnout2 = turnout; 764 cbhd._mTUL_AdditionalExternalTurnout2FeedbackDifferent = feedback; 765 } 766 if (rowNumber == 3) { 767 cbhd._mTUL_AdditionalExternalTurnout3 = turnout; 768 cbhd._mTUL_AdditionalExternalTurnout3FeedbackDifferent = feedback; 769 } 770 } 771 } 772 } 773 774 @Override 775 public int loadOrder() { 776 return InstanceManager.getDefault(jmri.jmrit.ctc.CtcManager.class).getXMLOrder(); 777 } 778 779 private final static Logger log = LoggerFactory.getLogger(CtcManagerXml.class); 780}