001package jmri.jmrix.can.cbus;
002
003import java.util.Locale;
004import javax.annotation.*;
005import jmri.*;
006import jmri.jmrix.can.CanSystemConnectionMemo;
007import jmri.managers.AbstractLightManager;
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011/**
012 * Implement LightManager for CAN CBUS systems.
013 * <p>
014 * System names are "ML+n;-m", where M is the user configurable system prefix, n
015 * and m are the events (signed for on/off, separated by ;).
016 * <p>
017 * Lights must be explicitly created, they are not polled.
018 *
019 * @author Matthew Harris Copyright (C) 2015
020 * @author Egbert Broerse Copyright (C) 2019
021 * @since 3.11.7
022 */
023public class CbusLightManager extends AbstractLightManager {
024
025    /**
026     * Ctor using a given system connection memo
027     * @param memo System Connection
028     */
029    public CbusLightManager(CanSystemConnectionMemo memo) {
030        super(memo);
031    }
032
033    /**
034     * {@inheritDoc}
035     */
036    @Override
037    @Nonnull
038    public CanSystemConnectionMemo getMemo() {
039        return (CanSystemConnectionMemo) memo;
040    }
041
042    /**
043     * Internal method to invoke the factory, after all the logic for returning
044     * an existing method has been invoked.
045     *
046     * @return never null
047     */
048    @Nonnull
049    @Override
050    protected Light createNewLight(@Nonnull String systemName, String userName) throws IllegalArgumentException {
051        String addr;
052        // first, check validity
053        try {
054            validateSystemNameFormat(systemName);
055            addr = systemName.substring(getSystemNamePrefix().length());
056        } catch (IllegalArgumentException e) {
057            log.error("Unable to create CbusLight, {}", e.getMessage());
058            throw e;
059        }
060        // validate (will add "+" to unsigned int)
061        String newAddress = CbusAddress.validateSysName(addr);
062        // OK, make
063        Light l = new CbusLight(getSystemPrefix(), newAddress, getMemo().getTrafficController());
064        l.setUserName(userName);
065        return l;
066    }
067
068    /**
069     * {@inheritDoc}
070     */
071    @Override
072    public boolean allowMultipleAdditions(@Nonnull String systemName) {
073        return true;
074    }
075
076    /**
077     * {@inheritDoc}
078     */
079    @Override
080    @Nonnull
081    public String validateSystemNameFormat(@Nonnull String name, @Nonnull Locale locale) {
082        validateSystemNamePrefix(name, locale);
083        try {
084            CbusAddress.validateSysName(name.substring(getSystemNamePrefix().length()));
085        } catch (IllegalArgumentException ex) {
086            throw new jmri.NamedBean.BadSystemNameException(locale, "InvalidSystemNameCustom", ex.getMessage());
087        }
088        return name;
089    }
090
091    /**
092     * {@inheritDoc}
093     */
094    @Override
095    public NameValidity validSystemNameFormat(@Nonnull String systemName) {
096        String addr;
097        try {
098            addr = systemName.substring(getSystemPrefix().length() + 1); // get only the address part
099            CbusAddress.validateSysName(addr);
100        } catch (StringIndexOutOfBoundsException | IllegalArgumentException e) {
101            return NameValidity.INVALID;
102        }
103        return NameValidity.VALID;
104    }
105
106    /**
107     * {@inheritDoc}
108     */
109    @Override
110    public String createSystemName(@Nonnull String curAddress, @Nonnull String prefix) throws jmri.JmriException {
111        try {
112            return prefix + typeLetter() + CbusAddress.validateSysName(curAddress);
113        } catch (IllegalArgumentException e) {
114            throw new jmri.JmriException(e.getMessage());
115        }
116    }
117
118    /**
119     * {@inheritDoc}
120     */
121    @Override
122    public boolean validSystemNameConfig(@Nonnull String systemName) {
123        return validSystemNameFormat(systemName) == NameValidity.VALID;
124    }
125
126    @Override
127    @Nonnull
128    @CheckReturnValue
129    public String getNextValidSystemName(@Nonnull NamedBean currentBean) throws JmriException {
130        if (!allowMultipleAdditions(currentBean.getSystemName())) throw new UnsupportedOperationException("Not supported");
131
132        String currentName = currentBean.getSystemName();
133        String suffix = Manager.getSystemSuffix(currentName);
134        String type = Manager.getTypeLetter(currentName);
135        String prefix = Manager.getSystemPrefix(currentName);
136
137        String nextName = CbusAddress.getIncrement(suffix);
138
139        if (nextName==null) {
140            throw new JmriException("No existing number found when incrementing " + currentName);
141        }
142        return prefix+type+nextName;
143
144    }
145
146    /**
147     * {@inheritDoc}
148     */
149    @Override
150    public String getEntryToolTip() {
151        return Bundle.getMessage("AddCbusLightEntryToolTip");
152    }
153
154    private static final Logger log = LoggerFactory.getLogger(CbusLightManager.class);
155
156}