001package jmri.managers.configurexml;
002
003import java.awt.GraphicsEnvironment;
004import java.util.List;
005import java.util.SortedSet;
006
007import jmri.InstanceManager;
008import jmri.Route;
009import jmri.RouteManager;
010import jmri.Sensor;
011import jmri.Turnout;
012import jmri.managers.DefaultRouteManager;
013import jmri.util.swing.JmriJOptionPane;
014
015import org.jdom2.Element;
016
017/**
018 * Provides the functionality for configuring RouteManagers.
019 *
020 * @author Dave Duchamp Copyright (c) 2004
021 * @author Daniel Boudreau Copyright (c) 2007
022 * @author Simon Reader Copyright (C) 2008
023 */
024public class DefaultRouteManagerXml extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML {
025
026    private static final String STR_ROUTE = "route";
027    private static final String STR_ROUTES = "routes";
028
029    private static final String STR_CONTROL_TURNOUT = "controlTurnout";
030    private static final String STR_CONTROL_TURNOUT_FEEDBACK = "controlTurnoutFeedback";
031    private static final String STR_CONTROL_TURNOUT_STATE = "controlTurnoutState";
032    private static final String STR_CONTROL_LOCK_TURNOUT = "controlLockTurnout";
033    private static final String STR_CONTROL_LOCK_TURNOUT_STATE = "controlLockTurnoutState";
034
035    private static final String STR_ACTIVE = "ACTIVE";
036    private static final String STR_INACTIVE = "INACTIVE";
037    private static final String STR_ON_ACTIVE = "onActive";
038    private static final String STR_ON_INACTIVE = "onInactive";
039    private static final String STR_ON_CHANGE = "onChange";
040    private static final String STR_VETO_ACTIVE = "vetoActive";
041    private static final String STR_VETO_INACTIVE = "vetoInactive";
042
043    private static final String STR_THROWN = "THROWN";
044    private static final String STR_CLOSED = "CLOSED";
045    private static final String STR_CHANGE = "CHANGE";
046    private static final String STR_TOGGLE = "TOGGLE";
047    private static final String STR_VETO_CLOSED = "VETOCLOSED";
048    private static final String STR_VETO_THROWN = "VETOTHROWN";
049    private static final String STR_ADDED_DELAY = "addedDelay";
050
051    private static final String STR_ROUTE_LOCKED = "routeLocked";
052    private static final String STR_ROUTE_SENSOR = "routeSensor";
053    private static final String STR_ROUTE_OUTPUT_SENSOR = "routeOutputSensor";
054    private static final String STR_ROUTE_OUTPUT_TURNOUT = "routeOutputTurnout";
055    private static final String STR_STATE = "state";
056    private static final String STR_MODE = "mode";
057    private static final String STR_NAME = "name";
058
059    private static final String STR_ROUTE_SOUND_FILE = "routeSoundFile";
060    private static final String STR_ROUTE_SCRIPT_FILE = "routeScriptFile";
061    private static final String STR_TURNOUTS_ALIGNED_SENSOR = "turnoutsAlignedSensor";
062
063    public DefaultRouteManagerXml() {
064    }
065
066    /**
067     * Default implementation for storing the contents of a RouteManager.
068     *
069     * @param o Object to store, of type RouteManager
070     * @return Element containing the complete info
071     */
072    @Override
073    public Element store(Object o) {
074        Element routes = new Element(STR_ROUTES);
075        setStoreElementClass(routes);
076        RouteManager rm = (RouteManager) o;
077        if (rm != null) {
078            SortedSet<Route> routeList = rm.getNamedBeanSet();
079            // don't return an element if there are no routes to include
080            if (routeList.isEmpty()) {
081                return null;
082            }
083            for (Route r : routeList) {
084                // store the routes
085                String rName = r.getSystemName();
086                log.debug("system name is {}", rName);
087
088                String cTurnout = r.getControlTurnout();
089                int addedDelay = r.getRouteCommandDelay();
090                String cLockTurnout = r.getLockControlTurnout();
091
092                Element elem = new Element(STR_ROUTE);
093                elem.addContent(new Element(STR_SYSTEM_NAME).addContent(rName));
094
095                // As a work-around for backward compatibility, store systemName and userName as attribute.
096                // TODO Remove this in e.g. JMRI 4.11.1 and then update all the loadref comparison files
097                String uName = r.getUserName();
098                if (uName != null && !uName.isEmpty()) {
099                    elem.setAttribute(STR_USER_NAME, uName);
100                }
101
102                // store common parts
103                storeCommon(r, elem);
104
105                if (cTurnout != null && !cTurnout.isEmpty()) {
106                    elem.setAttribute(STR_CONTROL_TURNOUT, cTurnout);
107                    int state = r.getControlTurnoutState();
108                    switch (state) {
109                        case Route.ONTHROWN:
110                            elem.setAttribute(STR_CONTROL_TURNOUT_STATE, STR_THROWN);
111                            break;
112                        case Route.ONCHANGE:
113                            elem.setAttribute(STR_CONTROL_TURNOUT_STATE, STR_CHANGE);
114                            break;
115                        case Route.VETOCLOSED:
116                            elem.setAttribute(STR_CONTROL_TURNOUT_STATE, STR_VETO_CLOSED);
117                            break;
118                        case Route.VETOTHROWN:
119                            elem.setAttribute(STR_CONTROL_TURNOUT_STATE, STR_VETO_THROWN);
120                            break;
121                        default:
122                            elem.setAttribute(STR_CONTROL_TURNOUT_STATE, STR_CLOSED);
123                            break;
124                    }
125                    
126                    if (r.getControlTurnoutFeedback()) {
127                        elem.setAttribute(STR_CONTROL_TURNOUT_FEEDBACK, STR_TRUE);
128                    } // don't write if not set, accept default
129                }
130                if (cLockTurnout != null && !cLockTurnout.isEmpty()) {
131                    elem.setAttribute(STR_CONTROL_LOCK_TURNOUT, cLockTurnout);
132                    int state = r.getLockControlTurnoutState();
133                    switch (state) {
134                        case Route.ONTHROWN:
135                            elem.setAttribute(STR_CONTROL_LOCK_TURNOUT_STATE, STR_THROWN);
136                            break;
137                        case Route.ONCHANGE:
138                            elem.setAttribute(STR_CONTROL_LOCK_TURNOUT_STATE, STR_CHANGE);
139                            break;
140                        default:
141                            elem.setAttribute(STR_CONTROL_LOCK_TURNOUT_STATE, STR_CLOSED);
142                            break;
143                    }
144                }
145                if (addedDelay > 0) {
146                    elem.setAttribute(STR_ADDED_DELAY, Integer.toString(addedDelay));
147                }
148
149                if ( r.getLocked() ) {
150                    // TODO - For consistency in class, convert True to true
151                    elem.setAttribute(STR_ROUTE_LOCKED, "True");
152                }
153                // add route output Turnouts, if any
154                int index = 0;
155                String rTurnout;
156                while ((rTurnout = r.getOutputTurnoutByIndex(index)) != null) {
157                    Element rElem = new Element(STR_ROUTE_OUTPUT_TURNOUT)
158                            .setAttribute(STR_SYSTEM_NAME, rTurnout);
159                    String sState = STR_CLOSED;
160                    if (r.getOutputTurnoutSetState(rTurnout) == Turnout.THROWN) {
161                        sState = STR_THROWN;
162                    } else if (r.getOutputTurnoutSetState(rTurnout) == Route.TOGGLE) {
163                        sState = STR_TOGGLE;
164                    }
165                    rElem.setAttribute(STR_STATE, sState);
166                    elem.addContent(rElem);
167                    index++;
168                }
169                // add route output Sensors, if any
170                index = 0;
171                String rSensor;
172                while ((rSensor = r.getOutputSensorByIndex(index)) != null) {
173                    Element rElem = new Element(STR_ROUTE_OUTPUT_SENSOR)
174                            .setAttribute(STR_SYSTEM_NAME, rSensor);
175                    String sState = STR_INACTIVE;
176                    if (r.getOutputSensorSetState(rSensor) == Sensor.ACTIVE) {
177                        sState = STR_ACTIVE;
178                    } else if (r.getOutputSensorSetState(rSensor) == Route.TOGGLE) {
179                        sState = STR_TOGGLE;
180                    }
181                    rElem.setAttribute(STR_STATE, sState);
182                    elem.addContent(rElem);
183                    index++;
184                }
185                // add route control Sensors, if any
186                index = 0;
187                while ((rSensor = r.getRouteSensorName(index)) != null) {
188                    Element rsElem = new Element(STR_ROUTE_SENSOR)
189                            .setAttribute(STR_SYSTEM_NAME, rSensor);
190                    int mode = r.getRouteSensorMode(index);
191                    String modeName;
192                    switch (mode) {
193                        case Route.ONACTIVE:
194                            modeName = STR_ON_ACTIVE;
195                            break;
196                        case Route.ONINACTIVE:
197                            modeName = STR_ON_INACTIVE;
198                            break;
199                        case Route.ONCHANGE:
200                            modeName = STR_ON_CHANGE;
201                            break;
202                        case Route.VETOACTIVE:
203                            modeName = STR_VETO_ACTIVE;
204                            break;
205                        case Route.VETOINACTIVE:
206                            modeName = STR_VETO_INACTIVE;
207                            break;
208                        default:
209                            modeName = null;
210                    }
211                    if (modeName != null) {
212                        rsElem.setAttribute(STR_MODE, modeName);
213                    }
214                    elem.addContent(rsElem);
215                    index++;
216                }
217                // add sound and script file elements if needed
218                String osn = r.getOutputSoundName();
219                if ( osn != null && !osn.isEmpty()) {
220                    Element rsElem = new Element(STR_ROUTE_SOUND_FILE)
221                        .setAttribute(STR_NAME,
222                            jmri.util.FileUtil.getPortableFilename(
223                                new java.io.File(osn))
224                        );
225                    elem.addContent(rsElem);
226                }
227                osn = r.getOutputScriptName();
228                if ( osn != null && !osn.isEmpty()) {
229                    Element rsElem = new Element(STR_ROUTE_SCRIPT_FILE)
230                        .setAttribute(STR_NAME,
231                            jmri.util.FileUtil.getPortableFilename(
232                                new java.io.File(osn))
233                        );
234                    elem.addContent(rsElem);
235                }
236
237                // add turnouts aligned sensor if there is one
238                osn = r.getTurnoutsAlignedSensor();
239                if ( osn != null && !osn.isEmpty()) {
240                    Element rsElem = new Element(STR_TURNOUTS_ALIGNED_SENSOR)
241                        .setAttribute(STR_NAME, osn);
242                    elem.addContent(rsElem);
243                }
244
245                log.debug("store Route {}", rName);
246                routes.addContent(elem);
247            }
248        }
249        return routes;
250    }
251
252    /**
253     * Subclass provides implementation to create the correct top element,
254     * including the type information. Default implementation is to use the
255     * local class here.
256     *
257     * @param routes The top-level element being created
258     */
259    public void setStoreElementClass(Element routes) {
260        routes.setAttribute(STR_CLASS, this.getClass().getName());
261    }
262
263    /**
264     * Create a RouteManager object of the correct class, then register and fill
265     * it.
266     *
267     * @param sharedRoutes Top level Element to unpack.
268     * @param perNodeRoutes unused.
269     * @return true if successful
270     */
271    @Override
272    public boolean load(Element sharedRoutes, Element perNodeRoutes) {
273        // create the master object
274        replaceRouteManager();
275        // load individual sharedRoutes
276        loadRoutes(sharedRoutes);
277        return true;
278    }
279
280    /**
281     * Utility method to load the individual Route objects. If there's no
282     * additional info needed for a specific route type, invoke this with the
283     * parent of the set of Route elements.
284     *
285     * @param routes Element containing the Route elements to load.
286     */
287    public void loadRoutes(Element routes) {
288        List<Element> routeList = routes.getChildren(STR_ROUTE);
289        log.debug("Found {} routes", routeList.size());
290        RouteManager tm = InstanceManager.getDefault(RouteManager.class);
291        int namesChanged = 0;
292
293        for (Element el : routeList) {
294
295            String sysName = getSystemName(el);
296            if (sysName == null) {
297                log.warn("unexpected null in systemName {}", el);
298                break;
299            }
300            // convert typeLetter from R to tm.typeLetter()
301            if (sysName.startsWith(tm.getSystemPrefix() + 'R')) {
302                String old = sysName;
303                sysName = tm.getSystemNamePrefix() + sysName.substring(tm.getSystemNamePrefix().length());
304                log.warn("Converting route system name {} to {}", old, sysName);
305                namesChanged++;
306            }
307            // prepend systemNamePrefix if missing
308            if (!sysName.startsWith(tm.getSystemNamePrefix())) {
309                String old = sysName;
310                sysName = tm.getSystemNamePrefix() + sysName;
311                log.warn("Converting route system name {} to {}", old, sysName);
312                namesChanged++;
313            }
314
315            String userName = getUserName(el);
316            String cTurnout = null;
317            String cTurnoutState = null;
318            boolean cTurnoutFeedback = false;
319            String routeLockedTxt = null;
320            String cLockTurnout = null;
321            String cLockTurnoutState = null;
322            int addedDelay = 0;
323
324            if (el.getAttribute(STR_CONTROL_TURNOUT) != null) {
325                cTurnout = el.getAttribute(STR_CONTROL_TURNOUT).getValue();
326            }
327            if (el.getAttribute(STR_CONTROL_TURNOUT_STATE) != null) {
328                cTurnoutState = el.getAttribute(STR_CONTROL_TURNOUT_STATE).getValue();
329            }
330            if (el.getAttribute(STR_CONTROL_TURNOUT_FEEDBACK) != null) {
331                cTurnoutFeedback = el.getAttribute(STR_CONTROL_TURNOUT_FEEDBACK).getValue().equals(STR_TRUE);
332            }
333            if (el.getAttribute(STR_CONTROL_LOCK_TURNOUT) != null) {
334                cLockTurnout = el.getAttribute(STR_CONTROL_LOCK_TURNOUT).getValue();
335            }
336            if (el.getAttribute(STR_CONTROL_LOCK_TURNOUT_STATE) != null) {
337                cLockTurnoutState = el.getAttribute(STR_CONTROL_LOCK_TURNOUT_STATE).getValue();
338            }
339            if (el.getAttribute(STR_ADDED_DELAY) != null) {
340                String addedDelayTxt = el.getAttribute(STR_ADDED_DELAY).getValue();
341                if (addedDelayTxt != null) {
342                    addedDelay = Integer.parseInt(addedDelayTxt);
343                }
344            }
345            if (el.getAttribute(STR_ROUTE_LOCKED) != null) {
346                routeLockedTxt = el.getAttribute(STR_ROUTE_LOCKED).getValue();
347            }
348
349            log.debug("create route: ({})({})", sysName, (userName == null ? "<null>" : userName));
350            
351            Route r;
352            try {
353                r = tm.provideRoute(sysName, userName);
354            } catch (IllegalArgumentException ex) {
355                log.error("failed to create Route: {}", sysName);
356                return;
357            }
358
359            // load common parts
360            loadCommon(r, el);
361
362            // add control turnout if there is one
363            if (cTurnout != null) {
364                r.setControlTurnout(cTurnout);
365                if (cTurnoutState != null) {
366                    switch (cTurnoutState) {
367                        case STR_THROWN:
368                            r.setControlTurnoutState(Route.ONTHROWN);
369                            break;
370                        case STR_CHANGE:
371                            r.setControlTurnoutState(Route.ONCHANGE);
372                            break;
373                        case STR_VETO_CLOSED:
374                            r.setControlTurnoutState(Route.VETOCLOSED);
375                            break;
376                        case STR_VETO_THROWN:
377                            r.setControlTurnoutState(Route.VETOTHROWN);
378                            break;
379                        default:
380                            r.setControlTurnoutState(Route.ONCLOSED);
381                    }
382                } else {
383                    log.error("cTurnoutState was null!");
384                }
385                r.setControlTurnoutFeedback(cTurnoutFeedback);
386            }
387            // set added delay
388            r.setRouteCommandDelay(addedDelay);
389
390            // determine if route locked
391            if (routeLockedTxt != null && routeLockedTxt.equals("True")) {
392                r.setLocked(true);
393            }
394
395            // add lock control turout if there is one
396            if (cLockTurnout != null) {
397                r.setLockControlTurnout(cLockTurnout);
398                if (cLockTurnoutState != null) {
399                    switch (cLockTurnoutState) {
400                        case STR_THROWN:
401                            r.setLockControlTurnoutState(Route.ONTHROWN);
402                            break;
403                        case STR_CHANGE:
404                            r.setLockControlTurnoutState(Route.ONCHANGE);
405                            break;
406                        default:
407                            r.setLockControlTurnoutState(Route.ONCLOSED);
408                            break;
409                    }
410                } else {
411                    log.error("cLockTurnoutState was null!");
412                }
413            }
414
415            // load output turnouts if there are any - old format first (1.7.6 and before)
416            List<Element> routeTurnoutList = el.getChildren("routeTurnout");
417            if (!routeTurnoutList.isEmpty()) {
418                // This route has turnouts
419                for (Element element : routeTurnoutList) {
420                    if (element.getAttribute(STR_SYSTEM_NAME) == null) {
421                        log.warn("unexpected null in route turnout systemName {} {}", element, element.getAttributes());
422                        break;
423                    }
424                    String tSysName = element.getAttribute(STR_SYSTEM_NAME).getValue();
425                    String rState = element.getAttribute(STR_STATE).getValue();
426                    int tSetState = Turnout.CLOSED;
427                    if (rState.equals(STR_THROWN)) {
428                        tSetState = Turnout.THROWN;
429                    } else if (rState.equals(STR_TOGGLE)) {
430                        tSetState = Route.TOGGLE;
431                    }
432                    // Add turnout to route
433                    r.addOutputTurnout(tSysName, tSetState);
434                }
435            }
436            // load output turnouts if there are any - new format
437            routeTurnoutList = el.getChildren(STR_ROUTE_OUTPUT_TURNOUT);
438            if (!routeTurnoutList.isEmpty()) {
439                // This route has turnouts
440                for (int k = 0; k < routeTurnoutList.size(); k++) { // index k is required later to get Locked state
441                    if (routeTurnoutList.get(k).getAttribute(STR_SYSTEM_NAME) == null) {
442                        log.warn("unexpected null in route turnout systemName {} {}", routeTurnoutList.get(k),
443                                routeTurnoutList.get(k).getAttributes());
444                        break;
445                    }
446                    String tSysName = routeTurnoutList.get(k)
447                            .getAttribute(STR_SYSTEM_NAME).getValue();
448                    String rState = routeTurnoutList.get(k)
449                            .getAttribute(STR_STATE).getValue();
450                    int tSetState = Turnout.CLOSED;
451                    if (rState.equals(STR_THROWN)) {
452                        tSetState = Turnout.THROWN;
453                    } else if (rState.equals(STR_TOGGLE)) {
454                        tSetState = Route.TOGGLE;
455                    }
456                    // If the Turnout has already been added to the route and is the same as that loaded, 
457                    // we will not re add the turnout.
458                    if (!r.isOutputTurnoutIncluded(tSysName)) {
459
460                        // Add turnout to route
461                        r.addOutputTurnout(tSysName, tSetState);
462
463                        // determine if turnout should be locked
464                        Turnout t = r.getOutputTurnout(k);
465                        if ( t == null ) {
466                            log.error("could not find output Turnout {}", tSysName);
467                        } else if (r.getLocked()) {
468                            t.setLocked(Turnout.CABLOCKOUT + Turnout.PUSHBUTTONLOCKOUT, true);
469                        }
470                    }
471                }
472            }
473            // load output sensors if there are any - new format
474            List<Element> routeSensorList = el.getChildren(STR_ROUTE_OUTPUT_SENSOR);
475            for (Element sen : routeSensorList) { // this route has output sensors
476                if (sen.getAttribute(STR_SYSTEM_NAME) == null) {
477                    log.warn("unexpected null in systemName {} {}", sen, sen.getAttributes());
478                    break;
479                }
480                String tSysName = sen.getAttribute(STR_SYSTEM_NAME).getValue();
481                String rState = sen.getAttribute(STR_STATE).getValue();
482                int tSetState = Sensor.INACTIVE;
483                if (rState.equals(STR_ACTIVE)) {
484                    tSetState = Sensor.ACTIVE;
485                } else if (rState.equals(STR_TOGGLE)) {
486                    tSetState = Route.TOGGLE;
487                }
488                // If the Turnout has already been added to the route and is the same as that loaded,
489                // we will not re add the turnout.
490                if (r.isOutputSensorIncluded(tSysName)) {
491                    break;
492                }
493                // Add turnout to route
494                r.addOutputSensor(tSysName, tSetState);
495            }
496            // load sound, script files if present
497            Element fileElement = el.getChild(STR_ROUTE_SOUND_FILE);
498            if (fileElement != null) {
499                // convert to absolute path name
500                r.setOutputSoundName(
501                        jmri.util.FileUtil.getExternalFilename(fileElement.getAttribute(STR_NAME).getValue())
502                );
503            }
504            fileElement = el.getChild(STR_ROUTE_SCRIPT_FILE);
505            if (fileElement != null) {
506                r.setOutputScriptName(
507                        jmri.util.FileUtil.getExternalFilename(fileElement.getAttribute(STR_NAME).getValue())
508                );
509            }
510            // load turnouts aligned sensor if there is one
511            fileElement = el.getChild(STR_TURNOUTS_ALIGNED_SENSOR);
512            if (fileElement != null) {
513                r.setTurnoutsAlignedSensor(fileElement.getAttribute(STR_NAME).getValue());
514            }
515
516            // load route control sensors, if there are any
517            routeSensorList = el.getChildren(STR_ROUTE_SENSOR);
518            for (Element sen : routeSensorList) { // this route has sensors
519                if (sen.getAttribute(STR_SYSTEM_NAME) == null) {
520                    log.warn("unexpected null in systemName {} {}", sen, sen.getAttributes());
521                    break;
522                } else {
523                int mode = Route.ONACTIVE;  // default mode
524                if (sen.getAttribute(STR_MODE) == null) {
525                    break;
526                }
527                String sm = sen.getAttribute(STR_MODE).getValue();
528                switch (sm) {
529                    case STR_ON_ACTIVE:
530                        mode = Route.ONACTIVE;
531                        break;
532                    case STR_ON_INACTIVE:
533                        mode = Route.ONINACTIVE;
534                        break;
535                    case STR_ON_CHANGE:
536                        mode = Route.ONCHANGE;
537                        break;
538                    case STR_VETO_ACTIVE:
539                        mode = Route.VETOACTIVE;
540                        break;
541                    case STR_VETO_INACTIVE:
542                        mode = Route.VETOINACTIVE;
543                        break;
544                    default:
545                        log.warn("unexpected sensor mode in route {} was {}", sysName, sm);
546                }
547                // Add Sensor to route
548                r.addSensorToRoute(sen.getAttribute(STR_SYSTEM_NAME).getValue(), mode);
549                }
550            }
551            // and start it working
552            r.activateRoute();
553        }
554        if (namesChanged > 0) {
555            // TODO: replace the System property check with an in-application mechanism
556            // for notifying users of multiple changes that can be silenced as part of
557            // normal operations
558            if (!GraphicsEnvironment.isHeadless() && !Boolean.getBoolean("jmri.test.no-dialogs")) {
559                JmriJOptionPane.showMessageDialog(null,
560                    Bundle.getMessage(namesChanged > 1 ? "RouteManager.SystemNamesChanged.Message" :
561                        "RouteManager.SystemNameChanged.Message", namesChanged),
562                    Bundle.getMessage("Manager.SystemNamesChanged.Title",
563                        namesChanged, tm.getBeanTypeHandled(namesChanged > 1)),
564                    JmriJOptionPane.WARNING_MESSAGE);
565            }
566            log.warn("System names for {} Routes changed; this may have operational impacts.", namesChanged); 
567        }
568    }
569
570    /**
571     * Replace the current RouteManager, if there is one, with one newly created
572     * during a load operation. This is skipped if the present one is already of
573     * the right type.
574     */
575    protected void replaceRouteManager() {
576        RouteManager current = InstanceManager.getNullableDefault(RouteManager.class);
577        if (current != null && current.getClass().getName()
578                .equals(DefaultRouteManager.class.getName())) {
579            return;
580        }
581        // if old manager exists, remove it from configuration process
582        if (current != null) {
583            InstanceManager.getDefault(jmri.ConfigureManager.class).deregister(current);
584            InstanceManager.deregister(current, RouteManager.class);
585        }
586
587        // register new one with InstanceManager
588        DefaultRouteManager pManager = InstanceManager.getDefault(DefaultRouteManager.class);
589        InstanceManager.store(pManager, RouteManager.class);
590        // register new one for configuration
591        InstanceManager.getDefault(jmri.ConfigureManager.class).registerConfig(pManager, jmri.Manager.ROUTES);
592    }
593
594    @Override
595    public int loadOrder() {
596        return InstanceManager.getDefault(RouteManager.class).getXMLOrder();
597    }
598
599    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultRouteManagerXml.class);
600
601}