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    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}