001package jmri.managers;
002
003import java.util.ArrayList;
004import java.util.Set;
005import jmri.AddressedProgrammer;
006import jmri.AddressedProgrammerManager;
007import jmri.GlobalProgrammerManager;
008import jmri.InstanceInitializer;
009import jmri.InstanceManager;
010import jmri.Programmer;
011import jmri.ProgrammingMode;
012import jmri.beans.PropertyChangeSupport;
013import jmri.implementation.AbstractInstanceInitializer;
014import org.openide.util.lookup.ServiceProvider;
015import org.slf4j.Logger;
016import org.slf4j.LoggerFactory;
017
018/**
019 * Defers global programmer operations to the default global Programmer, and
020 * addressed programmer operations to the default AddressedProgrammer.
021 * <p>
022 * The underlying Programmer is looked up for each access to ensure that it is
023 * current.
024 *
025 * @see jmri.GlobalProgrammerManager
026 * @see jmri.AddressedProgrammerManager
027 * @author Bob Jacobsen Copyright (C) 2014
028 */
029public class DeferringProgrammerManager extends PropertyChangeSupport implements AddressedProgrammerManager, GlobalProgrammerManager {
030
031    public DeferringProgrammerManager() {
032    }
033
034    String userName = "<Default>";
035
036    /**
037     * Provides the human-readable representation for including
038     * ProgrammerManagers directly in user interface components, so it should
039     * return a user-provided name for this particular one.
040     */
041    @Override
042    public String getUserName() {
043        return userName;
044    }
045
046    /**
047     * Provides the human-readable representation for including
048     * ProgrammerManagers directly in user interface components, so it should
049     * return a user-provided name for this particular one.
050     */
051    @Override
052    public String toString() {
053        return getUserName();
054    }
055
056    @Override
057    public Programmer getGlobalProgrammer() {
058        GlobalProgrammerManager gp = InstanceManager.getNullableDefault(GlobalProgrammerManager.class);
059        if (gp == null || this.equals(gp)) {
060            log.debug("no defaultGlobal ProgrammerManager, getGlobalProgrammer returns null");
061            return null;
062        }
063        Programmer p = gp.getGlobalProgrammer();
064        log.debug("getGlobalProgrammer returns default service-mode programmer of type {} from {}",
065                (p != null ? p.getClass() : "(null)"), gp.getClass());
066        return p;
067    }
068
069    @Override
070    public Programmer reserveGlobalProgrammer() {
071        GlobalProgrammerManager gp = InstanceManager.getNullableDefault(GlobalProgrammerManager.class);
072        if (gp == null || this.equals(gp)) {
073            return null;
074        }
075        return gp.reserveGlobalProgrammer();
076    }
077
078    @Override
079    public void releaseGlobalProgrammer(Programmer p) {
080        GlobalProgrammerManager gp = InstanceManager.getNullableDefault(GlobalProgrammerManager.class);
081        if (gp == null || this.equals(gp)) {
082            return;
083        }
084        gp.releaseGlobalProgrammer(p);
085    }
086
087    /**
088     * Allow for implementations that do not support Service mode programming
089     *
090     * @return false if there's no chance of getting one
091     */
092    @Override
093    public boolean isGlobalProgrammerAvailable() {
094        GlobalProgrammerManager gp = InstanceManager.getNullableDefault(GlobalProgrammerManager.class);
095        if (gp == null || this.equals(gp)) {
096            return false;
097        }
098        return InstanceManager.getDefault(GlobalProgrammerManager.class).isGlobalProgrammerAvailable();
099    }
100
101    @Override
102    public AddressedProgrammer getAddressedProgrammer(boolean pLongAddress, int pAddress) {
103        AddressedProgrammerManager ap = InstanceManager.getNullableDefault(AddressedProgrammerManager.class);
104        if (ap == null || this.equals(ap)) {
105            return null;
106        }
107        return ap.getAddressedProgrammer(pLongAddress, pAddress);
108    }
109
110    @Override
111    public AddressedProgrammer reserveAddressedProgrammer(boolean pLongAddress, int pAddress) {
112        AddressedProgrammerManager ap = InstanceManager.getNullableDefault(AddressedProgrammerManager.class);
113        if (ap == null || this.equals(ap)) {
114            return null;
115        }
116        return ap.reserveAddressedProgrammer(pLongAddress, pAddress);
117    }
118
119    @Override
120    public void releaseAddressedProgrammer(AddressedProgrammer p) {
121        AddressedProgrammerManager ap = InstanceManager.getNullableDefault(AddressedProgrammerManager.class);
122        if (ap == null || this.equals(ap)) {
123            return;
124        }
125        ap.releaseAddressedProgrammer(p);
126    }
127
128    /**
129     * Default programmer does not provide Ops Mode
130     *
131     * @return false if there's no chance of getting one
132     */
133    @Override
134    public boolean isAddressedModePossible() {
135        AddressedProgrammerManager ap = InstanceManager.getNullableDefault(AddressedProgrammerManager.class);
136        if (ap == null || this.equals(ap)) {
137            return false;
138        }
139        return ap.isAddressedModePossible();
140    }
141
142    /**
143     * Default programmer doesn't depend on address
144     *
145     * @return false if there's no chance of getting one
146     */
147    @Override
148    public boolean isAddressedModePossible(jmri.LocoAddress l) {
149        return isAddressedModePossible();
150    }
151
152    @Override
153    public java.util.List<ProgrammingMode> getDefaultModes() {
154        AddressedProgrammerManager ap = InstanceManager.getNullableDefault(AddressedProgrammerManager.class);
155        if (ap == null || this.equals(ap)) {
156            return new ArrayList<>();
157        }
158        return InstanceManager.getDefault(AddressedProgrammerManager.class).getDefaultModes();
159    }
160
161    @ServiceProvider(service=InstanceInitializer.class)
162    public static final class Initializer extends AbstractInstanceInitializer {
163
164        @Override
165        public <T> Object getDefault(Class<T> type) {
166            if (type == AddressedProgrammerManager.class) {
167                return new DeferringProgrammerManager();
168            }
169            if (type == GlobalProgrammerManager.class) {
170                return new DeferringProgrammerManager();
171            }
172            return super.getDefault(type);
173        }
174
175        @Override
176        public Set<Class<?>> getInitalizes() {
177            Set<Class<?>> set = super.getInitalizes();
178            set.add(AddressedProgrammerManager.class);
179            set.add(GlobalProgrammerManager.class);
180            return set;
181        }
182
183    }
184    private final static Logger log = LoggerFactory.getLogger(DeferringProgrammerManager.class);
185}