001package jmri.managers.configurexml;
002
003import java.util.Hashtable;
004import java.util.List;
005import jmri.Block;
006import jmri.InstanceManager;
007import jmri.NamedBeanHandle;
008import jmri.Section;
009import jmri.Sensor;
010import jmri.SignalMast;
011import jmri.SignalMastLogic;
012import jmri.SignalMastLogicManager;
013import jmri.SignalMastManager;
014import jmri.Turnout;
015import org.jdom2.Element;
016import org.slf4j.Logger;
017import org.slf4j.LoggerFactory;
018
019/**
020 *
021 * @author kevin
022 */
023public class DefaultSignalMastLogicManagerXml extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML {
024
025    public DefaultSignalMastLogicManagerXml() {
026    }
027
028    protected jmri.NamedBeanHandleManager nbhm = jmri.InstanceManager.getDefault(jmri.NamedBeanHandleManager.class);
029
030    @Override
031    public Element store(Object o) {
032        Element signalMastLogic = new Element("signalmastlogics");
033        setStoreElementClass(signalMastLogic);
034        SignalMastLogicManager smlm = (SignalMastLogicManager) o;
035        signalMastLogic.addContent(new Element("logicDelay").addContent(Long.toString(smlm.getSignalLogicDelay())));
036        List<SignalMastLogic> smll = smlm.getSignalMastLogicList();
037        for (SignalMastLogic sml : smll) {
038        
039            List<SignalMast> destinations = sml.getDestinationList();
040            
041            // write in consistent order
042            java.util.Comparator<SignalMast> comparator = new jmri.util.NamedBeanComparator<>();
043            java.util.Collections.sort(destinations, comparator);
044
045            if (destinations.isEmpty()) {
046                log.warn("Empty SML for source mast {} skipped", sml.getSourceMast().getDisplayName());
047                continue;
048            }
049            Element source = new Element("signalmastlogic");
050            source.setAttribute("source", sml.getSourceMast().getDisplayName());// added purely to make human reading of the xml easier
051            source.addContent(new Element("sourceSignalMast").addContent(sml.getSourceMast().getDisplayName()));
052            for (SignalMast dest : destinations) {
053                if (sml.getStoreState(dest) != SignalMastLogic.STORENONE) {
054                    Element elem = new Element("destinationMast");
055                    elem.setAttribute("destination", dest.getDisplayName()); // added purely to make human reading of the xml easier
056                    elem.addContent(new Element("destinationSignalMast").addContent(dest.getDisplayName()));
057                    elem.addContent(new Element("comment").addContent(sml.getComment(dest)));
058                    if (sml.isEnabled(dest)) {
059                        elem.addContent(new Element("enabled").addContent("yes"));
060                    } else {
061                        elem.addContent(new Element("enabled").addContent("no"));
062                    }
063
064                    if (sml.allowAutoMaticSignalMastGeneration(dest)) {
065                        elem.addContent(new Element("allowAutoMaticSignalMastGeneration").addContent("yes"));
066                    } else {
067                        elem.addContent(new Element("allowAutoMaticSignalMastGeneration").addContent("no"));
068                    }
069
070                    if (sml.useLayoutEditor(dest)) {
071                        elem.addContent(new Element("useLayoutEditor").addContent("yes"));
072                    } else {
073                        elem.addContent(new Element("useLayoutEditor").addContent("no"));
074                    }
075
076                    if (sml.useLayoutEditorTurnouts(dest)) {
077                        elem.addContent(new Element("useLayoutEditorTurnouts").addContent("yes"));
078                    } else {
079                        elem.addContent(new Element("useLayoutEditorTurnouts").addContent("no"));
080                    }
081
082                    if (sml.useLayoutEditorBlocks(dest)) {
083                        elem.addContent(new Element("useLayoutEditorBlocks").addContent("yes"));
084                    } else {
085                        elem.addContent(new Element("useLayoutEditorBlocks").addContent("no"));
086                    }
087
088                    if (sml.getAssociatedSection(dest) != null) {
089                        elem.addContent(new Element("associatedSection").addContent(sml.getAssociatedSection(dest).getDisplayName()));
090                    }
091                    if (sml.isTurnoutLockAllowed(dest)) {
092                        elem.addContent(new Element("lockTurnouts").addContent("yes"));
093                    } else {
094                        elem.addContent(new Element("lockTurnouts").addContent("no"));
095                    }
096
097                    if (sml.getStoreState(dest) == SignalMastLogic.STOREALL) {
098                        List<Block> blocks = sml.getBlocks(dest);
099
100                        // write in consistent order
101                        java.util.Comparator<Block> blockComp = new jmri.util.NamedBeanComparator<>();
102                        java.util.Collections.sort(blocks, blockComp);
103
104                        if (blocks.size() > 0) {
105                            Element blockElement = new Element("blocks");
106                            for (Block bl : blocks) {
107                                Element bloc = new Element("block");
108                                bloc.addContent(new Element("blockName").addContent(bl.getDisplayName()));
109                                String blkState = "anyState";
110                                if (sml.getBlockState(bl, dest) == Block.OCCUPIED) {
111                                    blkState = "occupied";
112                                } else if (sml.getBlockState(bl, dest) == Block.UNOCCUPIED) {
113                                    blkState = "unoccupied";
114                                }
115                                bloc.addContent(new Element("blockState").addContent(blkState));
116                                blockElement.addContent(bloc);
117                            }
118                            elem.addContent(blockElement);
119                        }
120
121                        List<NamedBeanHandle<Turnout>> turnouts = sml.getNamedTurnouts(dest);
122
123                        // write in consistent order
124                        java.util.Comparator<NamedBeanHandle<Turnout>> turnoutComp = new jmri.util.NamedBeanHandleComparator<>();
125                        java.util.Collections.sort(turnouts, turnoutComp);
126
127                        if (turnouts.size() > 0) {
128                            Element turnoutElement = new Element("turnouts");
129                            for (NamedBeanHandle<Turnout> t : turnouts) {
130                                Element turn = new Element("turnout");
131                                turn.addContent(new Element("turnoutName").addContent(t.getName()));
132                                String turnState = "thrown";
133                                if (sml.getTurnoutState(t.getBean(), dest) == Turnout.CLOSED) {
134                                    turnState = "closed";
135                                }
136                                turn.addContent(new Element("turnoutState").addContent(turnState));
137                                turnoutElement.addContent(turn);
138                            }
139                            elem.addContent(turnoutElement);
140                        }
141
142                        List<NamedBeanHandle<Sensor>> sensors = sml.getNamedSensors(dest);
143                        
144                        // write in consistent order
145                        java.util.Comparator<NamedBeanHandle<Sensor>> sensorsComp = new jmri.util.NamedBeanHandleComparator<>();
146                        java.util.Collections.sort(sensors, sensorsComp);
147
148                        if (sensors.size() > 0) {
149                            Element sensorElement = new Element("sensors");
150                            for (NamedBeanHandle<Sensor> s : sensors) {
151                                Element sensor = new Element("sensor");
152                                sensor.addContent(new Element("sensorName").addContent(s.getName()));
153                                String sensorState = "inActive";
154                                if (sml.getSensorState(s.getBean(), dest) == Sensor.ACTIVE) {
155                                    sensorState = "active";
156                                }
157                                sensor.addContent(new Element("sensorState").addContent(sensorState));
158                                sensorElement.addContent(sensor);
159                            }
160                            elem.addContent(sensorElement);
161                        }
162
163                        List<SignalMast> masts = sml.getSignalMasts(dest);
164
165                        // write in consistent order
166                        java.util.Comparator<SignalMast> mastComp = new jmri.util.NamedBeanComparator<>();
167                        java.util.Collections.sort(masts, mastComp);
168
169                        if (masts.size() > 0) {
170                            Element mastElement = new Element("masts");
171                            for (SignalMast sm : masts) {
172                                Element mast = new Element("mast");
173                                mast.addContent(new Element("mastName").addContent(sm.getDisplayName()));
174                                mast.addContent(new Element("mastState").addContent(sml.getSignalMastState(sm, dest)));
175                                mastElement.addContent(mast);
176                            }
177                            elem.addContent(mastElement);
178                        }
179                    }
180                    source.addContent(elem);
181                }
182            }
183            signalMastLogic.addContent(source);
184        }
185        return signalMastLogic;
186    }
187
188    public void setStoreElementClass(Element signalMastLogic) {
189        signalMastLogic.setAttribute("class", "jmri.managers.configurexml.DefaultSignalMastLogicManagerXml");
190    }
191
192    @Override
193    public void load(Element element, Object o) {
194        log.error("Invalid method called");
195    }
196
197    @Override
198    public boolean load(Element shared, Element perNode) {
199        // load individual Transits
200        return loadSignalMastLogic(shared);
201    }
202
203    public boolean loadSignalMastLogic(Element signalMastLogic) {
204        List<Element> logicList = signalMastLogic.getChildren("signalmastlogic");
205        log.debug("Found {} signal mast logics", logicList.size());
206
207        SignalMastManager sm = InstanceManager.getDefault(jmri.SignalMastManager.class);
208        SignalMastLogicManager smlm = InstanceManager.getDefault(jmri.SignalMastLogicManager.class);
209        try {
210            String logicDelay = signalMastLogic.getChild("logicDelay").getText();
211            smlm.setSignalLogicDelay(Integer.parseInt(logicDelay));
212        } catch (java.lang.NullPointerException e) {
213            //Considered normal if it doesn't exists
214        }
215        boolean loadOk = true;
216        for (Element sml : logicList) {
217            String source = sml.getChild("sourceSignalMast").getText();
218            SignalMast sourceMast = sm.getSignalMast(source);
219            if (sourceMast != null) {
220                SignalMastLogic logic = smlm.newSignalMastLogic(sourceMast);
221                List<Element> destList = sml.getChildren("destinationMast");
222                for (Element d : destList) {
223                    String destination = d.getChild("destinationSignalMast").getText();
224                    SignalMast dest = sm.getSignalMast(destination);
225                    if (dest != null) {
226                        logic.setDestinationMast(dest);
227                        if (d.getChild("comment") != null) {
228                            logic.setComment(d.getChild("comment").getText(), dest);
229                        }
230                        if (d.getChild("enabled") != null) {
231                            if (d.getChild("enabled").getText().equals("yes")) {
232                                logic.setEnabled(dest);
233                            } else {
234                                logic.setDisabled(dest);
235                            }
236                        }
237
238                        if (d.getChild("allowAutoMaticSignalMastGeneration") != null) {
239                            if (d.getChild("allowAutoMaticSignalMastGeneration").getText().equals("no")) {
240                                logic.allowAutoMaticSignalMastGeneration(false, dest);
241                            } else {
242                                logic.allowAutoMaticSignalMastGeneration(true, dest);
243                            }
244                        }
245
246                        boolean useLayoutEditorTurnout = true;
247                        boolean useLayoutEditorBlock = true;
248                        if (d.getChild("useLayoutEditorTurnouts") != null) {
249                            if (d.getChild("useLayoutEditorTurnouts").getText().equals("no")) {
250                                useLayoutEditorTurnout = false;
251                            }
252                        }
253
254                        if (d.getChild("useLayoutEditorBlocks") != null) {
255                            if (d.getChild("useLayoutEditorBlocks").getText().equals("no")) {
256                                useLayoutEditorBlock = false;
257                            }
258                        }
259                        try {
260                            logic.useLayoutEditorDetails(useLayoutEditorTurnout, useLayoutEditorBlock, dest);
261                        } catch (jmri.JmriException ex) {
262                            log.error("use LayoutEditor details failed");
263                        }
264
265                        if (d.getChild("useLayoutEditor") != null) {
266                            try {
267                                if (d.getChild("useLayoutEditor").getText().equals("yes")) {
268                                    logic.useLayoutEditor(true, dest);
269                                } else {
270                                    logic.useLayoutEditor(false, dest);
271                                }
272                            } catch (jmri.JmriException e) {
273                                //Considered normal if layout editor hasn't yet been set up.
274                            }
275                        }
276
277                        if (d.getChild("associatedSection") != null) {
278                            Section sect = InstanceManager.getDefault(jmri.SectionManager.class).getSection(d.getChild("associatedSection").getText());
279                            logic.setAssociatedSection(sect, dest);
280                        }
281
282                        Element turnoutElem = d.getChild("turnouts");
283                        if (turnoutElem != null) {
284                            List<Element> turnoutList = turnoutElem.getChildren("turnout");
285                            if (turnoutList.size() > 0) {
286                                Hashtable<NamedBeanHandle<Turnout>, Integer> list = new Hashtable<>();
287                                for (Element t : turnoutList) {
288                                    String turnout = t.getChild("turnoutName").getText();
289                                    String state = t.getChild("turnoutState").getText();
290                                    int value = Turnout.CLOSED;
291                                    if (state.equals("thrown")) {
292                                        value = Turnout.THROWN;
293                                    }
294                                    Turnout turn = InstanceManager.turnoutManagerInstance().getTurnout(turnout);
295                                    if (turn != null) {
296                                        NamedBeanHandle<Turnout> namedTurnout = nbhm.getNamedBeanHandle(turnout, turn);
297                                        list.put(namedTurnout, value);
298                                    }
299                                    log.debug("Unable to add Turnout {} as it does not exist in the panel file", turnout);
300                                }
301                                logic.setTurnouts(list, dest);
302                            }
303                        }
304                        Element sensorElem = d.getChild("sensors");
305                        if (sensorElem != null) {
306                            List<Element> sensorList = sensorElem.getChildren("sensor");
307                            if (sensorList.size() > 0) {
308                                Hashtable<NamedBeanHandle<Sensor>, Integer> list = new Hashtable<>();
309                                for (Element sl : sensorList) {
310                                    String sensorName = sl.getChild("sensorName").getText();
311                                    String state = sl.getChild("sensorState").getText();
312                                    int value = Sensor.INACTIVE;
313                                    if (state.equals("active")) {
314                                        value = Sensor.ACTIVE;
315                                    }
316
317                                    Sensor sen = InstanceManager.sensorManagerInstance().getSensor(sensorName);
318                                    if (sen != null) {
319                                        NamedBeanHandle<Sensor> namedSensor = nbhm.getNamedBeanHandle(sensorName, sen);
320                                        list.put(namedSensor, value);
321                                    }
322                                    log.debug("Unable to add sensor {} as it does not exist in the panel file", sensorName);
323                                }
324                                logic.setSensors(list, dest);
325                            }
326                        }
327                        Element blockElem = d.getChild("blocks");
328                        if (blockElem != null) {
329                            List<Element> blockList = blockElem.getChildren("block");
330                            if (blockList.size() > 0) {
331                                Hashtable<Block, Integer> list = new Hashtable<>();
332                                for (Element b : blockList) {
333                                    String block = b.getChild("blockName").getText();
334                                    String state = b.getChild("blockState").getText();
335                                    int value = 0x03;
336                                    if (state.equals("occupied")) {
337                                        value = Block.OCCUPIED;
338                                    } else if (state.equals("unoccupied")) {
339                                        value = Block.UNOCCUPIED;
340                                    }
341
342                                    Block blk = InstanceManager.getDefault(jmri.BlockManager.class).getBlock(block);
343                                    if (blk != null) {
344                                        list.put(blk, value);
345                                    }
346                                    log.debug("Unable to add Block {} as it does not exist in the panel file", block);
347                                }
348                                logic.setBlocks(list, dest);
349                            }
350                        }
351                        Element mastElem = d.getChild("masts");
352                        if (mastElem != null) {
353                            List<Element> mastList = mastElem.getChildren("mast");
354                            if (mastList.size() > 0) {
355                                Hashtable<SignalMast, String> list = new Hashtable<>();
356                                for (Element m : mastList) {
357                                    String mast = m.getChild("mastName").getText();
358                                    String state = m.getChild("mastState").getText();
359                                    SignalMast mst = InstanceManager.getDefault(jmri.SignalMastManager.class).getSignalMast(mast);
360                                    if (mst != null) {
361                                        list.put(mst, state);
362                                    }
363                                    log.debug("Unable to add Signal Mast {} as it does not exist in the panel file", mast);
364                                }
365                                logic.setMasts(list, dest);
366                            }
367                        }
368                    } else {
369                        log.error("Destination Mast {} not found, logic not loaded", destination);
370                        loadOk = false;
371                    }
372                }
373            } else {
374                log.error("Source Mast {} Not found, logic not loaded", source);
375                loadOk = false;
376            }
377        }
378        smlm.initialise();
379        return loadOk;
380    }
381
382    @Override
383    public int loadOrder() {
384        return InstanceManager.getDefault(jmri.SignalMastLogicManager.class).getXMLOrder();
385    }
386
387    private final static Logger log = LoggerFactory.getLogger(DefaultSignalMastLogicManagerXml.class);
388
389}