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
114            // store car attributes
115            for (Car car : _carList) {
116                fileOut.printRecord(car.getNumber(),
117                        car.getRoadName(),
118                        car.getTypeName(),
119                        car.getLength(),
120                        car.getWeight(),
121                        car.getColor(),
122                        car.getOwnerName(),
123                        car.getBuilt(),
124                        car.getLocationName(),
125                        LOCATION_TRACK_SEPARATOR,
126                        car.getTrackName(),
127                        car.getLoadName(),
128                        car.getKernelName(),
129                        car.getMoves(),
130                        car.getValue(),
131                        car.getComment(),
132                        car.isOutOfService() ? Bundle.getMessage("OutOfService") : "",
133                        car.getTypeExtensions(),
134                        car.getWait(),
135                        car.getPickupScheduleName(),
136                        car.getSortDate(),
137                        car.getReturnWhenEmptyDestinationName(),
138                        LOCATION_TRACK_SEPARATOR,
139                        car.getReturnWhenEmptyDestTrackName(),
140                        car.getReturnWhenEmptyLoadName(),
141                        car.getReturnWhenLoadedDestinationName(),
142                        LOCATION_TRACK_SEPARATOR,
143                        car.getReturnWhenLoadedDestTrackName(),
144                        car.getReturnWhenLoadedLoadName(),
145                        car.getDivisionName(),
146                        car.getTrainName(),
147                        car.getDestinationName(),
148                        LOCATION_TRACK_SEPARATOR,
149                        car.getDestinationTrackName(),
150                        car.getFinalDestinationName(),
151                        LOCATION_TRACK_SEPARATOR,
152                        car.getFinalDestinationTrackName(),
153                        car.getScheduleItemId(),
154                        car.getRfid());
155            }
156            fileOut.flush();
157            fileOut.close();
158            log.info("Exported {} cars to file {}", _carList.size(), defaultOperationsFilename());
159            JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("ExportedCarsToFile",
160                _carList.size(), defaultOperationsFilename()), Bundle.getMessage("ExportComplete"),
161                    JmriJOptionPane.INFORMATION_MESSAGE);
162        } catch (IOException e) {
163            log.error("Can not open export cars CSV file: {}", e.getLocalizedMessage());
164            JmriJOptionPane.showMessageDialog(null,
165                    Bundle.getMessage("ExportedCarsToFile",
166                            0, defaultOperationsFilename()),
167                    Bundle.getMessage("ExportFailed"), JmriJOptionPane.ERROR_MESSAGE);
168        }
169    }
170
171    // Operation files always use the same directory
172    public static String defaultOperationsFilename() {
173        return OperationsSetupXml.getFileLocation()
174                + OperationsSetupXml.getOperationsDirectoryName()
175                + File.separator
176                + getOperationsFileName();
177    }
178
179    public static void setOperationsFileName(String name) {
180        operationsFileName = name;
181    }
182
183    public static String getOperationsFileName() {
184        return operationsFileName;
185    }
186
187    private static String operationsFileName = "ExportOperationsCarRoster.csv"; // NOI18N
188
189    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ExportCars.class);
190
191}