001package jmri.implementation; 002 003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 004import jmri.NamedBeanHandle; 005import jmri.Turnout; 006import org.slf4j.Logger; 007import org.slf4j.LoggerFactory; 008 009/** 010 * Drive a single signal head via three "Turnout" objects. 011 * <p> 012 * After much confusion, the user-level terminology was changed to call these 013 * "Triple Output"; the class name remains the same to reduce recoding. 014 * <p> 015 * The three Turnout objects are provided during construction, and each drives a 016 * specific color (RED, YELLOW and GREEN). Normally, "THROWN" is on, and 017 * "CLOSED" is off. 018 * <p> 019 * This class doesn't currently listen to the Turnout's to see if they've been 020 * changed via some other mechanism. 021 * 022 * @author Bob Jacobsen Copyright (C) 2003, 2008 023 */ 024public class TripleTurnoutSignalHead extends DoubleTurnoutSignalHead { 025 026 public TripleTurnoutSignalHead(String sys, String user, NamedBeanHandle<Turnout> green, NamedBeanHandle<Turnout> yellow, NamedBeanHandle<Turnout> red) { 027 super(sys, user, green, red); 028 mYellow = yellow; 029 } 030 031 public TripleTurnoutSignalHead(String sys, NamedBeanHandle<Turnout> green, NamedBeanHandle<Turnout> yellow, NamedBeanHandle<Turnout> red) { 032 super(sys, green, red); 033 mYellow = yellow; 034 } 035 036 @SuppressWarnings("fallthrough") 037 @SuppressFBWarnings(value = "SF_SWITCH_FALLTHROUGH") 038 @Override 039 protected void updateOutput() { 040 // assumes that writing a turnout to an existing state is cheap! 041 if (mLit == false) { 042 mRed.getBean().setCommandedState(Turnout.CLOSED); 043 mYellow.getBean().setCommandedState(Turnout.CLOSED); 044 mGreen.getBean().setCommandedState(Turnout.CLOSED); 045 return; 046 } else if (!mFlashOn 047 && ((mAppearance == FLASHGREEN) 048 || (mAppearance == FLASHYELLOW) 049 || (mAppearance == FLASHRED))) { 050 // flash says to make output dark 051 mRed.getBean().setCommandedState(Turnout.CLOSED); 052 mYellow.getBean().setCommandedState(Turnout.CLOSED); 053 mGreen.getBean().setCommandedState(Turnout.CLOSED); 054 return; 055 056 } else { 057 switch (mAppearance) { 058 case RED: 059 case FLASHRED: 060 mRed.getBean().setCommandedState(Turnout.THROWN); 061 mYellow.getBean().setCommandedState(Turnout.CLOSED); 062 mGreen.getBean().setCommandedState(Turnout.CLOSED); 063 break; 064 case YELLOW: 065 case FLASHYELLOW: 066 mRed.getBean().setCommandedState(Turnout.CLOSED); 067 mYellow.getBean().setCommandedState(Turnout.THROWN); 068 mGreen.getBean().setCommandedState(Turnout.CLOSED); 069 break; 070 case GREEN: 071 case FLASHGREEN: 072 mRed.getBean().setCommandedState(Turnout.CLOSED); 073 mYellow.getBean().setCommandedState(Turnout.CLOSED); 074 mGreen.getBean().setCommandedState(Turnout.THROWN); 075 break; 076 default: 077 log.warn("Unexpected new appearance: {}", mAppearance); 078 // go dark by falling through 079 case DARK: 080 mRed.getBean().setCommandedState(Turnout.CLOSED); 081 mYellow.getBean().setCommandedState(Turnout.CLOSED); 082 mGreen.getBean().setCommandedState(Turnout.CLOSED); 083 break; 084 } 085 } 086 } 087 088 /** 089 * Remove references to and from this object, so that it can eventually be 090 * garbage-collected. 091 */ 092 @Override 093 public void dispose() { 094 mYellow = null; 095 super.dispose(); 096 } 097 098 NamedBeanHandle<Turnout> mYellow; 099 100 public NamedBeanHandle<Turnout> getYellow() { 101 return mYellow; 102 } 103 104 public void setYellow(NamedBeanHandle<Turnout> t) { 105 mYellow = t; 106 } 107 108 @Override 109 public boolean isTurnoutUsed(Turnout t) { 110 if (super.isTurnoutUsed(t)) { 111 return true; 112 } 113 if (getYellow() != null && t.equals(getYellow().getBean())) { 114 return true; 115 } 116 return false; 117 } 118 119 /** 120 * Disables the feedback mechanism of the DoubleTurnoutSignalHead. 121 */ 122 @Override 123 void readOutput() { } 124 125 private final static Logger log = LoggerFactory.getLogger(TripleTurnoutSignalHead.class); 126}