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