001package jmri.implementation; 002 003import java.util.*; 004import javax.annotation.*; 005import jmri.InstanceManager; 006import jmri.SignalAppearanceMap; 007import jmri.SignalMast; 008import jmri.SignalSystem; 009 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013/** 014 * Abstract class providing the basic logic of the SignalMast interface. 015 * 016 * @author Bob Jacobsen Copyright (C) 2009 017 */ 018public abstract class AbstractSignalMast extends AbstractNamedBean 019 implements SignalMast, java.beans.VetoableChangeListener { 020 021 private final static Logger log = LoggerFactory.getLogger(AbstractSignalMast.class); 022 023 public AbstractSignalMast(String systemName, String userName) { 024 super(systemName, userName); 025 } 026 027 public AbstractSignalMast(String systemName) { 028 super(systemName); 029 } 030 031 @Override 032 public void setAspect(@Nonnull String aspect) { 033 String oldAspect = this.aspect; 034 this.aspect = aspect; 035 this.speed = (String) getSignalSystem().getProperty(aspect, "speed"); 036 firePropertyChange("Aspect", oldAspect, aspect); 037 } 038 039 @Override 040 public String getAspect() { 041 return aspect; 042 } 043 protected String aspect = null; 044 045 public String getSpeed() { 046 return speed; 047 } 048 protected String speed = null; 049 050 /** 051 * The state is the index of the current aspect in the list of possible 052 * aspects. 053 */ 054 @Override 055 public int getState() { 056 return -1; 057 } 058 059 @Override 060 public void setState(int i) { 061 } 062 063 /** 064 * By default, signals are lit. 065 */ 066 private boolean mLit = true; 067 068 /** 069 * Default behavior for "lit" property is to track value and return it. 070 */ 071 @Override 072 public boolean getLit() { 073 return mLit; 074 } 075 076 /** 077 * By default, signals are not held. 078 */ 079 private boolean mHeld = false; 080 081 /** 082 * "Held" property is just tracked and notified. 083 */ 084 @Override 085 public boolean getHeld() { 086 return mHeld; 087 } 088 089 /** 090 * Set the lit property. 091 * <p> 092 * This acts on all the SignalHeads included in this SignalMast 093 * 094 * @param newLit the new value of lit 095 */ 096 @Override 097 public void setLit(boolean newLit) { 098 boolean oldLit = mLit; 099 mLit = newLit; 100 if (oldLit != newLit) { 101 //updateOutput(); 102 // notify listeners, if any 103 firePropertyChange("Lit", oldLit, newLit); 104 } 105 } 106 107 /** 108 * Set the held property of the signal mast. 109 * <p> 110 * Note that this does not directly effect the output on the layout; the 111 * held property is a local variable which effects the aspect only via 112 * higher-level logic. 113 * 114 * @param newHeld the new value of the help property 115 */ 116 @Override 117 public void setHeld(boolean newHeld) { 118 boolean oldHeld = mHeld; 119 mHeld = newHeld; 120 if (oldHeld != newHeld) { 121 // notify listeners, if any 122 firePropertyChange("Held", oldHeld, newHeld); 123 } 124 } 125 126 @Override 127 public boolean isAtStop() { 128 if (speed.equals("0")) return true; // should this also include DANGER? 129 return false; 130 } 131 132 @Override 133 public boolean isShowingRestricting() { 134 String displayedAspect = getAspect(); 135 if ( displayedAspect != null && displayedAspect.equals(getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.PERMISSIVE))) return true; 136 return false; 137 } 138 139 @Override 140 public boolean isCleared() { 141 String displayedAspect = getAspect(); 142 if ( displayedAspect == null ) { 143 return false; 144 } 145 if (displayedAspect.equals(getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.PERMISSIVE))) return false; 146 if (displayedAspect.equals(getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.HELD))) return false; 147 if (displayedAspect.equals(getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.DANGER))) return false; 148 return true; 149 } 150 151 protected DefaultSignalAppearanceMap map; 152 SignalSystem systemDefn; 153 154 boolean disablePermissiveSignalMastLogic = false; 155 @Override 156 public void setPermissiveSmlDisabled(boolean disabled) { 157 disablePermissiveSignalMastLogic = disabled; 158 firePropertyChange("PermissiveSmlDisabled", null, disabled); 159 } 160 /** 161 * {@inheritDoc } 162 */ 163 @Override 164 public boolean isPermissiveSmlDisabled() { 165 return disablePermissiveSignalMastLogic; 166 } 167 168 protected void configureSignalSystemDefinition(String name) { 169 systemDefn = InstanceManager.getDefault(jmri.SignalSystemManager.class).getSystem(name); 170 if (systemDefn == null) { 171 log.error("Did not find signal definition: {}", name); 172 throw new IllegalArgumentException("Signal definition not found: " + name); 173 } 174 } 175 176 protected void configureAspectTable(String signalSystemName, String aspectMapName) { 177 map = DefaultSignalAppearanceMap.getMap(signalSystemName, aspectMapName); 178 } 179 180 @Override 181 public SignalSystem getSignalSystem() { 182 return systemDefn; 183 } 184 185 @Override 186 public SignalAppearanceMap getAppearanceMap() { 187 return map; 188 } 189 190 protected ArrayList<String> disabledAspects = new ArrayList<>(1); 191 192 @Override 193 @Nonnull 194 public Vector<String> getValidAspects() { 195 java.util.Enumeration<String> e = map.getAspects(); 196 // copy List to Vector 197 Vector<String> v = new Vector<>(); 198 while (e.hasMoreElements()) { 199 String a = e.nextElement(); 200 if (!disabledAspects.contains(a)) { 201 v.add(a); 202 } 203 } 204 return v; 205 } 206 207 /** 208 * {@inheritDoc } 209 */ 210 @Override 211 public String getMastType() { return mastType; } 212 @Override 213 public void setMastType(@Nonnull String type) { 214 Objects.requireNonNull(type, "MastType cannot be null"); 215 mastType = type; 216 } 217 String mastType; 218 219 /** 220 * Get a list of all the known aspects for this mast, including those that 221 * have been disabled. 222 * 223 * @return list of known aspects; may be empty 224 */ 225 public Vector<String> getAllKnownAspects() { 226 java.util.Enumeration<String> e = map.getAspects(); 227 Vector<String> v = new Vector<>(); 228 while (e.hasMoreElements()) { 229 v.add(e.nextElement()); 230 } 231 return v; 232 } 233 234 public void setAspectDisabled(String aspect) { 235 if (aspect == null || aspect.equals("")) { 236 return; 237 } 238 if (!map.checkAspect(aspect)) { 239 log.warn("attempting to disable an aspect: {} that is not on the mast {}", aspect, getDisplayName()); 240 return; 241 } 242 if (!disabledAspects.contains(aspect)) { 243 disabledAspects.add(aspect); 244 firePropertyChange("aspectDisabled", null, aspect); 245 } 246 } 247 248 public void setAspectEnabled(String aspect) { 249 if (aspect == null || aspect.equals("")) { 250 return; 251 } 252 if (!map.checkAspect(aspect)) { 253 log.warn("attempting to disable an aspect: {} that is not on the mast {}", aspect, getDisplayName()); 254 return; 255 } 256 if (disabledAspects.contains(aspect)) { 257 disabledAspects.remove(aspect); 258 firePropertyChange("aspectEnabled", null, aspect); 259 } 260 } 261 262 public List<String> getDisabledAspects() { 263 return disabledAspects; 264 } 265 266 @Override 267 public boolean isAspectDisabled(String aspect) { 268 return disabledAspects.contains(aspect); 269 } 270 271 boolean allowUnLit = true; 272 273 @Override 274 public void setAllowUnLit(boolean boo) { 275 allowUnLit = boo; 276 } 277 278 @Override 279 public boolean allowUnLit() { 280 return allowUnLit; 281 } 282 283 @Override 284 public void vetoableChange(java.beans.PropertyChangeEvent evt) throws java.beans.PropertyVetoException { 285 } 286 287 @Override 288 public String getBeanType() { 289 return Bundle.getMessage("BeanNameSignalMast"); 290 } 291 292}