001package jmri.jmrit.display.layoutEditor.configurexml;
002
003import java.util.HashMap;
004import java.util.List;
005
006import jmri.configurexml.JmriConfigureXmlException;
007import jmri.jmrit.catalog.NamedIcon;
008import jmri.jmrit.display.*;
009import jmri.jmrit.display.configurexml.PositionableLabelXml;
010import jmri.jmrit.display.layoutEditor.OutputIndicator;
011
012import org.jdom2.Attribute;
013import org.jdom2.Element;
014import org.slf4j.Logger;
015import org.slf4j.LoggerFactory;
016
017/**
018 * Handle configuration for display.OutputIndicator objects.
019 *
020 * @author Bob Jacobsen Copyright: Copyright (c) 2002
021 */
022public class OutputIndicatorXml extends PositionableLabelXml {
023
024    static final HashMap<String, String> _nameMap = new HashMap<>();
025
026    public OutputIndicatorXml() {
027        // map previous store names to property key names
028        _nameMap.put("closed", "TurnoutStateClosed");
029        _nameMap.put("thrown", "TurnoutStateThrown");
030        _nameMap.put("unknown", "BeanStateUnknown");
031        _nameMap.put("inconsistent", "BeanStateInconsistent");
032    }
033
034    /**
035     * Default implementation for storing the contents of a OutputIndicator
036     *
037     * @param o Object to store, of type OutputIndicator
038     * @return Element containing the complete info
039     */
040    @Override
041    public Element store(Object o) {
042
043        OutputIndicator p = (OutputIndicator) o;
044        if (!p.isActive()) {
045            return null;  // if flagged as inactive, don't store
046        }
047        Element element = new Element("outputindicator");
048        element.setAttribute("turnout", p.getNamedTurnout().getName());
049        storeCommonAttributes(p, element);
050
051        element.setAttribute("tristate", p.getTristate() ? "true" : "false");
052        element.setAttribute("momentary", p.getMomentary() ? "true" : "false");
053        element.setAttribute("directControl", p.getDirectControl() ? "true" : "false");
054
055        Element elem = new Element("icons");
056        elem.addContent(storeIcon("closed", p.getIcon("TurnoutStateClosed")));
057        elem.addContent(storeIcon("thrown", p.getIcon("TurnoutStateThrown")));
058        elem.addContent(storeIcon("unknown", p.getIcon("BeanStateUnknown")));
059        elem.addContent(storeIcon("inconsistent", p.getIcon("BeanStateInconsistent")));
060        element.addContent(elem);
061        elem = new Element("iconmaps");
062        String family = p.getFamily();
063        if (family != null) {
064            elem.setAttribute("family", family);
065        }
066        element.addContent(elem);
067
068        storeLogixNG_Data(p, element);
069
070        element.setAttribute("class", "jmri.jmrit.display.layoutEditor.configurexml.OutputIndicatorXml");
071
072        return element;
073    }
074
075    /**
076     * Create a PositionableLabel, then add to a target JLayeredPane
077     *
078     * @param element Top level Element to unpack.
079     * @param o       Editor as an Object
080     * @throws JmriConfigureXmlException when a error prevents creating the objects as as
081     *                   required by the input XML
082     */
083    @Override
084    public void load(Element element, Object o) throws JmriConfigureXmlException {
085        // create the objects
086        Editor p = (Editor) o;
087
088        OutputIndicator l = new OutputIndicator(p);
089
090        String name;
091        try {
092            name = element.getAttribute("turnout").getValue();
093        } catch (NullPointerException e) {
094            log.error("incorrect information for turnout; must use turnout name");
095            p.loadFailed();
096            return;
097        }
098        l.setTurnout(name);
099
100        Attribute a = element.getAttribute("tristate");
101        if ((a == null) || a.getValue().equals("true")) {
102            l.setTristate(true);
103        } else {
104            l.setTristate(false);
105        }
106
107        a = element.getAttribute("momentary");
108        if ((a != null) && a.getValue().equals("true")) {
109            l.setMomentary(true);
110        } else {
111            l.setMomentary(false);
112        }
113
114        a = element.getAttribute("directControl");
115        if ((a != null) && a.getValue().equals("true")) {
116            l.setDirectControl(true);
117        } else {
118            l.setDirectControl(false);
119        }
120
121        List<Element> states = element.getChildren();
122        if (states.size() > 0) {
123            if (log.isDebugEnabled()) {
124                log.debug("Main element has{} items", states.size());
125            }
126            Element elem = element;     // the element containing the icons
127            Element icons = element.getChild("icons");
128            if (icons != null) {
129                states = icons.getChildren();
130                elem = icons;          // the element containing the icons
131                if (log.isDebugEnabled()) {
132                    log.debug("icons element has{} items", states.size());
133                }
134            }
135            for (Element value : states) {
136                String state = value.getName();
137                if (log.isDebugEnabled()) {
138                    log.debug("setIcon for state \"{}\" and {}", state, _nameMap.get(state));
139                }
140                NamedIcon icon = loadIcon(l, state, elem, "TurnoutIcon \"" + name + "\": icon \"" + state + "\" ", p);
141                if (icon != null) {
142                    l.setIcon(_nameMap.get(state), icon);
143                } else {
144                    log.info("OutputIndicator \"{}\": icon \"{}\" removed", name, state);
145                    return;
146                }
147            }
148            log.debug("{} icons loaded for {}", states.size(), l.getNameString());
149        } else {        // case when everything was attributes
150            int rotation = 0;
151            try {
152                rotation = element.getAttribute("rotate").getIntValue();
153            } catch (org.jdom2.DataConversionException e) {
154            } catch (NullPointerException e) {  // considered normal if the attributes are not present
155            }
156            if (loadTurnoutIcon("thrown", rotation, l, element, name, p) == null) {
157                return;
158            }
159            if (loadTurnoutIcon("closed", rotation, l, element, name, p) == null) {
160                return;
161            }
162            if (loadTurnoutIcon("unknown", rotation, l, element, name, p) == null) {
163                return;
164            }
165            if (loadTurnoutIcon("inconsistent", rotation, l, element, name, p) == null) {
166                return;
167            }
168        }
169        Element elem = element.getChild("iconmaps");
170        if (elem != null) {
171            Attribute attr = elem.getAttribute("family");
172            if (attr != null) {
173                l.setFamily(attr.getValue());
174            }
175        }
176
177        try {
178            p.putItem(l);
179        } catch (Positionable.DuplicateIdException e) {
180            throw new JmriConfigureXmlException("Positionable id is not unique", e);
181        }
182
183        loadLogixNG_Data(l, element);
184
185        // load individual item's option settings after editor has set its global settings
186        loadCommonAttributes(l, Editor.TURNOUTS, element);
187    }
188
189    private NamedIcon loadTurnoutIcon(String state, int rotation, TurnoutIcon l, Element element,
190            String name, Editor ed) {
191        NamedIcon icon = null;
192        if (element.getAttribute(state) != null) {
193            String iconName = element.getAttribute(state).getValue();
194            icon = NamedIcon.getIconByName(iconName);
195            if (icon == null) {
196                icon = ed.loadFailed("Turnout \"" + name + "\" icon \"" + state + "\" ", iconName);
197                if (icon == null) {
198                    log.info("Turnout \"{}\" icon \"{}\" removed for url= {}", name, state, iconName);
199                }
200            } else {
201                icon.setRotation(rotation, l);
202            }
203        } else {
204            log.warn("did not locate {} icon file for Turnout {}", state, name);
205        }
206        if (icon == null) {
207            log.info("Turnout Icon \"{}\": icon \"{}\" removed", name, state);
208        } else {
209            l.setIcon(_nameMap.get(state), icon);
210        }
211        return icon;
212    }
213
214    private static final Logger log = LoggerFactory.getLogger(OutputIndicatorXml.class);
215}