001package jmri.jmrix;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006/**
007 * Basic implementation of a node for JMRI protocol support.
008 * <p>
009 * Integrated with {@link AbstractMRNodeTrafficController}.
010 *
011 * @author Bob Jacobsen Copyright 2008
012 */
013public abstract class AbstractNode {
014
015    /**
016     * Create a new instance of AbstractNode.
017     */
018    public AbstractNode() {
019    }
020
021    public int nodeAddress = 0; // Node address, valid range varies by subclass
022
023    /**
024     * Public method to return the node address.
025     *
026     * @return node address number
027     */
028    public int getNodeAddress() {
029        return (nodeAddress);
030    }
031
032    /**
033     * Public method to set the node address. Address range is checked in
034     * subclasses.
035     *
036     * @param address address index to set in node
037     * @throws IllegalArgumentException if out of range
038     */
039    public void setNodeAddress(int address) {
040        if (checkNodeAddress(address)) {
041            nodeAddress = address;
042        } else {
043            log.error("illegal node address: {}", Integer.toString(address));
044            nodeAddress = 0;
045            throw new IllegalArgumentException("Attempt to set address to invalid value: " + address);
046        }
047    }
048
049    /**
050     * Check for valid address with respect to range, etc.
051     *
052     * @param address node number to check.
053     * @return true if valid
054     */
055    abstract protected boolean checkNodeAddress(int address);
056
057    /**
058     * Create the needed Initialization packet (AbstractMRMessage) for this
059     * node.
060     *
061     * @return the packet, or 'null' if not needed
062     */
063    abstract public AbstractMRMessage createInitPacket();
064
065    /**
066     * Create a Transmit packet (AbstractMRMessage) to send current state.
067     * @return packet to send current node state.
068     */
069    abstract public AbstractMRMessage createOutPacket();
070
071    /**
072     * Are any sensors present, and hence will this node need to be polled?
073     *
074     * @return 'true' if at least one sensor is active for this node
075     */
076    abstract public boolean getSensorsActive();
077
078    /**
079     * Deal with a timeout in the transmission controller.
080     *
081     * @param m message that didn't receive a reply
082     * @param l listener that sent the message
083     * @return true if initialization is required
084     */
085    abstract public boolean handleTimeout(AbstractMRMessage m, AbstractMRListener l);
086
087    /**
088     * A reply was received, so there was no timeout, do any needed processing.
089     *
090     * @param m message received that has reset the timeout and is waiting to be handled
091     */
092    abstract public void resetTimeout(AbstractMRMessage m);
093
094    /**
095     * Get Must Send state.
096     * @return state of needSend flag.
097     */
098    public boolean mustSend() {
099        return needSend;
100    }
101
102    /**
103     * Public to reset state of needSend flag. Subclasses may override to
104     * enforce conditions.
105     */
106    public void resetMustSend() {
107        needSend = false;
108    }
109
110    /**
111     * Public to set state of needSend flag.
112     */
113    public void setMustSend() {
114        needSend = true;
115    }
116
117    boolean needSend = true; // 'true' if something has changed that requires data to be sent
118
119    private final static Logger log = LoggerFactory.getLogger(AbstractNode.class);
120
121}