001package jmri.jmrit.logixng.expressions; 002 003import java.beans.*; 004import java.util.*; 005 006import jmri.*; 007import jmri.jmrit.logixng.*; 008import jmri.jmrit.logixng.util.LogixNG_SelectNamedBean; 009import jmri.jmrit.logixng.util.LogixNG_SelectEnum; 010import jmri.jmrit.logixng.util.parser.*; 011 012/** 013 * This expression evaluates the state of a Section. 014 * The supported characteristics are: 015 * <ul> 016 * <li>Is [not] Free</li> 017 * <li>Is [not] Forward</li> 018 * <li>Is [not] Reverse</li> 019 * </ul> 020 * @author Dave Sand Copyright 2023 021 */ 022public class ExpressionSection extends AbstractDigitalExpression 023 implements PropertyChangeListener { 024 025 private final LogixNG_SelectNamedBean<Section> _selectNamedBean = 026 new LogixNG_SelectNamedBean<>( 027 this, Section.class, InstanceManager.getDefault(SectionManager.class)); 028 029 private Is_IsNot_Enum _is_IsNot = Is_IsNot_Enum.Is; 030 031 private final LogixNG_SelectEnum<SectionState> _selectEnum = 032 new LogixNG_SelectEnum<>(this, SectionState.values(), SectionState.Free); 033 034 public ExpressionSection(String sys, String user) 035 throws BadUserNameException, BadSystemNameException { 036 super(sys, user); 037 } 038 039 @Override 040 public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws ParserException { 041 DigitalExpressionManager manager = InstanceManager.getDefault(DigitalExpressionManager.class); 042 String sysName = systemNames.get(getSystemName()); 043 String userName = userNames.get(getSystemName()); 044 if (sysName == null) sysName = manager.getAutoSystemName(); 045 ExpressionSection copy = new ExpressionSection(sysName, userName); 046 copy.setComment(getComment()); 047 048 _selectNamedBean.copy(copy._selectNamedBean); 049 _selectEnum.copy(copy._selectEnum); 050 051 copy.set_Is_IsNot(_is_IsNot); 052 053 return manager.registerExpression(copy); 054 } 055 056 public LogixNG_SelectNamedBean<Section> getSelectNamedBean() { 057 return _selectNamedBean; 058 } 059 060 public LogixNG_SelectEnum<SectionState> getSelectEnum() { 061 return _selectEnum; 062 } 063 064 public void set_Is_IsNot(Is_IsNot_Enum is_IsNot) { 065 _is_IsNot = is_IsNot; 066 } 067 068 public Is_IsNot_Enum get_Is_IsNot() { 069 return _is_IsNot; 070 } 071 072 /** {@inheritDoc} */ 073 @Override 074 public LogixNG_Category getCategory() { 075 return LogixNG_Category.ITEM; 076 } 077 078 /** {@inheritDoc} */ 079 @Override 080 public boolean evaluate() throws JmriException { 081 ConditionalNG conditionalNG = getConditionalNG(); 082 083 Section section = _selectNamedBean.evaluateNamedBean(conditionalNG); 084 085 if (section == null) return false; 086 087 SectionState checkSectionState = _selectEnum.evaluateEnum(conditionalNG); 088 089 int currentState = 0; 090 if (_selectEnum.getEnum() == SectionState.Occupied) { 091 currentState = section.getOccupancy(); 092 } else { 093 currentState = section.getState(); 094 } 095 096 if (_is_IsNot == Is_IsNot_Enum.Is) { 097 return currentState == checkSectionState.getID(); 098 } else { 099 return currentState != checkSectionState.getID(); 100 } 101 } 102 103 @Override 104 public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException { 105 throw new UnsupportedOperationException("Not supported."); 106 } 107 108 @Override 109 public int getChildCount() { 110 return 0; 111 } 112 113 @Override 114 public String getShortDescription(Locale locale) { 115 return Bundle.getMessage(locale, "Section_Short"); 116 } 117 118 @Override 119 public String getLongDescription(Locale locale) { 120 String namedBean = _selectNamedBean.getDescription(locale); 121 String state; 122 123 if (_selectEnum.isDirectAddressing()) { 124 SectionState sectionState = _selectEnum.getEnum(); 125 state = Bundle.getMessage(locale, "AddressByDirect", sectionState._text); 126 } else { 127 state = _selectEnum.getDescription(locale); 128 } 129 130 return Bundle.getMessage(locale, "Section_Long", namedBean, _is_IsNot.toString(), state); 131 } 132 133 /** {@inheritDoc} */ 134 @Override 135 public void setup() { 136 // Do nothing 137 } 138 139 /** {@inheritDoc} */ 140 @Override 141 public void registerListenersForThisClass() { 142 if (_selectEnum.getEnum() == SectionState.Occupied) { 143 if (!_selectNamedBean.isDirectAddressing()) { 144 log.error("The section occupied expression requires a 'Direct' section reference"); 145 return; 146 } 147 148 if (_selectNamedBean.getBean() == null) { 149 log.error("The section occupied expression requires a selected section"); 150 return; 151 } 152 153 // Sections are not active until Section.initializeBlocks is invoked by Dispatcher. 154 // Section.getNumBlocks is a public method that will invoke Section.initializeBlocks if needed. 155 _selectNamedBean.getBean().getNumBlocks(); 156 } 157 158 if (!_listenersAreRegistered) { 159 _selectNamedBean.addPropertyChangeListener(this); 160 _listenersAreRegistered = true; 161 } 162 } 163 164 /** {@inheritDoc} */ 165 @Override 166 public void unregisterListenersForThisClass() { 167 if (_listenersAreRegistered) { 168 _selectNamedBean.removePropertyChangeListener(this); 169 _listenersAreRegistered = false; 170 } 171 } 172 173 /** {@inheritDoc} */ 174 @Override 175 public void propertyChange(PropertyChangeEvent evt) { 176 getConditionalNG().execute(); 177 } 178 179 /** {@inheritDoc} */ 180 @Override 181 public void disposeMe() { 182 } 183 184 public enum SectionState { 185 Free(Section.FREE, Bundle.getMessage("Section_StateFree")), 186 Forward(Section.FORWARD, Bundle.getMessage("Section_StateForward")), 187 Reverse(Section.REVERSE, Bundle.getMessage("Section_StateReverse")), 188 Separator1(-1, Base.SEPARATOR), 189 Occupied(Section.OCCUPIED, Bundle.getMessage("Section_StateOccupied")); 190 191 private final int _id; 192 private final String _text; 193 194 private SectionState(int id, String text) { 195 this._id = id; 196 this._text = text; 197 } 198 199 public int getID() { 200 return _id; 201 } 202 203 @Override 204 public String toString() { 205 return _text; 206 } 207 } 208 209 /** {@inheritDoc} */ 210 @Override 211 public void getUsageDetail(int level, NamedBean bean, List<NamedBeanUsageReport> report, NamedBean cdl) { 212 log.debug("getUsageReport :: ExpressionSection: bean = {}, report = {}", cdl, report); 213 _selectNamedBean.getUsageDetail(level, bean, report, cdl, this, LogixNG_SelectNamedBean.Type.Expression); 214 } 215 216 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ExpressionSection.class); 217 218}