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    @Override
049    public StringIO getStringIO(@Nonnull String name) {
050        var t = getByUserName(name);
051        if (t != null) {
052            return t;
053        }
054        return getBySystemName(name);
055    }
056
057    /**
058     * Create a New StringIO.
059     * {@inheritDoc}
060     */
061    @Override
062    @Nonnull
063    final public StringIO newStringIO(@Nonnull String systemName, String userName) throws IllegalArgumentException {
064        log.debug(" newStringIO(\"{}\", \"{}\")", systemName, (userName == null ? "null" : userName));
065        Objects.requireNonNull(systemName, "SystemName cannot be null. UserName was "
066                + (userName == null ? "null" : userName));  // NOI18N
067        systemName = validateSystemNameFormat(systemName);
068        // return existing if there is one
069        StringIO s;
070        if (userName != null) {
071            s = getByUserName(userName);
072            if (s != null) {
073                if (getBySystemName(systemName) != s) {
074                    log.error("inconsistent user ({}) and system name ({}) results; userName related to ({})", userName, systemName, s.getSystemName());
075                }
076                return s;
077            }
078        }
079        s = getBySystemName(systemName);
080        if (s != null) {
081            if ((s.getUserName() == null) && (userName != null)) {
082                s.setUserName(userName);
083            } else if (userName != null) {
084                log.warn("Found StringIO via system name ({}) with non-null user name ({}). StringIO \"{}({})\" cannot be used.",
085                        systemName, s.getUserName(), systemName, userName);
086            }
087            return s;
088        }
089        // doesn't exist, make a new one
090        s = createNewStringIO(systemName, userName);
091        // save in the maps
092        register(s);
093
094        return s;
095    }
096
097
098
099    /**
100     * {@inheritDoc}
101     */
102    @Override
103    public char typeLetter() {
104        return 'C';
105    }
106
107    /**
108     * Get bean type handled.
109     *
110     * @return a string for the type of object handled by this manager
111     */
112    @Override
113    @Nonnull
114    public String getBeanTypeHandled(boolean plural) {
115        return Bundle.getMessage(plural ? "BeanNameStringIOs" : "BeanNameStringIO");
116    }
117
118    /**
119     * {@inheritDoc}
120     */
121    @Override
122    public Class<StringIO> getNamedBeanClass() {
123        return StringIO.class;
124    }
125    
126    /**
127     * Internal method to invoke the factory and create a new StringIO.
128     *
129     * Called after all the logic for returning an existing StringIO
130     * has been invoked.
131     * An existing SystemName is not found, existing UserName not found.
132     *
133     * Implementing classes should base StringIO on the system name, then add user name.
134     *
135     * @param systemName the system name to use for the new StringIO
136     * @param userName   the optional user name to use for the new StringIO
137     * @return the new StringIO
138     * @throws IllegalArgumentException if unsuccessful with reason for fail.
139     */
140    @Nonnull
141    abstract protected StringIO createNewStringIO(@Nonnull String systemName, String userName) throws IllegalArgumentException;
142
143    /** {@inheritDoc} */
144    @Override
145    public String getEntryToolTip() {
146        return Bundle.getMessage("EnterStringToolTip");
147    }
148
149
150    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractStringIOManager.class);
151
152}