001package jmri.jmrit.logixng.implementation.configurexml;
002
003import java.util.List;
004
005import jmri.ConfigureManager;
006import jmri.InstanceManager;
007import jmri.jmrit.logixng.ConditionalNG;
008import jmri.jmrit.logixng.ConditionalNG_Manager;
009import jmri.jmrit.logixng.LogixNG;
010import jmri.jmrit.logixng.LogixNG_Manager;
011import jmri.jmrit.logixng.MaleSocket;
012import jmri.jmrit.logixng.implementation.DefaultConditionalNG;
013import jmri.jmrit.logixng.implementation.DefaultConditionalNGManager;
014import jmri.jmrit.logixng.util.LogixNG_Thread;
015import jmri.util.ThreadingUtil;
016
017import org.jdom2.Element;
018
019/**
020 * Provides the functionality for configuring ConditionalNGManagers
021 *
022 * @author Dave Duchamp     Copyright (c) 2007
023 * @author Daniel Bergqvist Copyright (c) 2018
024 * @author Dave Sand        Copyright (c) 2021
025 */
026public class DefaultConditionalNGManagerXml extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML {
027
028    public DefaultConditionalNGManagerXml() {
029    }
030
031    /**
032     * Default implementation for storing the contents of a ConditionalNG_Manager
033     *
034     * @param o Object to store, of type ConditionalNG_Manager
035     * @return Element containing the complete info
036     */
037    @Override
038    public Element store(Object o) {
039        Element conditionalNGs = new Element("LogixNGConditionalNGs");
040        setStoreElementClass(conditionalNGs);
041        ConditionalNG_Manager tm = (ConditionalNG_Manager) o;
042        LogixNG_Manager lm = InstanceManager.getDefault(LogixNG_Manager.class);
043        if (tm != null) {
044            if (lm.getNamedBeanSet().isEmpty()) return null;
045            for (LogixNG logixNG : lm.getNamedBeanSet()) {
046                for (int i=0; i < logixNG.getNumConditionalNGs(); i++) {
047                    ConditionalNG conditionalNG = logixNG.getConditionalNG(i);
048
049                    log.debug("ConditionalNG system name is {}", conditionalNG.getSystemName());  // NOI18N
050                    boolean enabled = conditionalNG.isEnabled();
051                    boolean executeAtStartup = conditionalNG.isExecuteAtStartup();
052                    Element elem = new Element("ConditionalNG");  // NOI18N
053                    elem.addContent(new Element("systemName").addContent(conditionalNG.getSystemName()));  // NOI18N
054
055                    // store common part
056                    storeCommon(conditionalNG, elem);
057
058                    elem.addContent(new Element("thread").addContent(
059                            Integer.toString(conditionalNG.getStartupThreadId())));  // NOI18N
060
061                    Element e2 = new Element("Socket");
062                    e2.addContent(new Element("socketName").addContent(conditionalNG.getChild(0).getName()));
063                    MaleSocket socket = conditionalNG.getChild(0).getConnectedSocket();
064                    String socketSystemName;
065                    if (socket != null) {
066                        socketSystemName = socket.getSystemName();
067                    } else {
068                        socketSystemName = ((DefaultConditionalNG)conditionalNG).getSocketSystemName();
069                    }
070                    if (socketSystemName != null) {
071                        e2.addContent(new Element("systemName").addContent(socketSystemName));
072                    }
073                    elem.addContent(e2);
074
075                    elem.setAttribute("enabled", enabled ? "yes" : "no");  // NOI18N
076
077                    // executeAtStartup is by default true so only store it if it's false
078                    if (!executeAtStartup) {
079                        elem.setAttribute("executeAtStartup", "no");  // NOI18N
080                    }
081
082                    conditionalNGs.addContent(elem);
083                }
084            }
085        }
086        return (conditionalNGs);
087    }
088
089    /**
090     * Subclass provides implementation to create the correct top element,
091     * including the type information. Default implementation is to use the
092     * local class here.
093     *
094     * @param logixngs The top-level element being created
095     */
096    public void setStoreElementClass(Element logixngs) {
097        logixngs.setAttribute("class", this.getClass().getName());  // NOI18N
098    }
099
100    /**
101     * Create a ConditionalNG_Manager object of the correct class, then register and
102     * fill it.
103     *
104     * @param sharedConditionalNG  Shared top level Element to unpack.
105     * @param perNodeConditionalNG Per-node top level Element to unpack.
106     * @return true if successful
107     */
108    @Override
109    public boolean load(Element sharedConditionalNG, Element perNodeConditionalNG) {
110        // create the master object
111        replaceConditionalNGManager();
112        // load individual sharedLogix
113        loadConditionalNGs(sharedConditionalNG);
114        return true;
115    }
116
117    /**
118     * Utility method to load the individual ConditionalNG objects. If there's no
119     * additional info needed for a specific logixng type, invoke this with the
120     * parent of the set of ConditionalNG elements.
121     *
122     * @param conditionalNGs Element containing the ConditionalNG elements to load.
123     */
124    public void loadConditionalNGs(Element conditionalNGs) {
125        List<Element> conditionalNGList = conditionalNGs.getChildren("ConditionalNG");  // NOI18N
126        log.debug("Found {} ConditionalNGs", conditionalNGList.size() );  // NOI18N
127        ConditionalNG_Manager tm = InstanceManager.getDefault(jmri.jmrit.logixng.ConditionalNG_Manager.class);
128
129        for (int i = 0; i < conditionalNGList.size(); i++) {
130
131            Element conditionalNG_Element = conditionalNGList.get(i);
132
133            String sysName = getSystemName(conditionalNG_Element);
134            if (sysName == null) {
135                log.warn("unexpected null in systemName {}", conditionalNG_Element);  // NOI18N
136                break;
137            }
138
139            String userName = getUserName(conditionalNG_Element);
140
141            int threadId = LogixNG_Thread.DEFAULT_LOGIXNG_THREAD;
142            Element threadElem = conditionalNG_Element.getChild("thread");
143            if (threadElem != null) threadId = Integer.parseInt(threadElem.getTextTrim());
144
145            String enabled = "";
146            if (conditionalNG_Element.getAttribute("enabled") != null) {  // NOI18N
147                enabled = conditionalNG_Element.getAttribute("enabled").getValue();  // NOI18N
148            }
149            log.debug("create ConditionalNG: ({})({})", // NOI18N
150                sysName, userName == null ? "<null>" : userName);  // NOI18N
151
152            // Create a new ConditionalNG but don't setup the initial tree.
153            LogixNG logixNG = tm.getParentLogixNG(sysName);
154            if (logixNG == null) {
155                log.warn("unexpected null while finding parent logixNG for '{}'", conditionalNG_Element);  // NOI18N
156                break;
157            }
158
159            DefaultConditionalNG conditionalNG =
160                    (DefaultConditionalNG)tm.createConditionalNG(logixNG, sysName, userName, threadId);
161
162            if (conditionalNG != null) {
163                // load common part
164                loadCommon(conditionalNG, conditionalNG_Element);
165
166                Element socketName = conditionalNG_Element.getChild("Socket").getChild("socketName");
167                if (socketName != null) {
168                    conditionalNG.getFemaleSocket().setName(socketName.getTextTrim());
169                }
170                Element socketSystemName = conditionalNG_Element.getChild("Socket").getChild("systemName");
171                if (socketSystemName != null) {
172//                    log.warn("Socket system name: {}", socketSystemName.getTextTrim());
173                    conditionalNG.setSocketSystemName(socketSystemName.getTextTrim());
174                }
175
176                // set enabled/disabled if attribute was present
177                if ((enabled != null) && (!enabled.equals(""))) {
178                    if (enabled.equals("yes")) {  // NOI18N
179                        conditionalNG.setEnabled(true);
180                    } else if (enabled.equals("no")) {  // NOI18N
181                        conditionalNG.setEnabled(false);
182                    }
183                }
184
185                String executeAtStartup = "";
186                if (conditionalNG_Element.getAttribute("executeAtStartup") != null) {  // NOI18N
187                    executeAtStartup = conditionalNG_Element.getAttribute("executeAtStartup").getValue();  // NOI18N
188                }
189                // set enabled/disabled if attribute was present
190                if ((executeAtStartup != null) && (!executeAtStartup.equals(""))) {
191                    if (executeAtStartup.equals("yes")) {  // NOI18N
192                        conditionalNG.setExecuteAtStartup(true);
193                    } else if (executeAtStartup.equals("no")) {  // NOI18N
194                        conditionalNG.setExecuteAtStartup(false);
195                    }
196                }
197            }
198        }
199    }
200
201    /**
202     * Replace the current LogixManager, if there is one, with one newly created
203     * during a load operation. This is skipped if they are of the same absolute
204     * type.
205     */
206    protected void replaceConditionalNGManager() {
207        if (InstanceManager.getDefault(jmri.jmrit.logixng.ConditionalNG_Manager.class).getClass().getName()
208                .equals(DefaultConditionalNGManager.class.getName())) {
209            return;
210        }
211        // if old manager exists, remove it from configuration process
212        if (InstanceManager.getNullableDefault(jmri.jmrit.logixng.ConditionalNG_Manager.class) != null) {
213            ConfigureManager cmOD = InstanceManager.getNullableDefault(jmri.ConfigureManager.class);
214            if (cmOD != null) {
215                cmOD.deregister(InstanceManager.getDefault(jmri.jmrit.logixng.ConditionalNG_Manager.class));
216            }
217
218        }
219
220        ThreadingUtil.runOnGUI(() -> {
221            // register new one with InstanceManager
222            DefaultConditionalNGManager pManager = DefaultConditionalNGManager.instance();
223            InstanceManager.store(pManager, ConditionalNG_Manager.class);
224            // register new one for configuration
225            ConfigureManager cmOD = InstanceManager.getNullableDefault(jmri.ConfigureManager.class);
226            if (cmOD != null) {
227                cmOD.registerConfig(pManager, jmri.Manager.LOGIXNGS);
228            }
229        });
230    }
231
232    @Override
233    public int loadOrder() {
234        return InstanceManager.getDefault(jmri.jmrit.logixng.ConditionalNG_Manager.class).getXMLOrder();
235    }
236
237    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultConditionalNGManagerXml.class);
238}