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