001package jmri.jmrit.operations.rollingstock.cars.tools;
002
003import java.io.*;
004import java.nio.charset.StandardCharsets;
005import java.util.List;
006
007import org.apache.commons.csv.CSVFormat;
008import org.apache.commons.csv.CSVPrinter;
009
010import jmri.jmrit.XmlFile;
011import jmri.jmrit.operations.rollingstock.cars.Car;
012import jmri.jmrit.operations.setup.OperationsSetupXml;
013import jmri.jmrit.operations.setup.Setup;
014import jmri.util.swing.JmriJOptionPane;
015
016/**
017 * Exports the car roster into a comma delimited file (CSV).
018 *
019 * @author Daniel Boudreau Copyright (C) 2010, 2011, 2016, 2024
020 */
021public class ExportCars extends XmlFile {
022
023    protected static final String LOCATION_TRACK_SEPARATOR = "-";
024    List<Car> _carList;
025
026    public ExportCars(List<Car> carList) {
027        _carList = carList;
028    }
029
030    /**
031     * Create CSV file based on the car list.
032     */
033    public void writeOperationsCarFile() {
034        makeBackupFile(defaultOperationsFilename());
035        try {
036            if (!checkFile(defaultOperationsFilename())) {
037                // The file does not exist, create it before writing
038                java.io.File file = new java.io.File(defaultOperationsFilename());
039                java.io.File parentDir = file.getParentFile();
040                if (!parentDir.exists()) {
041                    if (!parentDir.mkdir()) {
042                        log.error("Directory wasn't created");
043                    }
044                }
045                if (file.createNewFile()) {
046                    log.debug("File created");
047                }
048            }
049            writeFile(defaultOperationsFilename());
050        } catch (IOException e) {
051            log.error("Exception while writing the new CSV operations file, may not be complete: {}",
052                    e.getLocalizedMessage());
053        }
054    }
055
056    /**
057     * Any changes to the column order should also be made to the ImportCars.java
058     * file.
059     *
060     * @param name file name
061     */
062    private void writeFile(String name) {
063        log.debug("writeFile {}", name);
064        // This is taken in large part from "Java and XML" page 368
065        File file = findFile(name);
066        if (file == null) {
067            file = new File(name);
068        }
069
070        try (CSVPrinter fileOut = new CSVPrinter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)),
071                CSVFormat.DEFAULT)) {
072
073            // create header
074            fileOut.printRecord(Bundle.getMessage("Number"),
075                    Bundle.getMessage("Road"),
076                    Bundle.getMessage("Type"),
077                    Bundle.getMessage("Length"),
078                    Bundle.getMessage("Weight"),
079                    Bundle.getMessage("Color"),
080                    Bundle.getMessage("Owner"),
081                    Bundle.getMessage("Built"),
082                    Bundle.getMessage("Location"),
083                    LOCATION_TRACK_SEPARATOR,
084                    Bundle.getMessage("Track"),
085                    Bundle.getMessage("Load"),
086                    Bundle.getMessage("Kernel"),
087                    Bundle.getMessage("Moves"),
088                    Setup.getValueLabel(),
089                    Bundle.getMessage("Comment"),
090                    Bundle.getMessage("Miscellaneous"),
091                    Bundle.getMessage("Extensions"),
092                    Bundle.getMessage("Wait"),
093                    Bundle.getMessage("Pickup"),
094                    Bundle.getMessage("Last"),
095                    Bundle.getMessage("RWELocation"),
096                    LOCATION_TRACK_SEPARATOR,
097                    Bundle.getMessage("Track"),
098                    Bundle.getMessage("RWELoad"),
099                    Bundle.getMessage("RWLLocation"),
100                    LOCATION_TRACK_SEPARATOR,
101                    Bundle.getMessage("Track"),
102                    Bundle.getMessage("RWLLoad"),
103                    Bundle.getMessage("Division"),
104                    Bundle.getMessage("Train"),
105                    Bundle.getMessage("Destination"),
106                    LOCATION_TRACK_SEPARATOR,
107                    Bundle.getMessage("Track"),
108                    Bundle.getMessage("FinalDestination"),
109                    LOCATION_TRACK_SEPARATOR,
110                    Bundle.getMessage("Track"),
111                    Bundle.getMessage("SchId"),
112                    Bundle.getMessage("RFID_Tag"),
113                    Bundle.getMessage("Route"));
114
115            // store car attributes
116            for (Car car : _carList) {
117                fileOut.printRecord(car.getNumber(),
118                        car.getRoadName(),
119                        car.getTypeName(),
120                        car.getLength(),
121                        car.getWeight(),
122                        car.getColor(),
123                        car.getOwnerName(),
124                        car.getBuilt(),
125                        car.getLocationName(),
126                        LOCATION_TRACK_SEPARATOR,
127                        car.getTrackName(),
128                        car.getLoadName(),
129                        car.getKernelName(),
130                        car.getMoves(),
131                        car.getValue(),
132                        car.getComment(),
133                        car.isOutOfService() ? Bundle.getMessage("OutOfService") : "",
134                        car.getTypeExtensions(),
135                        car.getWait(),
136                        car.getPickupScheduleName(),
137                        car.getSortDate(),
138                        car.getReturnWhenEmptyDestinationName(),
139                        LOCATION_TRACK_SEPARATOR,
140                        car.getReturnWhenEmptyDestTrackName(),
141                        car.getReturnWhenEmptyLoadName(),
142                        car.getReturnWhenLoadedDestinationName(),
143                        LOCATION_TRACK_SEPARATOR,
144                        car.getReturnWhenLoadedDestTrackName(),
145                        car.getReturnWhenLoadedLoadName(),
146                        car.getDivisionName(),
147                        car.getTrainName(),
148                        car.getDestinationName(),
149                        LOCATION_TRACK_SEPARATOR,
150                        car.getDestinationTrackName(),
151                        car.getFinalDestinationName(),
152                        LOCATION_TRACK_SEPARATOR,
153                        car.getFinalDestinationTrackName(),
154                        car.getScheduleItemId(),
155                        car.getRfid(),
156                        car.getRoutePath());
157            }
158            fileOut.flush();
159            fileOut.close();
160            log.info("Exported {} cars to file {}", _carList.size(), defaultOperationsFilename());
161            JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("ExportedCarsToFile",
162                _carList.size(), defaultOperationsFilename()), Bundle.getMessage("ExportComplete"),
163                    JmriJOptionPane.INFORMATION_MESSAGE);
164        } catch (IOException e) {
165            log.error("Can not open export cars CSV file: {}", e.getLocalizedMessage());
166            JmriJOptionPane.showMessageDialog(null,
167                    Bundle.getMessage("ExportedCarsToFile",
168                            0, defaultOperationsFilename()),
169                    Bundle.getMessage("ExportFailed"), JmriJOptionPane.ERROR_MESSAGE);
170        }
171    }
172
173    // Operation files always use the same directory
174    public static String defaultOperationsFilename() {
175        return OperationsSetupXml.getFileLocation()
176                + OperationsSetupXml.getOperationsDirectoryName()
177                + File.separator
178                + getOperationsFileName();
179    }
180
181    public static void setOperationsFileName(String name) {
182        operationsFileName = name;
183    }
184
185    public static String getOperationsFileName() {
186        return operationsFileName;
187    }
188
189    private static String operationsFileName = "ExportOperationsCarRoster.csv"; // NOI18N
190
191    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ExportCars.class);
192
193}