001package jmri.jmrit.display.configurexml;
002
003import java.util.ArrayList;
004import java.util.HashMap;
005import java.util.Iterator;
006import java.util.List;
007import java.util.Map.Entry;
008
009import jmri.NamedBeanHandle;
010import jmri.Sensor;
011import jmri.Turnout;
012import jmri.configurexml.JmriConfigureXmlException;
013import jmri.jmrit.catalog.NamedIcon;
014import jmri.jmrit.display.*;
015import jmri.jmrit.logix.OBlock;
016
017import org.jdom2.Attribute;
018import org.jdom2.Element;
019import org.slf4j.Logger;
020import org.slf4j.LoggerFactory;
021
022/**
023 * Handle configuration for display.IndicatorTurnoutIconXml objects.
024 *
025 * @author Pete Cressman Copyright: Copyright (c) 2010
026 */
027public class IndicatorTurnoutIconXml extends PositionableLabelXml {
028
029    public IndicatorTurnoutIconXml() {
030    }
031
032    /**
033     * Default implementation for storing the contents of a IndicatorTurnoutIcon
034     *
035     * @param o Object to store, of type IndicatorTurnoutIcon
036     * @return Element containing the complete info
037     */
038    @Override
039    public Element store(Object o) {
040
041        IndicatorTurnoutIcon p = (IndicatorTurnoutIcon) o;
042        if (!p.isActive()) {
043            return null;  // if flagged as inactive, don't store
044        }
045        Element element = new Element("indicatorturnouticon");
046        storeCommonAttributes(p, element);
047
048        NamedBeanHandle<Turnout> t = p.getNamedTurnout();
049        if (t != null) {
050            element.addContent(storeNamedBean("turnout", t));
051        }
052        NamedBeanHandle<OBlock> b = p.getNamedOccBlock();
053        if (b != null) {
054            element.addContent(storeNamedBean("occupancyblock", b));
055            // additional oblock information for web server is extracted by ControlPanelServlet at runtime, not stored
056        }
057        NamedBeanHandle<Sensor> s = p.getNamedOccSensor();
058        if (b == null && s != null) { // only write sensor if no OBlock
059            element.addContent(storeNamedBean("occupancysensor", s));
060        }
061
062        Element elem = new Element("showTrainName");
063        String show = "no";
064        if (p.showTrain()) {
065            show = "yes";
066        }
067        elem.addContent(show);
068        element.addContent(elem);
069
070        HashMap<String, HashMap<Integer, NamedIcon>> iconMaps = p.getIconMaps();
071        Iterator<Entry<String, HashMap<Integer, NamedIcon>>> it = iconMaps.entrySet().iterator();
072        Element el = new Element("iconmaps");
073        String family = p.getFamily();
074        if (family != null) {
075            el.setAttribute("family", family);
076        }
077        while (it.hasNext()) {
078            Entry<String, HashMap<Integer, NamedIcon>> ent = it.next();
079            elem = new Element(ent.getKey());
080            for (Entry<Integer, NamedIcon> entry : ent.getValue().entrySet()) {
081                elem.addContent(storeIcon(p.getStateName(entry.getKey()), entry.getValue()));
082            }
083            el.addContent(elem);
084        }
085        element.addContent(el);
086
087        elem = new Element("paths");
088        ArrayList<String> paths = p.getPaths();
089        if (paths != null) {
090            for (String path : paths) {
091                Element e = new Element("path");
092                e.addContent(path);
093                elem.addContent(e);
094
095            }
096            element.addContent(elem);
097        }
098
099        element.setAttribute("class", "jmri.jmrit.display.configurexml.IndicatorTurnoutIconXml");
100
101        storeLogixNG_Data(p, element);
102
103        return element;
104    }
105
106    Element storeNamedBean(String elemName, NamedBeanHandle<?> nb) {
107        Element elem = new Element(elemName);
108        elem.addContent(nb.getName());
109        return elem;
110    }
111
112    /**
113     * Create a IndicatorTurnoutIcon, then add to a target JLayeredPane
114     *
115     * @param element Top level Element to unpack.
116     * @param o       Editor as an Object
117     * @throws JmriConfigureXmlException when a error prevents creating the objects as as
118     *                   required by the input XML
119     */
120    @Override
121    public void load(Element element, Object o) throws JmriConfigureXmlException {
122        // create the objects
123        Editor p = (Editor) o;
124
125        IndicatorTurnoutIcon l = new IndicatorTurnoutIcon(p);
126        Element name = element.getChild("turnout");
127
128        if (name == null) {
129            log.error("incorrect information for turnout; must use turnout name");
130        } else {
131            l.setTurnout(name.getText());
132        }
133        Element elem = element.getChild("iconmaps");
134        if (elem != null) {
135            List<Element> maps = elem.getChildren();
136            if (maps.size() > 0) {
137                for (Element map : maps) {
138                    String status = map.getName();
139                    List<Element> states = map.getChildren();
140                    for (Element state : states) {
141                        String msg = "IndicatorTurnout \"" + l.getNameString() + "\" icon \"" + state.getName() + "\" ";
142                        NamedIcon icon = loadIcon(l, state.getName(), map, msg, p);
143                        if (icon != null) {
144                            l.setIcon(status, state.getName(), icon);
145                        } else {
146                            log.info("{} removed for url= {}", msg, name);
147                            return;
148                        }
149                    }
150                }
151            }
152            Attribute attr = elem.getAttribute("family");
153            if (attr != null) {
154                l.setFamily(attr.getValue());
155            }
156        }
157
158        name = element.getChild("occupancyblock");
159        if (name != null) {
160            l.setOccBlock(name.getText());
161        } else {        // we only wrote sensor if no OBlock, so assume sensor is empty
162            name = element.getChild("occupancysensor");
163            if (name != null) {
164                l.setOccSensor(name.getText());
165            }            
166        }
167
168        l.setShowTrain(false);
169        name = element.getChild("showTrainName");
170        if (name != null) {
171            if ("yes".equals(name.getText())) {
172                l.setShowTrain(true);
173            }
174        }
175
176        elem = element.getChild("paths");
177        if (elem != null) {
178            ArrayList<String> paths = new ArrayList<>();
179            List<Element> pth = elem.getChildren();
180            for (Element value : pth) {
181                paths.add(value.getText());
182            }
183            l.setPaths(paths);
184        }
185
186        l.updateSize();
187        try {
188            p.putItem(l);
189        } catch (Positionable.DuplicateIdException e) {
190            throw new JmriConfigureXmlException("Positionable id is not unique", e);
191        }
192
193        loadLogixNG_Data(l, element);
194
195        // load individual item's option settings after editor has set its global settings
196        loadCommonAttributes(l, Editor.TURNOUTS, element);
197    }
198
199    private final static Logger log = LoggerFactory.getLogger(IndicatorTurnoutIconXml.class);
200}