001package jmri.jmrit.ctc.topology; 002 003import java.util.*; 004import jmri.*; 005import jmri.jmrit.ctc.ctcserialdata.CTCSerialData; 006 007/** 008 * This class contains all of the information needed (in lists) for the higher level 009 * "TRL_Rules" to generate all of the entries in "_mTRL_TrafficLockingRulesSSVList" 010 * 011 * @author Gregory J. Bedlek Copyright (C) 2018, 2019, 2020 012 */ 013 014public class TopologyInfo { 015 private final CTCSerialData _mCTCSerialData; // Needed to look up a turnout in order to return an O.S. section text. 016 private final String _mDestinationSignalMast; 017 private final String _mNormal; // Bundle.getMessage("TLE_Normal") 018 private final String _mReverse; // Bundle.getMessage("TLE_Reverse") 019 public TopologyInfo() { // Temporary for test suite only 020 _mCTCSerialData = null; 021 _mDestinationSignalMast = null; 022 _mNormal = null; 023 _mReverse = null; 024 } 025 public TopologyInfo(CTCSerialData CTCSerialData, String destinationSignalMast, String normal, String reverse) { 026 _mCTCSerialData = CTCSerialData; 027 _mDestinationSignalMast = destinationSignalMast; 028 _mNormal = normal; 029 _mReverse = reverse; 030 } 031 public String getDestinationSignalMast() { return _mDestinationSignalMast; } 032 033 /** 034 * Simple class to contain simple info about a turnout. 035 */ 036 private static class TurnoutInfo { 037 public final String _mOSSectionText; 038 public final String _mNormalReversed; 039 public final int _mUniqueID; 040 public TurnoutInfo(String OSSectionText, String normalReversed, int uniqueID) { 041 _mOSSectionText = OSSectionText; 042 _mNormalReversed = normalReversed; 043 _mUniqueID = uniqueID; 044 } 045 } 046 private final ArrayList<Sensor> _mSensors = new ArrayList<>(); 047// private final LinkedList<String> _mSensorNamesDebug = new LinkedList<>(); //Debugging 048 private final ArrayList<TurnoutInfo> _mTurnoutInfos = new ArrayList<>(); 049// private final LinkedList<String> _mOSSectionInfosDebug = new LinkedList<>(); //Debugging 050 private final ArrayList<Turnout> _mTurnouts = new ArrayList<>(); // ONLY used for duplicate check (lazy). 051 052 /** 053 * @return true if any of our lists have anything. 054 */ 055 public boolean nonEmpty() { return !_mSensors.isEmpty() || !_mTurnoutInfos.isEmpty(); } 056 057 /** 058 * Quick and dirty routine to get O.S. section information. 059 * 060 * @param index Index into array 061 * @return null if no information, else text (of form "29/30" for instance) 062 */ 063 public String getOSSectionText(int index) { 064 if (index < _mTurnoutInfos.size()) { // Safety: Can return info: 065 return _mTurnoutInfos.get(index)._mOSSectionText; 066 } else { 067 return null; 068 } 069 } 070 071 072 /** 073 * Quick and dirty routine to get "Normal"/"Reverse" information. 074 * 075 * @param index Index into array 076 * @return "Normal" if no information, else text (of form "Normal" for instance) 077 */ 078 public String getNormalReversed(int index) { 079 if (index < _mTurnoutInfos.size()) { // Safety: Can return info: 080 return _mTurnoutInfos.get(index)._mNormalReversed; 081 } else { 082 return "Normal"; // Doesn't hurt to return this for a turnout that has no information. 083 } 084 } 085 086 087 /** 088 * Quick and dirty routine to get the Display Name of the sensor. 089 * 090 * @param index Index into array 091 * @return "" if no information, else text (of form "SW31-OS" for instance) 092 */ 093 public String getSensorDisplayName(int index) { 094 if (index < _mSensors.size()) { // Safety: Can return info: 095 return _mSensors.get(index).getDisplayName(); 096 } else { 097 return ""; 098 } 099 } 100 101 102 /** 103 * Quick and dirty routine to get the unique id.. 104 * 105 * @param index Index into array 106 * @return null if no information, else uniqueID as String of the O.S. section. 107 */ 108 public String getUniqueID(int index) { 109 if (index < _mTurnoutInfos.size()) { // Safety: Can return info: 110 return Integer.toString(_mTurnoutInfos.get(index)._mUniqueID); 111 } else { 112 return null; 113 } 114 } 115 116 117 /** 118 * Quick and dirty routine to all all of the sensors in the passed blocks to 119 * our internal lists. Duplicates are ignored. It is possible that the user 120 * didn't associate a sensor with the block. Ignore such entries. 121 * @param blocks List of Blocks to add. 122 */ 123 public void addBlocks(List<Block> blocks) { 124 for (Block block : blocks) { 125 Sensor sensor = block.getSensor(); 126 if (null != sensor && !_mSensors.contains(sensor)) { // Safety: valid && VERIFY not in list already for some reason (safety, shouldn't happen): 127 _mSensors.add(sensor); 128// _mSensorNamesDebug.add(sensor.getDisplayName()); 129 } 130 } 131 } 132 133 134 /** 135 * Quick and dirty routine to add all of the turnouts in SML to our internal lists. 136 * Duplicates are ignored. 137 * 138 * @param signalMastLogic SML to work against. 139 * @param signalMast Destination mast in SML. 140 */ 141 public void addTurnouts(SignalMastLogic signalMastLogic, SignalMast signalMast) { 142// Right now, I cannot make a subroutine call out of this, because I have to call two different 143// routines at the lowest level: "signalMastLogic.getTurnoutState" and "signalMastLogic.getAutoTurnoutState" 144// depending on which it is. In Java method reference is a way. But I'm lazy and in a hurry: 145 for (Turnout turnout : signalMastLogic.getTurnouts(signalMast)) { 146 if (!_mTurnouts.contains(turnout)) { // VERIFY not in list already for some reason (safety, shouldn't happen): 147 _mTurnouts.add(turnout); // For above if statement dup check. 148// Need to convert the turnout to an O.S. section text: 149 CTCSerialData.CTCTurnoutData turnoutData = _mCTCSerialData.getCTCTurnoutData(turnout); 150 if (null != turnoutData) { // Safety: 151// ToDo someday: Reverse "isNormal" if feedback different? 152 boolean isNormal = signalMastLogic.getTurnoutState(turnout, signalMast) == Turnout.CLOSED; 153 _mTurnoutInfos.add(new TurnoutInfo(turnoutData._mOSSectionText, isNormal ? _mNormal : _mReverse, turnoutData._mUniqueID)); 154// _mOSSectionInfosDebug.add(OSSectionText); 155 } 156 } 157 } 158 for (Turnout turnout : signalMastLogic.getAutoTurnouts(signalMast)) { 159 if (!_mTurnouts.contains(turnout)) { // VERIFY not in list already for some reason (safety, shouldn't happen): 160 _mTurnouts.add(turnout); // For above if statement dup check. 161// Need to convert the turnout to an O.S. section text: 162 CTCSerialData.CTCTurnoutData turnoutData = _mCTCSerialData.getCTCTurnoutData(turnout); 163 if (null != turnoutData) { // Safety: 164// ToDo someday: Reverse "isNormal" if feedback different? 165 boolean isNormal = signalMastLogic.getAutoTurnoutState(turnout, signalMast) == Turnout.CLOSED; 166 _mTurnoutInfos.add(new TurnoutInfo(turnoutData._mOSSectionText, isNormal ? _mNormal : _mReverse, turnoutData._mUniqueID)); 167// _mOSSectionInfosDebug.add(OSSectionText); 168 } 169 } 170 } 171 } 172}