001package jmri.jmrix.grapevine;
002
003import java.util.Locale;
004import javax.annotation.Nonnull;
005import jmri.JmriException;
006import jmri.Turnout;
007import jmri.managers.AbstractTurnoutManager;
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011/**
012 * Implement turnout manager for Grapevine systems.
013 * <p>
014 * System names are "GTnnn", where G is the (multichar) system connection prefix,
015 * nnn is the turnout number without padding.
016 *
017 * @author Bob Jacobsen Copyright (C) 2003, 2006, 2007, 2008
018 */
019public class SerialTurnoutManager extends AbstractTurnoutManager {
020
021    public SerialTurnoutManager(GrapevineSystemConnectionMemo memo) {
022        super(memo);
023    }
024
025    /**
026     * {@inheritDoc}
027     */
028    @Override
029    @Nonnull
030    public GrapevineSystemConnectionMemo getMemo() {
031        return (GrapevineSystemConnectionMemo) memo;
032    }
033
034    /**
035     * {@inheritDoc}
036     */
037    @Nonnull
038    @Override
039    protected Turnout createNewTurnout(@Nonnull String systemName, String userName) throws IllegalArgumentException {
040        String prefix = getSystemPrefix();
041        // validate the system name, and normalize it
042        String sName = SerialAddress.normalizeSystemName(systemName, prefix);
043        if (sName.isEmpty()) {
044            // system name is not valid
045            throw new IllegalArgumentException("Cannot create System Name from " + systemName);
046        }
047        // does this turnout already exist
048        Turnout t = getBySystemName(sName);
049        if (t != null) {
050            return t;
051        }
052        // check under alternate name
053        String altName = SerialAddress.convertSystemNameToAlternate(sName, prefix);
054        t = getBySystemName(altName);
055        if (t != null) {
056            return t;
057        }
058        // create the turnout
059        t = new SerialTurnout(sName, userName, getMemo());
060
061        // does system name correspond to configured hardware
062        if (!SerialAddress.validSystemNameConfig(sName, 'T', getMemo().getTrafficController())) {
063            // system name does not correspond to configured hardware
064            log.warn("Turnout '{}' refers to an undefined Serial Node.", sName);
065        }
066        log.debug("new turnout {} for prefix {}", systemName, prefix);
067        return t;
068    }
069
070    @Override
071    public boolean allowMultipleAdditions(@Nonnull String systemName) {
072        return false; // Turnout address format is more than a simple number.
073    }
074
075    /** {@inheritDoc} */
076    @Override
077    public String createSystemName(@Nonnull String curAddress, @Nonnull String prefix) throws JmriException {
078        String tmpSName = prefix + "T" + curAddress;
079
080        if (curAddress.contains(":")) {
081            // Address format passed is in the form of node:cardOutput or node:card:address
082            int separator = curAddress.indexOf(":");
083            try {
084                nNode = Integer.parseInt(curAddress.substring(0, separator));
085                int nxSeparator = curAddress.indexOf(":", separator + 1);
086                if (nxSeparator == -1) {
087                    //Address has been entered in the format node:cardOutput
088                    bitNum = Integer.parseInt(curAddress.substring(separator + 1));
089                } else {
090                    //Address has been entered in the format node:card:output
091                    nCard = Integer.parseInt(curAddress.substring(separator + 1, nxSeparator)) * 100;
092                    bitNum = Integer.parseInt(curAddress.substring(nxSeparator + 1));
093                }
094            } catch (NumberFormatException ex) {
095                log.error("Unable to convert {} Hardware Address to a number", curAddress);
096                throw new JmriException("Hardware Address passed should be a number");
097            }
098            tmpSName = prefix + "T" + nNode + (nCard + bitNum);
099        } else {
100            bitNum = SerialAddress.getBitFromSystemName(tmpSName, prefix);
101            nNode = SerialAddress.getNodeAddressFromSystemName(tmpSName, prefix);
102            tmpSName = prefix + "T" + nNode + bitNum;
103            log.debug("createSystemName {}", tmpSName);
104        }
105        return (tmpSName);
106    }
107
108    private int nCard = 0;
109    private int bitNum = 0;
110    private int nNode = 0;
111
112    /**
113     * {@inheritDoc}
114     */
115    @Override
116    @Nonnull
117    public String validateSystemNameFormat(@Nonnull String name, @Nonnull Locale locale) {
118        return SerialAddress.validateSystemNameFormat(name, this, locale);
119    }
120
121    /**
122     * {@inheritDoc}
123     */
124    @Override
125    public NameValidity validSystemNameFormat(@Nonnull String systemName) {
126        return SerialAddress.validSystemNameFormat(systemName, typeLetter(), getSystemPrefix());
127    }
128
129    /**
130     * {@inheritDoc}
131     */
132    @Override
133    public String getEntryToolTip() {
134        return Bundle.getMessage("AddOutputEntryToolTip");
135    }
136
137    private final static Logger log = LoggerFactory.getLogger(SerialTurnoutManager.class);
138
139}