001package jmri.jmrit.operations.trains.tools; 002 003import java.io.*; 004import java.nio.charset.StandardCharsets; 005import java.util.ArrayList; 006import java.util.Arrays; 007 008import org.apache.commons.csv.CSVFormat; 009import org.apache.commons.csv.CSVPrinter; 010 011import jmri.InstanceManager; 012import jmri.jmrit.XmlFile; 013import jmri.jmrit.operations.setup.OperationsSetupXml; 014import jmri.jmrit.operations.trains.Train; 015import jmri.jmrit.operations.trains.TrainManager; 016import jmri.jmrit.operations.trains.trainbuilder.TrainCommon; 017import jmri.util.swing.JmriJOptionPane; 018 019/** 020 * Exports the train roster into a comma delimited file (CSV). Only trains that 021 * have the "Build" checkbox selected are exported. If a train is built, a 022 * summary of the train's route and work is provided. 023 * 024 * @author Daniel Boudreau Copyright (C) 2010, 2011, 2019 025 * 026 */ 027public class ExportTrains extends XmlFile { 028 029 public ExportTrains(){ 030 // nothing to do 031 } 032 033 public void writeOperationsTrainsFile() { 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 public void writeFile(String name) { 057 log.debug("writeFile {}", name); 058 // This is taken in large part from "Java and XML" page 368 059 File file = findFile(name); 060 if (file == null) { 061 file = new File(name); 062 } 063 064 try (CSVPrinter fileOut = new CSVPrinter( 065 new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)), 066 CSVFormat.DEFAULT)) { 067 068 // create header 069 fileOut.printRecord(Bundle.getMessage("Name"), Bundle.getMessage("Description"), Bundle.getMessage("Time"), 070 Bundle.getMessage("Done"), 071 Bundle.getMessage("Route"), Bundle.getMessage("Departs"), Bundle.getMessage("Terminates"), 072 Bundle.getMessage("Status"), Bundle.getMessage("Comment"), Bundle.getMessage("LocoTypes"), 073 Bundle.getMessage("CarTypes"), Bundle.getMessage("RoadOption"), Bundle.getMessage("RoadsCar"), 074 Bundle.getMessage("RoadOption"), Bundle.getMessage("RoadsCaboose"), Bundle.getMessage("RoadOption"), 075 Bundle.getMessage("RoadsLoco"), 076 Bundle.getMessage("LoadOption"), Bundle.getMessage("Loads"), Bundle.getMessage("OwnerOption"), 077 Bundle.getMessage("Owners"), Bundle.getMessage("Built"), 078 Bundle.getMessage("NormalModeWhenBuilding"), Bundle.getMessage("AllowCarsToReturn"), 079 Bundle.getMessage("AllowThroughCars"), Bundle.getMessage("SendCustomToStaging"), 080 Bundle.getMessage("SendToTerminal", ""), 081 Bundle.getMessage("AllowLocalMoves"), Bundle.getMessage("ServiceAllCars"), 082 Bundle.getMessage("BuildConsist")); 083 084 int count = 0; 085 086 for (Train train : InstanceManager.getDefault(TrainManager.class).getTrainsByTimeList()) { 087 if (!train.isBuildEnabled()) { 088 continue; 089 } 090 count++; 091 String routeName = ""; 092 if (train.getRoute() != null) { 093 routeName = train.getRoute().getName(); 094 } 095 fileOut.printRecord(train.getName(), train.getDescription(), train.getDepartureTime(), 096 train.getExpectedDepartureTime(train.getTrainTerminatesRouteLocation(), true), routeName, 097 train.getTrainDepartsName(), train.getTrainTerminatesName(), train.getStatus(), 098 train.getComment(), TrainCommon.formatStringToCommaSeparated(train.getLocoTypeNames()), 099 TrainCommon.formatStringToCommaSeparated(train.getCarTypeNames()), getCarRoadOption(train), 100 getCarRoads(train), getCabooseRoadOption(train), getCabooseRoads(train), 101 getLocoRoadOption(train), getLocoRoads(train), getLoadOption(train), 102 getLoads(train), getOwnerOption(train), getOwners(train), getBuilt(train), 103 train.isBuildTrainNormalEnabled() ? Bundle.getMessage("ButtonYes") : "", 104 train.isAllowReturnToStagingEnabled() ? Bundle.getMessage("ButtonYes") : "", 105 train.isAllowThroughCarsEnabled() ? Bundle.getMessage("ButtonYes") : "", 106 train.isSendCarsWithCustomLoadsToStagingEnabled() ? Bundle.getMessage("ButtonYes") : "", 107 train.isSendCarsToTerminalEnabled() ? Bundle.getMessage("ButtonYes") : "", 108 train.isAllowLocalMovesEnabled() ? Bundle.getMessage("ButtonYes") : "", 109 train.isServiceAllCarsWithFinalDestinationsEnabled() ? Bundle.getMessage("ButtonYes") : "", 110 train.isBuildConsistEnabled() ? Bundle.getMessage("ButtonYes") : ""); 111 } 112 113 fileOut.println(); 114 // second create header for built trains 115 fileOut.printRecord(Bundle.getMessage("Name"), Bundle.getMessage("csvParameters"), 116 Bundle.getMessage("Attributes")); 117 118 for (Train train : InstanceManager.getDefault(TrainManager.class).getTrainsByTimeList()) { 119 if (!train.isBuildEnabled()) { 120 continue; 121 } 122 123 if (train.isBuilt() && train.getRoute() != null) { 124 ArrayList<Object> line = new ArrayList<>(); 125 line.addAll(Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("Route") })); 126 train.getRoute().getLocationsBySequenceList().forEach(rl -> line.add(rl.getName())); 127 fileOut.printRecord(line); 128 129 line.clear(); 130 line.addAll(Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("csvArrivalTime") })); 131 train.getRoute().getLocationsBySequenceList() 132 .forEach(rl -> line.add(train.getExpectedArrivalTime(rl))); 133 fileOut.printRecord(line); 134 135 line.clear(); 136 line.addAll(Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("csvDepartureTime") })); 137 train.getRoute().getLocationsBySequenceList() 138 .forEach(rl -> line.add(train.getExpectedDepartureTime(rl))); 139 fileOut.printRecord(line); 140 141 line.clear(); 142 line.addAll( 143 Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("csvTrainDirection") })); 144 train.getRoute().getLocationsBySequenceList().forEach(rl -> line.add(rl.getTrainDirectionString())); 145 fileOut.printRecord(line); 146 147 line.clear(); 148 line.addAll(Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("csvTrainWeight") })); 149 train.getRoute().getLocationsBySequenceList().forEach(rl -> line.add(train.getTrainWeight(rl))); 150 fileOut.printRecord(line); 151 152 line.clear(); 153 line.addAll(Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("csvTrainLength") })); 154 train.getRoute().getLocationsBySequenceList().forEach(rl -> line.add(train.getTrainLength(rl))); 155 fileOut.printRecord(line); 156 157 line.clear(); 158 line.addAll(Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("Engine") })); 159 train.getRoute().getLocationsBySequenceList().forEach(rl -> line.add(train.getLeadEngine(rl))); 160 fileOut.printRecord(line); 161 162 line.clear(); 163 line.addAll(Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("Cars") })); 164 train.getRoute().getLocationsBySequenceList() 165 .forEach(rl -> line.add(train.getNumberCarsInTrain(rl))); 166 fileOut.printRecord(line); 167 168 line.clear(); 169 line.addAll(Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("csvEmpties") })); 170 train.getRoute().getLocationsBySequenceList() 171 .forEach(rl -> line.add(train.getNumberEmptyCarsInTrain(rl))); 172 fileOut.printRecord(line); 173 174 line.clear(); 175 line.addAll(Arrays.asList(new Object[] { train.getName(), Bundle.getMessage("Loads") })); 176 train.getRoute().getLocationsBySequenceList() 177 .forEach(rl -> line.add(train.getNumberLoadedCarsInTrain(rl))); 178 fileOut.printRecord(line); 179 180 fileOut.println(); 181 } 182 } 183 184 log.info("Exported {} trains to file {}", count, defaultOperationsFilename()); 185 JmriJOptionPane.showMessageDialog(null, 186 Bundle.getMessage("ExportedTrainsToFile", 187 count, defaultOperationsFilename()), 188 Bundle.getMessage("ExportComplete"), JmriJOptionPane.INFORMATION_MESSAGE); 189 } catch (IOException e) { 190 log.error("Can not open export trains CSV file: {}", e.getLocalizedMessage()); 191 JmriJOptionPane.showMessageDialog(null, 192 Bundle.getMessage("ExportedTrainsToFile", 193 0, defaultOperationsFilename()), 194 Bundle.getMessage("ExportFailed"), JmriJOptionPane.ERROR_MESSAGE); 195 } 196 } 197 198 private String getCarRoadOption(Train train) { 199 String roadOption = Bundle.getMessage("AcceptAll"); 200 if (train.getCarRoadOption().equals(Train.INCLUDE_ROADS)) { 201 roadOption = Bundle.getMessage( 202 "AcceptOnly") + " " + train.getCarRoadNames().length + " " + Bundle.getMessage("Roads"); 203 } else if (train.getCarRoadOption().equals(Train.EXCLUDE_ROADS)) { 204 roadOption = Bundle.getMessage( 205 "Exclude") + " " + train.getCarRoadNames().length + " " + Bundle.getMessage("Roads"); 206 } 207 return roadOption; 208 } 209 210 private String getCarRoads(Train train) { 211 if (train.getCarRoadOption().equals(Train.ALL_ROADS)) { 212 return ""; 213 } else { 214 return TrainCommon.formatStringToCommaSeparated(train.getCarRoadNames()); 215 } 216 } 217 218 private String getCabooseRoadOption(Train train) { 219 String roadOption = Bundle.getMessage("AcceptAll"); 220 if (train.getCabooseRoadOption().equals(Train.INCLUDE_ROADS)) { 221 roadOption = Bundle.getMessage( 222 "AcceptOnly") + " " + train.getCabooseRoadNames().length + " " + Bundle.getMessage("Roads"); 223 } else if (train.getCabooseRoadOption().equals(Train.EXCLUDE_ROADS)) { 224 roadOption = Bundle.getMessage( 225 "Exclude") + " " + train.getCabooseRoadNames().length + " " + Bundle.getMessage("Roads"); 226 } 227 return roadOption; 228 } 229 230 private String getCabooseRoads(Train train) { 231 if (train.getCabooseRoadOption().equals(Train.ALL_ROADS)) { 232 return ""; 233 } else { 234 return TrainCommon.formatStringToCommaSeparated(train.getCabooseRoadNames()); 235 } 236 } 237 238 private String getLocoRoadOption(Train train) { 239 String roadOption = Bundle.getMessage("AcceptAll"); 240 if (train.getLocoRoadOption().equals(Train.INCLUDE_ROADS)) { 241 roadOption = Bundle.getMessage( 242 "AcceptOnly") + " " + train.getLocoRoadNames().length + " " + Bundle.getMessage("Roads"); 243 } else if (train.getLocoRoadOption().equals(Train.EXCLUDE_ROADS)) { 244 roadOption = Bundle.getMessage( 245 "Exclude") + " " + train.getLocoRoadNames().length + " " + Bundle.getMessage("Roads"); 246 } 247 return roadOption; 248 } 249 250 private String getLocoRoads(Train train) { 251 if (train.getLocoRoadOption().equals(Train.ALL_ROADS)) { 252 return ""; 253 } else { 254 return TrainCommon.formatStringToCommaSeparated(train.getLocoRoadNames()); 255 } 256 } 257 258 private String getLoadOption(Train train) { 259 String loadOption = Bundle.getMessage("AcceptAll"); 260 if (train.getLoadOption().equals(Train.INCLUDE_LOADS)) { 261 loadOption = Bundle.getMessage( 262 "AcceptOnly") + " " + train.getLoadNames().length + " " + Bundle.getMessage("Loads"); 263 } else if (train.getLoadOption().equals(Train.EXCLUDE_LOADS)) { 264 loadOption = Bundle.getMessage( 265 "Exclude") + " " + train.getLoadNames().length + " " + Bundle.getMessage("Loads"); 266 } 267 return loadOption; 268 } 269 270 private String getLoads(Train train) { 271 if (train.getLoadOption().equals(Train.ALL_LOADS)) { 272 return ""; 273 } else { 274 return TrainCommon.formatStringToCommaSeparated(train.getLoadNames()); 275 } 276 } 277 278 private String getOwnerOption(Train train) { 279 String ownerOption = Bundle.getMessage("AcceptAll"); 280 if (train.getOwnerOption().equals(Train.INCLUDE_OWNERS)) { 281 ownerOption = Bundle.getMessage( 282 "AcceptOnly") + " " + train.getOwnerNames().length + " " + Bundle.getMessage("Owners"); 283 } else if (train.getOwnerOption().equals(Train.EXCLUDE_OWNERS)) { 284 ownerOption = Bundle.getMessage( 285 "Exclude") + " " + train.getOwnerNames().length + " " + Bundle.getMessage("Owners"); 286 } 287 return ownerOption; 288 } 289 290 private String getOwners(Train train) { 291 if (train.getOwnerOption().equals(Train.ALL_OWNERS)) { 292 return ""; 293 } else { 294 return TrainCommon.formatStringToCommaSeparated(train.getOwnerNames()); 295 } 296 } 297 298 private String getBuilt(Train train) { 299 if (!train.getBuiltStartYear().equals(Train.NONE) && train.getBuiltEndYear().equals(Train.NONE)) { 300 return Bundle.getMessage("After") + " " + train.getBuiltStartYear(); 301 } 302 if (train.getBuiltStartYear().equals(Train.NONE) && !train.getBuiltEndYear().equals(Train.NONE)) { 303 return Bundle.getMessage("Before") + " " + train.getBuiltEndYear(); 304 } 305 if (!train.getBuiltStartYear().equals(Train.NONE) && !train.getBuiltEndYear().equals(Train.NONE)) { 306 return Bundle.getMessage("Range") + " " + train.getBuiltStartYear() + ":" + train.getBuiltEndYear(); 307 } 308 return ""; 309 } 310 311 // Operation files always use the same directory 312 public static String defaultOperationsFilename() { 313 return OperationsSetupXml.getFileLocation() + 314 OperationsSetupXml.getOperationsDirectoryName() + 315 File.separator + 316 getOperationsFileName(); 317 } 318 319 public static void setOperationsFileName(String name) { 320 operationsFileName = name; 321 } 322 323 public static String getOperationsFileName() { 324 return operationsFileName; 325 } 326 327 private static String operationsFileName = "ExportOperationsTrainRoster.csv"; // NOI18N 328 329 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ExportTrains.class); 330 331}