001package jmri;
002
003import javax.annotation.Nonnull;
004import javax.annotation.CheckReturnValue;
005
006/**
007 * Interface that indicates that a Manager class
008 * capable of providing the
009 * next system name
010 * after the name of a given NamedBean.
011 * <p>
012 * This is used for e.g. providing a range of NamedBeans
013 *
014 * @author Bob Jacobsen Copyright 2022
015 */
016public interface NameIncrementingManager {
017
018    /**
019     * Determines if it is possible to add a range of NamedBeans in numerical
020     * order for a particular system implementation.
021     * <p>
022     * Default is not providing this service.  Systems should override this
023     * method if they do provide the service.
024     *
025     * @param systemName the system name to check against; appears to be ignored
026     *                   in all implementations
027     * @return true if possible; false otherwise
028     */
029    @CheckReturnValue
030    default boolean allowMultipleAdditions(@Nonnull String systemName) {
031        return false;
032    }
033
034    /**
035     * Get the next valid NamedBean system name.
036     * <p>
037     * For example, if the system name of the provided NamedBean is IS10, the next valid name is IS11.
038     * <p>
039     * This should not be called if {@link #allowMultipleAdditions} returns false.
040     * <p>
041     * Pays no attention to whether the next NamedBean already exists or not, just works out the name.
042     * Nor is there any guarantee that the return value can actually be created:
043     * a provide() call on the return value can still perhaps fail in some circumstances.
044     * <p>
045     * In some cases, there is no clear next address.  In that case, a JmriException is thrown.
046     * For example, some systems have no concept of a "next" address; Internal sensors don't necessarily
047     * have numeric suffixes; etc.
048     * <p>
049     * Default implementation works for names of the form (prefix)(type letter)(numeric string) by
050     * incrementing the numeric string as needed.
051     *
052     * @param  currentBean      The NamedBean who's system name that provides the base for "next"
053     * @return                  The next valid system name
054     * @throws JmriException    If unable to create a valid next address
055     */
056    @Nonnull
057    @CheckReturnValue
058    default String getNextValidSystemName(@Nonnull NamedBean currentBean) throws JmriException {
059        if (!allowMultipleAdditions(currentBean.getSystemName())) throw new UnsupportedOperationException("Not supported");
060
061        String currentName = currentBean.getSystemName();
062
063        int increment = ( currentBean instanceof VariableControlSpanBean ? ((VariableControlSpanBean)currentBean).getNumberControlBits() : 1);
064
065        String nextName = jmri.util.StringUtil.incrementLastNumberInString(currentName, increment);
066
067        if (nextName==null) {
068            throw new JmriException("No existing number found when incrementing " + currentName);
069        }
070        return nextName;
071
072    }
073}