001package jmri.managers.configurexml;
002
003import java.util.List;
004import java.util.SortedSet;
005
006import jmri.InstanceManager;
007import jmri.SignalGroup;
008import jmri.SignalGroupManager;
009import jmri.SignalHead;
010
011import org.jdom2.Element;
012
013/**
014 * Handle XML configuration for a DefaultSignalGroupManager objects.
015 *
016 * @author Bob Jacobsen Copyright: Copyright (c) 2009
017 */
018public class DefaultSignalGroupManagerXml
019        extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML {
020
021    public DefaultSignalGroupManagerXml() {
022    }
023
024    /**
025     * Default implementation for storing the contents of a
026     * DefaultSignalGroupManager.
027     *
028     * @param o Object to store, of type SignalGroup
029     * @return Element containing the complete info
030     */
031    @Override
032    public Element store(Object o) {
033        Element groups = new Element("signalgroups");
034        groups.setAttribute("class", this.getClass().getName());
035        SignalGroupManager sgm = (SignalGroupManager) o;
036        if (sgm != null) {
037            SortedSet<SignalGroup> sgList = sgm.getNamedBeanSet();
038            // don't return an element if there are no SignalGroups to include
039            if (sgList.isEmpty()) {
040                return null;
041            }
042            for (SignalGroup sg : sgList) {
043                // store the signalgroups
044                String sgName = sg.getSystemName();
045                log.debug("SignalGroup system name is {}", sgName);  // NOI18N
046
047                Element e = new Element("signalgroup");
048                e.addContent(new Element("systemName").addContent(sgName));
049                storeCommon(sg, e);
050                groups.addContent(e);
051                for (int x = 0; x < sg.getNumSignalMastAspects(); x++) {
052                    Element app = new Element("aspect").setAttribute("valid", sg.getSignalMastAspectByIndex(x));
053                    e.addContent(app);
054                }
055                e.setAttribute("signalMast", sg.getSignalMastName());
056
057                for (int x = 0; x < sg.getNumHeadItems(); x++) {
058                    storeSignalHead(e, sg, x);
059                }
060            }
061        }
062        return groups;
063    }
064
065    private void storeSignalHead(Element element, SignalGroup _group, int x) {
066        Element group = new Element("signalHead");
067        String name = _group.getHeadItemNameByIndex(x);
068        group.setAttribute("name", name);
069        group.setAttribute("onAppearance", getSignalColour(_group.getHeadOnStateByIndex(x)));
070        group.setAttribute("offAppearance", getSignalColour(_group.getHeadOffStateByIndex(x)));
071        if (_group.getSensorTurnoutOperByIndex(x)) {
072            group.setAttribute("sensorTurnoutLogic", "AND");
073        } else {
074            group.setAttribute("sensorTurnoutLogic", "OR");
075        }
076
077        for (int i = 0; i < _group.getNumHeadTurnoutsByIndex(x); i++) {
078            storeTurnout(group, _group, x, i);
079        }
080        for (int i = 0; i < _group.getNumHeadSensorsByIndex(x); i++) {
081            storeSensor(group, _group, x, i);
082        }
083
084        element.addContent(group);
085    }
086
087    private void storeTurnout(Element element, SignalGroup _group, int x, int turn) {
088        Element turnout = new Element("turnout").setAttribute("name", _group.getTurnoutNameByIndex(x, turn));
089        turnout.setAttribute("state", "" + _group.getTurnoutStateByIndex(x, turn));
090        element.addContent(turnout);
091    }
092
093    private void storeSensor(Element element, SignalGroup _group, int x, int sensor) {
094        Element Sensor = new Element("sensor").setAttribute("name", _group.getSensorNameByIndex(x, sensor));
095        Sensor.setAttribute("state", "" + _group.getSensorStateByIndex(x, sensor));
096        element.addContent(Sensor);
097    }
098
099    public void setStoreElementClass(Element signalGroup) {
100        signalGroup.setAttribute("class", this.getClass().getName());
101    }
102
103    private String getSignalColour(int mAppearance) {
104        switch (mAppearance) {
105            case SignalHead.RED:
106                return "RED";
107            case SignalHead.FLASHRED:
108                return "FLASHRED";
109            case SignalHead.YELLOW:
110                return "YELLOW";
111            case SignalHead.FLASHYELLOW:
112                return "FLASHYELLOW";
113            case SignalHead.GREEN:
114                return "GREEN";
115            case SignalHead.FLASHGREEN:
116                return "FLASHGREEN";
117            case SignalHead.LUNAR:
118                return "LUNAR";
119            case SignalHead.FLASHLUNAR:
120                return "FLASHLUNAR";
121            case SignalHead.DARK:
122                return "DARK";
123            default:
124                log.warn("Unexpected appearance: {}", mAppearance);
125                // go dark
126                return "DARK";
127        }
128    }
129
130    @Override
131    public boolean load(Element shared, Element perNode) {
132        // loop over contained signalgroup elements
133        List<Element> list = shared.getChildren("signalgroup");
134
135        SignalGroupManager sgm = InstanceManager.getDefault(jmri.SignalGroupManager.class);
136
137        for (Element e : list) {
138            SignalGroup sg;
139            String primary;
140            String yesno;
141            boolean inverse;
142            int state;
143
144            String sys = getSystemName(e);
145
146            sg = sgm.provideSignalGroup(sys, getUserName(e));
147
148            //loadCommon(sg, e); // would store comment, now a separate element
149            loadComment(sg, e);
150
151            primary = e.getAttribute("signalMast").getValue();
152            sg.setSignalMast(primary);
153
154            List<Element> appList = e.getChildren("appearance"); // deprecated 4.7.2 for aspect; warning added 4.19.1
155            for (Element app : appList) {
156                String value = app.getAttribute("valid").getValue();
157                jmri.util.LoggingUtil.deprecationWarning(log, "appearance elements in file");
158                sg.addSignalMastAspect(value);
159            }
160            List<Element> aspList = e.getChildren("aspect");
161            for (Element asp : aspList) {
162                String value = asp.getAttribute("valid").getValue();
163                sg.addSignalMastAspect(value);
164            }
165
166            List<Element> signalHeadList = e.getChildren("signalHead");
167            for (Element sh : signalHeadList) {
168                String head = sh.getAttribute("name").getValue();
169                SignalHead sigHead = jmri.InstanceManager.getDefault(jmri.SignalHeadManager.class).getSignalHead(head);
170                sg.addSignalHead(sigHead);
171                yesno = sh.getAttribute("sensorTurnoutLogic").getValue();
172                inverse = false;
173                if ((yesno != null) && (!yesno.isEmpty())) {
174                    if (yesno.equals("AND")) {
175                        inverse = true;
176                    // } else if (yesno.equals("OR")) {
177                    //     inverse = false; // value already assigned as default
178                    }
179                }
180                sg.setSensorTurnoutOper(sigHead, inverse);
181
182                try {
183                    sg.setHeadOnState(sigHead, getIntFromColour(sh.getAttribute("onAppearance").getValue()));
184                } catch (NullPointerException ex) {  // considered normal if the attributes are not present
185                }
186                try {
187                    sg.setHeadOffState(sigHead, getIntFromColour(sh.getAttribute("offAppearance").getValue()));
188                } catch (NullPointerException ex) {  // considered normal if the attributes are not present
189                }
190                List<Element> signalTurnoutList = sh.getChildren("turnout");
191                for (Element sgt : signalTurnoutList) {
192                    String tName = sgt.getAttribute("name").getValue();
193                    jmri.Turnout turnout = jmri.InstanceManager.turnoutManagerInstance().getTurnout(tName);
194                    state = 0;
195                    try {
196                        state = sgt.getAttribute("state").getIntValue();
197                    } catch (org.jdom2.DataConversionException ex) {
198                        log.warn("invalid state attribute value");
199                    }
200                    sg.setHeadAlignTurnout(sigHead, turnout, state);
201                }
202                List<Element> signalSensorList = sh.getChildren("sensor");
203                for (Element sgs: signalSensorList) {
204                    String sName = sgs.getAttribute("name").getValue();
205                    jmri.Sensor sensor = jmri.InstanceManager.sensorManagerInstance().getSensor(sName);
206                    state = 0;
207                    try {
208                        state = sgs.getAttribute("state").getIntValue();
209                    } catch (org.jdom2.DataConversionException ex) {
210                        log.warn("invalid style attribute value");
211                    }
212                    sg.setHeadAlignSensor(sigHead, sensor, state);
213                }
214            }
215        }
216        return true;
217    }
218
219    private int getIntFromColour(String color) {
220        switch (color) {
221            case "RED":
222                return SignalHead.RED;
223            case "YELLOW":
224                return SignalHead.YELLOW;
225            case "GREEN":
226                return SignalHead.GREEN;
227            case "LUNAR":
228                return SignalHead.LUNAR;
229            case "DARK":
230                return SignalHead.DARK;
231            case "FLASHRED":
232                return SignalHead.FLASHRED;
233            case "FLASHYELLOW":
234                return SignalHead.FLASHYELLOW;
235            case "FLASHGREEN":
236                return SignalHead.FLASHGREEN;
237            case "FLASHLUNAR":
238                return SignalHead.FLASHLUNAR;
239            default:
240                log.warn("Unexpected appearance: {}", color);
241                return SignalHead.DARK;
242        }
243    }
244
245    @Override
246    public int loadOrder() {
247        return InstanceManager.getDefault(jmri.SignalGroupManager.class).getXMLOrder();
248    }
249
250    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultSignalGroupManagerXml.class);
251
252}