001package jmri.managers;
002
003import java.util.Objects;
004import javax.annotation.Nonnull;
005import jmri.Audio;
006import jmri.AudioException;
007import jmri.AudioManager;
008import jmri.SystemConnectionMemo;
009import org.slf4j.Logger;
010import org.slf4j.LoggerFactory;
011
012/**
013 * Abstract partial implementation of an AudioManager.
014 *
015 * <hr>
016 * This file is part of JMRI.
017 * <p>
018 * JMRI is free software; you can redistribute it and/or modify it under the
019 * terms of version 2 of the GNU General Public License as published by the Free
020 * Software Foundation. See the "COPYING" file for a copy of this license.
021 * <p>
022 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
024 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
025 *
026 * @author Matthew Harris copyright (c) 2009
027 */
028public abstract class AbstractAudioManager extends AbstractManager<Audio>
029        implements AudioManager {
030
031    public AbstractAudioManager(SystemConnectionMemo memo) {
032        super(memo);
033    }
034
035    /** {@inheritDoc} */
036    @Override
037    public char typeLetter() {
038        return 'A';
039    }
040
041    /** {@inheritDoc} */
042    @Override
043    @Nonnull
044    public Audio provideAudio(@Nonnull String name) throws AudioException {
045        Audio a = getAudio(name);
046        if (a != null) {
047            return a;
048        }
049        if (name.startsWith(getSystemPrefix() + typeLetter())) {
050            return newAudio(name, null);
051        } else {
052            return newAudio(makeSystemName(name), null);
053        }
054    }
055
056    /** {@inheritDoc} */
057    @Override
058    public Audio getAudio(@Nonnull String name) {
059        Audio a = getByUserName(name);
060        if (a != null) {
061            return a;
062        }
063
064        return getBySystemName(name);
065    }
066
067    /** {@inheritDoc} */
068    @Override
069    public Audio getBySystemName(@Nonnull String key) {
070        return _tsys.get(key);
071    }
072
073    /** {@inheritDoc} */
074    @Override
075    public Audio getByUserName(@Nonnull String key) {
076        //return key==null?null:_tuser.get(key);
077        if (key == null) {
078            return (null);
079        }
080        Audio rv = _tuser.get(key);
081        if (rv == null) {
082            rv = this.getBySystemName(key);
083        }
084        return (rv);
085    }
086
087    /** {@inheritDoc} */
088    @Override
089    @Nonnull
090    public Audio newAudio(@Nonnull String systemName, String userName) throws AudioException {
091        Objects.requireNonNull(systemName, "SystemName cannot be null. UserName was " + (userName == null ? "null" : userName));  // NOI18N
092
093        log.debug("new Audio: {}; {}", systemName, userName); // NOI18N
094 
095        // is system name in correct format?
096        if ((!systemName.startsWith("" + getSystemPrefix() + typeLetter() + Audio.BUFFER))
097                && (!systemName.startsWith("" + getSystemPrefix() + typeLetter() + Audio.SOURCE))
098                && (!systemName.startsWith("" + getSystemPrefix() + typeLetter() + Audio.LISTENER))) {
099            log.error("Invalid system name for Audio: {} needed either {}{}" + Audio.BUFFER + " or {}{}" + Audio.SOURCE + " or {}{}" + Audio.LISTENER, systemName, getSystemPrefix(), typeLetter(), getSystemPrefix(), typeLetter(), getSystemPrefix(), typeLetter());        // NOI18N
100            throw new AudioException("Invalid system name for Audio: " + systemName
101                    + " needed either " + getSystemPrefix() + typeLetter() + Audio.BUFFER
102                    + " or " + getSystemPrefix() + typeLetter() + Audio.SOURCE
103                    + " or " + getSystemPrefix() + typeLetter() + Audio.LISTENER);
104        }
105
106        // return existing if there is one
107        Audio s;
108        if ((userName != null) && ((s = getByUserName(userName)) != null)) {
109            if (getBySystemName(systemName) != s) {
110                log.error("inconsistent user ({}) and system name ({}) results; userName related to ({})",
111                        userName, systemName, s.getSystemName());
112            }
113            log.debug("Found existing Audio ({}). Returning existing (1).", s.getSystemName());  // NOI18N
114            return s;
115        }
116        if ((s = getBySystemName(systemName)) != null) {
117            if ((s.getUserName() == null) && (userName != null)) {
118                s.setUserName(userName);
119            } else if (userName != null) {
120                log.warn("Found audio via system name ({}) with non-null user name ({})", systemName, userName); // NOI18N
121            }
122            log.debug("Found existing Audio ({}). Returning existing (2).", s.getSystemName());
123            return s;
124        }
125
126        log.debug("Existing audio not found. Creating new. ({})", systemName);  // NOI18N
127        // doesn't exist, make a new one
128        s = createNewAudio(systemName, userName);
129
130        // save in the maps
131        if (s != null) {
132            register(s);
133        } else {
134            // must have failed to create
135            throw new IllegalArgumentException("can't create audio with System Name \""+systemName+"\"");  // NOI18N
136        }
137
138        return s;
139    }
140
141    /**
142     * Internal method to invoke the factory, after all the logic for returning
143     * an existing Audio has been invoked.
144     *
145     * @param systemName Audio object system name (for example IAS1, IAB4)
146     * @param userName   Audio object user name
147     * @return never null
148     * @throws AudioException if error occurs during creation
149     */
150    abstract protected Audio createNewAudio(@Nonnull String systemName, String userName) throws AudioException;
151
152    /** {@inheritDoc} */
153    @Override
154    @Nonnull 
155    public String getBeanTypeHandled(boolean plural) {
156        return Bundle.getMessage(plural ? "BeanNameAudios" : "BeanNameAudio");  // NOI18N
157    }
158
159    /**
160     * {@inheritDoc}
161     */
162    @Override
163    public Class<Audio> getNamedBeanClass() {
164        return Audio.class;
165    }
166
167    private static final Logger log = LoggerFactory.getLogger(AbstractAudioManager.class);
168
169}