001package jmri.implementation.configurexml;
002
003import java.util.List;
004import jmri.InstanceManager;
005import jmri.JmriException;
006import jmri.SignalAppearanceMap;
007import jmri.implementation.MatrixSignalMast;
008import org.jdom2.Element;
009
010/**
011 * Handle XML configuration for MatrixSignalMast objects.
012 *
013 * @author Bob Jacobsen Copyright: (C) 2009
014 * @author Egbert Broerse Copyright: (C) 2016, 2017
015 */
016public class MatrixSignalMastXml
017        extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML {
018
019    public MatrixSignalMastXml() {
020    }
021
022    /**
023     * Default implementation for storing the contents of a
024     * MatrixSignalMastManager.
025     *
026     * @param o Object to store, of type MatrixSignalMast
027     * @return e Element containing the complete info
028     */
029    @Override
030    public Element store(Object o) { // from mast p to XML
031        MatrixSignalMast p = (MatrixSignalMast) o;
032
033        Element e = new Element("matrixsignalmast");
034        e.setAttribute("class", this.getClass().getName());
035
036        // include content
037        e.addContent(new Element("systemName").addContent(p.getSystemName()));
038
039        storeCommon(p, e); // username, comment & properties
040
041        // mast properties:
042        Element unlit = new Element("unlit");
043        if (p.allowUnLit()) {
044            unlit.setAttribute("allowed", "yes");
045            unlit.addContent(new Element("bitString").addContent(p.getUnLitChars()));
046        } else {
047            unlit.setAttribute("allowed", "no");
048        }
049        e.addContent(unlit);
050
051        // store mast-specific delay, since 4.15.7
052        Element delay = new Element("delay");
053        if (p.getMatrixMastCommandDelay() > 0) {
054            delay.setAttribute("duration", Integer.toString(p.getMatrixMastCommandDelay()));
055        } else {
056            delay.setAttribute("duration", "0");
057        }
058        e.addContent(delay);
059
060        List<String> outputs = p.getOutputs();
061        // convert char[] to xml-storable simple String
062        // outputs (either: turnouts (bean names) [or ToDo: DCC addresses (numbers)]
063        // spotted by SpotBugs as to never be null (check on creation of MatrixMast)
064        Element outps = new Element("outputs");
065        int i = 1;
066        for (String _output : outputs) {
067            log.debug("   handling {}", _output);
068            String key = ("output" + i);
069            Element outp = new Element("output");
070            outp.setAttribute("matrixCol", key);
071            outp.addContent(p.getOutputName(i)); // get name (Turnout)
072            outps.addContent(outp);
073            i++;
074        }
075        if (outputs.size() != 0) {
076            e.addContent(outps);
077        }
078
079        // string of "001010" describing matrix row per aspect
080        SignalAppearanceMap appMap = p.getAppearanceMap();
081        if (appMap != null) {
082            Element bss = new Element("bitStrings");
083            java.util.Enumeration<String> aspects = appMap.getAspects();
084            while (aspects.hasMoreElements()) {
085                String key = aspects.nextElement();
086                Element bs = new Element("bitString");
087                bs.setAttribute("aspect", key);
088                bs.addContent(p.getBitstring(key));
089                bss.addContent(bs);
090            }
091            e.addContent(bss);
092
093        }
094        List<String> disabledAspects = p.getDisabledAspects();
095        if (disabledAspects != null) {
096            Element el = new Element("disabledAspects");
097            for (String aspect : disabledAspects) {
098                Element ele = new Element("disabledAspect");
099                ele.addContent(aspect);
100                el.addContent(ele);
101            }
102            if (disabledAspects.size() != 0) {
103                e.addContent(el);
104            }
105        }
106        if (p.resetPreviousStates()) {
107            e.addContent(new Element("resetPreviousStates").addContent("yes"));
108        }
109        return e;
110    }
111
112    @Override
113    public boolean load(Element shared, Element perNode) { // from XML to mast m
114        MatrixSignalMast m;
115        String sys = getSystemName(shared);
116        try {
117            m = (MatrixSignalMast) InstanceManager.getDefault(jmri.SignalMastManager.class)
118                    .provideCustomSignalMast(sys, MatrixSignalMast.class);
119        } catch (JmriException e) {
120            log.error("Failed to load MatrixSignalMast {}", sys, e);
121            return false;
122        }
123
124        if (getUserName(shared) != null) {
125            m.setUserName(getUserName(shared));
126        }
127
128        loadCommon(m, shared); // username & comment
129
130        if (shared.getChild("unlit") != null) {
131            Element unlit = shared.getChild("unlit");
132            if (unlit.getAttribute("allowed") != null) {
133                if (unlit.getAttribute("allowed").getValue().equals("no")) {
134                    m.setAllowUnLit(false);
135                } else {
136                    m.setAllowUnLit(true);
137                    String bits = unlit.getChild("bitString").getText();
138                    m.setUnLitBits(bits);
139                }
140            }
141        }
142
143        if (shared.getChild("delay") != null) { // load mast-specific delay, since 4.15.7
144            Element delay = shared.getChild("delay");
145            if (delay.getAttribute("duration") != null) {
146                m.setMatrixMastCommandDelay(Integer.parseInt(delay.getAttribute("duration").getValue()));
147            }
148        }
149
150        Element outps = shared.getChild("outputs"); // multiple
151        if (outps != null) {
152            List<Element> list = outps.getChildren("output"); // singular
153            m.setBitNum(list.size()); // set char[] size before creating outputs
154            for (Element outp : list) {
155                String outputname = outp.getAttribute("matrixCol").getValue();
156                String turnoutname = outp.getText();
157                m.setOutput(outputname, turnoutname);
158            }
159        }
160
161        Element bss = shared.getChild("bitStrings"); // multiple
162        if (bss != null) {
163            List<Element> list = bss.getChildren("bitString"); // singular
164            for (Element bs : list) {
165                m.setBitstring(bs.getAttribute("aspect").getValue(), bs.getText()); // OK if value is null
166            }
167        }
168
169        Element disabled = shared.getChild("disabledAspects"); // multiple
170        if (disabled != null) {
171            List<Element> list = disabled.getChildren("disabledAspect"); // singular
172            for (Element asp : list) {
173                m.setAspectDisabled(asp.getText());
174            }
175        }
176
177        if ((shared.getChild("resetPreviousStates") != null) // load mast-specific delay, since 4.19.4
178                && shared.getChild("resetPreviousStates").getText().equals("yes")) {
179            m.resetPreviousStates(true);
180        }
181
182        return true;
183    }
184
185    @Override
186    public void load(Element element, Object o) {
187        log.error("Invalid method called");
188    }
189
190    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MatrixSignalMastXml.class);
191
192}