001package jmri.jmrix.openlcb.configurexml;
002
003import java.util.List;
004import jmri.InstanceManager;
005import jmri.JmriException;
006import jmri.SignalAppearanceMap;
007import jmri.jmrix.openlcb.OlcbSignalMast;
008
009import org.jdom2.Element;
010
011import org.openlcb.EventID;
012
013import javax.annotation.Nonnull;
014
015/**
016 * Handle XML configuration for OlcbSignalMast objects.
017 *
018 * @author Bob Jacobsen Copyright: Copyright (c) 2017, 2018
019 *
020 */
021public class OlcbSignalMastXml
022        extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML {
023
024    public OlcbSignalMastXml() {
025    }
026
027    /**
028     * Default implementation for storing the contents of a
029     * DefaultSignalMastManager
030     *
031     * @param o Object to store, of type OlcbSignalMast
032     * @return Element containing the complete info
033     */
034    @Override
035    public Element store(Object o) {
036        OlcbSignalMast p = (OlcbSignalMast) o;
037        Element e = new Element("olcbsignalmast");
038        e.setAttribute("class", this.getClass().getName());
039        e.addContent(new Element("systemName").addContent(p.getSystemName()));
040
041        storeCommon(p, e);
042
043        Element lit = new Element("lit");
044        lit.addContent(new Element("lit").addContent(nullToEmpty(p.getLitEventId())));
045        lit.addContent(new Element("notlit").addContent(nullToEmpty(p.getNotLitEventId())));
046        e.addContent(lit);
047
048        Element held = new Element("held");
049        held.addContent(new Element("held").addContent(nullToEmpty(p.getHeldEventId())));
050        held.addContent(new Element("notheld").addContent(nullToEmpty(p.getNotHeldEventId())));
051        e.addContent(held);
052
053        SignalAppearanceMap appMap = p.getAppearanceMap();
054        if (appMap != null) {
055            java.util.Enumeration<String> aspects = appMap.getAspects();
056            while (aspects.hasMoreElements()) {
057                String key = aspects.nextElement();
058                Element el = new Element("aspect");
059                el.setAttribute("defines", key);
060                el.addContent(new Element("event").addContent(nullToEmpty(p.getOutputForAppearance(key))));
061                e.addContent(el);
062            }
063        }
064        List<String> disabledAspects = p.getDisabledAspects();
065        if (disabledAspects != null) {
066            Element el = new Element("disabledAspects");
067            for (String aspect : disabledAspects) {
068                Element ele = new Element("disabledAspect");
069                ele.addContent(aspect);
070                el.addContent(ele);
071            }
072            if (disabledAspects.size() != 0) {
073                e.addContent(el);
074            }
075        }
076        return e;
077    }
078
079    @Override
080    public boolean load(@Nonnull Element shared, Element perNode) {
081        OlcbSignalMast m;
082        String sys = getSystemName(shared);
083        try {
084            m = (OlcbSignalMast) InstanceManager.getDefault(jmri.SignalMastManager.class)
085                    .provideCustomSignalMast(sys, OlcbSignalMast.class);
086        } catch (JmriException e) {
087            log.error("Failed to load OlcbSignalMast {}", sys, e);
088            return false;
089        }
090
091        if (getUserName(shared) != null) {
092            m.setUserName(getUserName(shared));
093        }
094
095        return loadCommonOlcbMast(m, shared);
096    }
097
098    /**
099     * If the input string is a zero Event ID, replace it 
100     * with the empty String
101     * @param event an event ID read from an element
102     * @param m the relevant signal mast, used for a warning message
103     * @return the event ID or the empty String
104     */
105    private String convertZeroEvent(String event, OlcbSignalMast m) {
106        if ("".equals(event)) {
107            return "";
108        }
109        if (event == null) {
110            return "";
111        }
112        try {
113            var eventID = new EventID(event);
114            if (eventID.getContents()[0] == 0) {
115                // migrate starting-with-zero event ID to blank
116                log.warn("Migrating zero-initial-value event {} to a blank entry in signal mast \"{}\"", event, m.getDisplayName());
117                return "";
118            } else {
119                // non-zero-starting event ID, normal case
120                return event;
121            }
122        } catch (IllegalArgumentException ex) {
123            // not dotted-hex, assume this is a event name
124            return event;
125        }
126        
127    }
128    
129    protected boolean loadCommonOlcbMast(OlcbSignalMast m, Element element) {
130        loadCommon(m, element);
131        
132        if (element.getChild("lit") != null) {
133            Element lit = element.getChild("lit");
134            m.setLitEventId(convertZeroEvent(childValue(lit, "lit"), m));
135            m.setNotLitEventId(convertZeroEvent(childValue(lit, "notlit"), m));
136        }
137
138        if (element.getChild("held") != null) {
139            Element held = element.getChild("held");
140            m.setHeldEventId(convertZeroEvent(childValue(held, "held"), m));
141            m.setNotHeldEventId(convertZeroEvent(childValue(held, "notheld"), m));
142        }
143
144        List<Element> list = element.getChildren("aspect");
145        for (Element e : list) {
146            String aspect = e.getAttribute("defines").getValue();
147            String event = convertZeroEvent(childValue(e, "event"), m);
148            m.setOutputForAppearance(aspect, event);
149        }
150        Element e = element.getChild("disabledAspects");
151        if (e != null) {
152            list = e.getChildren("disabledAspect");
153            for (Element aspect : list) {
154                m.setAspectDisabled(aspect.getText());
155            }
156        }
157
158        return true;
159
160    }
161
162    @Override
163    public void load(Element element, Object o) {
164        log.error("Invalid method called");
165    }
166
167    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(OlcbSignalMastXml.class);
168}