001package jmri.managers;
002
003import javax.annotation.Nonnull;
004import jmri.InstanceManager;
005import jmri.Logix;
006import jmri.LogixManager;
007import jmri.Manager;
008import jmri.implementation.DefaultLogix;
009import jmri.jmrit.beantable.LRouteTableAction;
010import jmri.jmrix.internal.InternalSystemConnectionMemo;
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014/**
015 * Basic Implementation of a LogixManager.
016 * <p>
017 * Note that Logix system names must begin with system prefix and type character,
018 * usually IX, and be followed by a string, usually, but not always, a number. This
019 * is enforced when a Logix is created.
020 * <p>
021 * The system names of Conditionals belonging to a Logix begin with the Logix's
022 * system name, then there is a capital C and a number.
023 *
024 * @author Dave Duchamp Copyright (C) 2007
025 */
026public class DefaultLogixManager extends AbstractManager<Logix>
027        implements LogixManager {
028
029    public DefaultLogixManager(InternalSystemConnectionMemo memo) {
030        super(memo);
031        jmri.InstanceManager.turnoutManagerInstance().addVetoableChangeListener(this);
032        jmri.InstanceManager.sensorManagerInstance().addVetoableChangeListener(this);
033        jmri.InstanceManager.memoryManagerInstance().addVetoableChangeListener(this);
034        jmri.InstanceManager.getDefault(jmri.SignalHeadManager.class).addVetoableChangeListener(this);
035        jmri.InstanceManager.getDefault(jmri.SignalMastManager.class).addVetoableChangeListener(this);
036        jmri.InstanceManager.getDefault(jmri.BlockManager.class).addVetoableChangeListener(this);
037        jmri.InstanceManager.lightManagerInstance().addVetoableChangeListener(this);
038        jmri.InstanceManager.getDefault(jmri.ConditionalManager.class).addVetoableChangeListener(this);
039        InstanceManager.getDefault(jmri.jmrit.logix.WarrantManager.class).addVetoableChangeListener(this);
040        InstanceManager.getDefault(jmri.jmrit.logix.OBlockManager.class).addVetoableChangeListener(this);
041        InstanceManager.getDefault(jmri.jmrit.entryexit.EntryExitPairs.class).addVetoableChangeListener(this);
042    }
043
044    @Override
045    public int getXMLOrder() {
046        return Manager.LOGIXS;
047    }
048
049    @Override
050    public char typeLetter() {
051        return 'X';
052    }
053
054    /**
055     * Create a new Logix if the Logix does not exist.
056     *
057     * @return null if a Logix with the same systemName or userName
058     * already exists, or if there is trouble creating a new Logix
059     */
060    @Override
061    public Logix createNewLogix(String systemName, String userName) {
062        // Check that Logix does not already exist
063        Logix x;
064        if (userName != null && !userName.equals("")) {
065            x = getByUserName(userName);
066            if (x != null) {
067                return null;
068            }
069        }
070        x = getBySystemName(systemName);
071        if (x != null) {
072            return null;
073        }
074        // Logix does not exist, create a new Logix
075        x = new DefaultLogix(systemName, userName);
076        // save in the maps
077        register(x);
078
079        // Keep track of the last created auto system name
080        updateAutoNumber(systemName);
081
082        return x;
083    }
084
085    @Override
086    public Logix createNewLogix(String userName) {
087        return createNewLogix(getAutoSystemName(), userName);
088    }
089
090    /**
091     * Remove an existing Logix and delete all its conditionals. Logix must have
092     * been deactivated before invoking this.
093     */
094    @Override
095    public void deleteLogix(Logix x) {
096        // delete the Logix
097        deregister(x);
098        x.dispose();
099        jmri.ConditionalManager cm = InstanceManager.getNullableDefault(jmri.ConditionalManager.class);
100        if (cm != null) {
101            cm.forgetParentLogix(x);
102        }
103    }
104
105    /**
106     * Activate all Logixs that are not currently active This method is called
107     * after a configuration file is loaded.
108     */
109    @Override
110    public void activateAllLogixs() {
111        // Guarantee Initializer executes first.
112        Logix x = getBySystemName(LRouteTableAction.getLogixInitializer());
113        if (x != null) {
114            x.activateLogix();
115            x.setGuiNames();
116        }
117        // iterate thru all Logixs that exist
118        java.util.Iterator<Logix> iter
119                = getNamedBeanSet().iterator();
120        while (iter.hasNext()) {
121            // get the next Logix
122            x = iter.next();
123
124            if (x.getSystemName().equals(LRouteTableAction.getLogixInitializer())) {
125                continue;
126            }
127
128            if (loadDisabled) {
129                // user has requested that Logixs be loaded disabled
130                log.warn("load disabled set - will not activate logic for: {}", x.getDisplayName());
131                x.setEnabled(false);
132            }
133            if (x.getEnabled()) {
134                //System.out.println("logix set enabled");
135                x.activateLogix();
136            }
137            x.setGuiNames();
138        }
139        // reset the load switch
140        loadDisabled = false;
141    }
142
143    /**
144     * Get an existing Logix. First looks up assuming name is a
145     * User Name. If this fails looks up assuming name is a System Name. If
146     * both fail, returns null.
147     */
148    @Override
149    public Logix getLogix(String name) {
150        Logix x = getByUserName(name);
151        if (x != null) {
152            return x;
153        }
154        return getBySystemName(name);
155    }
156
157    /**
158     * Support for loading Logixs in a disabled state to debug loops
159     */
160    boolean loadDisabled = false;
161
162    @Override
163    public void setLoadDisabled(boolean s) {
164        loadDisabled = s;
165    }
166
167    @Override
168    @Nonnull
169    public String getBeanTypeHandled(boolean plural) {
170        return Bundle.getMessage(plural ? "BeanNameLogixes" : "BeanNameLogix");
171    }
172
173    /**
174     * {@inheritDoc}
175     */
176    @Override
177    public Class<Logix> getNamedBeanClass() {
178        return Logix.class;
179    }
180
181    private static final Logger log = LoggerFactory.getLogger(DefaultLogixManager.class);
182
183}