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_LOCAL_MOVES_ALLOWED = 7;
042    protected static final int FIELD_ROUTE_LOCATION_TRAVEL = 8;
043    protected static final int FIELD_ROUTE_LOCATION_DEPARTURE_TIME = 9;
044    protected static final int FIELD_ROUTE_LOCATION_TRAIN_LENGTH = 10;
045    protected static final int FIELD_ROUTE_LOCATION_GRADE = 11;
046    protected static final int FIELD_ROUTE_LOCATION_ICON_X = 12;
047    protected static final int FIELD_ROUTE_LOCATION_ICON_Y = 13;
048    protected static final int FIELD_ROUTE_LOCATION_COMMENT = 14;
049    protected static final int FIELD_ROUTE_LOCATION_COMMENT_COLOR = 15;
050
051    @Override
052    public void run() {
053        File file = getFile();
054        if (file == null) {
055            return;
056        }
057        BufferedReader rdr = getBufferedReader(file);
058        if (rdr == null) {
059            return;
060        }
061        createStatusFrame(Bundle.getMessage("TitleImportRoutes"));
062
063        String[] inputLine;
064        boolean headerFound = false;
065        Route route = null;
066
067        while (true) {
068            inputLine = readNextLine(rdr);
069            if (inputLine == BREAK) {
070                log.debug("Done");
071                break;
072            }
073            if (inputLine.length < 1) {
074                log.debug("Skipping blank line");
075                continue;
076            }
077            // header?
078            if (!headerFound && inputLine[FIELD_ROUTE_NAME].equals(Bundle.getMessage("Route"))) {
079                headerFound = true;
080                int elementNum = 0;
081                for (String lineElement : inputLine) {
082                    log.debug("Header {} is: {}", elementNum++, lineElement);
083                }
084                continue; // skip header
085            }
086            // add route?
087            if (inputLine.length == 3) {
088                log.debug("Found start of route: {}", inputLine[FIELD_ROUTE_NAME]);
089                route = routeManager.getRouteByName(inputLine[FIELD_ROUTE_NAME]);
090                if (route != null) {
091                    log.info("Route: {} already exists, will not import!", inputLine[FIELD_ROUTE_NAME]);
092                    route = null;
093                } else {
094                    routesAdded++;
095                    route = routeManager.newRoute(inputLine[FIELD_ROUTE_NAME]);
096                    log.info("Creating route: {}", inputLine[FIELD_ROUTE_NAME]);
097                    route.setComment(inputLine[FIELD_ROUTE_COMMENT]);
098                }
099            }
100            // add route location?
101            if (route != null && inputLine.length == 16) {
102                log.debug("Adding route location: {}", inputLine[FIELD_ROUTE_LOCATION_NAME]);
103                Location location = locationManager.getLocationByName(inputLine[FIELD_ROUTE_LOCATION_NAME]);
104                if (location == null) {
105                    log.error("Location ({}) in route ({}) does not exist", inputLine[FIELD_ROUTE_LOCATION_NAME],
106                            route.getName());
107                    break;
108                }
109                RouteLocation rl = route.addLocation(location);
110                rl.setTrainDirection(Setup.getDirectionInt(inputLine[FIELD_ROUTE_LOCATION_DIRECTION]));
111                rl.setMaxCarMoves(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_MOVES]));
112                rl.setRandomControl(inputLine[FIELD_ROUTE_LOCATION_RANDOM]);
113                rl.setPickUpAllowed(inputLine[FIELD_ROUTE_LOCATION_PICKUP_ALLOWED].equals(Bundle.getMessage("yes")));
114                rl.setDropAllowed(inputLine[FIELD_ROUTE_LOCATION_DROP_ALLOWED].equals(Bundle.getMessage("yes")));
115                rl.setLocalMovesAllowed(
116                        inputLine[FIELD_ROUTE_LOCATION_LOCAL_MOVES_ALLOWED].equals(Bundle.getMessage("yes")));
117                rl.setWait(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_TRAVEL]) - Setup.getTravelTime());
118                rl.setDepartureTime(inputLine[FIELD_ROUTE_LOCATION_DEPARTURE_TIME]);
119                rl.setMaxTrainLength(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_TRAIN_LENGTH]));
120                rl.setGrade(Double.parseDouble(inputLine[FIELD_ROUTE_LOCATION_GRADE]));
121                rl.setTrainIconX(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_ICON_X]));
122                rl.setTrainIconY(Integer.parseInt(inputLine[FIELD_ROUTE_LOCATION_ICON_Y]));
123                rl.setComment(inputLine[FIELD_ROUTE_LOCATION_COMMENT]);
124                rl.setCommentTextColor(inputLine[FIELD_ROUTE_LOCATION_COMMENT_COLOR]);
125            }
126        }
127
128        ThreadingUtil.runOnGUI(()->{
129            if (importOkay) {
130                JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("ImportRoutesAdded", routesAdded),
131                        Bundle.getMessage("SuccessfulImport"), JmriJOptionPane.INFORMATION_MESSAGE);
132            } else {
133                JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("ImportRoutesAdded", routesAdded),
134                        Bundle.getMessage("ImportFailed"), JmriJOptionPane.ERROR_MESSAGE);
135            }
136        });
137        fstatus.dispose();
138    }
139
140    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ImportRoutes.class);
141}