001package jmri.jmrit.operations.setup;
002
003import java.awt.Color;
004import java.awt.JobAttributes.SidesType;
005import java.io.IOException;
006import java.util.*;
007
008import javax.swing.JComboBox;
009
010import org.jdom2.Element;
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014import jmri.*;
015import jmri.beans.PropertyChangeSupport;
016import jmri.jmris.AbstractOperationsServer;
017import jmri.jmrit.operations.rollingstock.RollingStockLogger;
018import jmri.jmrit.operations.setup.backup.AutoBackup;
019import jmri.jmrit.operations.setup.backup.AutoSave;
020import jmri.jmrit.operations.trains.TrainLogger;
021import jmri.jmrit.operations.trains.TrainManagerXml;
022import jmri.util.ColorUtil;
023import jmri.util.swing.JmriColorChooser;
024import jmri.web.server.WebServerPreferences;
025
026/**
027 * Operations settings.
028 *
029 * @author Daniel Boudreau Copyright (C) 2008, 2010, 2012, 2014, 2025
030 */
031public class Setup extends PropertyChangeSupport implements InstanceManagerAutoDefault, Disposable {
032
033    public static final String NONE = "";
034
035    // scale ratios from NMRA
036    private static final int Z_RATIO = 220;
037    private static final int N_RATIO = 160;
038    private static final int TT_RATIO = 120;
039    private static final int OO_RATIO = 76; // actual ratio 76.2
040    private static final int HO_RATIO = 87;
041    private static final int S_RATIO = 64;
042    private static final int O_RATIO = 48;
043    private static final int G_RATIO = 32; // NMRA #1
044
045    // initial weight in milli ounces from NMRA
046    private static final int Z_INITIAL_WEIGHT = 364; // not specified by NMRA
047    private static final int N_INITIAL_WEIGHT = 500;
048    private static final int TT_INITIAL_WEIGHT = 750;
049    private static final int HOn3_INITIAL_WEIGHT = 750;
050    private static final int OO_INITIAL_WEIGHT = 750; // not specified by NMRA
051    private static final int HO_INITIAL_WEIGHT = 1000;
052    private static final int Sn3_INITIAL_WEIGHT = 1000;
053    private static final int S_INITIAL_WEIGHT = 2000;
054    private static final int On3_INITIAL_WEIGHT = 1500;
055    private static final int O_INITIAL_WEIGHT = 5000;
056    private static final int G_INITIAL_WEIGHT = 10000; // not specified by NMRA
057
058    // additional weight in milli ounces from NMRA
059    private static final int Z_ADD_WEIGHT = 100; // not specified by NMRA
060    private static final int N_ADD_WEIGHT = 150;
061    private static final int TT_ADD_WEIGHT = 375;
062    private static final int HOn3_ADD_WEIGHT = 375;
063    private static final int OO_ADD_WEIGHT = 500; // not specified by NMRA
064    private static final int HO_ADD_WEIGHT = 500;
065    private static final int Sn3_ADD_WEIGHT = 500;
066    private static final int S_ADD_WEIGHT = 500;
067    private static final int On3_ADD_WEIGHT = 750;
068    private static final int O_ADD_WEIGHT = 1000;
069    private static final int G_ADD_WEIGHT = 2000; // not specified by NMRA
070
071    // actual weight to tons conversion ratios (based on 40' boxcar at ~80 tons)
072    private static final int Z_RATIO_TONS = 130;
073    private static final int N_RATIO_TONS = 80;
074    private static final int TT_RATIO_TONS = 36;
075    private static final int HOn3_RATIO_TONS = 20;
076    private static final int OO_RATIO_TONS = 20;
077    private static final int HO_RATIO_TONS = 20; // 20 tons per ounce
078    private static final int Sn3_RATIO_TONS = 16;
079    private static final int S_RATIO_TONS = 14;
080    private static final int On3_RATIO_TONS = 8;
081    private static final int O_RATIO_TONS = 5;
082    private static final int G_RATIO_TONS = 2;
083
084    public static final int Z_SCALE = 1;
085    public static final int N_SCALE = 2;
086    public static final int TT_SCALE = 3;
087    public static final int HOn3_SCALE = 4;
088    public static final int OO_SCALE = 5;
089    public static final int HO_SCALE = 6;
090    public static final int Sn3_SCALE = 7;
091    public static final int S_SCALE = 8;
092    public static final int On3_SCALE = 9;
093    public static final int O_SCALE = 10;
094    public static final int G_SCALE = 11; // NMRA #1
095
096    public static final int EAST = 1; // train direction serviced by this location
097    public static final int WEST = 2;
098    public static final int NORTH = 4;
099    public static final int SOUTH = 8;
100
101    public static final String EAST_DIR = Bundle.getMessage("East");
102    public static final String WEST_DIR = Bundle.getMessage("West");
103    public static final String NORTH_DIR = Bundle.getMessage("North");
104    public static final String SOUTH_DIR = Bundle.getMessage("South");
105
106    public static final String DESCRIPTIVE = Bundle.getMessage("Descriptive"); // Car types
107    public static final String AAR = Bundle.getMessage("ArrCodes"); // Car types
108
109    public static final String MONOSPACED = Bundle.getMessage("Monospaced"); // default printer font
110
111    public static final String STANDARD_FORMAT = Bundle.getMessage("StandardFormat");
112    public static final String TWO_COLUMN_FORMAT = Bundle.getMessage("TwoColumnFormat");
113    public static final String TWO_COLUMN_TRACK_FORMAT = Bundle.getMessage("TwoColumnTrackFormat");
114
115    public static final String PORTRAIT = Bundle.getMessage("Portrait");
116    public static final String LANDSCAPE = Bundle.getMessage("Landscape");
117    public static final String HALFPAGE = Bundle.getMessage("HalfPage");
118    public static final String HANDHELD = Bundle.getMessage("HandHeld");
119
120    public static final String PAGE_NORMAL = Bundle.getMessage("PageNormal");
121    public static final String PAGE_PER_TRAIN = Bundle.getMessage("PagePerTrain");
122    public static final String PAGE_PER_VISIT = Bundle.getMessage("PagePerVisit");
123
124    public static final String BUILD_REPORT_MINIMAL = "1";
125    public static final String BUILD_REPORT_NORMAL = "3";
126    public static final String BUILD_REPORT_DETAILED = "5";
127    public static final String BUILD_REPORT_VERY_DETAILED = "7";
128
129    // the following are converted to English spelling when storing to file, see KEYS below
130    public static final String ROAD = Bundle.getMessage("Road"); // the supported message format options
131    public static final String NUMBER = Bundle.getMessage("Number");
132    public static final String TYPE = Bundle.getMessage("Type");
133    public static final String MODEL = Bundle.getMessage("Model");
134    public static final String LENGTH = Bundle.getMessage("Length");
135    public static final String WEIGHT = Bundle.getMessage("Weight");
136    public static final String HP = Bundle.getMessage("HP");
137    public static final String LOAD = Bundle.getMessage("Load");
138    public static final String LOAD_TYPE = Bundle.getMessage("Load_Type");
139    public static final String COLOR = Bundle.getMessage("Color");
140    public static final String TRACK = Bundle.getMessage("Track");
141    public static final String DESTINATION = Bundle.getMessage("Destination");
142    public static final String DEST_TRACK = Bundle.getMessage("Dest&Track");
143    public static final String FINAL_DEST = Bundle.getMessage("Final_Dest");
144    public static final String FINAL_DEST_TRACK = Bundle.getMessage("FD&Track");
145    public static final String LOCATION = Bundle.getMessage("Location");
146    public static final String CONSIST = Bundle.getMessage("Consist");
147    public static final String DCC_ADDRESS = Bundle.getMessage("DCC_Address");
148    public static final String KERNEL = Bundle.getMessage("Kernel");
149    public static final String KERNEL_SIZE = Bundle.getMessage("Kernel_Size");
150    public static final String OWNER = Bundle.getMessage("Owner");
151    public static final String DIVISION = Bundle.getMessage("Division");
152    public static final String BLOCKING_ORDER = Bundle.getMessage("Blocking_Order");
153    public static final String RWE = Bundle.getMessage("RWE");
154    public static final String COMMENT = Bundle.getMessage("Comment");
155    public static final String DROP_COMMENT = Bundle.getMessage("SetOut_Msg");
156    public static final String PICKUP_COMMENT = Bundle.getMessage("PickUp_Msg");
157    public static final String HAZARDOUS = Bundle.getMessage("Hazardous");
158    public static final String LAST_TRAIN = Bundle.getMessage("LastTrain");
159    public static final String BLANK = " "; // blank has be a character or a space
160    public static final String TAB = Bundle.getMessage("Tab"); // used to tab out in tabular mode
161    public static final String TAB2 = Bundle.getMessage("Tab2");
162    public static final String TAB3 = Bundle.getMessage("Tab3");
163    
164    public static final String BOX = " [ ] "; // NOI18N
165
166    // these are for the utility printing when using tabs
167    public static final String NO_ROAD = "NO_ROAD"; // NOI18N
168    public static final String NO_NUMBER = "NO_NUMBER"; // NOI18N
169    public static final String NO_COLOR = "NO_COLOR"; // NOI18N
170
171    // truncated manifests
172    public static final String NO_DESTINATION = "NO_DESTINATION"; // NOI18N
173    public static final String NO_DEST_TRACK = "NO_DEST_TRACK"; // NOI18N
174    public static final String NO_LOCATION = "NO_LOCATION"; // NOI18N
175    public static final String NO_TRACK = "NO_TRACK"; // NOI18N
176
177    // Unit of Length
178    public static final String FEET = Bundle.getMessage("Feet");
179    public static final String METER = Bundle.getMessage("Meter");
180    public static final String FEET_ABV = Bundle.getMessage("FeetAbbreviation");
181    public static final String METER_ABV = Bundle.getMessage("MeterAbbreviation");
182
183    private static final String[] CAR_ATTRIBUTES = { ROAD, NUMBER, TYPE, LENGTH, WEIGHT, LOAD, LOAD_TYPE, HAZARDOUS,
184            COLOR, KERNEL, KERNEL_SIZE, OWNER, DIVISION, TRACK, LOCATION, DESTINATION, DEST_TRACK, FINAL_DEST, FINAL_DEST_TRACK,
185            BLOCKING_ORDER, COMMENT, DROP_COMMENT, PICKUP_COMMENT, RWE, LAST_TRAIN};
186    
187    private static final String[] ENGINE_ATTRIBUTES = {ROAD, NUMBER, TYPE, MODEL, LENGTH, WEIGHT, HP, CONSIST, OWNER,
188            TRACK, LOCATION, DESTINATION, COMMENT, DCC_ADDRESS, LAST_TRAIN};
189    /*
190     * The print Manifest and switch list user selectable options are stored in the
191     * xml file using the English translations.
192     */
193    private static final String[] KEYS = {"Road", "Number", "Type", "Model", "Length", "Weight", "Load", "Load_Type",
194            "HP", "Color", "Track", "Destination", "Dest&Track", "Final_Dest", "FD&Track", "Location", "Consist",
195            "DCC_Address", "Kernel", "Kernel_Size", "Owner", "Division", "Blocking_Order", "RWE", "Comment",
196            "SetOut_Msg", "PickUp_Msg", "Hazardous", "LastTrain", "Tab", "Tab2", "Tab3"};
197
198    private int scale = HO_SCALE; // Default scale
199    private int ratio = HO_RATIO;
200    private int ratioTons = HO_RATIO_TONS;
201    private int initWeight = HO_INITIAL_WEIGHT;
202    private int addWeight = HO_ADD_WEIGHT;
203    private String railroadName = NONE;
204    private int traindir = EAST + WEST + NORTH + SOUTH;
205    private int maxTrainLength = 1000; // maximum train length
206    private int maxEngineSize = 6; // maximum number of engines that can be assigned to a train
207    private double horsePowerPerTon = 1; // Horsepower per ton
208    private int carMoves = 5; // default number of moves when creating a route
209    private String carTypes = DESCRIPTIVE;
210    private String ownerName = NONE;
211    private String fontName = MONOSPACED;
212    private int manifestFontSize = 10;
213    private int buildReportFontSize = 10;
214    private String manifestOrientation = PORTRAIT;
215    private String switchListOrientation = PORTRAIT;
216    private SidesType sidesType = SidesType.ONE_SIDED;
217    private boolean printHeader = true;
218    private Color pickupEngineColor = Color.black;
219    private Color dropEngineColor = Color.black;
220    private Color pickupColor = Color.black;
221    private Color dropColor = Color.black;
222    private Color localColor = Color.black;
223    private String[] pickupEngineMessageFormat = { ROAD, NUMBER, BLANK, MODEL, BLANK, BLANK, LOCATION, COMMENT };
224    private String[] dropEngineMessageFormat = { ROAD, NUMBER, BLANK, MODEL, BLANK, BLANK, DESTINATION, COMMENT };
225    private String[] pickupManifestMessageFormat = { ROAD, NUMBER, TYPE, LENGTH, COLOR, LOAD, HAZARDOUS, LOCATION,
226            COMMENT, PICKUP_COMMENT };
227    private String[] dropManifestMessageFormat = { ROAD, NUMBER, TYPE, LENGTH, COLOR, LOAD, HAZARDOUS, DESTINATION,
228            COMMENT, DROP_COMMENT };
229    private String[] localManifestMessageFormat = { ROAD, NUMBER, TYPE, LENGTH, COLOR, LOAD, HAZARDOUS, LOCATION,
230            DESTINATION, COMMENT };
231    private String[] pickupSwitchListMessageFormat = { ROAD, NUMBER, TYPE, LENGTH, COLOR, LOAD, HAZARDOUS, LOCATION,
232            COMMENT, PICKUP_COMMENT };
233    private String[] dropSwitchListMessageFormat = { ROAD, NUMBER, TYPE, LENGTH, COLOR, LOAD, HAZARDOUS, DESTINATION,
234            COMMENT, DROP_COMMENT };
235    private String[] localSwitchListMessageFormat = { ROAD, NUMBER, TYPE, LENGTH, COLOR, LOAD, HAZARDOUS, LOCATION,
236            DESTINATION, COMMENT };
237    private String[] missingCarMessageFormat = { ROAD, NUMBER, TYPE, LENGTH, COLOR, COMMENT };
238    private String pickupEnginePrefix = BOX + Bundle.getMessage("PickUpPrefix");
239    private String dropEnginePrefix = BOX + Bundle.getMessage("SetOutPrefix");
240    private String pickupCarPrefix = BOX + Bundle.getMessage("PickUpPrefix");
241    private String dropCarPrefix = BOX + Bundle.getMessage("SetOutPrefix");
242    private String localPrefix = BOX + Bundle.getMessage("LocalCarPrefix");
243    private String switchListPickupCarPrefix = BOX + Bundle.getMessage("PickUpPrefix");
244    private String switchListDropCarPrefix = BOX + Bundle.getMessage("SetOutPrefix");
245    private String switchListLocalPrefix = BOX + Bundle.getMessage("LocalCarPrefix");
246    private String miaComment = Bundle.getMessage("misplacedCars");
247    private String hazardousMsg = "(" + Bundle.getMessage("Hazardous") + ")";
248    private String logoURL = NONE;
249    private String panelName = "Panel"; // NOI18N
250    private String buildReportLevel = BUILD_REPORT_VERY_DETAILED;
251    private String routerBuildReportLevel = BUILD_REPORT_NORMAL;
252    private int carSwitchTime = 3; // how long it takes to move a car in minutes
253    private int travelTime = 4; // how long it takes a train to move from one location to another in minutes
254    private String yearModeled = NONE; // year being modeled
255    private String lengthUnit = FEET;
256    private String lengthUnitAbv = FEET_ABV;
257    private String iconNorthColor = NONE;
258    private String iconSouthColor = NONE;
259    private String iconEastColor = NONE;
260    private String iconWestColor = NONE;
261    private String iconLocalColor = NONE;
262    private String iconTerminateColor = NONE;
263
264    private boolean tab = false; // when true, tab out manifest and switch lists
265    private int tab1CharLength = Control.max_len_string_attibute;
266    private int tab2CharLength = 6; // arbitrary lengths
267    private int tab3CharLength = 8;
268
269    private String manifestFormat = STANDARD_FORMAT;
270    private boolean manifestEditorEnabled = false; // when true use text editor to view build report
271    private boolean switchListSameManifest = true; // when true switch list format is the same as the manifest
272    private boolean manifestTruncated = false; // when true, manifest is truncated if switch list is available
273    private boolean manifestDepartureTime = false; // when true, manifest shows train's departure time
274    private boolean switchListDepartureTime = false; // when true, switch list shows train's departure time
275    private boolean switchListRouteComment = true; // when true, switch list have route location comments
276    private boolean trackSummary = true; // when true, print switch list track summary
277    private boolean groupCarMoves = false; // when true, car moves are grouped together
278    private boolean locoLast = false; // when true, loco set outs printed last
279
280    private boolean switchListRealTime = true; // when true switch list only show work for built trains
281    private boolean switchListAllTrains = true; // when true show all trains that visit the location
282    private String switchListPageFormat = PAGE_NORMAL; // how switch lists pages are printed
283
284    private boolean buildReportEditorEnabled = false; // when true use text editor to view build report
285    private boolean buildReportIndentEnabled = true; // when true use text editor to view build report
286    private boolean buildReportAlwaysPreviewEnabled = false; // when true use text editor to view build report
287
288    private boolean enableTrainIconXY = true;
289    private boolean appendTrainIcon = false; // when true, append engine number to train name
290    private String setupComment = NONE;
291
292    private boolean mainMenuEnabled = false; // when true add operations menu to main menu bar
293    private boolean closeWindowOnSave = false; // when true, close window when save button is activated
294    private boolean autoSave = true; // when true, automatically save files if modified
295    private boolean autoBackup = true; // when true, automatically backup files
296    private boolean enableValue = false; // when true show value fields for rolling stock
297    private String labelValue = Bundle.getMessage("Value");
298    private boolean enableRfid = false; // when true show RFID fields for rolling stock
299    private String labelRfid = Bundle.getMessage("RFID");
300
301    private boolean carRoutingEnabled = true; // when true enable car routing
302    private boolean carRoutingYards = true; // when true enable car routing via yard tracks
303    private boolean carRoutingStaging = false; // when true staging tracks can be used for car routing
304    private boolean forwardToYardEnabled = true; // when true forward car to yard if track is full
305    private boolean onlyActiveTrains = false; // when true only active trains are used for routing
306    private boolean checkCarDestination = false; // when true check car's track for valid destination
307
308    private boolean carLogger = false; // when true car logger is enabled
309    private boolean engineLogger = false; // when true engine logger is enabled
310    private boolean trainLogger = false; // when true train logger is enabled
311    private boolean saveTrainManifests = false; // when true save previous train manifest
312
313    private boolean aggressiveBuild = false; // when true subtract car length from track reserve length
314    private int numberPasses = 2; // the number of passes in train builder
315    private boolean allowLocalInterchangeMoves = false; // when true local C/I to C/I moves are allowed
316    private boolean allowLocalYardMoves = false; // when true local yard to yard moves are allowed
317    private boolean allowLocalSpurMoves = false; // when true local spur to spur moves are allowed
318
319    private boolean trainIntoStagingCheck = true; // staging track must accept train's rolling stock types and roads
320    private boolean trackImmediatelyAvail = false; // when true staging track is available for other trains
321    private boolean allowCarsReturnStaging = false; // allow cars on a turn to return to staging if necessary (prevent
322                                                    // build failure)
323    private boolean promptFromStaging = false; // prompt user to specify which departure staging track to use
324    private boolean promptToStaging = false; // prompt user to specify which arrival staging track to use
325    private boolean tryNormalModeStaging = true; // try normal build if route length failure using aggressive
326
327    private boolean generateCsvManifest = false; // when true generate csv manifest
328    private boolean generateCsvSwitchList = false; // when true generate csv switch list
329    private boolean enableVsdPhysicalLocations = false;
330
331    private boolean printLocationComments = false; // when true print location comments on the manifest
332    private boolean printRouteComments = false; // when true print route comments on the manifest
333    private boolean printLoadsAndEmpties = false; // when true print Loads and Empties on the manifest
334    private boolean printTrainScheduleName = false; // when true print train schedule name on manifests and switch lists
335    private boolean use12hrFormat = false; // when true use 12hr rather than 24hr format
336    private boolean printValid = true; // when true print out the valid time and date
337    private boolean sortByTrack = false; // when true manifest work is sorted by track names
338    private boolean printHeaders = false; // when true add headers to manifest and switch lists
339    private boolean printHeaderLine1 = true; // when true add header line 1 to manifest and switch lists
340    private boolean printHeaderLine2 = true; // when true add header line 2 to manifest and switch lists
341    private boolean printHeaderLine3 = true; // when true add header line 3 to manifest and switch lists
342
343    private boolean printCabooseLoad = false; // when true print caboose load
344    private boolean printPassengerLoad = false; // when true print passenger car load
345    private boolean showTrackMoves = false; // when true show track moves in table
346
347    // property changes
348    public static final String SWITCH_LIST_CSV_PROPERTY_CHANGE = "setupSwitchListCSVChange"; // NOI18N
349    public static final String MANIFEST_CSV_PROPERTY_CHANGE = "setupManifestCSVChange"; // NOI18N
350    public static final String REAL_TIME_PROPERTY_CHANGE = "setupSwitchListRealTime"; // NOI18N
351    public static final String SHOW_TRACK_MOVES_PROPERTY_CHANGE = "setupShowTrackMoves"; // NOI18N
352    public static final String SAVE_TRAIN_MANIFEST_PROPERTY_CHANGE = "saveTrainManifestChange"; // NOI18N
353    public static final String ALLOW_CARS_TO_RETURN_PROPERTY_CHANGE = "allowCarsToReturnChange"; // NOI18N
354    public static final String TRAIN_DIRECTION_PROPERTY_CHANGE = "setupTrainDirectionChange"; // NOI18N
355    public static final String ROUTING_STAGING_PROPERTY_CHANGE = "setupRoutingStagingChange"; // NOI18N
356    public static final String TRAVEL_TIME_PROPERTY_CHANGE = "setupTravelTimeChange"; // NOI18N
357
358    public static boolean isMainMenuEnabled() {
359        InstanceManager.getDefault(OperationsSetupXml.class); // load file
360        return getDefault().mainMenuEnabled;
361    }
362
363    public static void setMainMenuEnabled(boolean enabled) {
364        getDefault().mainMenuEnabled = enabled;
365    }
366
367    public static boolean isCloseWindowOnSaveEnabled() {
368        return getDefault().closeWindowOnSave;
369    }
370
371    public static void setCloseWindowOnSaveEnabled(boolean enabled) {
372        getDefault().closeWindowOnSave = enabled;
373    }
374
375    public static boolean isAutoSaveEnabled() {
376        return getDefault().autoSave;
377    }
378
379    public static void setAutoSaveEnabled(boolean enabled) {
380        getDefault().autoSave = enabled;
381        if (enabled) {
382            AutoSave.start();
383        } else {
384            AutoSave.stop();
385        }
386    }
387
388    public static boolean isAutoBackupEnabled() {
389        return getDefault().autoBackup;
390    }
391
392    public static void setAutoBackupEnabled(boolean enabled) {
393        // Do an autoBackup only if we are changing the setting from false to
394        // true.
395        if (enabled && !getDefault().autoBackup) {
396            try {
397                new AutoBackup().autoBackup();
398            } catch (IOException ex) {
399                log.debug("Autobackup after setting AutoBackup flag true", ex);
400            }
401        }
402
403        getDefault().autoBackup = enabled;
404    }
405
406    public static boolean isValueEnabled() {
407        return getDefault().enableValue;
408    }
409
410    public static void setValueEnabled(boolean enabled) {
411        getDefault().enableValue = enabled;
412    }
413
414    public static String getValueLabel() {
415        return getDefault().labelValue;
416    }
417
418    public static void setValueLabel(String label) {
419        getDefault().labelValue = label;
420    }
421
422    public static boolean isRfidEnabled() {
423        return getDefault().enableRfid;
424    }
425
426    public static void setRfidEnabled(boolean enabled) {
427        getDefault().enableRfid = enabled;
428    }
429
430    public static String getRfidLabel() {
431        return getDefault().labelRfid;
432    }
433
434    public static void setRfidLabel(String label) {
435        getDefault().labelRfid = label;
436    }
437
438    public static boolean isCarRoutingEnabled() {
439        return getDefault().carRoutingEnabled;
440    }
441
442    public static void setCarRoutingEnabled(boolean enabled) {
443        getDefault().carRoutingEnabled = enabled;
444    }
445
446    public static boolean isCarRoutingViaYardsEnabled() {
447        return getDefault().carRoutingYards;
448    }
449
450    public static void setCarRoutingViaYardsEnabled(boolean enabled) {
451        getDefault().carRoutingYards = enabled;
452    }
453
454    public static boolean isCarRoutingViaStagingEnabled() {
455        return getDefault().carRoutingStaging;
456    }
457
458    public static void setCarRoutingViaStagingEnabled(boolean enabled) {
459        boolean old = isCarRoutingViaStagingEnabled();
460        getDefault().carRoutingStaging = enabled;
461        setDirtyAndFirePropertyChange(ROUTING_STAGING_PROPERTY_CHANGE, old, enabled);
462    }
463
464    public static boolean isForwardToYardEnabled() {
465        return getDefault().forwardToYardEnabled;
466    }
467
468    public static void setForwardToYardEnabled(boolean enabled) {
469        getDefault().forwardToYardEnabled = enabled;
470    }
471
472    public static boolean isOnlyActiveTrainsEnabled() {
473        return getDefault().onlyActiveTrains;
474    }
475
476    public static void setOnlyActiveTrainsEnabled(boolean enabled) {
477        getDefault().onlyActiveTrains = enabled;
478    }
479
480    /**
481     * When true, router checks that the car's destination is serviced by departure
482     * track. Very restrictive, not recommended.
483     * 
484     * @return true if enabled.
485     */
486    public static boolean isCheckCarDestinationEnabled() {
487        return getDefault().checkCarDestination;
488    }
489
490    public static void setCheckCarDestinationEnabled(boolean enabled) {
491        getDefault().checkCarDestination = enabled;
492    }
493
494    public static boolean isBuildAggressive() {
495        return getDefault().aggressiveBuild;
496    }
497
498    public static void setBuildAggressive(boolean enabled) {
499        getDefault().aggressiveBuild = enabled;
500    }
501
502    public static int getNumberPasses() {
503        return getDefault().numberPasses;
504    }
505
506    public static void setNumberPasses(int number) {
507        getDefault().numberPasses = number;
508    }
509
510    public static boolean isLocalInterchangeMovesEnabled() {
511        return getDefault().allowLocalInterchangeMoves;
512    }
513
514    public static void setLocalInterchangeMovesEnabled(boolean enabled) {
515        getDefault().allowLocalInterchangeMoves = enabled;
516    }
517
518    public static boolean isLocalYardMovesEnabled() {
519        return getDefault().allowLocalYardMoves;
520    }
521
522    public static void setLocalYardMovesEnabled(boolean enabled) {
523        getDefault().allowLocalYardMoves = enabled;
524    }
525
526    public static boolean isLocalSpurMovesEnabled() {
527        return getDefault().allowLocalSpurMoves;
528    }
529
530    public static void setLocalSpurMovesEnabled(boolean enabled) {
531        getDefault().allowLocalSpurMoves = enabled;
532    }
533
534    public static boolean isStagingTrainCheckEnabled() {
535        return getDefault().trainIntoStagingCheck;
536    }
537
538    /**
539     * Controls staging track selection, when true, the terminus staging track has
540     * to have the same characteristics as the train.
541     *
542     * @param enabled when true, the terminal staging track must service the same
543     *                car types, loads, etc. as the train
544     */
545    public static void setStagingTrainCheckEnabled(boolean enabled) {
546        getDefault().trainIntoStagingCheck = enabled;
547    }
548
549    public static boolean isStagingTrackImmediatelyAvail() {
550        return getDefault().trackImmediatelyAvail;
551    }
552
553    public static void setStagingTrackImmediatelyAvail(boolean enabled) {
554        getDefault().trackImmediatelyAvail = enabled;
555    }
556
557    /**
558     * allow cars to return to the same staging location if no other options
559     * (tracks) are available. Also available on a per train basis.
560     * 
561     * @return true if cars are allowed to depart and return to same staging
562     *         location
563     */
564    public static boolean isStagingAllowReturnEnabled() {
565        return getDefault().allowCarsReturnStaging;
566    }
567
568    public static void setStagingAllowReturnEnabled(boolean enabled) {
569        boolean old = getDefault().allowCarsReturnStaging;
570        getDefault().allowCarsReturnStaging = enabled;
571        setDirtyAndFirePropertyChange(ALLOW_CARS_TO_RETURN_PROPERTY_CHANGE, old, enabled);
572    }
573
574    public static boolean isStagingPromptFromEnabled() {
575        return getDefault().promptFromStaging;
576    }
577
578    public static void setStagingPromptFromEnabled(boolean enabled) {
579        getDefault().promptFromStaging = enabled;
580    }
581
582    public static boolean isStagingPromptToEnabled() {
583        return getDefault().promptToStaging;
584    }
585
586    public static void setStagingPromptToEnabled(boolean enabled) {
587        getDefault().promptToStaging = enabled;
588    }
589
590    public static boolean isStagingTryNormalBuildEnabled() {
591        return getDefault().tryNormalModeStaging;
592    }
593
594    public static void setStagingTryNormalBuildEnabled(boolean enabled) {
595        getDefault().tryNormalModeStaging = enabled;
596    }
597
598    public static boolean isGenerateCsvManifestEnabled() {
599        return getDefault().generateCsvManifest;
600    }
601
602    public static void setGenerateCsvManifestEnabled(boolean enabled) {
603        boolean old = getDefault().generateCsvManifest;
604        getDefault().generateCsvManifest = enabled;
605        if (enabled && !old) {
606            InstanceManager.getDefault(TrainManagerXml.class).createDefaultCsvManifestDirectory();
607        }
608        setDirtyAndFirePropertyChange(MANIFEST_CSV_PROPERTY_CHANGE, old, enabled);
609    }
610
611    public static boolean isGenerateCsvSwitchListEnabled() {
612        return getDefault().generateCsvSwitchList;
613    }
614
615    public static void setGenerateCsvSwitchListEnabled(boolean enabled) {
616        boolean old = getDefault().generateCsvSwitchList;
617        getDefault().generateCsvSwitchList = enabled;
618        if (enabled && !old) {
619            InstanceManager.getDefault(TrainManagerXml.class).createDefaultCsvSwitchListDirectory();
620        }
621        setDirtyAndFirePropertyChange(SWITCH_LIST_CSV_PROPERTY_CHANGE, old, enabled);
622    }
623
624    public static boolean isVsdPhysicalLocationEnabled() {
625        return getDefault().enableVsdPhysicalLocations;
626    }
627
628    public static void setVsdPhysicalLocationEnabled(boolean enabled) {
629        getDefault().enableVsdPhysicalLocations = enabled;
630    }
631
632    public static String getRailroadName() {
633        if (getDefault().railroadName.isEmpty()) {
634            return InstanceManager.getDefault(WebServerPreferences.class).getRailroadName();
635        }
636        return getDefault().railroadName;
637    }
638
639    public static void setRailroadName(String name) {
640        String old = getDefault().railroadName;
641        getDefault().railroadName = name;
642        if (old == null || !old.equals(name)) {
643            setDirtyAndFirePropertyChange("Railroad Name Change", old, name); // NOI18N
644        }
645    }
646
647    public static String getHazardousMsg() {
648        return getDefault().hazardousMsg;
649    }
650
651    public static void setHazardousMsg(String message) {
652        getDefault().hazardousMsg = message;
653    }
654
655    public static String getMiaComment() {
656        return getDefault().miaComment;
657    }
658
659    public static void setMiaComment(String comment) {
660        getDefault().miaComment = comment;
661    }
662
663    public static void setTrainDirection(int direction) {
664        int old = getDefault().traindir;
665        getDefault().traindir = direction;
666        if (old != direction) {
667            setDirtyAndFirePropertyChange(TRAIN_DIRECTION_PROPERTY_CHANGE, old, direction);
668        }
669    }
670
671    public static int getTrainDirection() {
672        return getDefault().traindir;
673    }
674
675    public static void setMaxTrainLength(int length) {
676        getDefault().maxTrainLength = length;
677    }
678
679    public static int getMaxTrainLength() {
680        return getDefault().maxTrainLength;
681    }
682
683    public static void setMaxNumberEngines(int value) {
684        getDefault().maxEngineSize = value;
685    }
686
687    public static int getMaxNumberEngines() {
688        return getDefault().maxEngineSize;
689    }
690
691    public static void setHorsePowerPerTon(double value) {
692        getDefault().horsePowerPerTon = value;
693    }
694
695    public static double getHorsePowerPerTon() {
696        return getDefault().horsePowerPerTon;
697    }
698
699    public static void setCarMoves(int moves) {
700        getDefault().carMoves = moves;
701    }
702
703    public static int getCarMoves() {
704        return getDefault().carMoves;
705    }
706
707    public static String getPanelName() {
708        return getDefault().panelName;
709    }
710
711    public static void setPanelName(String name) {
712        getDefault().panelName = name;
713    }
714
715    public static String getLengthUnit() {
716        return getDefault().lengthUnit;
717    }
718
719    /**
720     * Abbreviation unit of length
721     * 
722     * @return symbol for feet or meter
723     */
724    public static String getLengthUnitAbv() {
725        return getDefault().lengthUnitAbv;
726    }
727
728    public static void setLengthUnit(String unit) {
729        getDefault().lengthUnit = unit;
730        if (unit.equals(FEET)) {
731            getDefault().lengthUnitAbv = FEET_ABV;
732        } else {
733            getDefault().lengthUnitAbv = METER_ABV;
734        }
735    }
736
737    public static String getYearModeled() {
738        return getDefault().yearModeled;
739    }
740
741    public static void setYearModeled(String year) {
742        getDefault().yearModeled = year;
743    }
744
745    public static String getCarTypes() {
746        return getDefault().carTypes;
747    }
748
749    public static void setCarTypes(String types) {
750        getDefault().carTypes = types;
751    }
752
753    public static void setTrainIconCordEnabled(boolean enable) {
754        getDefault().enableTrainIconXY = enable;
755    }
756
757    public static boolean isTrainIconCordEnabled() {
758        return getDefault().enableTrainIconXY;
759    }
760
761    public static void setTrainIconAppendEnabled(boolean enable) {
762        getDefault().appendTrainIcon = enable;
763    }
764
765    public static boolean isTrainIconAppendEnabled() {
766        return getDefault().appendTrainIcon;
767    }
768
769    public static void setComment(String comment) {
770        getDefault().setupComment = comment;
771    }
772
773    public static String getComment() {
774        return getDefault().setupComment;
775    }
776
777    public static void setBuildReportLevel(String level) {
778        getDefault().buildReportLevel = level;
779    }
780
781    public static String getBuildReportLevel() {
782        return getDefault().buildReportLevel;
783    }
784
785    /**
786     * Sets the report level for the car router.
787     * 
788     * @param level BUILD_REPORT_NORMAL, BUILD_REPORT_DETAILED,
789     *              BUILD_REPORT_VERY_DETAILED
790     */
791    public static void setRouterBuildReportLevel(String level) {
792        getDefault().routerBuildReportLevel = level;
793    }
794
795    public static String getRouterBuildReportLevel() {
796        return getDefault().routerBuildReportLevel;
797    }
798
799    public static void setManifestEditorEnabled(boolean enable) {
800        getDefault().manifestEditorEnabled = enable;
801    }
802
803    public static boolean isManifestEditorEnabled() {
804        return getDefault().manifestEditorEnabled;
805    }
806
807    public static void setBuildReportEditorEnabled(boolean enable) {
808        getDefault().buildReportEditorEnabled = enable;
809    }
810
811    public static boolean isBuildReportEditorEnabled() {
812        return getDefault().buildReportEditorEnabled;
813    }
814
815    public static void setBuildReportIndentEnabled(boolean enable) {
816        getDefault().buildReportIndentEnabled = enable;
817    }
818
819    public static boolean isBuildReportIndentEnabled() {
820        return getDefault().buildReportIndentEnabled;
821    }
822
823    public static void setBuildReportAlwaysPreviewEnabled(boolean enable) {
824        getDefault().buildReportAlwaysPreviewEnabled = enable;
825    }
826
827    public static boolean isBuildReportAlwaysPreviewEnabled() {
828        return getDefault().buildReportAlwaysPreviewEnabled;
829    }
830
831    public static void setSwitchListFormatSameAsManifest(boolean b) {
832        getDefault().switchListSameManifest = b;
833    }
834
835    public static boolean isSwitchListFormatSameAsManifest() {
836        return getDefault().switchListSameManifest;
837    }
838
839    public static void setPrintTrackSummaryEnabled(boolean b) {
840        getDefault().trackSummary = b;
841    }
842
843    public static boolean isPrintTrackSummaryEnabled() {
844        return getDefault().trackSummary;
845    }
846
847    public static void setSwitchListRouteLocationCommentEnabled(boolean b) {
848        getDefault().switchListRouteComment = b;
849    }
850
851    public static boolean isSwitchListRouteLocationCommentEnabled() {
852        return getDefault().switchListRouteComment;
853    }
854
855    public static void setGroupCarMoves(boolean b) {
856        getDefault().groupCarMoves = b;
857    }
858
859    public static boolean isGroupCarMovesEnabled() {
860        return getDefault().groupCarMoves;
861    }
862
863    public static void setPrintLocoLast(boolean b) {
864        getDefault().locoLast = b;
865    }
866
867    public static boolean isPrintLocoLastEnabled() {
868        return getDefault().locoLast;
869    }
870
871    public static void setSwitchListRealTime(boolean b) {
872        boolean old = getDefault().switchListRealTime;
873        getDefault().switchListRealTime = b;
874        setDirtyAndFirePropertyChange(REAL_TIME_PROPERTY_CHANGE, old, b);
875    }
876
877    public static boolean isSwitchListRealTime() {
878        return getDefault().switchListRealTime;
879    }
880
881    public static void setSwitchListAllTrainsEnabled(boolean b) {
882        boolean old = getDefault().switchListAllTrains;
883        getDefault().switchListAllTrains = b;
884        setDirtyAndFirePropertyChange("Switch List All Trains", old, b); // NOI18N
885    }
886
887    /**
888     * When true switch list shows all trains visiting a location, even if the train
889     * doesn't have any work at that location. When false, switch lists only report
890     * a train if it has work at the location.
891     *
892     * @return When true show all trains visiting a location.
893     */
894    public static boolean isSwitchListAllTrainsEnabled() {
895        return getDefault().switchListAllTrains;
896    }
897
898    /**
899     * Used to determine if there's spaces or form feed between trains and locations
900     * when printing switch lists. see getSwitchListPageFormatComboBox()
901     *
902     * @param format PAGE_NORMAL, PAGE_PER_TRAIN, or PAGE_PER_VISIT
903     */
904    public static void setSwitchListPageFormat(String format) {
905        getDefault().switchListPageFormat = format;
906    }
907
908    public static String getSwitchListPageFormat() {
909        return getDefault().switchListPageFormat;
910    }
911
912    public static void setPrintTruncateManifestEnabled(boolean b) {
913        getDefault().manifestTruncated = b;
914    }
915
916    public static boolean isPrintTruncateManifestEnabled() {
917        return getDefault().manifestTruncated;
918    }
919
920    public static void setUseDepartureTimeEnabled(boolean b) {
921        getDefault().manifestDepartureTime = b;
922    }
923
924    public static boolean isUseDepartureTimeEnabled() {
925        return getDefault().manifestDepartureTime;
926    }
927
928    public static void setUseSwitchListDepartureTimeEnabled(boolean b) {
929        getDefault().switchListDepartureTime = b;
930    }
931
932    public static boolean isUseSwitchListDepartureTimeEnabled() {
933        return getDefault().switchListDepartureTime;
934    }
935
936    public static void setPrintLocationCommentsEnabled(boolean enable) {
937        getDefault().printLocationComments = enable;
938    }
939
940    public static boolean isPrintLocationCommentsEnabled() {
941        return getDefault().printLocationComments;
942    }
943
944    public static void setPrintRouteCommentsEnabled(boolean enable) {
945        getDefault().printRouteComments = enable;
946    }
947
948    public static boolean isPrintRouteCommentsEnabled() {
949        return getDefault().printRouteComments;
950    }
951
952    public static void setPrintLoadsAndEmptiesEnabled(boolean enable) {
953        getDefault().printLoadsAndEmpties = enable;
954    }
955
956    public static boolean isPrintLoadsAndEmptiesEnabled() {
957        return getDefault().printLoadsAndEmpties;
958    }
959
960    public static void setPrintTrainScheduleNameEnabled(boolean enable) {
961        getDefault().printTrainScheduleName = enable;
962    }
963
964    public static boolean isPrintTrainScheduleNameEnabled() {
965        return getDefault().printTrainScheduleName;
966    }
967
968    public static void set12hrFormatEnabled(boolean enable) {
969        getDefault().use12hrFormat = enable;
970    }
971
972    public static boolean is12hrFormatEnabled() {
973        return getDefault().use12hrFormat;
974    }
975
976    public static void setPrintValidEnabled(boolean enable) {
977        getDefault().printValid = enable;
978    }
979
980    public static boolean isPrintValidEnabled() {
981        return getDefault().printValid;
982    }
983
984    public static void setSortByTrackNameEnabled(boolean enable) {
985        getDefault().sortByTrack = enable;
986    }
987
988    /**
989     * when true manifest work is sorted by track names.
990     * 
991     * @return true if work at a location is to be sorted by track names.
992     */
993    public static boolean isSortByTrackNameEnabled() {
994        return getDefault().sortByTrack;
995    }
996
997    public static void setPrintHeadersEnabled(boolean enable) {
998        getDefault().printHeaders = enable;
999    }
1000
1001    public static boolean isPrintHeadersEnabled() {
1002        return getDefault().printHeaders;
1003    }
1004
1005    public static void setPrintHeaderLine1Enabled(boolean enable) {
1006        getDefault().printHeaderLine1 = enable;
1007    }
1008
1009    public static boolean isPrintHeaderLine1Enabled() {
1010        return getDefault().printHeaderLine1;
1011    }
1012
1013    public static void setPrintHeaderLine2Enabled(boolean enable) {
1014        getDefault().printHeaderLine2 = enable;
1015    }
1016
1017    public static boolean isPrintHeaderLine2Enabled() {
1018        return getDefault().printHeaderLine2;
1019    }
1020
1021    public static void setPrintHeaderLine3Enabled(boolean enable) {
1022        getDefault().printHeaderLine3 = enable;
1023    }
1024
1025    public static boolean isPrintHeaderLine3Enabled() {
1026        return getDefault().printHeaderLine3;
1027    }
1028
1029    public static void setPrintCabooseLoadEnabled(boolean enable) {
1030        getDefault().printCabooseLoad = enable;
1031    }
1032
1033    public static boolean isPrintCabooseLoadEnabled() {
1034        return getDefault().printCabooseLoad;
1035    }
1036
1037    public static void setPrintPassengerLoadEnabled(boolean enable) {
1038        getDefault().printPassengerLoad = enable;
1039    }
1040
1041    public static boolean isPrintPassengerLoadEnabled() {
1042        return getDefault().printPassengerLoad;
1043    }
1044
1045    public static void setShowTrackMovesEnabled(boolean enable) {
1046        boolean old = getDefault().showTrackMoves;
1047        getDefault().showTrackMoves = enable;
1048        setDirtyAndFirePropertyChange(SHOW_TRACK_MOVES_PROPERTY_CHANGE, old, enable);
1049    }
1050
1051    public static boolean isShowTrackMovesEnabled() {
1052        return getDefault().showTrackMoves;
1053    }
1054
1055    public static void setSwitchTime(int minutes) {
1056        getDefault().carSwitchTime = minutes;
1057    }
1058
1059    public static int getSwitchTime() {
1060        return getDefault().carSwitchTime;
1061    }
1062
1063    public static void setTravelTime(int minutes) {
1064        int old = getTravelTime();
1065        getDefault().travelTime = minutes;
1066        setDirtyAndFirePropertyChange(TRAVEL_TIME_PROPERTY_CHANGE, old, minutes);
1067    }
1068
1069    public static int getTravelTime() {
1070        return getDefault().travelTime;
1071    }
1072
1073    public static void setTrainIconColorNorth(String color) {
1074        getDefault().iconNorthColor = color;
1075    }
1076
1077    public static String getTrainIconColorNorth() {
1078        return getDefault().iconNorthColor;
1079    }
1080
1081    public static void setTrainIconColorSouth(String color) {
1082        getDefault().iconSouthColor = color;
1083    }
1084
1085    public static String getTrainIconColorSouth() {
1086        return getDefault().iconSouthColor;
1087    }
1088
1089    public static void setTrainIconColorEast(String color) {
1090        getDefault().iconEastColor = color;
1091    }
1092
1093    public static String getTrainIconColorEast() {
1094        return getDefault().iconEastColor;
1095    }
1096
1097    public static void setTrainIconColorWest(String color) {
1098        getDefault().iconWestColor = color;
1099    }
1100
1101    public static String getTrainIconColorWest() {
1102        return getDefault().iconWestColor;
1103    }
1104
1105    public static void setTrainIconColorLocal(String color) {
1106        getDefault().iconLocalColor = color;
1107    }
1108
1109    public static String getTrainIconColorLocal() {
1110        return getDefault().iconLocalColor;
1111    }
1112
1113    public static void setTrainIconColorTerminate(String color) {
1114        getDefault().iconTerminateColor = color;
1115    }
1116
1117    public static String getTrainIconColorTerminate() {
1118        return getDefault().iconTerminateColor;
1119    }
1120
1121    public static String getFontName() {
1122        return getDefault().fontName;
1123    }
1124
1125    public static void setFontName(String name) {
1126        getDefault().fontName = name;
1127    }
1128
1129    public static int getManifestFontSize() {
1130        return getDefault().manifestFontSize;
1131    }
1132
1133    public static void setManifestFontSize(int size) {
1134        getDefault().manifestFontSize = size;
1135    }
1136
1137    public static SidesType getPrintDuplexSides() {
1138        return getDefault().sidesType;
1139    }
1140
1141    public static void setPrintDuplexSides(SidesType sidesType) {
1142        getDefault().sidesType = sidesType;
1143    }
1144
1145    public static boolean isPrintPageHeaderEnabled() {
1146        return getDefault().printHeader;
1147    }
1148
1149    public static void setPrintPageHeaderEnabled(boolean enable) {
1150        getDefault().printHeader = enable;
1151    }
1152
1153    public static int getBuildReportFontSize() {
1154        return getDefault().buildReportFontSize;
1155    }
1156
1157    public static void setBuildReportFontSize(int size) {
1158        getDefault().buildReportFontSize = size;
1159    }
1160
1161    public static String getManifestOrientation() {
1162        return getDefault().manifestOrientation;
1163    }
1164
1165    public static void setManifestOrientation(String orientation) {
1166        getDefault().manifestOrientation = orientation;
1167    }
1168
1169    public static String getSwitchListOrientation() {
1170        if (isSwitchListFormatSameAsManifest()) {
1171            return getDefault().manifestOrientation;
1172        } else {
1173            return getDefault().switchListOrientation;
1174        }
1175    }
1176
1177    public static void setSwitchListOrientation(String orientation) {
1178        getDefault().switchListOrientation = orientation;
1179    }
1180
1181    public static boolean isTabEnabled() {
1182        return getDefault().tab;
1183    }
1184
1185    public static void setTabEnabled(boolean enable) {
1186        getDefault().tab = enable;
1187    }
1188
1189    public static int getTab1Length() {
1190        return getDefault().tab1CharLength;
1191    }
1192
1193    public static void setTab1length(int length) {
1194        getDefault().tab1CharLength = length;
1195    }
1196
1197    public static int getTab2Length() {
1198        return getDefault().tab2CharLength;
1199    }
1200
1201    public static void setTab2length(int length) {
1202        getDefault().tab2CharLength = length;
1203    }
1204
1205    public static int getTab3Length() {
1206        return getDefault().tab3CharLength;
1207    }
1208
1209    public static void setTab3length(int length) {
1210        getDefault().tab3CharLength = length;
1211    }
1212
1213    public static String getManifestFormat() {
1214        return getDefault().manifestFormat;
1215    }
1216
1217    /**
1218     * Sets the format for manifests
1219     * 
1220     * @param format STANDARD_FORMAT, TWO_COLUMN_FORMAT, or TWO_COLUMN_TRACK_FORMAT
1221     */
1222    public static void setManifestFormat(String format) {
1223        getDefault().manifestFormat = format;
1224    }
1225
1226    public static boolean isCarLoggerEnabled() {
1227        return getDefault().carLogger;
1228    }
1229
1230    public static void setCarLoggerEnabled(boolean enable) {
1231        getDefault().carLogger = enable;
1232        InstanceManager.getDefault(RollingStockLogger.class).enableCarLogging(enable);
1233    }
1234
1235    public static boolean isEngineLoggerEnabled() {
1236        return getDefault().engineLogger;
1237    }
1238
1239    public static void setEngineLoggerEnabled(boolean enable) {
1240        getDefault().engineLogger = enable;
1241        InstanceManager.getDefault(RollingStockLogger.class).enableEngineLogging(enable);
1242    }
1243
1244    public static boolean isTrainLoggerEnabled() {
1245        return getDefault().trainLogger;
1246    }
1247
1248    public static void setTrainLoggerEnabled(boolean enable) {
1249        getDefault().trainLogger = enable;
1250        InstanceManager.getDefault(TrainLogger.class).enableTrainLogging(enable);
1251    }
1252
1253    public static boolean isSaveTrainManifestsEnabled() {
1254        return getDefault().saveTrainManifests;
1255    }
1256
1257    public static void setSaveTrainManifestsEnabled(boolean enable) {
1258        boolean old = getDefault().saveTrainManifests;
1259        getDefault().saveTrainManifests = enable;
1260        setDirtyAndFirePropertyChange(SAVE_TRAIN_MANIFEST_PROPERTY_CHANGE, old, enable);
1261    }
1262
1263    public static String getPickupEnginePrefix() {
1264        return getDefault().pickupEnginePrefix;
1265    }
1266
1267    public static void setPickupEnginePrefix(String prefix) {
1268        getDefault().pickupEnginePrefix = prefix;
1269    }
1270
1271    public static String getDropEnginePrefix() {
1272        return getDefault().dropEnginePrefix;
1273    }
1274
1275    public static void setDropEnginePrefix(String prefix) {
1276        getDefault().dropEnginePrefix = prefix;
1277    }
1278
1279    public static String getPickupCarPrefix() {
1280        return getDefault().pickupCarPrefix;
1281    }
1282
1283    public static void setPickupCarPrefix(String prefix) {
1284        getDefault().pickupCarPrefix = prefix;
1285    }
1286
1287    public static String getDropCarPrefix() {
1288        return getDefault().dropCarPrefix;
1289    }
1290
1291    public static void setDropCarPrefix(String prefix) {
1292        getDefault().dropCarPrefix = prefix;
1293    }
1294
1295    public static String getLocalPrefix() {
1296        return getDefault().localPrefix;
1297    }
1298
1299    public static void setLocalPrefix(String prefix) {
1300        getDefault().localPrefix = prefix;
1301    }
1302
1303    public static int getManifestPrefixLength() {
1304        int maxLength = getPickupEnginePrefix().length();
1305        if (getDropEnginePrefix().length() > maxLength) {
1306            maxLength = getDropEnginePrefix().length();
1307        }
1308        if (getPickupCarPrefix().length() > maxLength) {
1309            maxLength = getPickupCarPrefix().length();
1310        }
1311        if (getDropCarPrefix().length() > maxLength) {
1312            maxLength = getDropCarPrefix().length();
1313        }
1314        if (getLocalPrefix().length() > maxLength) {
1315            maxLength = getLocalPrefix().length();
1316        }
1317        return maxLength;
1318    }
1319
1320    public static String getSwitchListPickupCarPrefix() {
1321        if (isSwitchListFormatSameAsManifest()) {
1322            return getDefault().pickupCarPrefix;
1323        } else {
1324            return getDefault().switchListPickupCarPrefix;
1325        }
1326    }
1327
1328    public static void setSwitchListPickupCarPrefix(String prefix) {
1329        getDefault().switchListPickupCarPrefix = prefix;
1330    }
1331
1332    public static String getSwitchListDropCarPrefix() {
1333        if (isSwitchListFormatSameAsManifest()) {
1334            return getDefault().dropCarPrefix;
1335        } else {
1336            return getDefault().switchListDropCarPrefix;
1337        }
1338    }
1339
1340    public static void setSwitchListDropCarPrefix(String prefix) {
1341        getDefault().switchListDropCarPrefix = prefix;
1342    }
1343
1344    public static String getSwitchListLocalPrefix() {
1345        if (isSwitchListFormatSameAsManifest()) {
1346            return getDefault().localPrefix;
1347        } else {
1348            return getDefault().switchListLocalPrefix;
1349        }
1350    }
1351
1352    public static void setSwitchListLocalPrefix(String prefix) {
1353        getDefault().switchListLocalPrefix = prefix;
1354    }
1355
1356    public static int getSwitchListPrefixLength() {
1357        int maxLength = getPickupEnginePrefix().length();
1358        if (getDropEnginePrefix().length() > maxLength) {
1359            maxLength = getDropEnginePrefix().length();
1360        }
1361        if (getSwitchListPickupCarPrefix().length() > maxLength) {
1362            maxLength = getSwitchListPickupCarPrefix().length();
1363        }
1364        if (getSwitchListDropCarPrefix().length() > maxLength) {
1365            maxLength = getSwitchListDropCarPrefix().length();
1366        }
1367        if (getSwitchListLocalPrefix().length() > maxLength) {
1368            maxLength = getSwitchListLocalPrefix().length();
1369        }
1370        return maxLength;
1371    }
1372
1373    public static String[] getEngineAttributes() {
1374        return ENGINE_ATTRIBUTES.clone();
1375    }
1376
1377    public static String[] getPickupEngineMessageFormat() {
1378        return getDefault().pickupEngineMessageFormat.clone();
1379    }
1380
1381    public static void setPickupEngineMessageFormat(String[] format) {
1382        getDefault().pickupEngineMessageFormat = format;
1383    }
1384
1385    public static String[] getDropEngineMessageFormat() {
1386        return getDefault().dropEngineMessageFormat.clone();
1387    }
1388
1389    public static void setDropEngineMessageFormat(String[] format) {
1390        getDefault().dropEngineMessageFormat = format;
1391    }
1392
1393    public static String[] getCarAttributes() {
1394        return CAR_ATTRIBUTES.clone();
1395    }
1396
1397    public static String[] getPickupManifestMessageFormat() {
1398        return getDefault().pickupManifestMessageFormat.clone();
1399    }
1400
1401    public static void setPickupManifestMessageFormat(String[] format) {
1402        getDefault().pickupManifestMessageFormat = format;
1403    }
1404
1405    public static String[] getDropManifestMessageFormat() {
1406        return getDefault().dropManifestMessageFormat.clone();
1407    }
1408
1409    public static void setDropManifestMessageFormat(String[] format) {
1410        getDefault().dropManifestMessageFormat = format;
1411    }
1412
1413    public static String[] getLocalManifestMessageFormat() {
1414        return getDefault().localManifestMessageFormat.clone();
1415    }
1416
1417    public static void setLocalManifestMessageFormat(String[] format) {
1418        getDefault().localManifestMessageFormat = format;
1419    }
1420
1421    public static String[] getMissingCarMessageFormat() {
1422        return getDefault().missingCarMessageFormat.clone();
1423    }
1424
1425    public static void setMissingCarMessageFormat(String[] format) {
1426        getDefault().missingCarMessageFormat = format;
1427    }
1428
1429    public static String[] getPickupSwitchListMessageFormat() {
1430        if (isSwitchListFormatSameAsManifest()) {
1431            return getDefault().pickupManifestMessageFormat.clone();
1432        } else {
1433            return getDefault().pickupSwitchListMessageFormat.clone();
1434        }
1435    }
1436
1437    public static void setPickupSwitchListMessageFormat(String[] format) {
1438        getDefault().pickupSwitchListMessageFormat = format;
1439    }
1440
1441    public static String[] getDropSwitchListMessageFormat() {
1442        if (isSwitchListFormatSameAsManifest()) {
1443            return getDefault().dropManifestMessageFormat.clone();
1444        } else {
1445            return getDefault().dropSwitchListMessageFormat.clone();
1446        }
1447    }
1448
1449    public static void setDropSwitchListMessageFormat(String[] format) {
1450        getDefault().dropSwitchListMessageFormat = format;
1451    }
1452
1453    public static String[] getLocalSwitchListMessageFormat() {
1454        if (isSwitchListFormatSameAsManifest()) {
1455            return getDefault().localManifestMessageFormat.clone();
1456        } else {
1457            return getDefault().localSwitchListMessageFormat.clone();
1458        }
1459    }
1460
1461    public static void setLocalSwitchListMessageFormat(String[] format) {
1462        getDefault().localSwitchListMessageFormat = format;
1463    }
1464
1465    /**
1466     * Gets the manifest format for utility cars. The car's road, number, and color
1467     * are not printed.
1468     *
1469     * @return Utility car format
1470     */
1471    public static String[] getPickupUtilityManifestMessageFormat() {
1472        return createUitlityCarMessageFormat(getPickupManifestMessageFormat());
1473    }
1474
1475    public static String[] getDropUtilityManifestMessageFormat() {
1476        return createUitlityCarMessageFormat(getDropManifestMessageFormat());
1477    }
1478
1479    public static String[] getLocalUtilityManifestMessageFormat() {
1480        return createUitlityCarMessageFormat(getLocalManifestMessageFormat());
1481    }
1482
1483    public static String[] getPickupUtilitySwitchListMessageFormat() {
1484        return createUitlityCarMessageFormat(getPickupSwitchListMessageFormat());
1485    }
1486
1487    public static String[] getDropUtilitySwitchListMessageFormat() {
1488        return createUitlityCarMessageFormat(getDropSwitchListMessageFormat());
1489    }
1490
1491    public static String[] getLocalUtilitySwitchListMessageFormat() {
1492        return createUitlityCarMessageFormat(getLocalSwitchListMessageFormat());
1493    }
1494
1495    private static String[] createUitlityCarMessageFormat(String[] format) {
1496        // remove car's road, number, color
1497        for (int i = 0; i < format.length; i++) {
1498            if (format[i].equals(ROAD)) {
1499                format[i] = NO_ROAD;
1500            } else if (format[i].equals(NUMBER)) {
1501                format[i] = NO_NUMBER;
1502            } else if (format[i].equals(COLOR)) {
1503                format[i] = NO_COLOR;
1504            }
1505        }
1506        return format;
1507    }
1508
1509    public static String[] getPickupTruncatedManifestMessageFormat() {
1510        return createTruncatedManifestMessageFormat(getPickupManifestMessageFormat());
1511    }
1512
1513    public static String[] getDropTruncatedManifestMessageFormat() {
1514        return createTruncatedManifestMessageFormat(getDropManifestMessageFormat());
1515    }
1516
1517    public static String[] createTruncatedManifestMessageFormat(String[] format) {
1518        // remove car's destination and location
1519        for (int i = 0; i < format.length; i++) {
1520            if (format[i].equals(DESTINATION)) {
1521                format[i] = NO_DESTINATION;
1522            } else if (format[i].equals(DEST_TRACK)) {
1523                format[i] = NO_DEST_TRACK;
1524            } else if (format[i].equals(LOCATION)) {
1525                format[i] = NO_LOCATION;
1526            } else if (format[i].equals(TRACK)) {
1527                format[i] = NO_TRACK;
1528            }
1529        }
1530        return format;
1531    }
1532
1533    public static String[] getPickupTwoColumnByTrackManifestMessageFormat() {
1534        return createTwoColumnByTrackPickupMessageFormat(getPickupManifestMessageFormat());
1535    }
1536
1537    public static String[] getPickupTwoColumnByTrackSwitchListMessageFormat() {
1538        return createTwoColumnByTrackPickupMessageFormat(getPickupSwitchListMessageFormat());
1539    }
1540
1541    public static String[] getPickupTwoColumnByTrackUtilityManifestMessageFormat() {
1542        return createTwoColumnByTrackPickupMessageFormat(getPickupUtilityManifestMessageFormat());
1543    }
1544
1545    public static String[] getPickupTwoColumnByTrackUtilitySwitchListMessageFormat() {
1546        return createTwoColumnByTrackPickupMessageFormat(getPickupUtilitySwitchListMessageFormat());
1547    }
1548
1549    private static String[] createTwoColumnByTrackPickupMessageFormat(String[] format) {
1550        for (int i = 0; i < format.length; i++) {
1551            if (format[i].equals(LOCATION)) {
1552                format[i] = BLANK;
1553            } else if (format[i].equals(TRACK)) {
1554                format[i] = BLANK;
1555            }
1556        }
1557        return format;
1558    }
1559
1560    public static String[] getDropTwoColumnByTrackManifestMessageFormat() {
1561        return createTwoColumnByTrackDropMessageFormat(getDropManifestMessageFormat());
1562    }
1563
1564    public static String[] getDropTwoColumnByTrackSwitchListMessageFormat() {
1565        return createTwoColumnByTrackDropMessageFormat(getDropSwitchListMessageFormat());
1566    }
1567
1568    public static String[] getDropTwoColumnByTrackUtilityManifestMessageFormat() {
1569        return createTwoColumnByTrackDropMessageFormat(getDropUtilityManifestMessageFormat());
1570    }
1571
1572    public static String[] getDropTwoColumnByTrackUtilitySwitchListMessageFormat() {
1573        return createTwoColumnByTrackDropMessageFormat(getDropUtilitySwitchListMessageFormat());
1574    }
1575
1576    private static String[] createTwoColumnByTrackDropMessageFormat(String[] format) {
1577        for (int i = 0; i < format.length; i++) {
1578            if (format[i].equals(DESTINATION)) {
1579                format[i] = BLANK;
1580            } else if (format[i].equals(TRACK)) {
1581                format[i] = BLANK;
1582            }
1583        }
1584        return format;
1585    }
1586
1587    public static String getDropEngineTextColor() {
1588        return ColorUtil.colorToColorName(getDefault().dropEngineColor);
1589    }
1590
1591    public static void setDropEngineTextColor(String color) {
1592        setDropEngineColor(ColorUtil.stringToColor(color));
1593    }
1594
1595    public static void setDropEngineColor(Color c) {
1596        getDefault().dropEngineColor = c;
1597        JmriColorChooser.addRecentColor(c);
1598    }
1599
1600    public static String getPickupEngineTextColor() {
1601        return ColorUtil.colorToColorName(getDefault().pickupEngineColor);
1602    }
1603
1604    public static void setPickupEngineTextColor(String color) {
1605        setPickupEngineColor(ColorUtil.stringToColor(color));
1606    }
1607
1608    public static void setPickupEngineColor(Color c) {
1609        getDefault().pickupEngineColor = c;
1610        JmriColorChooser.addRecentColor(c);
1611    }
1612
1613    public static String getDropTextColor() {
1614        return ColorUtil.colorToColorName(getDefault().dropColor);
1615    }
1616
1617    public static void setDropTextColor(String color) {
1618        setDropColor(ColorUtil.stringToColor(color));
1619    }
1620
1621    public static void setDropColor(Color c) {
1622        getDefault().dropColor = c;
1623        JmriColorChooser.addRecentColor(c);
1624    }
1625
1626    public static String getPickupTextColor() {
1627        return ColorUtil.colorToColorName(getDefault().pickupColor);
1628    }
1629
1630    public static void setPickupTextColor(String color) {
1631        setPickupColor(ColorUtil.stringToColor(color));
1632    }
1633
1634    public static void setPickupColor(Color c) {
1635        getDefault().pickupColor = c;
1636        JmriColorChooser.addRecentColor(c);
1637    }
1638
1639    public static String getLocalTextColor() {
1640        return ColorUtil.colorToColorName(getDefault().localColor);
1641    }
1642
1643    public static void setLocalTextColor(String color) {
1644        setLocalColor(ColorUtil.stringToColor(color));
1645    }
1646
1647    public static void setLocalColor(Color c) {
1648        getDefault().localColor = c;
1649        JmriColorChooser.addRecentColor(c);
1650    }
1651
1652    public static Color getPickupEngineColor() {
1653        return getDefault().pickupEngineColor;
1654    }
1655
1656    public static Color getDropEngineColor() {
1657        return getDefault().dropEngineColor;
1658    }
1659
1660    public static Color getPickupColor() {
1661        return getDefault().pickupColor;
1662    }
1663
1664    public static Color getDropColor() {
1665        return getDefault().dropColor;
1666    }
1667
1668    public static Color getLocalColor() {
1669        return getDefault().localColor;
1670    }
1671
1672    public static Color getColor(String colorName) {
1673        return ColorUtil.stringToColor(colorName);
1674    }
1675
1676    public static String getManifestLogoURL() {
1677        return getDefault().logoURL;
1678    }
1679
1680    public static void setManifestLogoURL(String pathName) {
1681        getDefault().logoURL = pathName;
1682    }
1683
1684    public static String getOwnerName() {
1685        return getDefault().ownerName;
1686    }
1687
1688    public static void setOwnerName(String name) {
1689        getDefault().ownerName = name;
1690    }
1691
1692    public static int getScaleRatio() {
1693        if (getDefault().scale == 0) {
1694            log.error("Scale not set");
1695        }
1696        return getDefault().ratio;
1697    }
1698
1699    public static int getScaleTonRatio() {
1700        if (getDefault().scale == 0) {
1701            log.error("Scale not set");
1702        }
1703        return getDefault().ratioTons;
1704    }
1705
1706    public static int getInitalWeight() {
1707        if (getDefault().scale == 0) {
1708            log.error("Scale not set");
1709        }
1710        return getDefault().initWeight;
1711    }
1712
1713    public static int getAddWeight() {
1714        if (getDefault().scale == 0) {
1715            log.error("Scale not set");
1716        }
1717        return getDefault().addWeight;
1718    }
1719
1720    public static int getScale() {
1721        return getDefault().scale;
1722    }
1723
1724    public static void setScale(int s) {
1725        getDefault().scale = s;
1726        switch (getDefault().scale) {
1727            case Z_SCALE:
1728                getDefault().ratio = Z_RATIO;
1729                getDefault().initWeight = Z_INITIAL_WEIGHT;
1730                getDefault().addWeight = Z_ADD_WEIGHT;
1731                getDefault().ratioTons = Z_RATIO_TONS;
1732                break;
1733            case N_SCALE:
1734                getDefault().ratio = N_RATIO;
1735                getDefault().initWeight = N_INITIAL_WEIGHT;
1736                getDefault().addWeight = N_ADD_WEIGHT;
1737                getDefault().ratioTons = N_RATIO_TONS;
1738                break;
1739            case TT_SCALE:
1740                getDefault().ratio = TT_RATIO;
1741                getDefault().initWeight = TT_INITIAL_WEIGHT;
1742                getDefault().addWeight = TT_ADD_WEIGHT;
1743                getDefault().ratioTons = TT_RATIO_TONS;
1744                break;
1745            case HOn3_SCALE:
1746                getDefault().ratio = HO_RATIO;
1747                getDefault().initWeight = HOn3_INITIAL_WEIGHT;
1748                getDefault().addWeight = HOn3_ADD_WEIGHT;
1749                getDefault().ratioTons = HOn3_RATIO_TONS;
1750                break;
1751            case OO_SCALE:
1752                getDefault().ratio = OO_RATIO;
1753                getDefault().initWeight = OO_INITIAL_WEIGHT;
1754                getDefault().addWeight = OO_ADD_WEIGHT;
1755                getDefault().ratioTons = OO_RATIO_TONS;
1756                break;
1757            case HO_SCALE:
1758                getDefault().ratio = HO_RATIO;
1759                getDefault().initWeight = HO_INITIAL_WEIGHT;
1760                getDefault().addWeight = HO_ADD_WEIGHT;
1761                getDefault().ratioTons = HO_RATIO_TONS;
1762                break;
1763            case Sn3_SCALE:
1764                getDefault().ratio = S_RATIO;
1765                getDefault().initWeight = Sn3_INITIAL_WEIGHT;
1766                getDefault().addWeight = Sn3_ADD_WEIGHT;
1767                getDefault().ratioTons = Sn3_RATIO_TONS;
1768                break;
1769            case S_SCALE:
1770                getDefault().ratio = S_RATIO;
1771                getDefault().initWeight = S_INITIAL_WEIGHT;
1772                getDefault().addWeight = S_ADD_WEIGHT;
1773                getDefault().ratioTons = S_RATIO_TONS;
1774                break;
1775            case On3_SCALE:
1776                getDefault().ratio = O_RATIO;
1777                getDefault().initWeight = On3_INITIAL_WEIGHT;
1778                getDefault().addWeight = On3_ADD_WEIGHT;
1779                getDefault().ratioTons = On3_RATIO_TONS;
1780                break;
1781            case O_SCALE:
1782                getDefault().ratio = O_RATIO;
1783                getDefault().initWeight = O_INITIAL_WEIGHT;
1784                getDefault().addWeight = O_ADD_WEIGHT;
1785                getDefault().ratioTons = O_RATIO_TONS;
1786                break;
1787            case G_SCALE:
1788                getDefault().ratio = G_RATIO;
1789                getDefault().initWeight = G_INITIAL_WEIGHT;
1790                getDefault().addWeight = G_ADD_WEIGHT;
1791                getDefault().ratioTons = G_RATIO_TONS;
1792                break;
1793            default:
1794                log.error("Unknown scale");
1795        }
1796    }
1797
1798    public static JComboBox<String> getManifestFormatComboBox() {
1799        JComboBox<String> box = new JComboBox<>();
1800        box.addItem(STANDARD_FORMAT);
1801        box.addItem(TWO_COLUMN_FORMAT);
1802        box.addItem(TWO_COLUMN_TRACK_FORMAT);
1803        return box;
1804    }
1805
1806    public static JComboBox<String> getOrientationComboBox() {
1807        JComboBox<String> box = new JComboBox<>();
1808        box.addItem(PORTRAIT);
1809        box.addItem(LANDSCAPE);
1810        box.addItem(HALFPAGE);
1811        box.addItem(HANDHELD);
1812        return box;
1813    }
1814
1815    public static JComboBox<String> getSwitchListPageFormatComboBox() {
1816        JComboBox<String> box = new JComboBox<>();
1817        box.addItem(PAGE_NORMAL);
1818        box.addItem(PAGE_PER_TRAIN);
1819        box.addItem(PAGE_PER_VISIT);
1820        return box;
1821    }
1822
1823    public static JComboBox<String> getEngineMessageComboBox() {
1824        JComboBox<String> box = new JComboBox<>();
1825        box.addItem(BLANK);
1826        for (String attribute : getEngineAttributes()) {
1827            box.addItem(attribute);
1828        }
1829        if (isTabEnabled()) {
1830            box.addItem(TAB);
1831            box.addItem(TAB2);
1832            box.addItem(TAB3);
1833        }
1834        return box;
1835    }
1836
1837    public static JComboBox<String> getCarMessageComboBox() {
1838        JComboBox<String> box = new JComboBox<>();
1839        box.addItem(BLANK);
1840        for (String attribute : getCarAttributes()) {
1841            box.addItem(attribute);
1842        }
1843        if (isTabEnabled()) {
1844            box.addItem(TAB);
1845            box.addItem(TAB2);
1846            box.addItem(TAB3);
1847        }
1848        return box;
1849    }
1850
1851    /**
1852     *
1853     * @return JComboBox loaded with the strings (North, South, East, West) showing
1854     *         the available train directions for this railroad
1855     */
1856    public static JComboBox<String> getTrainDirectionComboBox() {
1857        JComboBox<String> box = new JComboBox<>();
1858        for (String direction : getTrainDirectionList()) {
1859            box.addItem(direction);
1860        }
1861        return box;
1862    }
1863
1864    /**
1865     * Get train directions String format
1866     *
1867     * @return List of valid train directions
1868     */
1869    public static List<String> getTrainDirectionList() {
1870        List<String> directions = new ArrayList<>();
1871        if ((getDefault().traindir & EAST) == EAST) {
1872            directions.add(EAST_DIR);
1873        }
1874        if ((getDefault().traindir & WEST) == WEST) {
1875            directions.add(WEST_DIR);
1876        }
1877        if ((getDefault().traindir & NORTH) == NORTH) {
1878            directions.add(NORTH_DIR);
1879        }
1880        if ((getDefault().traindir & SOUTH) == SOUTH) {
1881            directions.add(SOUTH_DIR);
1882        }
1883        return directions;
1884    }
1885
1886    /**
1887     * Converts binary direction to String direction
1888     *
1889     * @param direction EAST, WEST, NORTH, SOUTH
1890     * @return String representation of a direction
1891     */
1892    public static String getDirectionString(int direction) {
1893        switch (direction) {
1894            case EAST:
1895                return EAST_DIR;
1896            case WEST:
1897                return WEST_DIR;
1898            case NORTH:
1899                return NORTH_DIR;
1900            case SOUTH:
1901                return SOUTH_DIR;
1902            default:
1903                return "unknown"; // NOI18N
1904        }
1905    }
1906
1907    /**
1908     * Converts binary direction to a set of String directions
1909     *
1910     * @param directions EAST, WEST, NORTH, SOUTH
1911     * @return String[] representation of a set of directions
1912     */
1913    public static String[] getDirectionStrings(int directions) {
1914        String[] dir = new String[4];
1915        int i = 0;
1916        if ((directions & EAST) == EAST) {
1917            dir[i++] = EAST_DIR;
1918        }
1919        if ((directions & WEST) == WEST) {
1920            dir[i++] = WEST_DIR;
1921        }
1922        if ((directions & NORTH) == NORTH) {
1923            dir[i++] = NORTH_DIR;
1924        }
1925        if ((directions & SOUTH) == SOUTH) {
1926            dir[i++] = SOUTH_DIR;
1927        }
1928        return dir;
1929    }
1930
1931    /**
1932     * Converts String direction to binary direction
1933     *
1934     * @param direction EAST_DIR WEST_DIR NORTH_DIR SOUTH_DIR
1935     * @return integer representation of a direction
1936     */
1937    public static int getDirectionInt(String direction) {
1938        if (direction.equals(EAST_DIR)) {
1939            return EAST;
1940        } else if (direction.equals(WEST_DIR)) {
1941            return WEST;
1942        } else if (direction.equals(NORTH_DIR)) {
1943            return NORTH;
1944        } else if (direction.equals(SOUTH_DIR)) {
1945            return SOUTH;
1946        } else {
1947            return 0; // return unknown
1948        }
1949    }
1950
1951    // must synchronize changes with operation-config.dtd
1952    public static Element store() {
1953        Element values;
1954        Element e = new Element(Xml.OPERATIONS);
1955
1956        // only store railroad name if it doesn't match the preferences railroad name
1957        if (!InstanceManager.getDefault(WebServerPreferences.class).getRailroadName().equals(getRailroadName())) {
1958            e.addContent(values = new Element(Xml.RAIL_ROAD));
1959            values.setAttribute(Xml.NAME, getRailroadName());
1960        }
1961
1962        e.addContent(values = new Element(Xml.SETUP));
1963        values.setAttribute(Xml.COMMENT, getComment());
1964
1965        e.addContent(values = new Element(Xml.SETTINGS));
1966        values.setAttribute(Xml.MAIN_MENU, isMainMenuEnabled() ? Xml.TRUE : Xml.FALSE);
1967        values.setAttribute(Xml.CLOSE_ON_SAVE, isCloseWindowOnSaveEnabled() ? Xml.TRUE : Xml.FALSE);
1968        values.setAttribute(Xml.AUTO_SAVE, isAutoSaveEnabled() ? Xml.TRUE : Xml.FALSE);
1969        values.setAttribute(Xml.AUTO_BACKUP, isAutoBackupEnabled() ? Xml.TRUE : Xml.FALSE);
1970        values.setAttribute(Xml.TRAIN_DIRECTION, Integer.toString(getTrainDirection()));
1971        values.setAttribute(Xml.TRAIN_LENGTH, Integer.toString(getMaxTrainLength()));
1972        values.setAttribute(Xml.MAX_ENGINES, Integer.toString(getMaxNumberEngines()));
1973        values.setAttribute(Xml.HPT, Double.toString(getHorsePowerPerTon()));
1974        values.setAttribute(Xml.SCALE, Integer.toString(getScale()));
1975        values.setAttribute(Xml.CAR_TYPES, getCarTypes());
1976        values.setAttribute(Xml.SWITCH_TIME, Integer.toString(getSwitchTime()));
1977        values.setAttribute(Xml.TRAVEL_TIME, Integer.toString(getTravelTime()));
1978        values.setAttribute(Xml.SHOW_VALUE, isValueEnabled() ? Xml.TRUE : Xml.FALSE);
1979        values.setAttribute(Xml.VALUE_LABEL, getValueLabel());
1980        values.setAttribute(Xml.SHOW_RFID, isRfidEnabled() ? Xml.TRUE : Xml.FALSE);
1981        values.setAttribute(Xml.RFID_LABEL, getRfidLabel());
1982        values.setAttribute(Xml.LENGTH_UNIT, getLengthUnit());
1983        values.setAttribute(Xml.YEAR_MODELED, getYearModeled());
1984
1985        e.addContent(values = new Element(Xml.PICKUP_ENG_FORMAT));
1986        storeXmlMessageFormat(values, getPickupEnginePrefix(), getPickupEngineMessageFormat());
1987
1988        e.addContent(values = new Element(Xml.DROP_ENG_FORMAT));
1989        storeXmlMessageFormat(values, getDropEnginePrefix(), getDropEngineMessageFormat());
1990
1991        e.addContent(values = new Element(Xml.PICKUP_CAR_FORMAT));
1992        storeXmlMessageFormat(values, getPickupCarPrefix(), getPickupManifestMessageFormat());
1993
1994        e.addContent(values = new Element(Xml.DROP_CAR_FORMAT));
1995        storeXmlMessageFormat(values, getDropCarPrefix(), getDropManifestMessageFormat());
1996
1997        e.addContent(values = new Element(Xml.LOCAL_FORMAT));
1998        storeXmlMessageFormat(values, getLocalPrefix(), getLocalManifestMessageFormat());
1999
2000        e.addContent(values = new Element(Xml.MISSING_CAR_FORMAT));
2001        storeXmlMessageFormat(values, NONE, getMissingCarMessageFormat());
2002
2003        e.addContent(values = new Element(Xml.SWITCH_LIST));
2004        values.setAttribute(Xml.SAME_AS_MANIFEST, isSwitchListFormatSameAsManifest() ? Xml.TRUE : Xml.FALSE);
2005        values.setAttribute(Xml.REAL_TIME, isSwitchListRealTime() ? Xml.TRUE : Xml.FALSE);
2006        values.setAttribute(Xml.ALL_TRAINS, isSwitchListAllTrainsEnabled() ? Xml.TRUE : Xml.FALSE);
2007
2008        // save switch list format
2009        String format = Xml.PAGE_NORMAL;
2010        if (getSwitchListPageFormat().equals(PAGE_PER_TRAIN)) {
2011            format = Xml.PAGE_PER_TRAIN;
2012            values.setAttribute(Xml.PAGE_MODE, Xml.TRUE); // backwards compatible for versions before 3.11
2013        } else if (getSwitchListPageFormat().equals(PAGE_PER_VISIT)) {
2014            format = Xml.PAGE_PER_VISIT;
2015        }
2016        values.setAttribute(Xml.PAGE_FORMAT, format);
2017
2018        values.setAttribute(Xml.PRINT_ROUTE_LOCATION, isSwitchListRouteLocationCommentEnabled() ? Xml.TRUE : Xml.FALSE);
2019        values.setAttribute(Xml.TRACK_SUMMARY, isPrintTrackSummaryEnabled() ? Xml.TRUE : Xml.FALSE);
2020        values.setAttribute(Xml.USE_DEPARTURE_TIME, isUseSwitchListDepartureTimeEnabled() ? Xml.TRUE : Xml.FALSE);
2021
2022        e.addContent(values = new Element(Xml.SWITCH_LIST_PICKUP_CAR_FORMAT));
2023        storeXmlMessageFormat(values, getSwitchListPickupCarPrefix(), getPickupSwitchListMessageFormat());
2024
2025        e.addContent(values = new Element(Xml.SWITCH_LIST_DROP_CAR_FORMAT));
2026        storeXmlMessageFormat(values, getSwitchListDropCarPrefix(), getDropSwitchListMessageFormat());
2027
2028        e.addContent(values = new Element(Xml.SWITCH_LIST_LOCAL_FORMAT));
2029        storeXmlMessageFormat(values, getSwitchListLocalPrefix(), getLocalSwitchListMessageFormat());
2030
2031        e.addContent(values = new Element(Xml.PANEL));
2032        values.setAttribute(Xml.NAME, getPanelName());
2033        values.setAttribute(Xml.TRAIN_ICONXY, isTrainIconCordEnabled() ? Xml.TRUE : Xml.FALSE);
2034        values.setAttribute(Xml.TRAIN_ICON_APPEND, isTrainIconAppendEnabled() ? Xml.TRUE : Xml.FALSE);
2035
2036        e.addContent(values = new Element(Xml.FONT_NAME));
2037        values.setAttribute(Xml.NAME, getFontName());
2038
2039        e.addContent(values = new Element(Xml.FONT_SIZE));
2040        values.setAttribute(Xml.SIZE, Integer.toString(getManifestFontSize()));
2041
2042        e.addContent(values = new Element(Xml.PAGE_ORIENTATION));
2043        values.setAttribute(Xml.MANIFEST, getManifestOrientation());
2044        values.setAttribute(Xml.SWITCH_LIST, getSwitchListOrientation());
2045
2046        e.addContent(values = new Element(Xml.PRINT_DUPLEX));
2047        values.setAttribute(Xml.NAME, getPrintDuplexSides().toString());
2048
2049        e.addContent(values = new Element(Xml.MANIFEST_COLORS));
2050        values.setAttribute(Xml.DROP_ENGINE_COLOR, getDropEngineTextColor());
2051        values.setAttribute(Xml.PICKUP_ENGINE_COLOR, getPickupEngineTextColor());
2052        values.setAttribute(Xml.DROP_COLOR, getDropTextColor());
2053        values.setAttribute(Xml.PICKUP_COLOR, getPickupTextColor());
2054        values.setAttribute(Xml.LOCAL_COLOR, getLocalTextColor());
2055
2056        e.addContent(values = new Element(Xml.TAB));
2057        values.setAttribute(Xml.ENABLED, isTabEnabled() ? Xml.TRUE : Xml.FALSE);
2058        values.setAttribute(Xml.LENGTH, Integer.toString(getTab1Length()));
2059        values.setAttribute(Xml.TAB2_LENGTH, Integer.toString(getTab2Length()));
2060        values.setAttribute(Xml.TAB3_LENGTH, Integer.toString(getTab3Length()));
2061
2062        e.addContent(values = new Element(Xml.MANIFEST));
2063        values.setAttribute(Xml.PRINT_LOC_COMMENTS, isPrintLocationCommentsEnabled() ? Xml.TRUE : Xml.FALSE);
2064        values.setAttribute(Xml.PRINT_ROUTE_COMMENTS, isPrintRouteCommentsEnabled() ? Xml.TRUE : Xml.FALSE);
2065        values.setAttribute(Xml.PRINT_LOADS_EMPTIES, isPrintLoadsAndEmptiesEnabled() ? Xml.TRUE : Xml.FALSE);
2066        values.setAttribute(Xml.PRINT_TRAIN_SCHEDULE, isPrintTrainScheduleNameEnabled() ? Xml.TRUE : Xml.FALSE);
2067        values.setAttribute(Xml.USE12HR_FORMAT, is12hrFormatEnabled() ? Xml.TRUE : Xml.FALSE);
2068        values.setAttribute(Xml.PRINT_VALID, isPrintValidEnabled() ? Xml.TRUE : Xml.FALSE);
2069        values.setAttribute(Xml.SORT_BY_TRACK, isSortByTrackNameEnabled() ? Xml.TRUE : Xml.FALSE);
2070        values.setAttribute(Xml.PRINT_PAGE_HEADER, isPrintPageHeaderEnabled() ? Xml.TRUE : Xml.FALSE);
2071        values.setAttribute(Xml.PRINT_HEADERS, isPrintHeadersEnabled() ? Xml.TRUE : Xml.FALSE);
2072        values.setAttribute(Xml.TRUNCATE, isPrintTruncateManifestEnabled() ? Xml.TRUE : Xml.FALSE);
2073        values.setAttribute(Xml.USE_DEPARTURE_TIME, isUseDepartureTimeEnabled() ? Xml.TRUE : Xml.FALSE);
2074        values.setAttribute(Xml.USE_EDITOR, isManifestEditorEnabled() ? Xml.TRUE : Xml.FALSE);
2075        values.setAttribute(Xml.PRINT_CABOOSE_LOAD, isPrintCabooseLoadEnabled() ? Xml.TRUE : Xml.FALSE);
2076        values.setAttribute(Xml.PRINT_PASSENGER_LOAD, isPrintPassengerLoadEnabled() ? Xml.TRUE : Xml.FALSE);
2077        values.setAttribute(Xml.GROUP_MOVES, isGroupCarMovesEnabled() ? Xml.TRUE : Xml.FALSE);
2078        values.setAttribute(Xml.PRINT_LOCO_LAST, isPrintLocoLastEnabled() ? Xml.TRUE : Xml.FALSE);
2079        values.setAttribute(Xml.HAZARDOUS_MSG, getHazardousMsg());
2080
2081        // new format June 2014
2082        e.addContent(values = new Element(Xml.MANIFEST_FORMAT));
2083
2084        // save manifest format
2085        String value = Xml.STANDARD;
2086        if (getManifestFormat().equals(TWO_COLUMN_FORMAT)) {
2087            value = Xml.TWO_COLUMN;
2088        } else if (getManifestFormat().equals(TWO_COLUMN_TRACK_FORMAT)) {
2089            value = Xml.TWO_COLUMN_TRACK;
2090        }
2091        values.setAttribute(Xml.VALUE, value);
2092
2093        // new format June 2025
2094        e.addContent(values = new Element(Xml.HEADER_LINES));
2095        values.setAttribute(Xml.PRINT_HEADER_LINE1, isPrintHeaderLine1Enabled() ? Xml.TRUE : Xml.FALSE);
2096        values.setAttribute(Xml.PRINT_HEADER_LINE2, isPrintHeaderLine2Enabled() ? Xml.TRUE : Xml.FALSE);
2097        values.setAttribute(Xml.PRINT_HEADER_LINE3, isPrintHeaderLine3Enabled() ? Xml.TRUE : Xml.FALSE);
2098
2099        if (!getManifestLogoURL().equals(NONE)) {
2100            values = new Element(Xml.MANIFEST_LOGO);
2101            values.setAttribute(Xml.NAME, getManifestLogoURL());
2102            e.addContent(values);
2103        }
2104
2105        // manifest save file options
2106        e.addContent(values = new Element(Xml.MANIFEST_FILE_OPTIONS));
2107        values.setAttribute(Xml.MANIFEST_SAVE, isSaveTrainManifestsEnabled() ? Xml.TRUE : Xml.FALSE);
2108
2109        e.addContent(values = new Element(Xml.BUILD_OPTIONS));
2110        values.setAttribute(Xml.AGGRESSIVE, isBuildAggressive() ? Xml.TRUE : Xml.FALSE);
2111        values.setAttribute(Xml.NUMBER_PASSES, Integer.toString(getNumberPasses()));
2112
2113        values.setAttribute(Xml.ALLOW_LOCAL_INTERCHANGE, isLocalInterchangeMovesEnabled() ? Xml.TRUE : Xml.FALSE);
2114        values.setAttribute(Xml.ALLOW_LOCAL_SPUR, isLocalSpurMovesEnabled() ? Xml.TRUE : Xml.FALSE);
2115        values.setAttribute(Xml.ALLOW_LOCAL_YARD, isLocalYardMovesEnabled() ? Xml.TRUE : Xml.FALSE);
2116
2117        values.setAttribute(Xml.STAGING_RESTRICTION_ENABLED, isStagingTrainCheckEnabled() ? Xml.TRUE : Xml.FALSE);
2118        values.setAttribute(Xml.STAGING_TRACK_AVAIL, isStagingTrackImmediatelyAvail() ? Xml.TRUE : Xml.FALSE);
2119        values.setAttribute(Xml.ALLOW_RETURN_STAGING, isStagingAllowReturnEnabled() ? Xml.TRUE : Xml.FALSE);
2120        values.setAttribute(Xml.PROMPT_STAGING_ENABLED, isStagingPromptFromEnabled() ? Xml.TRUE : Xml.FALSE);
2121        values.setAttribute(Xml.PROMPT_TO_STAGING_ENABLED, isStagingPromptToEnabled() ? Xml.TRUE : Xml.FALSE);
2122        values.setAttribute(Xml.STAGING_TRY_NORMAL, isStagingTryNormalBuildEnabled() ? Xml.TRUE : Xml.FALSE);
2123
2124        values.setAttribute(Xml.GENERATE_CSV_MANIFEST, isGenerateCsvManifestEnabled() ? Xml.TRUE : Xml.FALSE);
2125        values.setAttribute(Xml.GENERATE_CSV_SWITCH_LIST, isGenerateCsvSwitchListEnabled() ? Xml.TRUE : Xml.FALSE);
2126
2127        e.addContent(values = new Element(Xml.BUILD_REPORT));
2128        values.setAttribute(Xml.LEVEL, getBuildReportLevel());
2129        values.setAttribute(Xml.ROUTER_LEVEL, getRouterBuildReportLevel());
2130        values.setAttribute(Xml.USE_EDITOR, isBuildReportEditorEnabled() ? Xml.TRUE : Xml.FALSE);
2131        values.setAttribute(Xml.INDENT, isBuildReportIndentEnabled() ? Xml.TRUE : Xml.FALSE);
2132        values.setAttribute(Xml.ALWAYS_PREVIEW, isBuildReportAlwaysPreviewEnabled() ? Xml.TRUE : Xml.FALSE);
2133        values.setAttribute(Xml.FONT_SIZE, Integer.toString(getBuildReportFontSize()));
2134
2135        // new format for router options
2136        e.addContent(values = new Element(Xml.ROUTER));
2137        values.setAttribute(Xml.CAR_ROUTING_ENABLED, isCarRoutingEnabled() ? Xml.TRUE : Xml.FALSE);
2138        values.setAttribute(Xml.CAR_ROUTING_VIA_YARDS, isCarRoutingViaYardsEnabled() ? Xml.TRUE : Xml.FALSE);
2139        values.setAttribute(Xml.CAR_ROUTING_VIA_STAGING, isCarRoutingViaStagingEnabled() ? Xml.TRUE : Xml.FALSE);
2140        values.setAttribute(Xml.FORWARD_TO_YARD, isForwardToYardEnabled() ? Xml.TRUE : Xml.FALSE);
2141        values.setAttribute(Xml.ONLY_ACTIVE_TRAINS, isOnlyActiveTrainsEnabled() ? Xml.TRUE : Xml.FALSE);
2142        values.setAttribute(Xml.CHECK_CAR_DESTINATION, isCheckCarDestinationEnabled() ? Xml.TRUE : Xml.FALSE);
2143
2144        // new format for logger options
2145        e.addContent(values = new Element(Xml.LOGGER));
2146        values.setAttribute(Xml.CAR_LOGGER, isCarLoggerEnabled() ? Xml.TRUE : Xml.FALSE);
2147        values.setAttribute(Xml.ENGINE_LOGGER, isEngineLoggerEnabled() ? Xml.TRUE : Xml.FALSE);
2148        values.setAttribute(Xml.TRAIN_LOGGER, isTrainLoggerEnabled() ? Xml.TRUE : Xml.FALSE);
2149
2150        e.addContent(values = new Element(Xml.OWNER));
2151        values.setAttribute(Xml.NAME, getOwnerName());
2152
2153        e.addContent(values = new Element(Xml.ICON_COLOR));
2154        values.setAttribute(Xml.NORTH, getTrainIconColorNorth());
2155        values.setAttribute(Xml.SOUTH, getTrainIconColorSouth());
2156        values.setAttribute(Xml.EAST, getTrainIconColorEast());
2157        values.setAttribute(Xml.WEST, getTrainIconColorWest());
2158        values.setAttribute(Xml.LOCAL, getTrainIconColorLocal());
2159        values.setAttribute(Xml.TERMINATE, getTrainIconColorTerminate());
2160
2161        e.addContent(values = new Element(Xml.COMMENTS));
2162        values.setAttribute(Xml.MISPLACED_CARS, getMiaComment());
2163
2164        e.addContent(values = new Element(Xml.DISPLAY));
2165        values.setAttribute(Xml.SHOW_TRACK_MOVES, isShowTrackMovesEnabled() ? Xml.TRUE : Xml.FALSE);
2166
2167        if (isVsdPhysicalLocationEnabled()) {
2168            e.addContent(values = new Element(Xml.VSD));
2169            values.setAttribute(Xml.ENABLE_PHYSICAL_LOCATIONS, isVsdPhysicalLocationEnabled() ? Xml.TRUE : Xml.FALSE);
2170        }
2171
2172        // Save CATS setting
2173        e.addContent(values = new Element(Xml.CATS));
2174        values.setAttribute(Xml.EXACT_LOCATION_NAME,
2175                AbstractOperationsServer.isExactLoationNameEnabled() ? Xml.TRUE : Xml.FALSE);
2176        return e;
2177    }
2178
2179    private static void storeXmlMessageFormat(Element values, String prefix, String[] messageFormat) {
2180        values.setAttribute(Xml.PREFIX, prefix);
2181        StringBuilder buf = new StringBuilder();
2182        stringToTagConversion(messageFormat);
2183        for (String attibute : messageFormat) {
2184            buf.append(attibute).append(",");
2185        }
2186        values.setAttribute(Xml.SETTING, buf.toString());
2187    }
2188
2189    public static void load(Element e) {
2190        if (e.getChild(Xml.OPERATIONS) == null) {
2191            log.warn("OperationsPro settings values not found");
2192            return;
2193        }
2194        Element operations = e.getChild(Xml.OPERATIONS);
2195        org.jdom2.Attribute a;
2196
2197        if ((operations.getChild(Xml.RAIL_ROAD) != null) &&
2198                (a = operations.getChild(Xml.RAIL_ROAD).getAttribute(Xml.NAME)) != null) {
2199            String name = a.getValue();
2200            log.debug("railroadName: {}", name);
2201            // code before 4.11 "useJmriRailroadName" when using the preferences railroad
2202            // name.
2203            // here for backwards compatibility
2204            if (!name.equals(Xml.USE_JMRI_RAILROAD_NAME)) {
2205                getDefault().railroadName = name; // don't set the dirty bit
2206            }
2207        }
2208
2209        if ((operations.getChild(Xml.SETUP) != null) &&
2210                (a = operations.getChild(Xml.SETUP).getAttribute(Xml.COMMENT)) != null) {
2211            String comment = a.getValue();
2212            log.debug("setup comment: {}", comment);
2213            getDefault().setupComment = comment;
2214        }
2215
2216        if (operations.getChild(Xml.SETTINGS) != null) {
2217            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.MAIN_MENU)) != null) {
2218                String enabled = a.getValue();
2219                log.debug("mainMenu: {}", enabled);
2220                setMainMenuEnabled(enabled.equals(Xml.TRUE));
2221            }
2222            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.CLOSE_ON_SAVE)) != null) {
2223                String enabled = a.getValue();
2224                log.debug("closeOnSave: {}", enabled);
2225                setCloseWindowOnSaveEnabled(enabled.equals(Xml.TRUE));
2226            }
2227            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.TRAIN_DIRECTION)) != null) {
2228                String dir = a.getValue();
2229                log.debug("direction: {}", dir);
2230                try {
2231                    getDefault().traindir = Integer.parseInt(dir);
2232                } catch (NumberFormatException ee) {
2233                    log.error("Train direction ({}) isn't a valid number", a.getValue());
2234                }
2235            }
2236            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.TRAIN_LENGTH)) != null) {
2237                String length = a.getValue();
2238                log.debug("Max train length: {}", length);
2239                try {
2240                    setMaxTrainLength(Integer.parseInt(length));
2241                } catch (NumberFormatException ee) {
2242                    log.error("Train maximum length ({}) isn't a valid number", a.getValue());
2243                }
2244            }
2245            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.MAX_ENGINES)) != null) {
2246                String size = a.getValue();
2247                log.debug("Max number of engines: {}", size);
2248                try {
2249                    setMaxNumberEngines(Integer.parseInt(size));
2250                } catch (NumberFormatException ee) {
2251                    log.error("Maximum number of engines ({}) isn't a valid number", a.getValue());
2252                }
2253            }
2254            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.HPT)) != null) {
2255                String value = a.getValue();
2256                log.debug("HPT: {}", value);
2257                try {
2258                    setHorsePowerPerTon(Double.parseDouble(value));
2259                } catch (NumberFormatException ee) {
2260                    log.error("Train HPT ({}) isn't a valid number", a.getValue());
2261                }
2262            }
2263            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.SCALE)) != null) {
2264                String scale = a.getValue();
2265                log.debug("scale: {}", scale);
2266                try {
2267                    setScale(Integer.parseInt(scale));
2268                } catch (NumberFormatException ee) {
2269                    log.error("Scale ({}) isn't a valid number", a.getValue());
2270                }
2271            }
2272            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.CAR_TYPES)) != null) {
2273                String types = a.getValue();
2274                log.debug("CarTypes: {}", types);
2275                setCarTypes(types);
2276            }
2277            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.SWITCH_TIME)) != null) {
2278                String minutes = a.getValue();
2279                log.debug("switchTime: {}", minutes);
2280                try {
2281                    setSwitchTime(Integer.parseInt(minutes));
2282                } catch (NumberFormatException ee) {
2283                    log.error("Switch time ({}) isn't a valid number", a.getValue());
2284                }
2285            }
2286            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.TRAVEL_TIME)) != null) {
2287                String minutes = a.getValue();
2288                log.debug("travelTime: {}", minutes);
2289                try {
2290                    setTravelTime(Integer.parseInt(minutes));
2291                } catch (NumberFormatException ee) {
2292                    log.error("Travel time ({}) isn't a valid number", a.getValue());
2293                }
2294            }
2295            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.SHOW_VALUE)) != null) {
2296                String enable = a.getValue();
2297                log.debug("showValue: {}", enable);
2298                setValueEnabled(enable.equals(Xml.TRUE));
2299            }
2300            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.VALUE_LABEL)) != null) {
2301                String label = a.getValue();
2302                log.debug("valueLabel: {}", label);
2303                setValueLabel(label);
2304            }
2305            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.SHOW_RFID)) != null) {
2306                String enable = a.getValue();
2307                log.debug("showRfid: {}", enable);
2308                setRfidEnabled(enable.equals(Xml.TRUE));
2309            }
2310            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.RFID_LABEL)) != null) {
2311                String label = a.getValue();
2312                log.debug("rfidLabel: {}", label);
2313                setRfidLabel(label);
2314            }
2315            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.LENGTH_UNIT)) != null) {
2316                String unit = a.getValue();
2317                log.debug("lengthUnit: {}", unit);
2318                setLengthUnit(unit);
2319            }
2320            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.YEAR_MODELED)) != null) {
2321                String year = a.getValue();
2322                log.debug("yearModeled: {}", year);
2323                setYearModeled(year);
2324            }
2325            // next eight attributes are here for backward compatibility
2326            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.PRINT_LOC_COMMENTS)) != null) {
2327                String enable = a.getValue();
2328                log.debug("printLocComments: {}", enable);
2329                setPrintLocationCommentsEnabled(enable.equals(Xml.TRUE));
2330            }
2331            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.PRINT_ROUTE_COMMENTS)) != null) {
2332                String enable = a.getValue();
2333                log.debug("printRouteComments: {}", enable);
2334                setPrintRouteCommentsEnabled(enable.equals(Xml.TRUE));
2335            }
2336            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.PRINT_LOADS_EMPTIES)) != null) {
2337                String enable = a.getValue();
2338                log.debug("printLoadsEmpties: {}", enable);
2339                setPrintLoadsAndEmptiesEnabled(enable.equals(Xml.TRUE));
2340            }
2341            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.PRINT_TRAIN_SCHEDULE)) != null) {
2342                String enable = a.getValue();
2343                log.debug("printTrainSchedule: {}", enable);
2344                setPrintTrainScheduleNameEnabled(enable.equals(Xml.TRUE));
2345            }
2346            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.USE12HR_FORMAT)) != null) {
2347                String enable = a.getValue();
2348                log.debug("use12hrFormat: {}", enable);
2349                set12hrFormatEnabled(enable.equals(Xml.TRUE));
2350            }
2351            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.PRINT_VALID)) != null) {
2352                String enable = a.getValue();
2353                log.debug("printValid: {}", enable);
2354                setPrintValidEnabled(enable.equals(Xml.TRUE));
2355            }
2356            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.SORT_BY_TRACK)) != null) {
2357                String enable = a.getValue();
2358                log.debug("sortByTrack: {}", enable);
2359                setSortByTrackNameEnabled(enable.equals(Xml.TRUE));
2360            }
2361            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.PRINT_HEADERS)) != null) {
2362                String enable = a.getValue();
2363                log.debug("printHeaders: {}", enable);
2364                setPrintHeadersEnabled(enable.equals(Xml.TRUE));
2365            }
2366        }
2367        if (operations.getChild(Xml.PICKUP_ENG_FORMAT) != null) {
2368            if ((a = operations.getChild(Xml.PICKUP_ENG_FORMAT).getAttribute(Xml.PREFIX)) != null) {
2369                setPickupEnginePrefix(a.getValue());
2370            }
2371            if ((a = operations.getChild(Xml.PICKUP_ENG_FORMAT).getAttribute(Xml.SETTING)) != null) {
2372                String setting = a.getValue();
2373                log.debug("pickupEngFormat: {}", setting);
2374                String[] keys = setting.split(",");
2375                xmlAttributeToKeyConversion(keys);
2376                keyToStringConversion(keys);
2377                setPickupEngineMessageFormat(keys);
2378            }
2379        }
2380        if (operations.getChild(Xml.DROP_ENG_FORMAT) != null) {
2381            if ((a = operations.getChild(Xml.DROP_ENG_FORMAT).getAttribute(Xml.PREFIX)) != null) {
2382                setDropEnginePrefix(a.getValue());
2383            }
2384            if ((a = operations.getChild(Xml.DROP_ENG_FORMAT).getAttribute(Xml.SETTING)) != null) {
2385                String setting = a.getValue();
2386                log.debug("dropEngFormat: {}", setting);
2387                String[] keys = setting.split(",");
2388                xmlAttributeToKeyConversion(keys);
2389                keyToStringConversion(keys);
2390                setDropEngineMessageFormat(keys);
2391            }
2392        }
2393        if (operations.getChild(Xml.PICKUP_CAR_FORMAT) != null) {
2394            if ((a = operations.getChild(Xml.PICKUP_CAR_FORMAT).getAttribute(Xml.PREFIX)) != null) {
2395                setPickupCarPrefix(a.getValue());
2396            }
2397            if ((a = operations.getChild(Xml.PICKUP_CAR_FORMAT).getAttribute(Xml.SETTING)) != null) {
2398                String setting = a.getValue();
2399                log.debug("pickupCarFormat: {}", setting);
2400                String[] keys = setting.split(",");
2401                replaceOldFormat(keys);
2402                xmlAttributeToKeyConversion(keys);
2403                keyToStringConversion(keys);
2404                setPickupManifestMessageFormat(keys);
2405            }
2406        }
2407        if (operations.getChild(Xml.DROP_CAR_FORMAT) != null) {
2408            if ((a = operations.getChild(Xml.DROP_CAR_FORMAT).getAttribute(Xml.PREFIX)) != null) {
2409                setDropCarPrefix(a.getValue());
2410            }
2411            if ((a = operations.getChild(Xml.DROP_CAR_FORMAT).getAttribute(Xml.SETTING)) != null) {
2412                String setting = a.getValue();
2413                log.debug("dropCarFormat: {}", setting);
2414                String[] keys = setting.split(",");
2415                replaceOldFormat(keys);
2416                xmlAttributeToKeyConversion(keys);
2417                keyToStringConversion(keys);
2418                setDropManifestMessageFormat(keys);
2419            }
2420        }
2421        if (operations.getChild(Xml.LOCAL_FORMAT) != null) {
2422            if ((a = operations.getChild(Xml.LOCAL_FORMAT).getAttribute(Xml.PREFIX)) != null) {
2423                setLocalPrefix(a.getValue());
2424            }
2425            if ((a = operations.getChild(Xml.LOCAL_FORMAT).getAttribute(Xml.SETTING)) != null) {
2426                String setting = a.getValue();
2427                log.debug("localFormat: {}", setting);
2428                String[] keys = setting.split(",");
2429                replaceOldFormat(keys);
2430                xmlAttributeToKeyConversion(keys);
2431                keyToStringConversion(keys);
2432                setLocalManifestMessageFormat(keys);
2433            }
2434        }
2435        if (operations.getChild(Xml.MISSING_CAR_FORMAT) != null) {
2436            if ((a = operations.getChild(Xml.MISSING_CAR_FORMAT).getAttribute(Xml.SETTING)) != null) {
2437                String setting = a.getValue();
2438                log.debug("missingCarFormat: {}", setting);
2439                String[] keys = setting.split(",");
2440                keyToStringConversion(keys);
2441                setMissingCarMessageFormat(keys);
2442            }
2443        }
2444        if (operations.getChild(Xml.SWITCH_LIST) != null) {
2445            if ((a = operations.getChild(Xml.SWITCH_LIST).getAttribute(Xml.SAME_AS_MANIFEST)) != null) {
2446                String b = a.getValue();
2447                log.debug("sameAsManifest: {}", b);
2448                setSwitchListFormatSameAsManifest(b.equals(Xml.TRUE));
2449            }
2450            if ((a = operations.getChild(Xml.SWITCH_LIST).getAttribute(Xml.REAL_TIME)) != null) {
2451                String b = a.getValue();
2452                log.debug("realTime: {}", b);
2453                getDefault().switchListRealTime = b.equals(Xml.TRUE);
2454            }
2455            if ((a = operations.getChild(Xml.SWITCH_LIST).getAttribute(Xml.ALL_TRAINS)) != null) {
2456                String b = a.getValue();
2457                log.debug("allTrains: {}", b);
2458                getDefault().switchListAllTrains = b.equals(Xml.TRUE);
2459            }
2460            if ((a = operations.getChild(Xml.SWITCH_LIST).getAttribute(Xml.PAGE_FORMAT)) != null) {
2461                switch (a.getValue()) {
2462                    case Xml.PAGE_NORMAL:
2463                        getDefault().switchListPageFormat = PAGE_NORMAL;
2464                        break;
2465                    case Xml.PAGE_PER_TRAIN:
2466                        getDefault().switchListPageFormat = PAGE_PER_TRAIN;
2467                        break;
2468                    case Xml.PAGE_PER_VISIT:
2469                        getDefault().switchListPageFormat = PAGE_PER_VISIT;
2470                        break;
2471                    default:
2472                        log.error("Unknown switch list page format {}", a.getValue());
2473                }
2474            } // old way to save switch list page format pre 3.11
2475            else if ((a = operations.getChild(Xml.SWITCH_LIST).getAttribute(Xml.PAGE_MODE)) != null) {
2476                String b = a.getValue();
2477                log.debug("old style pageMode: {}", b);
2478                if (b.equals(Xml.TRUE)) {
2479                    getDefault().switchListPageFormat = PAGE_PER_TRAIN;
2480                }
2481            }
2482            if ((a = operations.getChild(Xml.SWITCH_LIST).getAttribute(Xml.PRINT_ROUTE_LOCATION)) != null) {
2483                String b = a.getValue();
2484                log.debug("print route location comment: {}", b);
2485                setSwitchListRouteLocationCommentEnabled(b.equals(Xml.TRUE));
2486            }
2487            if ((a = operations.getChild(Xml.SWITCH_LIST).getAttribute(Xml.TRACK_SUMMARY)) != null) {
2488                String b = a.getValue();
2489                log.debug("track summary: {}", b);
2490                setPrintTrackSummaryEnabled(b.equals(Xml.TRUE));
2491            }
2492            if ((a = operations.getChild(Xml.SWITCH_LIST).getAttribute(Xml.USE_DEPARTURE_TIME)) != null) {
2493                String b = a.getValue();
2494                log.debug("switch list departure time: {}", b);
2495                setUseSwitchListDepartureTimeEnabled(b.equals(Xml.TRUE));
2496            }
2497        }
2498        if (operations.getChild(Xml.SWITCH_LIST_PICKUP_CAR_FORMAT) != null) {
2499            if ((a = operations.getChild(Xml.SWITCH_LIST_PICKUP_CAR_FORMAT).getAttribute(Xml.PREFIX)) != null) {
2500                setSwitchListPickupCarPrefix(a.getValue());
2501            }
2502            if ((a = operations.getChild(Xml.SWITCH_LIST_PICKUP_CAR_FORMAT).getAttribute(Xml.SETTING)) != null) {
2503                String setting = a.getValue();
2504                log.debug("switchListpickupCarFormat: {}", setting);
2505                String[] keys = setting.split(",");
2506                replaceOldFormat(keys);
2507                xmlAttributeToKeyConversion(keys);
2508                keyToStringConversion(keys);
2509                setPickupSwitchListMessageFormat(keys);
2510            }
2511        }
2512        if (operations.getChild(Xml.SWITCH_LIST_DROP_CAR_FORMAT) != null) {
2513            if ((a = operations.getChild(Xml.SWITCH_LIST_DROP_CAR_FORMAT).getAttribute(Xml.PREFIX)) != null) {
2514                setSwitchListDropCarPrefix(a.getValue());
2515            }
2516            if ((a = operations.getChild(Xml.SWITCH_LIST_DROP_CAR_FORMAT).getAttribute(Xml.SETTING)) != null) {
2517                String setting = a.getValue();
2518                log.debug("switchListDropCarFormat: {}", setting);
2519                String[] keys = setting.split(",");
2520                replaceOldFormat(keys);
2521                xmlAttributeToKeyConversion(keys);
2522                keyToStringConversion(keys);
2523                setDropSwitchListMessageFormat(keys);
2524            }
2525        }
2526        if (operations.getChild(Xml.SWITCH_LIST_LOCAL_FORMAT) != null) {
2527            if ((a = operations.getChild(Xml.SWITCH_LIST_LOCAL_FORMAT).getAttribute(Xml.PREFIX)) != null) {
2528                setSwitchListLocalPrefix(a.getValue());
2529            }
2530            if ((a = operations.getChild(Xml.SWITCH_LIST_LOCAL_FORMAT).getAttribute(Xml.SETTING)) != null) {
2531                String setting = a.getValue();
2532                log.debug("switchListLocalFormat: {}", setting);
2533                String[] keys = setting.split(",");
2534                replaceOldFormat(keys);
2535                xmlAttributeToKeyConversion(keys);
2536                keyToStringConversion(keys);
2537                setLocalSwitchListMessageFormat(keys);
2538            }
2539        }
2540        if (operations.getChild(Xml.PANEL) != null) {
2541            if ((a = operations.getChild(Xml.PANEL).getAttribute(Xml.NAME)) != null) {
2542                String panel = a.getValue();
2543                log.debug("panel: {}", panel);
2544                setPanelName(panel);
2545            }
2546            if ((a = operations.getChild(Xml.PANEL).getAttribute(Xml.TRAIN_ICONXY)) != null) {
2547                String enable = a.getValue();
2548                log.debug("TrainIconXY: {}", enable);
2549                setTrainIconCordEnabled(enable.equals(Xml.TRUE));
2550            }
2551            if ((a = operations.getChild(Xml.PANEL).getAttribute(Xml.TRAIN_ICON_APPEND)) != null) {
2552                String enable = a.getValue();
2553                log.debug("TrainIconAppend: {}", enable);
2554                setTrainIconAppendEnabled(enable.equals(Xml.TRUE));
2555            }
2556        }
2557        if ((operations.getChild(Xml.FONT_NAME) != null) &&
2558                (a = operations.getChild(Xml.FONT_NAME).getAttribute(Xml.NAME)) != null) {
2559            String font = a.getValue();
2560            log.debug("fontName: {}", font);
2561            setFontName(font);
2562        }
2563        if ((operations.getChild(Xml.FONT_SIZE) != null) &&
2564                (a = operations.getChild(Xml.FONT_SIZE).getAttribute(Xml.SIZE)) != null) {
2565            String size = a.getValue();
2566            log.debug("fontsize: {}", size);
2567            try {
2568                setManifestFontSize(Integer.parseInt(size));
2569            } catch (NumberFormatException ee) {
2570                log.error("Manifest font size ({}) isn't a valid number", a.getValue());
2571            }
2572        }
2573        if ((operations.getChild(Xml.PAGE_ORIENTATION) != null)) {
2574            if ((a = operations.getChild(Xml.PAGE_ORIENTATION).getAttribute(Xml.MANIFEST)) != null) {
2575                String orientation = a.getValue();
2576                log.debug("manifestOrientation: {}", orientation);
2577                setManifestOrientation(orientation);
2578            }
2579            if ((a = operations.getChild(Xml.PAGE_ORIENTATION).getAttribute(Xml.SWITCH_LIST)) != null) {
2580                String orientation = a.getValue();
2581                log.debug("switchListOrientation: {}", orientation);
2582                setSwitchListOrientation(orientation);
2583            }
2584        }
2585        if ((operations.getChild(Xml.PRINT_DUPLEX) != null)) {
2586            if ((a = operations.getChild(Xml.PRINT_DUPLEX).getAttribute(Xml.NAME)) != null) {
2587                String sides = a.getValue();
2588                log.debug("Print duplex: {}", sides);
2589                if (sides.equals(SidesType.TWO_SIDED_LONG_EDGE.toString())) {
2590                    setPrintDuplexSides(SidesType.TWO_SIDED_LONG_EDGE);
2591                }
2592                if (sides.equals(SidesType.TWO_SIDED_SHORT_EDGE.toString())) {
2593                    setPrintDuplexSides(SidesType.TWO_SIDED_SHORT_EDGE);
2594                }
2595            }
2596        }
2597        if ((operations.getChild(Xml.MANIFEST_COLORS) != null)) {
2598            if ((a = operations.getChild(Xml.MANIFEST_COLORS).getAttribute(Xml.DROP_COLOR)) != null) {
2599                String dropColor = a.getValue();
2600                log.debug("dropColor: {}", dropColor);
2601                setDropTextColor(dropColor);
2602            }
2603            if ((a = operations.getChild(Xml.MANIFEST_COLORS).getAttribute(Xml.PICKUP_COLOR)) != null) {
2604                String pickupColor = a.getValue();
2605                log.debug("pickupColor: {}", pickupColor);
2606                setPickupTextColor(pickupColor);
2607            }
2608            if ((a = operations.getChild(Xml.MANIFEST_COLORS).getAttribute(Xml.LOCAL_COLOR)) != null) {
2609                String localColor = a.getValue();
2610                log.debug("localColor: {}", localColor);
2611                setLocalTextColor(localColor);
2612            }
2613            if ((a = operations.getChild(Xml.MANIFEST_COLORS).getAttribute(Xml.DROP_ENGINE_COLOR)) != null) {
2614                String dropColor = a.getValue();
2615                log.debug("dropEngineColor: {}", dropColor);
2616                setDropEngineTextColor(dropColor);
2617            } else {
2618                // Engine drop color didn't exist before 5.11.3
2619                setDropEngineTextColor(getDropTextColor());
2620            }
2621            if ((a = operations.getChild(Xml.MANIFEST_COLORS).getAttribute(Xml.PICKUP_ENGINE_COLOR)) != null) {
2622                String pickupColor = a.getValue();
2623                log.debug("pickupEngineColor: {}", pickupColor);
2624                setPickupEngineTextColor(pickupColor);
2625            } else {
2626                // Engine pick up color didn't exist before 5.11.3
2627                setPickupEngineTextColor(getPickupTextColor());
2628            }
2629        }
2630        if ((operations.getChild(Xml.TAB) != null)) {
2631            if ((a = operations.getChild(Xml.TAB).getAttribute(Xml.ENABLED)) != null) {
2632                String enable = a.getValue();
2633                log.debug("tab: {}", enable);
2634                setTabEnabled(enable.equals(Xml.TRUE));
2635            }
2636            if ((a = operations.getChild(Xml.TAB).getAttribute(Xml.LENGTH)) != null) {
2637                String length = a.getValue();
2638                log.debug("tab 1 length: {}", length);
2639                try {
2640                    setTab1length(Integer.parseInt(length));
2641                } catch (NumberFormatException ee) {
2642                    log.error("Tab 1 length ({}) isn't a valid number", a.getValue());
2643                }
2644            }
2645            if ((a = operations.getChild(Xml.TAB).getAttribute(Xml.TAB2_LENGTH)) != null) {
2646                String length = a.getValue();
2647                log.debug("tab 2 length: {}", length);
2648                try {
2649                    setTab2length(Integer.parseInt(length));
2650                } catch (NumberFormatException ee) {
2651                    log.error("Tab 2 length ({}) isn't a valid number", a.getValue());
2652                }
2653            }
2654            if ((a = operations.getChild(Xml.TAB).getAttribute(Xml.TAB3_LENGTH)) != null) {
2655                String length = a.getValue();
2656                log.debug("tab 3 length: {}", length);
2657                try {
2658                    setTab3length(Integer.parseInt(length));
2659                } catch (NumberFormatException ee) {
2660                    log.error("Tab 3 length ({}) isn't a valid number", a.getValue());
2661                }
2662            }
2663        }
2664        if ((operations.getChild(Xml.MANIFEST) != null)) {
2665            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_LOC_COMMENTS)) != null) {
2666                String enable = a.getValue();
2667                log.debug("manifest printLocComments: {}", enable);
2668                setPrintLocationCommentsEnabled(enable.equals(Xml.TRUE));
2669            }
2670            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_ROUTE_COMMENTS)) != null) {
2671                String enable = a.getValue();
2672                log.debug("manifest printRouteComments: {}", enable);
2673                setPrintRouteCommentsEnabled(enable.equals(Xml.TRUE));
2674            }
2675            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_LOADS_EMPTIES)) != null) {
2676                String enable = a.getValue();
2677                log.debug("manifest printLoadsEmpties: {}", enable);
2678                setPrintLoadsAndEmptiesEnabled(enable.equals(Xml.TRUE));
2679            }
2680            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_TRAIN_SCHEDULE)) != null) {
2681                String enable = a.getValue();
2682                log.debug("manifest printTrainSchedule: {}", enable);
2683                setPrintTrainScheduleNameEnabled(enable.equals(Xml.TRUE));
2684            }
2685            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.USE12HR_FORMAT)) != null) {
2686                String enable = a.getValue();
2687                log.debug("manifest use12hrFormat: {}", enable);
2688                set12hrFormatEnabled(enable.equals(Xml.TRUE));
2689            }
2690            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_VALID)) != null) {
2691                String enable = a.getValue();
2692                log.debug("manifest printValid: {}", enable);
2693                setPrintValidEnabled(enable.equals(Xml.TRUE));
2694            }
2695            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.SORT_BY_TRACK)) != null) {
2696                String enable = a.getValue();
2697                log.debug("manifest sortByTrack: {}", enable);
2698                setSortByTrackNameEnabled(enable.equals(Xml.TRUE));
2699            }
2700            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_PAGE_HEADER)) != null) {
2701                String enable = a.getValue();
2702                log.debug("manifest printPageHeader: {}", enable);
2703                setPrintPageHeaderEnabled(enable.equals(Xml.TRUE));
2704            }
2705            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_HEADERS)) != null) {
2706                String enable = a.getValue();
2707                log.debug("manifest print headers: {}", enable);
2708                setPrintHeadersEnabled(enable.equals(Xml.TRUE));
2709            }
2710            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.TRUNCATE)) != null) {
2711                String enable = a.getValue();
2712                log.debug("manifest truncate: {}", enable);
2713                setPrintTruncateManifestEnabled(enable.equals(Xml.TRUE));
2714            }
2715            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.USE_DEPARTURE_TIME)) != null) {
2716                String enable = a.getValue();
2717                log.debug("manifest use departure time: {}", enable);
2718                setUseDepartureTimeEnabled(enable.equals(Xml.TRUE));
2719            }
2720            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.USE_EDITOR)) != null) {
2721                String enable = a.getValue();
2722                log.debug("manifest useEditor: {}", enable);
2723                setManifestEditorEnabled(enable.equals(Xml.TRUE));
2724            }
2725            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_CABOOSE_LOAD)) != null) {
2726                String enable = a.getValue();
2727                log.debug("manifest print caboose load: {}", enable);
2728                setPrintCabooseLoadEnabled(enable.equals(Xml.TRUE));
2729            }
2730            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_PASSENGER_LOAD)) != null) {
2731                String enable = a.getValue();
2732                log.debug("manifest print passenger load: {}", enable);
2733                setPrintPassengerLoadEnabled(enable.equals(Xml.TRUE));
2734            }
2735            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.GROUP_MOVES)) != null) {
2736                String enable = a.getValue();
2737                log.debug("manifest group car moves: {}", enable);
2738                setGroupCarMoves(enable.equals(Xml.TRUE));
2739            }
2740            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.PRINT_LOCO_LAST)) != null) {
2741                String enable = a.getValue();
2742                log.debug("manifest print loco last: {}", enable);
2743                setPrintLocoLast(enable.equals(Xml.TRUE));
2744            }
2745            if ((a = operations.getChild(Xml.MANIFEST).getAttribute(Xml.HAZARDOUS_MSG)) != null) {
2746                String message = a.getValue();
2747                log.debug("manifest hazardousMsg: {}", message);
2748                setHazardousMsg(message);
2749            }
2750        }
2751        if ((operations.getChild(Xml.MANIFEST_FORMAT) != null)) {
2752            if ((a = operations.getChild(Xml.MANIFEST_FORMAT).getAttribute(Xml.VALUE)) != null) {
2753                switch (a.getValue()) {
2754                    case Xml.STANDARD:
2755                        getDefault().manifestFormat = STANDARD_FORMAT;
2756                        break;
2757                    case Xml.TWO_COLUMN:
2758                        getDefault().manifestFormat = TWO_COLUMN_FORMAT;
2759                        break;
2760                    case Xml.TWO_COLUMN_TRACK:
2761                        getDefault().manifestFormat = TWO_COLUMN_TRACK_FORMAT;
2762                        break;
2763                    default:
2764                        log.debug("Unknown manifest format");
2765                }
2766            }
2767        } else if ((operations.getChild(Xml.COLUMN_FORMAT) != null)) {
2768            if ((a = operations.getChild(Xml.COLUMN_FORMAT).getAttribute(Xml.TWO_COLUMNS)) != null) {
2769                String enable = a.getValue();
2770                log.debug("two columns: {}", enable);
2771                if (enable.equals(Xml.TRUE)) {
2772                    setManifestFormat(TWO_COLUMN_FORMAT);
2773                }
2774            }
2775        }
2776        if ((operations.getChild(Xml.HEADER_LINES) != null)) {
2777            if ((a = operations.getChild(Xml.HEADER_LINES).getAttribute(Xml.PRINT_HEADER_LINE1)) != null) {
2778                String enable = a.getValue();
2779                setPrintHeaderLine1Enabled(enable.equals(Xml.TRUE));
2780            }
2781            if ((a = operations.getChild(Xml.HEADER_LINES).getAttribute(Xml.PRINT_HEADER_LINE2)) != null) {
2782                String enable = a.getValue();
2783                setPrintHeaderLine2Enabled(enable.equals(Xml.TRUE));
2784            }
2785            if ((a = operations.getChild(Xml.HEADER_LINES).getAttribute(Xml.PRINT_HEADER_LINE3)) != null) {
2786                String enable = a.getValue();
2787                setPrintHeaderLine3Enabled(enable.equals(Xml.TRUE));
2788            }
2789        }
2790        // get manifest logo
2791        if ((operations.getChild(Xml.MANIFEST_LOGO) != null)) {
2792            if ((a = operations.getChild(Xml.MANIFEST_LOGO).getAttribute(Xml.NAME)) != null) {
2793                setManifestLogoURL(a.getValue());
2794            }
2795        }
2796        // manifest file options
2797        if ((operations.getChild(Xml.MANIFEST_FILE_OPTIONS) != null)) {
2798            if ((a = operations.getChild(Xml.MANIFEST_FILE_OPTIONS).getAttribute(Xml.MANIFEST_SAVE)) != null) {
2799                String enable = a.getValue();
2800                log.debug("manifest file save option: {}", enable);
2801                getDefault().saveTrainManifests = enable.equals(Xml.TRUE);
2802            }
2803        }
2804        if ((operations.getChild(Xml.BUILD_OPTIONS) != null)) {
2805            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.AGGRESSIVE)) != null) {
2806                String enable = a.getValue();
2807                log.debug("aggressive: {}", enable);
2808                setBuildAggressive(enable.equals(Xml.TRUE));
2809            }
2810            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.NUMBER_PASSES)) != null) {
2811                String number = a.getValue();
2812                log.debug("number of passes: {}", number);
2813                try {
2814                    setNumberPasses(Integer.parseInt(number));
2815                } catch (NumberFormatException ne) {
2816                    log.debug("Number of passes isn't a number");
2817                }
2818            }
2819            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.ALLOW_LOCAL_INTERCHANGE)) != null) {
2820                String enable = a.getValue();
2821                log.debug("allowLocalInterchangeMoves: {}", enable);
2822                setLocalInterchangeMovesEnabled(enable.equals(Xml.TRUE));
2823            }
2824            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.ALLOW_LOCAL_SPUR)) != null) {
2825                String enable = a.getValue();
2826                log.debug("allowLocalSpurMoves: {}", enable);
2827                setLocalSpurMovesEnabled(enable.equals(Xml.TRUE));
2828            } else if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.ALLOW_LOCAL_SIDING)) != null) {
2829                String enable = a.getValue();
2830                log.debug("allowLocalSidingMoves: {}", enable);
2831                setLocalSpurMovesEnabled(enable.equals(Xml.TRUE));
2832            }
2833            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.ALLOW_LOCAL_YARD)) != null) {
2834                String enable = a.getValue();
2835                log.debug("allowLocalYardMoves: {}", enable);
2836                setLocalYardMovesEnabled(enable.equals(Xml.TRUE));
2837            }
2838            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.STAGING_RESTRICTION_ENABLED)) != null) {
2839                String enable = a.getValue();
2840                log.debug("stagingRestrictionEnabled: {}", enable);
2841                setStagingTrainCheckEnabled(enable.equals(Xml.TRUE));
2842            }
2843            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.STAGING_TRACK_AVAIL)) != null) {
2844                String enable = a.getValue();
2845                log.debug("stagingTrackAvail: {}", enable);
2846                setStagingTrackImmediatelyAvail(enable.equals(Xml.TRUE));
2847            }
2848            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.ALLOW_RETURN_STAGING)) != null) {
2849                String enable = a.getValue();
2850                log.debug("allowReturnStaging: {}", enable);
2851                getDefault().allowCarsReturnStaging = enable.equals(Xml.TRUE);
2852            }
2853            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.PROMPT_STAGING_ENABLED)) != null) {
2854                String enable = a.getValue();
2855                log.debug("promptStagingEnabled: {}", enable);
2856                setStagingPromptFromEnabled(enable.equals(Xml.TRUE));
2857            }
2858            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.PROMPT_TO_STAGING_ENABLED)) != null) {
2859                String enable = a.getValue();
2860                log.debug("promptToStagingEnabled: {}", enable);
2861                setStagingPromptToEnabled(enable.equals(Xml.TRUE));
2862            }
2863            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.STAGING_TRY_NORMAL)) != null) {
2864                String enable = a.getValue();
2865                log.debug("stagingTryNormalEnabled: {}", enable);
2866                setStagingTryNormalBuildEnabled(enable.equals(Xml.TRUE));
2867            }
2868            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.GENERATE_CSV_MANIFEST)) != null) {
2869                String enable = a.getValue();
2870                log.debug("generateCvsManifest: {}", enable);
2871                getDefault().generateCsvManifest = enable.equals(Xml.TRUE);
2872            }
2873            if ((a = operations.getChild(Xml.BUILD_OPTIONS).getAttribute(Xml.GENERATE_CSV_SWITCH_LIST)) != null) {
2874                String enable = a.getValue();
2875                log.debug("generateCvsSwitchList: {}", enable);
2876                getDefault().generateCsvSwitchList = enable.equals(Xml.TRUE);
2877            }
2878        }
2879        if (operations.getChild(Xml.BUILD_REPORT) != null) {
2880            if ((a = operations.getChild(Xml.BUILD_REPORT).getAttribute(Xml.LEVEL)) != null) {
2881                String level = a.getValue();
2882                log.debug("buildReportLevel: {}", level);
2883                setBuildReportLevel(level);
2884            }
2885            if ((a = operations.getChild(Xml.BUILD_REPORT).getAttribute(Xml.ROUTER_LEVEL)) != null) {
2886                String level = a.getValue();
2887                log.debug("routerBuildReportLevel: {}", level);
2888                setRouterBuildReportLevel(level);
2889            }
2890            if ((a = operations.getChild(Xml.BUILD_REPORT).getAttribute(Xml.USE_EDITOR)) != null) {
2891                String enable = a.getValue();
2892                log.debug("build report useEditor: {}", enable);
2893                setBuildReportEditorEnabled(enable.equals(Xml.TRUE));
2894            }
2895            if ((a = operations.getChild(Xml.BUILD_REPORT).getAttribute(Xml.INDENT)) != null) {
2896                String enable = a.getValue();
2897                log.debug("build report indent: {}", enable);
2898                setBuildReportIndentEnabled(enable.equals(Xml.TRUE));
2899            }
2900            if ((a = operations.getChild(Xml.BUILD_REPORT).getAttribute(Xml.FONT_SIZE)) != null) {
2901                String size = a.getValue();
2902                log.debug("build font size: {}", size);
2903                try {
2904                    setBuildReportFontSize(Integer.parseInt(size));
2905                } catch (NumberFormatException ee) {
2906                    log.error("Build report font size ({}) isn't a valid number", a.getValue());
2907                }
2908            }
2909            if ((a = operations.getChild(Xml.BUILD_REPORT).getAttribute(Xml.ALWAYS_PREVIEW)) != null) {
2910                String enable = a.getValue();
2911                log.debug("build report always preview: {}", enable);
2912                setBuildReportAlwaysPreviewEnabled(enable.equals(Xml.TRUE));
2913            }
2914        }
2915
2916        if (operations.getChild(Xml.ROUTER) != null) {
2917            if ((a = operations.getChild(Xml.ROUTER).getAttribute(Xml.CAR_ROUTING_ENABLED)) != null) {
2918                String enable = a.getValue();
2919                log.debug("carRoutingEnabled: {}", enable);
2920                setCarRoutingEnabled(enable.equals(Xml.TRUE));
2921            }
2922            if ((a = operations.getChild(Xml.ROUTER).getAttribute(Xml.CAR_ROUTING_VIA_YARDS)) != null) {
2923                String enable = a.getValue();
2924                log.debug("carRoutingViaYards: {}", enable);
2925                setCarRoutingViaYardsEnabled(enable.equals(Xml.TRUE));
2926            }
2927            if ((a = operations.getChild(Xml.ROUTER).getAttribute(Xml.CAR_ROUTING_VIA_STAGING)) != null) {
2928                String enable = a.getValue();
2929                log.debug("carRoutingViaStaging: {}", enable);
2930                setCarRoutingViaStagingEnabled(enable.equals(Xml.TRUE));
2931            }
2932            if ((a = operations.getChild(Xml.ROUTER).getAttribute(Xml.FORWARD_TO_YARD)) != null) {
2933                String enable = a.getValue();
2934                log.debug("forwardToYard: {}", enable);
2935                setForwardToYardEnabled(enable.equals(Xml.TRUE));
2936            }
2937            if ((a = operations.getChild(Xml.ROUTER).getAttribute(Xml.ONLY_ACTIVE_TRAINS)) != null) {
2938                String enable = a.getValue();
2939                log.debug("onlyActiveTrains: {}", enable);
2940                setOnlyActiveTrainsEnabled(enable.equals(Xml.TRUE));
2941            }
2942            if ((a = operations.getChild(Xml.ROUTER).getAttribute(Xml.CHECK_CAR_DESTINATION)) != null) {
2943                String enable = a.getValue();
2944                log.debug("checkCarDestination: {}", enable);
2945                setCheckCarDestinationEnabled(enable.equals(Xml.TRUE));
2946            }
2947        } else if (operations.getChild(Xml.SETTINGS) != null) {
2948            // the next four items are for backwards compatibility
2949            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.CAR_ROUTING_ENABLED)) != null) {
2950                String enable = a.getValue();
2951                log.debug("carRoutingEnabled: {}", enable);
2952                setCarRoutingEnabled(enable.equals(Xml.TRUE));
2953            }
2954            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.CAR_ROUTING_VIA_YARDS)) != null) {
2955                String enable = a.getValue();
2956                log.debug("carRoutingViaYards: {}", enable);
2957                setCarRoutingViaYardsEnabled(enable.equals(Xml.TRUE));
2958            }
2959            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.CAR_ROUTING_VIA_STAGING)) != null) {
2960                String enable = a.getValue();
2961                log.debug("carRoutingViaStaging: {}", enable);
2962                setCarRoutingViaStagingEnabled(enable.equals(Xml.TRUE));
2963            }
2964            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.FORWARD_TO_YARD)) != null) {
2965                String enable = a.getValue();
2966                log.debug("forwardToYard: {}", enable);
2967                setForwardToYardEnabled(enable.equals(Xml.TRUE));
2968            }
2969        }
2970
2971        if ((operations.getChild(Xml.OWNER) != null) &&
2972                (a = operations.getChild(Xml.OWNER).getAttribute(Xml.NAME)) != null) {
2973            String owner = a.getValue();
2974            log.debug("owner: {}", owner);
2975            setOwnerName(owner);
2976        }
2977        if (operations.getChild(Xml.ICON_COLOR) != null) {
2978            if ((a = operations.getChild(Xml.ICON_COLOR).getAttribute(Xml.NORTH)) != null) {
2979                String color = a.getValue();
2980                log.debug("north color: {}", color);
2981                setTrainIconColorNorth(color);
2982            }
2983            if ((a = operations.getChild(Xml.ICON_COLOR).getAttribute(Xml.SOUTH)) != null) {
2984                String color = a.getValue();
2985                log.debug("south color: {}", color);
2986                setTrainIconColorSouth(color);
2987            }
2988            if ((a = operations.getChild(Xml.ICON_COLOR).getAttribute(Xml.EAST)) != null) {
2989                String color = a.getValue();
2990                log.debug("east color: {}", color);
2991                setTrainIconColorEast(color);
2992            }
2993            if ((a = operations.getChild(Xml.ICON_COLOR).getAttribute(Xml.WEST)) != null) {
2994                String color = a.getValue();
2995                log.debug("west color: {}", color);
2996                setTrainIconColorWest(color);
2997            }
2998            if ((a = operations.getChild(Xml.ICON_COLOR).getAttribute(Xml.LOCAL)) != null) {
2999                String color = a.getValue();
3000                log.debug("local color: {}", color);
3001                setTrainIconColorLocal(color);
3002            }
3003            if ((a = operations.getChild(Xml.ICON_COLOR).getAttribute(Xml.TERMINATE)) != null) {
3004                String color = a.getValue();
3005                log.debug("terminate color: {}", color);
3006                setTrainIconColorTerminate(color);
3007            }
3008        }
3009        if (operations.getChild(Xml.COMMENTS) != null) {
3010            if ((a = operations.getChild(Xml.COMMENTS).getAttribute(Xml.MISPLACED_CARS)) != null) {
3011                String comment = a.getValue();
3012                log.debug("Misplaced comment: {}", comment);
3013                setMiaComment(comment);
3014            }
3015        }
3016
3017        if (operations.getChild(Xml.DISPLAY) != null) {
3018            if ((a = operations.getChild(Xml.DISPLAY).getAttribute(Xml.SHOW_TRACK_MOVES)) != null) {
3019                String enable = a.getValue();
3020                log.debug("show track moves: {}", enable);
3021                getDefault().showTrackMoves = enable.equals(Xml.TRUE);
3022            }
3023        }
3024
3025        if (operations.getChild(Xml.VSD) != null) {
3026            if ((a = operations.getChild(Xml.VSD).getAttribute(Xml.ENABLE_PHYSICAL_LOCATIONS)) != null) {
3027                String enable = a.getValue();
3028                setVsdPhysicalLocationEnabled(enable.equals(Xml.TRUE));
3029            }
3030        }
3031        if (operations.getChild(Xml.CATS) != null) {
3032            if ((a = operations.getChild(Xml.CATS).getAttribute(Xml.EXACT_LOCATION_NAME)) != null) {
3033                String enable = a.getValue();
3034                AbstractOperationsServer.setExactLocationName(enable.equals(Xml.TRUE));
3035            }
3036        }
3037
3038        if (operations.getChild(Xml.SETTINGS) != null) {
3039            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.AUTO_SAVE)) != null) {
3040                String enabled = a.getValue();
3041                log.debug("autoSave: {}", enabled);
3042                setAutoSaveEnabled(enabled.equals(Xml.TRUE));
3043            }
3044            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.AUTO_BACKUP)) != null) {
3045                String enabled = a.getValue();
3046                log.debug("autoBackup: {}", enabled);
3047                setAutoBackupEnabled(enabled.equals(Xml.TRUE));
3048            }
3049        }
3050
3051        if (operations.getChild(Xml.LOGGER) != null) {
3052            if ((a = operations.getChild(Xml.LOGGER).getAttribute(Xml.CAR_LOGGER)) != null) {
3053                String enable = a.getValue();
3054                log.debug("carLogger: {}", enable);
3055                getDefault().carLogger = enable.equals(Xml.TRUE);
3056            }
3057            if ((a = operations.getChild(Xml.LOGGER).getAttribute(Xml.ENGINE_LOGGER)) != null) {
3058                String enable = a.getValue();
3059                log.debug("engineLogger: {}", enable);
3060                getDefault().engineLogger = enable.equals(Xml.TRUE);
3061            }
3062            if ((a = operations.getChild(Xml.LOGGER).getAttribute(Xml.TRAIN_LOGGER)) != null) {
3063                String enable = a.getValue();
3064                log.debug("trainLogger: {}", enable);
3065                getDefault().trainLogger = enable.equals(Xml.TRUE);
3066            }
3067        } else if (operations.getChild(Xml.SETTINGS) != null) {
3068            // for backward compatibility
3069            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.CAR_LOGGER)) != null) {
3070                String enable = a.getValue();
3071                log.debug("carLogger: {}", enable);
3072                getDefault().carLogger = enable.equals(Xml.TRUE);
3073            }
3074            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.ENGINE_LOGGER)) != null) {
3075                String enable = a.getValue();
3076                log.debug("engineLogger: {}", enable);
3077                getDefault().engineLogger = enable.equals(Xml.TRUE);
3078            }
3079            if ((a = operations.getChild(Xml.SETTINGS).getAttribute(Xml.TRAIN_LOGGER)) != null) {
3080                String enable = a.getValue();
3081                log.debug("trainLogger: {}", enable);
3082                getDefault().trainLogger = enable.equals(Xml.TRUE);
3083            }
3084        }
3085    }
3086
3087    // replace old pickup and drop message keys
3088    // Change happened from 2.11.3 to 2.11.4
3089    // 4/16/2014
3090    private static void replaceOldFormat(String[] format) {
3091        for (int i = 0; i < format.length; i++) {
3092            if (format[i].equals("Pickup Msg")) // NOI18N
3093            {
3094                format[i] = PICKUP_COMMENT;
3095            } else if (format[i].equals("Drop Msg")) // NOI18N
3096            {
3097                format[i] = DROP_COMMENT;
3098            }
3099        }
3100    }
3101
3102    /**
3103     * Converts the xml key to the proper locale text
3104     *
3105     */
3106    private static void keyToStringConversion(String[] keys) {
3107        for (int i = 0; i < keys.length; i++) {
3108            if (keys[i].equals(BLANK)) {
3109                continue;
3110            }
3111            try {
3112                keys[i] = Bundle.getMessage(keys[i]);
3113            } catch (Exception e) {
3114                log.warn("Key {}: ({}) not found", i, keys[i]);
3115            }
3116        }
3117    }
3118
3119    /*
3120     * Converts the strings into English tags for xml storage
3121     *
3122     */
3123    public static void stringToTagConversion(String[] strings) {
3124        for (int i = 0; i < strings.length; i++) {
3125            if (strings[i].equals(BLANK)) {
3126                continue;
3127            }
3128            for (String key : KEYS) {
3129                if (strings[i].equals(Bundle.getMessage(key))) {
3130                    strings[i] = Bundle.getMessage(Locale.ROOT, key);
3131                    break;
3132                }
3133            }
3134            // log.debug("Converted {} to {}", old, strings[i]);
3135        }
3136    }
3137
3138    /*
3139     * The xml attributes stored using the English translation. This converts the
3140     * attribute to the appropriate key for language conversion.
3141     */
3142    private static void xmlAttributeToKeyConversion(String[] format) {
3143        for (int i = 0; i < format.length; i++) {
3144            for (String key : KEYS) {
3145                if (format[i].equals(Bundle.getMessage(Locale.ROOT, key))) {
3146                    format[i] = key;
3147                }
3148            }
3149        }
3150    }
3151
3152    protected static void setDirtyAndFirePropertyChange(String p, Object old, Object n) {
3153        InstanceManager.getDefault(OperationsSetupXml.class).setDirty(true);
3154        getDefault().firePropertyChange(p, old, n);
3155    }
3156
3157    public static Setup getDefault() {
3158        return InstanceManager.getDefault(Setup.class);
3159    }
3160
3161    private static final Logger log = LoggerFactory.getLogger(Setup.class);
3162
3163    @Override
3164    public void dispose() {
3165        AutoSave.stop();
3166    }
3167
3168}