001package jmri.managers;
002
003import javax.annotation.Nonnull;
004import java.util.Objects;
005
006import jmri.StringIO;
007import jmri.Manager;
008import jmri.SystemConnectionMemo;
009import jmri.StringIOManager;
010
011/**
012 * Abstract partial implementation of a StringIOManager.
013 * <p>
014 * Based on AbstractSignalHeadManager.java and AbstractSensorManager.java
015 *
016 * @author Dave Duchamp      Copyright (C) 2004
017 * @author Daniel Bergqvist  Copyright (C) 2020
018 */
019public abstract class AbstractStringIOManager extends AbstractManager<StringIO>
020        implements StringIOManager {
021
022    /**
023     * Create a new StringIOManager instance.
024     * 
025     * @param memo the system connection
026     */
027    public AbstractStringIOManager(SystemConnectionMemo memo) {
028        super(memo);
029    }
030
031    /** {@inheritDoc} */
032    @Override
033    public int getXMLOrder() {
034        return Manager.STRINGIOS;
035    }
036
037    /** {@inheritDoc} */
038    @Override
039    @Nonnull
040    public StringIO provideStringIO(@Nonnull String name) {
041        var t = getStringIO(name);
042        if (t == null) {
043            t = newStringIO(makeSystemName(name), null);
044        }
045        return t;
046    }
047
048    public StringIO getStringIO(@Nonnull String name) {
049        var t = getByUserName(name);
050        if (t != null) {
051            return t;
052        }
053        return getBySystemName(name);
054    }
055
056    /**
057     * Create a New StringIO.
058     * {@inheritDoc}
059     */
060    @Override
061    @Nonnull
062    final public StringIO newStringIO(@Nonnull String systemName, String userName) throws IllegalArgumentException {
063        log.debug(" newStringIO(\"{}\", \"{}\")", systemName, (userName == null ? "null" : userName));
064        Objects.requireNonNull(systemName, "SystemName cannot be null. UserName was "
065                + (userName == null ? "null" : userName));  // NOI18N
066        systemName = validateSystemNameFormat(systemName);
067        // return existing if there is one
068        StringIO s;
069        if (userName != null) {
070            s = getByUserName(userName);
071            if (s != null) {
072                if (getBySystemName(systemName) != s) {
073                    log.error("inconsistent user ({}) and system name ({}) results; userName related to ({})", userName, systemName, s.getSystemName());
074                }
075                return s;
076            }
077        }
078        s = getBySystemName(systemName);
079        if (s != null) {
080            if ((s.getUserName() == null) && (userName != null)) {
081                s.setUserName(userName);
082            } else if (userName != null) {
083                log.warn("Found StringIO via system name ({}) with non-null user name ({}). StringIO \"{}({})\" cannot be used.",
084                        systemName, s.getUserName(), systemName, userName);
085            }
086            return s;
087        }
088        // doesn't exist, make a new one
089        s = createNewStringIO(systemName, userName);
090        // save in the maps
091        register(s);
092
093        return s;
094    }
095
096
097
098    /**
099     * {@inheritDoc}
100     */
101    @Override
102    public char typeLetter() {
103        return 'C';
104    }
105
106    /**
107     * Get bean type handled.
108     *
109     * @return a string for the type of object handled by this manager
110     */
111    @Override
112    @Nonnull
113    public String getBeanTypeHandled(boolean plural) {
114        return Bundle.getMessage(plural ? "BeanNameStringIOs" : "BeanNameStringIO");
115    }
116
117    /**
118     * {@inheritDoc}
119     */
120    @Override
121    public Class<StringIO> getNamedBeanClass() {
122        return StringIO.class;
123    }
124    
125    /**
126     * Internal method to invoke the factory and create a new StringIO.
127     *
128     * Called after all the logic for returning an existing StringIO
129     * has been invoked.
130     * An existing SystemName is not found, existing UserName not found.
131     *
132     * Implementing classes should base StringIO on the system name, then add user name.
133     *
134     * @param systemName the system name to use for the new StringIO
135     * @param userName   the optional user name to use for the new StringIO
136     * @return the new StringIO
137     * @throws IllegalArgumentException if unsuccessful with reason for fail.
138     */
139    @Nonnull
140    abstract protected StringIO createNewStringIO(@Nonnull String systemName, String userName) throws IllegalArgumentException;
141
142    /** {@inheritDoc} */
143    @Override
144    public String getEntryToolTip() {
145        return Bundle.getMessage("EnterStringToolTip");
146    }
147
148
149    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractStringIOManager.class);
150
151}