001package jmri.managers;
002
003import java.util.List;
004import javax.annotation.Nonnull;
005import javax.annotation.CheckForNull;
006import jmri.AddressedProgrammer;
007import jmri.AddressedProgrammerManager;
008import jmri.GlobalProgrammerManager;
009import jmri.Programmer;
010import jmri.ProgrammingMode;
011import jmri.beans.PropertyChangeSupport;
012import org.slf4j.Logger;
013import org.slf4j.LoggerFactory;
014
015/**
016 * Provides a very basic implementation of a programmer manager by providing a
017 * union of the AddressedProgrammerManager and GlobalProgrammerManager
018 * interfaces.
019 * <p>
020 * This implementation requires a service-mode Programmer at construction time
021 * and returns that Programmer for all global programming mode requests. This
022 * implementation of AddressedProgrammerManager always returns null for Op Mode,
023 * or addressed programmer requests, indicating there is no programmer of that
024 * type.
025 *
026 * @see jmri.AddressedProgrammerManager
027 * @see jmri.GlobalProgrammerManager
028 * @author Bob Jacobsen Copyright (C) 2001, 2015, 2016
029 */
030public class DefaultProgrammerManager extends PropertyChangeSupport implements AddressedProgrammerManager, GlobalProgrammerManager {
031
032    // For the record, these were the original numerical definitions:
033    //     public static final ProgrammingMode NONE              = new ProgrammingMode("NONE", 0);
034    //     public static final ProgrammingMode REGISTERMODE      = new ProgrammingMode("REGISTERMODE", 11);
035    //     public static final ProgrammingMode PAGEMODE          = new ProgrammingMode("PAGEMODE", 21);
036    //     public static final ProgrammingMode DIRECTBITMODE     = new ProgrammingMode("DIRECTBITMODE", 31);
037    //     public static final ProgrammingMode DIRECTBYTEMODE    = new ProgrammingMode("DIRECTBYTEMODE", 32);
038    //     public static final ProgrammingMode ADDRESSMODE       = new ProgrammingMode("ADDRESSMODE", 41);
039    //     public static final ProgrammingMode OPSBYTEMODE       = new ProgrammingMode("OPSBYTEMODE", 101);
040    //     public static final ProgrammingMode OPSBITMODE        = new ProgrammingMode("OPSBITMODE", 102);
041    //     public static final ProgrammingMode OPSACCBYTEMODE    = new ProgrammingMode("OPSACCBYTEMODE", 111);
042    //     public static final ProgrammingMode OPSACCBITMODE     = new ProgrammingMode("OPSACCBITMODE", 112);
043    //     public static final ProgrammingMode OPSACCEXTBYTEMODE = new ProgrammingMode("OPSACCEXTBYTEMODE", 121);
044    //     public static final ProgrammingMode OPSACCEXTBITMODE  = new ProgrammingMode("OPSACCEXTBITMODE", 122);
045    private Programmer programmer;
046
047    /**
048     * Constructor when no global programmer is available.
049     */
050    public DefaultProgrammerManager() {
051        this(null);  // indicates not present
052    }
053
054    /**
055     * Constructor with a programmer.
056     *
057     * @param programmer the programmer to use; if null, acts as if no
058     *                   programmer is available
059     */
060    public DefaultProgrammerManager(@CheckForNull Programmer programmer) {
061        this.programmer = programmer;
062    }
063
064    /**
065     * Constructor with a programmer and associated connection.
066     *
067     * @param programmer the programmer to use; if null, acts as if no
068     *                   programmer is available
069     * @param memo       the associated connection
070     */
071    public DefaultProgrammerManager(@CheckForNull Programmer programmer, @Nonnull jmri.SystemConnectionMemo memo) {
072        this(programmer);
073        this.userName = memo.getUserName();
074    }
075
076    private String userName = "<Default>";
077
078    /**
079     * Provides the human-readable representation for including
080     * ProgrammerManagers directly in user interface components, so it should
081     * return a user-provided name for this particular one.
082     */
083    @Override
084    public String getUserName() {
085        return userName;
086    }
087
088    /**
089     * Provides the human-readable representation for including
090     * ProgrammerManagers directly in user interface components, so it should
091     * return a user-provided name for this particular one.
092     */
093    @Override
094    public String toString() {
095        return getUserName();
096    }
097
098    @Override
099    public final Programmer getGlobalProgrammer() {
100        return getConcreteGlobalProgrammer();
101    }
102
103    /**
104     * Gain access to the Global Mode Programmer without reservation.
105     *
106     * @return null only if there isn't a Global Mode Programmer available via
107     *         this Manager.
108     */
109    @CheckForNull
110    protected Programmer getConcreteGlobalProgrammer() {
111        log.debug("return default service-mode programmer of type {}", (programmer != null ? programmer.getClass() : "(null)"));
112        return programmer;
113    }
114
115    @Override
116    public final AddressedProgrammer getAddressedProgrammer(boolean pLongAddress, int pAddress) {
117        return getConcreteAddressedProgrammer(pLongAddress, pAddress);
118    }
119
120    /**
121     * Gain access to a Addressed Mode Programmer without reservation.
122     *
123     * @param pLongAddress true if this is a long (14 bit) address, else false
124     * @param pAddress     specific decoder address to use
125     * @return null only if there isn't an Ops Mode Programmer in the system
126     */
127    @CheckForNull
128    protected AddressedProgrammer getConcreteAddressedProgrammer(boolean pLongAddress, int pAddress) {
129        return null;
130    }
131
132    @Override
133    public final Programmer reserveGlobalProgrammer() {
134        return reserveConcreteGlobalProgrammer();
135    }
136
137    /**
138     * Gain access to the Global Mode Programmer, in the process reserving it
139     * for yourself.
140     *
141     * @return null if the existing Global Mode programmer is in use
142     */
143    protected Programmer reserveConcreteGlobalProgrammer() {
144        return programmer;
145    }
146
147    @Override
148    public void releaseGlobalProgrammer(@Nonnull Programmer p) {
149    }
150
151    @Override
152    public final AddressedProgrammer reserveAddressedProgrammer(boolean pLongAddress, int pAddress) {
153        return reserveConcreteAddressedProgrammer(pLongAddress, pAddress);
154    }
155
156    /**
157     * Gain access to a (the) Addressed Mode Programmer, in the process
158     * reserving it for yourself.
159     *
160     * @param pLongAddress true if this is a long (14 bit) address, else false
161     * @param pAddress     Specific decoder address to use
162     * @return null if the address is in use by a reserved programmer
163     */
164    @CheckForNull
165    protected AddressedProgrammer reserveConcreteAddressedProgrammer(boolean pLongAddress, int pAddress) {
166        return null;
167    }
168
169    @Override
170    public void releaseAddressedProgrammer(@Nonnull AddressedProgrammer p) {
171    }
172
173    /**
174     * {@inheritDoc}
175     *
176     * @return always false in this implementation
177     */
178    @Override
179    public boolean isAddressedModePossible() {
180        return false;
181    }
182
183    /**
184     * {@inheritDoc}
185     *
186     * @return always false in this implementation
187     */
188    @Override
189    public boolean isAddressedModePossible(@Nonnull jmri.LocoAddress l) {
190        return isAddressedModePossible();
191    }
192
193    /**
194     * {@inheritDoc}
195     *
196     * @return always false in this implementation
197     */
198    @Override
199    public boolean isGlobalProgrammerAvailable() {
200        return true;
201    }
202
203    /**
204     * {@inheritDoc}
205     *
206     * @return a default list of programming modes that most
207     *         {@link jmri.AddressedProgrammer}s make available
208     */
209    @Override
210    public List<ProgrammingMode> getDefaultModes() {
211        List<ProgrammingMode> retval = new java.util.ArrayList<>();
212        retval.add(ProgrammingMode.OPSBYTEMODE);
213        return retval;
214    }
215
216    public void dispose() {
217        if (programmer != null) {
218            programmer.dispose();
219        }
220    }
221
222    private final static Logger log = LoggerFactory.getLogger(DefaultProgrammerManager.class);
223}