001package jmri.jmrit.operations.routes.tools;
002
003import java.io.BufferedReader;
004import java.io.File;
005
006import jmri.InstanceManager;
007import jmri.jmrit.operations.locations.Location;
008import jmri.jmrit.operations.locations.LocationManager;
009import jmri.jmrit.operations.rollingstock.ImportCommon;
010import jmri.jmrit.operations.routes.*;
011import jmri.jmrit.operations.setup.Setup;
012import jmri.util.ThreadingUtil;
013import jmri.util.swing.JmriJOptionPane;
014
015/**
016 * This routine will import Routes from a CSV file into the operations database.
017 * The field order is as defined below.
018 * 
019 * @author Daniel Boudreau Copyright (C) 2025
020 */
021public class ImportRoutes extends ImportCommon {
022
023    RouteManager routeManager = InstanceManager.getDefault(RouteManager.class);
024    LocationManager locationManager = InstanceManager.getDefault(LocationManager.class);
025
026    int routesAdded = 0;
027
028    // each route starts with name and comment
029    protected static final int FIELD_ROUTE_NAME = 0;
030    protected static final int FIELD_EMPTY = 1;
031    protected static final int FIELD_ROUTE_COMMENT = 2;
032
033    // each route can have one or more route locations
034    protected static final int FIELD_ROUTE_LOCATION_EMPTY = 0;
035    protected static final int FIELD_ROUTE_LOCATION_NAME = 1;
036    protected static final int FIELD_ROUTE_LOCATION_DIRECTION = 2;
037    protected static final int FIELD_ROUTE_LOCATION_MOVES = 3;
038    protected static final int FIELD_ROUTE_LOCATION_RANDOM = 4;
039    protected static final int FIELD_ROUTE_LOCATION_PICKUP_ALLOWED = 5;
040    protected static final int FIELD_ROUTE_LOCATION_DROP_ALLOWED = 6;
041    protected static final int FIELD_ROUTE_LOCATION_TRAVEL = 7;
042    protected static final int FIELD_ROUTE_LOCATION_DEPARTURE_TIME = 8;
043    protected static final int FIELD_ROUTE_LOCATION_TRAIN_LENGTH = 9;
044    protected static final int FIELD_ROUTE_LOCATION_GRADE = 10;
045    protected static final int FIELD_ROUTE_LOCATION_ICON_X = 11;
046    protected static final int FIELD_ROUTE_LOCATION_ICON_Y = 12;
047    protected static final int FIELD_ROUTE_LOCATION_COMMENT = 13;
048    protected static final int FIELD_ROUTE_LOCATION_COMMENT_COLOR = 14;
049
050    @Override
051    public void run() {
052        File file = getFile();
053        if (file == null) {
054            return;
055        }
056        BufferedReader rdr = getBufferedReader(file);
057        if (rdr == null) {
058            return;
059        }
060        createStatusFrame(Bundle.getMessage("TitleImportRoutes"));
061
062        String[] inputLine;
063        boolean headerFound = false;
064        Route route = null;
065
066        while (true) {
067            inputLine = readNextLine(rdr);
068            if (inputLine == BREAK) {
069                log.debug("Done");
070                break;
071            }
072            if (inputLine.length < 1) {
073                log.debug("Skipping blank line");
074                continue;
075            }
076            // header?
077            if (!headerFound && inputLine[FIELD_ROUTE_NAME].equals(Bundle.getMessage("Route"))) {
078                headerFound = true;
079                int elementNum = 0;
080                for (String lineElement : inputLine) {
081                    log.debug("Header {} is: {}", elementNum++, lineElement);
082                }
083                continue; // skip header
084            }
085            // add route?
086            if (inputLine.length == 3) {
087                log.debug("Found start of route: {}", inputLine[FIELD_ROUTE_NAME]);
088                route = routeManager.getRouteByName(inputLine[FIELD_ROUTE_NAME]);
089                if (route != null) {
090                    log.info("Route: {} already exists, will not import!", inputLine[FIELD_ROUTE_NAME]);
091                    route = null;
092                } else {
093                    routesAdded++;
094                    route = routeManager.newRoute(inputLine[FIELD_ROUTE_NAME]);
095                    log.info("Creating route: {}", inputLine[FIELD_ROUTE_NAME]);
096                    route.setComment(inputLine[FIELD_ROUTE_COMMENT]);
097                }
098            }
099            // add route location?
100            if (route != null && inputLine.length == 15) {
101                log.debug("Adding route location: {}", inputLine[FIELD_ROUTE_LOCATION_NAME]);
102                Location location = locationManager.getLocationByName(inputLine[FIELD_ROUTE_LOCATION_NAME]);
103                if (location == null) {
104                    log.error("Location ({}) in route ({}) does not exist", inputLine[FIELD_ROUTE_LOCATION_NAME],
105                            route.getName());
106                    break;
107                }
108                RouteLocation rl = route.addLocation(location);
109                rl.setTrainDirection(Setup.getDirectionInt(inputLine[FIELD_ROUTE_LOCATION_DIRECTION]));
110                rl.setMaxCarMoves(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_MOVES]));
111                rl.setRandomControl(inputLine[FIELD_ROUTE_LOCATION_RANDOM]);
112                rl.setPickUpAllowed(inputLine[FIELD_ROUTE_LOCATION_PICKUP_ALLOWED].equals(Bundle.getMessage("yes")));
113                rl.setDropAllowed(inputLine[FIELD_ROUTE_LOCATION_DROP_ALLOWED].equals(Bundle.getMessage("yes")));
114                rl.setWait(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_TRAVEL]) - Setup.getTravelTime());
115                rl.setDepartureTime(inputLine[FIELD_ROUTE_LOCATION_DEPARTURE_TIME]);
116                rl.setMaxTrainLength(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_TRAIN_LENGTH]));
117                rl.setGrade(Double.parseDouble(inputLine[FIELD_ROUTE_LOCATION_GRADE]));
118                rl.setTrainIconX(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_ICON_X]));
119                rl.setTrainIconY(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_ICON_Y]));
120                rl.setComment(inputLine[FIELD_ROUTE_LOCATION_COMMENT]);
121                rl.setCommentTextColor(inputLine[FIELD_ROUTE_LOCATION_COMMENT_COLOR]);
122            }
123        }
124
125        ThreadingUtil.runOnGUI(()->{
126            if (importOkay) {
127                JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("ImportRoutesAdded", routesAdded),
128                        Bundle.getMessage("SuccessfulImport"), JmriJOptionPane.INFORMATION_MESSAGE);
129            } else {
130                JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("ImportRoutesAdded", routesAdded),
131                        Bundle.getMessage("ImportFailed"), JmriJOptionPane.ERROR_MESSAGE);
132            }
133        });
134        fstatus.dispose();
135    }
136
137    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ImportRoutes.class);
138}