001package jmri.jmrix.nce;
002
003import java.util.Locale;
004import javax.annotation.Nonnull;
005import jmri.Light;
006import jmri.NmraPacket;
007import jmri.managers.AbstractLightManager;
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011/**
012 * Implement LightManager for NCE systems
013 * <p>
014 * System names are "NLnnnnn", where N is the user configurable system prefix,
015 * nnnnn is the stationary decoder address.
016 * <p>
017 * Based in part on SerialLightManager.java
018 *
019 * @author Dave Duchamp Copyright (C) 2010
020 */
021public class NceLightManager extends AbstractLightManager {
022
023    public NceLightManager(NceSystemConnectionMemo memo) {
024        super(memo);
025    }
026
027    /**
028     * {@inheritDoc}
029     */
030    @Override
031    @Nonnull
032    public NceSystemConnectionMemo getMemo() {
033        return (NceSystemConnectionMemo) memo;
034    }
035
036    /**
037     * Method to create a new Light based on the system name
038     * Assumes calling method has checked
039     * that a Light with this system name does not already exist
040     */
041    @Override
042    @Nonnull
043    protected Light createNewLight(@Nonnull String systemName, String userName) throws IllegalArgumentException {
044        Light lgt;
045        // check if the output bit is available
046        int bitNum = getBitFromSystemName(systemName);
047        if (bitNum == 0) {
048            throw new IllegalArgumentException("Invalid Bit from System Name: " + systemName);
049        }
050        // Normalize the systemName
051        String sName = getSystemPrefix() + "L" + bitNum;   // removes any leading zeros
052        // make the new Light object
053        lgt = new NceLight(sName, userName, getMemo().getNceTrafficController(), this);
054        return lgt;
055    }
056
057    /**
058     * Get the bit address from the system name.
059     *
060     * @param systemName system name for light
061     * @return index value for light
062     */
063    public int getBitFromSystemName(String systemName) {
064        // validate the system Name leader characters
065        if ((!systemName.startsWith(getSystemPrefix())) || (!systemName.startsWith(getSystemPrefix() + "L"))) {
066            // here if an illegal nce light system name 
067            log.error("illegal character in header field of nce light system name: {}", systemName);
068            return (0);
069        }
070        // name must be in the NLnnnnn format (N is user configurable)
071        int num = 0;
072        try {
073            num = Integer.parseInt(systemName.substring(
074                    getSystemPrefix().length() + 1, systemName.length())
075                  );
076        } catch (NumberFormatException e) {
077            log.debug("illegal character in number field of system name: {}", systemName);
078            return (0);
079        }
080        if (num < NmraPacket.accIdLowLimit) {
081            log.error("invalid nce light system name: {}", systemName);
082            return (0);
083        } else if (num > NmraPacket.accIdHighLimit) {
084            log.warn("bit number out of range in nce light system name: {}", systemName);
085            return (0);
086        }
087        return (num);
088    }
089
090    /**
091     * A method that determines if it is possible to add a range of lights in
092     * numerical order eg 11 thru 18, primarily used to show/not show the add
093     * range box in the add Light window
094     */
095    @Override
096    public boolean allowMultipleAdditions(@Nonnull String systemName) {
097        return true;
098    }
099
100    /**
101     * {@inheritDoc}
102     */
103    @Override
104    @Nonnull
105    public String validateSystemNameFormat(@Nonnull String name, @Nonnull Locale locale) {
106        return super.validateNmraAccessorySystemNameFormat(name, locale);
107    }
108
109    /**
110     * {@inheritDoc}
111     */
112    @Override
113    public NameValidity validSystemNameFormat(@Nonnull String systemName) {
114        return (getBitFromSystemName(systemName) != 0) ? NameValidity.VALID : NameValidity.INVALID;
115    }
116
117    /**
118     * Public method to validate system name for configuration.
119     *
120     * @return 'true' if system name has a valid meaning in current configuration,
121     * else returns 'false'. For now, this method always returns 'true'; it is needed for the
122     * Abstract Light class.
123     */
124    @Override
125    public boolean validSystemNameConfig(@Nonnull String systemName) {
126        return (true);
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(NceLightManager.class);
138
139}