001package jmri.jmrix.dccpp;
002
003import static jmri.jmrix.dccpp.DCCppConstants.MAX_TURNOUT_ADDRESS;
004import javax.annotation.Nonnull;
005import java.util.Locale;
006import jmri.Light;
007import jmri.managers.AbstractLightManager;
008
009/**
010 * Implement LightManager for DCC++ systems.
011 * <p>
012 * System names are "DxppSnnn", where Dx is the system prefix and nnn is the sensor number without padding.
013 * <p>
014 * Based in part on SerialLightManager.java
015 *
016 * @author Paul Bender Copyright (C) 2008
017 * @author Mark Underwood Copyright (C) 2015
018 */
019public class DCCppLightManager extends AbstractLightManager {
020
021    private DCCppTrafficController tc = null;
022
023    /**
024     * Create an new DCC++ LightManager.
025     * Has to register for DCC++ events.
026     *
027     * @param memo the supporting system connection memo
028     */
029    public DCCppLightManager(DCCppSystemConnectionMemo memo) {
030        super(memo);
031        this.tc = memo.getDCCppTrafficController();
032    }
033
034    /**
035     * {@inheritDoc}
036     */
037    @Override
038    @Nonnull
039    public DCCppSystemConnectionMemo getMemo() {
040        return (DCCppSystemConnectionMemo) memo;
041    }
042
043    /**
044     * Create a new Light based on the system name.
045     * Assumes calling method has checked that a Light with this
046     * system name does not already exist.
047     *
048     * @return null if the system name is not in a valid format
049     */
050    @Override
051    @Nonnull
052    protected Light createNewLight(String systemName, String userName) throws IllegalArgumentException {
053        // check if the output bit is available
054        int bitNum = getBitFromSystemName(systemName);
055        if (bitNum == 0) {
056            throw new IllegalArgumentException("Invalid Bit from System Name: " + systemName);
057        }
058        // Normalize the systemName
059        String sName = getSystemNamePrefix() + bitNum;   // removes any leading zeros
060        // make the new Light object
061        return new DCCppLight(tc, this, sName, userName);
062    }
063
064    /**
065     * {@inheritDoc}
066     */
067    @Override
068    public NameValidity validSystemNameFormat(@Nonnull String systemName) {
069        return (getBitFromSystemName(systemName) != 0) ? NameValidity.VALID : NameValidity.INVALID;
070    }
071
072    /**
073     * {@inheritDoc}
074     */
075    @Override
076    @Nonnull
077    public String validateSystemNameFormat(@Nonnull String systemName, @Nonnull Locale locale) {
078        return validateIntegerSystemNameFormat(systemName, 1, MAX_TURNOUT_ADDRESS, locale);
079    }
080
081    /**
082     * Get the bit address from the system name.
083     * @param systemName a valid Light System Name
084     * @return the light number extracted from the system name
085     */
086    public int getBitFromSystemName(String systemName) {
087        try {
088            validateSystemNameFormat(systemName, Locale.getDefault());
089        } catch (IllegalArgumentException ex) {
090            return 0;
091        }
092        return Integer.parseInt(systemName.substring(getSystemNamePrefix().length()));
093    }
094
095    /**
096     * {@inheritDoc}
097     */
098    @Override
099    public boolean allowMultipleAdditions(@Nonnull String systemName) {
100        return true;
101    }
102
103    /**
104     * {@inheritDoc}
105     */
106    @Override
107    public String getEntryToolTip() {
108        return Bundle.getMessage("AddOutputEntryToolTip");
109    }
110
111}