001package jmri.jmrit.ussctc;
002
003
004import java.util.*;
005
006/**
007 * A Station represents a specific codeline field station.
008 * It defines the bits in the code message and holds references to the
009 * hardware at both ends that is controlled by those bits. For example:
010 * <ul>
011 * <li>Two bits for Turnouts, see {@link CodeGroupTwoBits}
012 * <li>Three bits for Signals, see {@link CodeGroupThreeBits}
013 * <li>One bit for maintainer call, track circuits, etc, see {@link CodeGroupOneBit}
014 * </ul>
015 * The basic structure is to mate two objects that interact via a
016 * shared enum. Alternately, this can be a single object: e.g. a
017 * {@link TurnoutSection} that functions in both the central CTC machine and field hardware roles.
018 * <ul>
019 * <li>The field object listens to the status of the layout and sends indications on changes.
020 * <p>The central (CTC machine) object responds to those indications.
021 * <li>The central (CTC machine) object sends when Code is pressed.
022 * <p>The field object responds to those when received.
023 * </ul>
024 *
025 * @author Bob Jacobsen Copyright (C) 2007, 2017
026 */
027public class Station<To extends Enum<To>, From extends Enum<From>> {
028
029    public Station(String name, CodeLine codeline, CodeButton button) {
030        this.name = name;
031        this.codeline = codeline;
032        this.button = button;
033
034        button.addStation(this);  // register with Codebutton
035    }
036
037    String name;
038    CodeLine codeline;
039    CodeButton button;
040
041    /**
042     * @param section next Section subclass that makes up part of this Station
043     * @return this Station to allow chaining
044     */
045    public Station<To, From> add(Section<To, From> section) {
046        sections.add(section);
047        return this;
048    }
049
050    /**
051     * Provide access to CodeLine to which this Station is attached.
052     * @return Codeline reference for this Station
053     */
054    CodeLine getCodeLine() { return codeline; }
055
056    /**
057     * Provide access this Station's name
058     * @return Human-readable name
059     */
060    String getName() { return name; }
061
062    @Override
063    public String toString() {
064        StringBuffer retval = new StringBuffer("Station "+name+"\n        sentValues:");
065
066        if (sentValues == null) retval.append(" (null)");
067        else {
068            for (Enum<?> e : sentValues)  {
069                retval.append(" ");
070                retval.append(e);
071            }
072        }
073
074        retval.append("\n  indicationValues:");
075        if (indicationValues == null) retval = retval.append(" (null)");
076        else {
077            for (Enum<?> e : sentValues)  {
078                retval.append(" ");
079                retval.append(e);
080            }
081        }
082
083        return new String(retval);
084    }
085
086    /**
087     * Tell the Sections to start a code-send operation (from machine to field).
088     * Usually comes from a {@link CodeButton}
089     */
090    public void codeSendRequest() {
091        log.debug("Station - start codeSendRequest");
092        sentValues = new ArrayList<>();
093        sections.forEach((section) -> {
094            // accumulate send values, which also sets indicators
095            sentValues.add(section.codeSendStart());
096        } );
097
098        codeline.requestSendCode(this);
099        log.debug("Station - end codeSendRequest");
100
101    }
102
103    public void codeSendComplete() {
104        log.debug("Station - start codeSendComplete");
105
106        // notify
107        sections.forEach((section) -> {
108            // accumulate send values, which also sets indicators
109            sentValues.add(section.codeSendStart());
110        } );
111
112        log.debug("Station - end codeSendComplete");
113    }
114
115    /**
116     * Tell the sections that code information has arrived in the field
117     */
118    public void codeValueDelivered() {
119        log.debug("Station - start codeValueDelivered");
120        // clear the code light
121        button.codeValueDelivered();
122
123        // tell each section
124        for (int i = 0; i < sections.size(); i++) {
125            sections.get(i).codeValueDelivered(sentValues.get(i));
126        }
127        log.debug("Station - end codeValueDelivered");
128    }
129
130
131    public void requestIndicationStart() {
132        log.debug("Station - start requestIndicationStart");
133        codeline.requestIndicationStart(this);
134        log.debug("Station - end requestIndicationStart");
135    }
136
137    /**
138     * Gather layout status and turn on code lamp.
139     *  Rest of action is on indicationComplete
140     */
141    public void indicationStart() {
142        log.debug("Station - start indicationStart");
143
144        button.indicationStart();
145
146        indicationValues = new ArrayList<>();
147        sections.forEach((section) -> {
148            // accumulate send values, which also sets indicators
149            indicationValues.add(section.indicationStart());
150        } );
151        log.debug("Station - end indicationStart");
152    }
153
154    /**
155     * Gather layout status and turn on code lamp.
156     *  Rest of action is on indicationComplete
157     */
158    public void indicationComplete() {
159        log.debug("Station - start indicationComplete");
160
161        // tell each section
162        for (int i = 0; i < sections.size(); i++) {
163            sections.get(i).indicationComplete(indicationValues.get(i));
164        }
165        // clear the code light
166        button.indicationComplete();
167
168        log.debug("Station - end indicationComplete");
169    }
170
171    ArrayList<Section<To, From>> sections = new ArrayList<>();
172    ArrayList<To> sentValues;
173    ArrayList<From> indicationValues;
174
175    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Station.class);
176}