001package jmri.jmrit.operations.rollingstock.cars.tools; 002 003import java.io.*; 004 005import jmri.IdTagManager; 006import jmri.InstanceManager; 007import jmri.jmrit.operations.locations.*; 008import jmri.jmrit.operations.locations.divisions.Division; 009import jmri.jmrit.operations.locations.divisions.DivisionManager; 010import jmri.jmrit.operations.rollingstock.ImportCommon; 011import jmri.jmrit.operations.rollingstock.RollingStock; 012import jmri.jmrit.operations.rollingstock.cars.*; 013import jmri.jmrit.operations.setup.Control; 014import jmri.jmrit.operations.setup.Setup; 015import jmri.jmrit.operations.trains.*; 016import jmri.jmrit.operations.trains.trainbuilder.TrainCommon; 017import jmri.util.swing.JmriJOptionPane; 018 019/** 020 * This routine will import cars into the operation database. Each field is 021 * space or comma delimited. Field order: Number Road Type Length Weight Color 022 * Owner Built Location - Track. If a CSV file, the import will accept these 023 * additional fields: Load Kernel Moves Value Comment Miscellaneous Extensions 024 * 025 * @author Dan Boudreau Copyright (C) 2008 2010 2011, 2013, 2016, 2021, 2024 026 */ 027public class ImportCars extends ImportCommon { 028 029 CarManager carManager = InstanceManager.getDefault(CarManager.class); 030 031 private int weightResults = JmriJOptionPane.NO_OPTION; 032 private boolean autoCalculate = true; 033 private boolean askAutoCreateTypes = true; 034 private boolean askAutoCreateLocations = true; 035 private boolean askAutoCreateTracks = true; 036 private boolean askAutoLocationType = true; 037 private boolean askAutoIncreaseTrackLength = true; 038 private boolean askAutoForceCar = true; 039 040 private boolean autoCreateTypes = false; 041 private boolean autoCreateLocations = false; 042 private boolean autoCreateTracks = false; 043 private boolean autoAdjustLocationType = false; 044 private boolean autoAdjustTrackLength = false; 045 private boolean autoForceCar = false; 046 047 private final boolean autoCreateRoads = true; 048 private final boolean autoCreateLoads = true; 049 private final boolean autoCreateLengths = true; 050 private final boolean autoCreateColors = true; 051 private final boolean autoCreateOwners = true; 052 053 // see ExportCars for column numbers 054 private static final int CAR_NUMBER = 0; 055 private static final int CAR_ROAD = 1; 056 private static final int CAR_TYPE = 2; 057 private static final int CAR_LENGTH = 3; 058 private static final int CAR_WEIGHT = 4; 059 private static final int CAR_COLOR = 5; 060 private static final int CAR_OWNER = 6; 061 private static final int CAR_BUILT = 7; 062 private static final int CAR_LOCATION = 8; 063 private static final int CAR_LOCATION_TRACK_SEPARATOR = 9; 064 private static final int CAR_TRACK = 10; 065 066 // only for CSV files 067 private static final int CAR_LOAD = 11; 068 private static final int CAR_KERNEL = 12; 069 private static final int CAR_MOVES = 13; 070 private static final int CAR_VALUE = 14; 071 private static final int CAR_COMMENT = 15; 072 private static final int CAR_MISCELLANEOUS = 16; 073 private static final int CAR_EXTENSIONS = 17; 074 075 // private static final int CAR_WAIT = 18; 076 // private static final int CAR_PICKUP_SCH = 19; 077 // private static final int CAR_LAST = 20; 078 079 private static final int CAR_RWE_DESTINATION = 21; 080 private static final int CAR_RWE_TRACK = 23; 081 private static final int CAR_RWE_LOAD = 24; 082 083 private static final int CAR_RWL_DESTINATION = 25; 084 private static final int CAR_RWL_TRACK = 27; 085 private static final int CAR_RWL_LOAD = 28; 086 087 private static final int CAR_DIVISION = 29; 088 private static final int CAR_TRAIN = 30; 089 090 private static final int CAR_DESTINATION = 31; 091 private static final int CAR_DEST_TRACK = 33; 092 093 private static final int CAR_FINAL_DESTINATION = 34; 094 private static final int CAR_FINAL_TRACK = 36; 095 private static final int CAR_SCH_ID = 37; 096 097 private static final int CAR_RFID_TAG = 38; 098 099 // we use a thread so the status frame will work! 100 @Override 101 public void run() { 102 File file = getFile(); 103 if (file == null) { 104 return; 105 } 106 BufferedReader in = getBufferedReader(file); 107 if (in == null) { 108 return; 109 } 110 111 createStatusFrame(Bundle.getMessage("ImportCars")); 112 113 // Now read the input file 114 boolean importOkay = false; 115 boolean comma = false; 116 boolean importKernel = false; 117 int lineNum = 0; 118 int carsAdded = 0; 119 String line = " "; 120 String carNumber; 121 String carRoad; 122 String carType; 123 String carLength; 124 String carWeight; 125 String carColor = ""; 126 String carOwner = ""; 127 String carBuilt = ""; 128 String carLocationName = ""; 129 String carTrackName = ""; 130 String carLoadName = ""; 131 String carKernelName = ""; 132 int carMoves = 0; 133 String carValue = ""; 134 String carComment = ""; 135 String[] inputLine; 136 137 // does the file name end with .csv? 138 if (file.getAbsolutePath().endsWith(".csv")) { // NOI18N 139 log.info("Using comma as delimiter for import cars"); 140 comma = true; 141 } 142 143 while (true) { 144 lineNumber.setText(Bundle.getMessage("LineNumber") + " " + Integer.toString(++lineNum)); 145 try { 146 line = in.readLine(); 147 } catch (IOException e) { 148 break; 149 } 150 151 if (line == null) { 152 importOkay = true; 153 break; 154 } 155 156 // has user canceled import? 157 if (!fstatus.isShowing()) { 158 break; 159 } 160 161 line = line.trim(); 162 log.debug("Import: {}", line); 163 importLine.setText(line); 164 165 if (line.startsWith(Bundle.getMessage("Number"))) { 166 continue; // skip header 167 } 168 if (line.equalsIgnoreCase("kernel")) { // NOI18N 169 log.info("Importing kernel names"); 170 importKernel = true; 171 continue; 172 } 173 if (line.equalsIgnoreCase("comma")) { // NOI18N 174 log.info("Using comma as delimiter for import cars"); 175 comma = true; 176 continue; 177 } 178 // use comma as delimiter if found otherwise use spaces 179 if (comma) { 180 inputLine = parseCommaLine(line); 181 } else { 182 inputLine = line.split("\\s+"); // NOI18N 183 } 184 if (inputLine.length < 1 || line.isEmpty()) { 185 log.debug("Skipping blank line"); 186 continue; 187 } 188 int base = 1; 189 if (comma || !inputLine[0].isEmpty()) { 190 base--; // skip over any spaces at start of line 191 } 192 193 // The minimum import is car number, road, type and length 194 if (inputLine.length > base + 3) { 195 196 carNumber = inputLine[base + CAR_NUMBER].trim(); 197 carRoad = inputLine[base + CAR_ROAD].trim(); 198 carType = inputLine[base + CAR_TYPE].trim(); 199 carLength = inputLine[base + CAR_LENGTH].trim(); 200 carWeight = "0"; 201 carColor = ""; 202 carOwner = ""; 203 carBuilt = ""; 204 carLocationName = ""; 205 carTrackName = ""; 206 carLoadName = InstanceManager.getDefault(CarLoads.class).getDefaultEmptyName(); 207 carKernelName = ""; 208 carMoves = 0; 209 carValue = ""; 210 carComment = ""; 211 212 if (inputLine.length > base + CAR_WEIGHT) { 213 carWeight = inputLine[base + CAR_WEIGHT].trim(); 214 } 215 if (inputLine.length > base + CAR_COLOR) { 216 carColor = inputLine[base + CAR_COLOR].trim(); 217 } 218 219 log.debug("Checking car number ({}) road ({}) type ({}) length ({}) weight ({}) color ({})", carNumber, 220 carRoad, carType, carLength, carWeight, carColor); // NOI18N 221 222 if (carNumber.isEmpty()) { 223 log.info("Import line {} missing car number", lineNum); 224 JmriJOptionPane.showMessageDialog(null, 225 Bundle.getMessage("RoadNumberNotSpecified", lineNum), 226 Bundle.getMessage("RoadNumberMissing"), JmriJOptionPane.ERROR_MESSAGE); 227 break; 228 } 229 if (carRoad.isEmpty()) { 230 log.info("Import line {} missing car road", lineNum); 231 JmriJOptionPane.showMessageDialog(null, 232 Bundle.getMessage("RoadNameNotSpecified", lineNum), 233 Bundle.getMessage("RoadNameMissing"), JmriJOptionPane.ERROR_MESSAGE); 234 break; 235 } 236 if (carType.isEmpty()) { 237 log.info("Import line {} missing car type", lineNum); 238 JmriJOptionPane.showMessageDialog(null, 239 Bundle.getMessage("CarTypeNotSpecified", carRoad, carNumber, lineNum), 240 Bundle.getMessage("CarTypeMissing"), JmriJOptionPane.ERROR_MESSAGE); 241 break; 242 } 243 if (carLength.isEmpty()) { 244 log.info("Import line {} missing car length", lineNum); 245 JmriJOptionPane.showMessageDialog(null, 246 Bundle.getMessage("CarLengthNotSpecified", carRoad, carNumber, lineNum), 247 Bundle.getMessage("CarLengthMissing"), JmriJOptionPane.ERROR_MESSAGE); 248 break; 249 } 250 if (TrainCommon.splitString(carNumber).length() > Control.max_len_string_road_number) { 251 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("CarRoadNumberTooLong", 252 carRoad, carNumber, carNumber), 253 Bundle.getMessage("RoadNumMustBeLess", 254 Control.max_len_string_road_number + 1), 255 JmriJOptionPane.ERROR_MESSAGE); 256 break; 257 } 258 try { 259 if (carRoad.split(TrainCommon.HYPHEN)[0].length() > Control.max_len_string_attibute) { 260 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("CarRoadNameTooLong", 261 carRoad, carNumber, carRoad), 262 Bundle.getMessage("carAttribute", 263 Control.max_len_string_attibute), 264 JmriJOptionPane.ERROR_MESSAGE); 265 break; 266 } 267 } catch (ArrayIndexOutOfBoundsException e) { 268 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("CarRoadNameWrong", 269 carRoad, lineNum), 270 Bundle.getMessage("CarAttributeMissing"), 271 JmriJOptionPane.ERROR_MESSAGE); 272 log.error("Road ({}) name not valid line {}", carRoad, lineNum); 273 break; 274 } 275 try { 276 if (carType.split(TrainCommon.HYPHEN)[0].length() > Control.max_len_string_attibute) { 277 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("CarTypeNameTooLong", 278 carRoad, carNumber, carType), 279 Bundle.getMessage("carAttribute", 280 Control.max_len_string_attibute), 281 JmriJOptionPane.ERROR_MESSAGE); 282 break; 283 } 284 } catch (ArrayIndexOutOfBoundsException e) { 285 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("CarTypeNameWrong", 286 carType, lineNum), 287 Bundle.getMessage("CarAttributeMissing"), 288 JmriJOptionPane.ERROR_MESSAGE); 289 log.error("Type ({}) name not valid line {}", carType, lineNum); 290 break; 291 } 292 if (!InstanceManager.getDefault(CarTypes.class).containsName(carType)) { 293 if (autoCreateTypes) { 294 log.debug("Adding car type ({})", carType); 295 InstanceManager.getDefault(CarTypes.class).addName(carType); 296 } else { 297 int results = JmriJOptionPane.showConfirmDialog(null, Bundle.getMessage("Car") + 298 " (" + 299 carRoad + 300 " " + 301 carNumber + 302 ")" + 303 NEW_LINE + 304 Bundle.getMessage("typeNameNotExist", carType), 305 Bundle.getMessage("carAddType"), JmriJOptionPane.YES_NO_CANCEL_OPTION); 306 if (results == JmriJOptionPane.YES_OPTION) { 307 InstanceManager.getDefault(CarTypes.class).addName(carType); 308 if (askAutoCreateTypes) { 309 results = JmriJOptionPane.showConfirmDialog(null, 310 Bundle.getMessage("DoYouWantToAutoAddCarTypes"), 311 Bundle.getMessage("OnlyAskedOnce"), 312 JmriJOptionPane.YES_NO_OPTION); 313 if (results == JmriJOptionPane.YES_OPTION) { 314 autoCreateTypes = true; 315 } 316 } 317 askAutoCreateTypes = false; 318 } else if (results == JmriJOptionPane.CANCEL_OPTION) { 319 break; 320 } 321 } 322 } 323 if (carLength.length() > Control.max_len_string_length_name) { 324 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("CarLengthNameTooLong", 325 carRoad, carNumber, carLength), 326 Bundle.getMessage("carAttribute", 327 Control.max_len_string_length_name), 328 JmriJOptionPane.ERROR_MESSAGE); 329 break; 330 } 331 try { 332 Integer.parseInt(carLength); 333 } catch (NumberFormatException e) { 334 JmriJOptionPane.showMessageDialog( 335 null, Bundle.getMessage("CarLengthNameNotNumber", 336 carRoad, carNumber, carLength), 337 Bundle.getMessage("CarLengthMissing"), JmriJOptionPane.ERROR_MESSAGE); 338 break; 339 } 340 if (carWeight.length() > Control.max_len_string_weight_name) { 341 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("CarWeightNameTooLong", 342 carRoad, carNumber, carWeight), 343 Bundle.getMessage("carAttribute", 344 Control.max_len_string_weight_name), 345 JmriJOptionPane.ERROR_MESSAGE); 346 break; 347 } 348 if (carColor.length() > Control.max_len_string_attibute) { 349 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("CarColorNameTooLong", 350 carRoad, carNumber, carColor), 351 Bundle.getMessage("carAttribute", 352 Control.max_len_string_attibute), 353 JmriJOptionPane.ERROR_MESSAGE); 354 break; 355 } 356 // calculate car weight if "0" 357 if (carWeight.equals("0")) { 358 try { 359 carWeight = CarManager.calculateCarWeight(carLength); // ounces. 360 } catch (NumberFormatException e) { 361 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("carLengthMustBe"), Bundle 362 .getMessage("carWeigthCanNot"), JmriJOptionPane.ERROR_MESSAGE); 363 } 364 } 365 Car existingCar = carManager.getByRoadAndNumber(carRoad, carNumber); 366 if (existingCar != null) { 367 log.info("Can not add, car number ({}) road ({}) already exists!", carNumber, carRoad); // NOI18N 368 continue; 369 } 370 if (inputLine.length > base + CAR_OWNER) { 371 carOwner = inputLine[base + CAR_OWNER].trim(); 372 if (carOwner.length() > Control.max_len_string_attibute) { 373 JmriJOptionPane.showMessageDialog(null, Bundle 374 .getMessage("CarOwnerNameTooLong", 375 carRoad, carNumber, carOwner), 376 Bundle.getMessage("carAttribute", 377 Control.max_len_string_attibute), 378 JmriJOptionPane.ERROR_MESSAGE); 379 break; 380 } 381 } 382 if (inputLine.length > base + CAR_BUILT) { 383 carBuilt = inputLine[base + CAR_BUILT].trim(); 384 if (carBuilt.length() > Control.max_len_string_built_name) { 385 JmriJOptionPane.showMessageDialog( 386 null, Bundle.getMessage("CarBuiltNameTooLong", 387 carRoad, carNumber, carBuilt), 388 Bundle.getMessage("carAttribute", 389 Control.max_len_string_built_name), 390 JmriJOptionPane.ERROR_MESSAGE); 391 break; 392 } 393 } 394 if (inputLine.length > base + CAR_LOCATION) { 395 carLocationName = inputLine[base + CAR_LOCATION].trim(); 396 } 397 if (comma && inputLine.length > base + CAR_TRACK) { 398 carTrackName = inputLine[base + CAR_TRACK].trim(); 399 } 400 // Location and track name can be one or more words in a 401 // space delimited file 402 if (!comma) { 403 int j = 0; 404 StringBuffer name = new StringBuffer(carLocationName); 405 for (int i = base + CAR_LOCATION_TRACK_SEPARATOR; i < inputLine.length; i++) { 406 if (inputLine[i].equals(LOCATION_TRACK_SEPARATOR)) { 407 j = i + 1; 408 break; 409 } else { 410 name.append(" " + inputLine[i]); 411 } 412 } 413 carLocationName = name.toString(); 414 log.debug("Car ({} {}) has location ({})", carRoad, carNumber, carLocationName); 415 // now get the track name 416 name = new StringBuffer(); 417 if (j != 0 && j < inputLine.length) { 418 name.append(inputLine[j]); 419 for (int i = j + 1; i < inputLine.length; i++) { 420 name.append(" " + inputLine[i]); 421 } 422 log.debug("Car ({} {}) has track ({})", carRoad, carNumber, carTrackName); 423 } 424 carTrackName = name.toString(); 425 } 426 427 // is there a load name? 428 if (comma && inputLine.length > CAR_LOAD) { 429 if (!inputLine[CAR_LOAD].isBlank()) { 430 carLoadName = inputLine[CAR_LOAD].trim(); 431 log.debug("Car ({} {}) has load ({})", carRoad, carNumber, carLoadName); 432 } 433 if (carLoadName.length() > Control.max_len_string_attibute) { 434 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("CarLoadNameTooLong", 435 carRoad, carNumber, carLoadName), 436 Bundle.getMessage("carAttribute", 437 Control.max_len_string_attibute), 438 JmriJOptionPane.ERROR_MESSAGE); 439 break; 440 } 441 } 442 // is there a kernel name? 443 if (comma && inputLine.length > CAR_KERNEL) { 444 carKernelName = inputLine[CAR_KERNEL].trim(); 445 log.debug("Car ({} {}) has kernel name ({})", carRoad, carNumber, carKernelName); 446 } 447 // is there a move count? 448 if (comma && inputLine.length > CAR_MOVES) { 449 if (!inputLine[CAR_MOVES].trim().isEmpty()) { 450 try { 451 carMoves = Integer.parseInt(inputLine[CAR_MOVES].trim()); 452 log.debug("Car ({} {}) has move count ({})", carRoad, carNumber, carMoves); 453 } catch (NumberFormatException e) { 454 log.error("Car ({} {}) has move count ({}) not a number", carRoad, carNumber, carMoves); 455 } 456 } 457 } 458 // is there a car value? 459 if (comma && inputLine.length > CAR_VALUE) { 460 carValue = inputLine[CAR_VALUE].trim(); 461 } 462 // is there a car comment? 463 if (comma && inputLine.length > CAR_COMMENT) { 464 carComment = inputLine[CAR_COMMENT]; 465 } 466 467 if (TrainCommon.splitString(carLocationName).length() > Control.max_len_string_location_name) { 468 JmriJOptionPane.showMessageDialog( 469 null, Bundle.getMessage("CarLocationNameTooLong", 470 carRoad, carNumber, carLocationName), 471 Bundle.getMessage("carAttribute", 472 Control.max_len_string_location_name), 473 JmriJOptionPane.ERROR_MESSAGE); 474 break; 475 } 476 if (TrainCommon.splitString(carTrackName).length() > Control.max_len_string_track_name) { 477 JmriJOptionPane.showMessageDialog(null, Bundle 478 .getMessage("CarTrackNameTooLong", 479 carRoad, carNumber, carTrackName), 480 Bundle.getMessage("carAttribute", 481 Control.max_len_string_track_name), 482 JmriJOptionPane.ERROR_MESSAGE); 483 break; 484 } 485 Location location = 486 InstanceManager.getDefault(LocationManager.class).getLocationByName(carLocationName); 487 Track track = null; 488 if (location == null && !carLocationName.isEmpty()) { 489 if (autoCreateLocations) { 490 log.debug("Create location ({})", carLocationName); 491 location = InstanceManager.getDefault(LocationManager.class).newLocation(carLocationName); 492 } else { 493 JmriJOptionPane.showMessageDialog(null, Bundle 494 .getMessage("CarLocationDoesNotExist", 495 carRoad, carNumber, carLocationName), 496 Bundle.getMessage("carLocation"), JmriJOptionPane.ERROR_MESSAGE); 497 int results = JmriJOptionPane.showConfirmDialog(null, Bundle 498 .getMessage("DoYouWantToCreateLoc", carLocationName), 499 Bundle 500 .getMessage("carLocation"), 501 JmriJOptionPane.YES_NO_OPTION); 502 if (results == JmriJOptionPane.YES_OPTION) { 503 log.debug("Create location ({})", carLocationName); 504 location = 505 InstanceManager.getDefault(LocationManager.class).newLocation(carLocationName); 506 if (askAutoCreateLocations) { 507 results = JmriJOptionPane.showConfirmDialog(null, Bundle 508 .getMessage("DoYouWantToAutoCreateLoc"), 509 Bundle.getMessage("OnlyAskedOnce"), JmriJOptionPane.YES_NO_OPTION); 510 if (results == JmriJOptionPane.YES_OPTION) { 511 autoCreateLocations = true; 512 } 513 } 514 askAutoCreateLocations = false; 515 } else { 516 break; 517 } 518 } 519 } 520 if (location != null && !carTrackName.isEmpty()) { 521 track = location.getTrackByName(carTrackName, null); 522 if (track == null) { 523 if (autoCreateTracks) { 524 if (!location.isStaging()) { 525 log.debug("Create 1000 foot yard track ({})", carTrackName); 526 track = location.addTrack(carTrackName, Track.YARD); 527 } else { 528 log.debug("Create 1000 foot staging track ({})", carTrackName); 529 track = location.addTrack(carTrackName, Track.STAGING); 530 } 531 track.setLength(1000); 532 } else { 533 JmriJOptionPane.showMessageDialog( 534 null, Bundle.getMessage("CarTrackDoesNotExist", 535 carRoad, carNumber, carTrackName, carLocationName), 536 Bundle.getMessage("carTrack"), JmriJOptionPane.ERROR_MESSAGE); 537 int results = JmriJOptionPane.showConfirmDialog(null, 538 Bundle.getMessage("DoYouWantToCreateTrack", 539 carTrackName, carLocationName), 540 Bundle.getMessage("carTrack"), JmriJOptionPane.YES_NO_OPTION); 541 if (results == JmriJOptionPane.YES_OPTION) { 542 if (!location.isStaging()) { 543 log.debug("Create 1000 foot yard track ({})", carTrackName); 544 track = location.addTrack(carTrackName, Track.YARD); 545 } else { 546 log.debug("Create 1000 foot staging track ({})", carTrackName); 547 track = location.addTrack(carTrackName, Track.STAGING); 548 } 549 track.setLength(1000); 550 if (askAutoCreateTracks) { 551 results = JmriJOptionPane.showConfirmDialog(null, 552 Bundle.getMessage("DoYouWantToAutoCreateTrack"), 553 Bundle.getMessage("OnlyAskedOnce"), 554 JmriJOptionPane.YES_NO_OPTION); 555 if (results == JmriJOptionPane.YES_OPTION) { 556 autoCreateTracks = true; 557 } 558 askAutoCreateTracks = false; 559 } 560 } else { 561 break; 562 } 563 } 564 } 565 } 566 567 log.debug("Add car ({} {}) owner ({}) built ({}) location ({}, {})", carRoad, carNumber, carOwner, 568 carBuilt, carLocationName, carTrackName); 569 Car car = carManager.newRS(carRoad, carNumber); 570 car.setTypeName(carType); 571 car.setLength(carLength); 572 car.setWeight(carWeight); 573 car.setColor(carColor); 574 car.setOwnerName(carOwner); 575 car.setBuilt(carBuilt); 576 car.setLoadName(carLoadName); 577 car.setKernel(InstanceManager.getDefault(KernelManager.class).newKernel(carKernelName)); 578 car.setMoves(carMoves); 579 car.setValue(carValue); 580 car.setComment(carComment); 581 carsAdded++; 582 583 // if the car's type name is "Caboose" then make it a 584 // caboose 585 car.setCaboose(carType.equals("Caboose")); 586 587 // Out of Service? 588 if (comma && inputLine.length > CAR_MISCELLANEOUS) { 589 car.setOutOfService(inputLine[CAR_MISCELLANEOUS].equals(Bundle.getMessage("OutOfService"))); 590 } 591 592 // determine if there are any car extensions 593 if (comma && inputLine.length > CAR_EXTENSIONS) { 594 String extensions = inputLine[CAR_EXTENSIONS]; 595 log.debug("Car ({}) has extension ({})", car.toString(), extensions); 596 String[] ext = extensions.split(Car.EXTENSION_REGEX); 597 for (int i = 0; i < ext.length; i++) { 598 if (ext[i].equals(Car.CABOOSE_EXTENSION)) { 599 car.setCaboose(true); 600 } 601 if (ext[i].equals(Car.FRED_EXTENSION)) { 602 car.setFred(true); 603 } 604 if (ext[i].equals(Car.PASSENGER_EXTENSION)) { 605 car.setPassenger(true); 606 car.setBlocking(Integer.parseInt(ext[i + 1])); 607 } 608 if (ext[i].equals(Car.UTILITY_EXTENSION)) { 609 car.setUtility(true); 610 } 611 if (ext[i].equals(Car.HAZARDOUS_EXTENSION)) { 612 car.setCarHazardous(true); 613 } 614 } 615 } 616 617 // TODO car wait, pick up schedule, last moved 618 619 // Return When Empty 620 if (comma && inputLine.length > CAR_RWE_DESTINATION) { 621 Location rweDestination = 622 InstanceManager.getDefault(LocationManager.class) 623 .getLocationByName(inputLine[CAR_RWE_DESTINATION]); 624 625 car.setReturnWhenEmptyDestination(rweDestination); 626 if (rweDestination != null && inputLine.length > CAR_RWE_TRACK) { 627 Track rweTrack = rweDestination.getTrackByName(inputLine[CAR_RWE_TRACK], null); 628 car.setReturnWhenEmptyDestTrack(rweTrack); 629 } 630 } 631 if (comma && inputLine.length > CAR_RWE_LOAD && !inputLine[CAR_RWE_LOAD].isBlank()) { 632 car.setReturnWhenEmptyLoadName(inputLine[CAR_RWE_LOAD].trim()); 633 } 634 635 // Return When Loaded 636 if (comma && inputLine.length > CAR_RWL_DESTINATION) { 637 Location rwlDestination = 638 InstanceManager.getDefault(LocationManager.class) 639 .getLocationByName(inputLine[CAR_RWL_DESTINATION]); 640 641 car.setReturnWhenLoadedDestination(rwlDestination); 642 if (rwlDestination != null && inputLine.length > CAR_RWL_TRACK) { 643 Track rweTrack = rwlDestination.getTrackByName(inputLine[CAR_RWL_TRACK], null); 644 car.setReturnWhenLoadedDestTrack(rweTrack); 645 } 646 } 647 if (comma && inputLine.length > CAR_RWL_LOAD && !inputLine[CAR_RWL_LOAD].isBlank()) { 648 car.setReturnWhenLoadedLoadName(inputLine[CAR_RWL_LOAD].trim()); 649 } 650 651 if (comma && inputLine.length > CAR_DIVISION) { 652 Division division = InstanceManager.getDefault(DivisionManager.class) 653 .getDivisionByName(inputLine[CAR_DIVISION].trim()); 654 car.setDivision(division); 655 } 656 657 if (comma && inputLine.length > CAR_TRAIN) { 658 Train train = InstanceManager.getDefault(TrainManager.class) 659 .getTrainByName(inputLine[CAR_TRAIN].trim()); 660 car.setTrain(train); 661 } 662 663 // Destination 664 if (comma && inputLine.length > CAR_DESTINATION) { 665 Location destination = 666 InstanceManager.getDefault(LocationManager.class) 667 .getLocationByName(inputLine[CAR_DESTINATION]); 668 if (destination != null && inputLine.length > CAR_DEST_TRACK) { 669 Track destTrack = destination.getTrackByName(inputLine[CAR_DEST_TRACK], null); 670 car.setDestination(destination, destTrack); 671 } 672 } 673 674 // Final Destination 675 if (comma && inputLine.length > CAR_FINAL_DESTINATION) { 676 Location finalDestination = 677 InstanceManager.getDefault(LocationManager.class) 678 .getLocationByName(inputLine[CAR_FINAL_DESTINATION]); 679 680 car.setFinalDestination(finalDestination); 681 if (finalDestination != null && inputLine.length > CAR_FINAL_TRACK) { 682 Track finalTrack = finalDestination.getTrackByName(inputLine[CAR_FINAL_TRACK], null); 683 car.setFinalDestinationTrack(finalTrack); 684 } 685 } 686 687 // Schedule Id 688 if (comma && inputLine.length > CAR_SCH_ID) { 689 car.setScheduleItemId(inputLine[CAR_SCH_ID]); 690 } 691 692 if (comma && inputLine.length > CAR_RFID_TAG) { 693 String newTag = inputLine[CAR_RFID_TAG]; 694 if (!newTag.trim().isEmpty()) { 695 InstanceManager.getDefault(IdTagManager.class).provideIdTag(newTag); 696 log.debug("New ID tag added - {}", newTag); 697 car.setRfid(newTag); 698 } 699 } 700 701 // add new roads 702 if (!InstanceManager.getDefault(CarRoads.class).containsName(carRoad)) { 703 if (autoCreateRoads) { 704 log.debug("add car road {}", carRoad); 705 InstanceManager.getDefault(CarRoads.class).addName(carRoad); 706 } 707 } 708 709 // add new loads 710 if (!InstanceManager.getDefault(CarLoads.class).containsName(carLoadName)) { 711 if (autoCreateLoads) { 712 log.debug("add car load {}", carLoadName); 713 InstanceManager.getDefault(CarLoads.class).addName(carType, carLoadName); 714 } 715 } 716 717 // add new lengths 718 if (!InstanceManager.getDefault(CarLengths.class).containsName(carLength)) { 719 if (autoCreateLengths) { 720 log.debug("add car length {}", carLength); 721 InstanceManager.getDefault(CarLengths.class).addName(carLength); 722 } 723 } 724 725 // add new colors 726 if (!InstanceManager.getDefault(CarColors.class).containsName(carColor)) { 727 if (autoCreateColors) { 728 log.debug("add car color {}", carColor); 729 InstanceManager.getDefault(CarColors.class).addName(carColor); 730 } 731 } 732 733 // add new owners 734 if (!InstanceManager.getDefault(CarOwners.class).containsName(carOwner)) { 735 if (autoCreateOwners) { 736 log.debug("add car owner {}", carOwner); 737 InstanceManager.getDefault(CarOwners.class).addName(carOwner); 738 } 739 } 740 741 if (car.getWeight().isEmpty()) { 742 log.debug("Car ({}) weight not specified", car.toString()); 743 if (weightResults != JmriJOptionPane.CANCEL_OPTION) { 744 weightResults = JmriJOptionPane.showOptionDialog(null, 745 Bundle.getMessage("CarWeightNotFound", 746 car.toString()), 747 Bundle.getMessage("CarWeightMissing"), 748 JmriJOptionPane.DEFAULT_OPTION, // custom buttons 749 JmriJOptionPane.INFORMATION_MESSAGE, null, 750 new Object[]{ 751 Bundle.getMessage("ButtonYes"), Bundle.getMessage("ButtonNo"), 752 Bundle.getMessage("ButtonDontShow")}, 753 autoCalculate ? Bundle.getMessage("ButtonYes") : Bundle.getMessage("ButtonNo")); 754 } 755 if (weightResults == 1) { // array position 1, ButtonNo 756 autoCalculate = false; 757 } 758 if (weightResults == 0 || // array position 0, ButtonYes 759 autoCalculate == true && weightResults == 2) { // array position 2 ButtonDontShow 760 autoCalculate = true; 761 try { 762 carWeight = CarManager.calculateCarWeight(carLength); 763 car.setWeight(carWeight); 764 int tons = (int) (Double.parseDouble(carWeight) * Setup.getScaleTonRatio()); 765 // adjust weight for caboose 766 if (car.isCaboose() || car.isPassenger()) { 767 tons = (int) (Double.parseDouble(car.getLength()) * .9); 768 } 769 car.setWeightTons(Integer.toString(tons)); 770 } catch (NumberFormatException e) { 771 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("carLengthMustBe"), Bundle 772 .getMessage("carWeigthCanNot"), JmriJOptionPane.ERROR_MESSAGE); 773 } 774 } 775 } 776 777 if (location != null && track != null) { 778 String status = car.setLocation(location, track); 779 if (!status.equals(Track.OKAY)) { 780 log.debug("Can't set car's location because of {}", status); 781 if (status.startsWith(Track.TYPE)) { 782 if (autoAdjustLocationType) { 783 location.addTypeName(carType); 784 track.addTypeName(carType); 785 status = car.setLocation(location, track); 786 } else { 787 JmriJOptionPane.showMessageDialog( 788 null, Bundle.getMessage("CanNotSetCarAtLocation", 789 car.toString(), carType, carLocationName, carTrackName, 790 status), 791 Bundle.getMessage("rsCanNotLoc"), JmriJOptionPane.ERROR_MESSAGE); 792 int results = JmriJOptionPane.showConfirmDialog(null, Bundle 793 .getMessage("DoYouWantToAllowService", 794 carLocationName, carTrackName, car.toString(), carType), 795 Bundle.getMessage("ServiceCarType"), 796 JmriJOptionPane.YES_NO_OPTION); 797 if (results == JmriJOptionPane.YES_OPTION) { 798 location.addTypeName(carType); 799 track.addTypeName(carType); 800 status = car.setLocation(location, track); 801 log.debug("Set car's location status: {}", status); 802 if (askAutoLocationType) { 803 results = JmriJOptionPane.showConfirmDialog(null, 804 Bundle.getMessage("DoYouWantToAutoAdjustLocations"), 805 Bundle.getMessage("OnlyAskedOnce"), JmriJOptionPane.YES_NO_OPTION); 806 if (results == JmriJOptionPane.YES_OPTION) { 807 autoAdjustLocationType = true; 808 } 809 askAutoLocationType = false; 810 } 811 } else { 812 break; 813 } 814 } 815 } 816 if (status.startsWith(Track.LENGTH) || status.startsWith(Track.CAPACITY)) { 817 if (autoAdjustTrackLength) { 818 track.setLength(track.getLength() + 1000); 819 status = car.setLocation(location, track); 820 log.debug("Set track length status: {}", status); 821 } else { 822 JmriJOptionPane.showMessageDialog(null, Bundle 823 .getMessage("CanNotSetCarAtLocation", 824 car.toString(), carType, carLocationName, carTrackName, 825 status), 826 Bundle.getMessage("rsCanNotLoc"), JmriJOptionPane.ERROR_MESSAGE); 827 int results = JmriJOptionPane.showConfirmDialog(null, Bundle 828 .getMessage("DoYouWantIncreaseLength", carTrackName), 829 Bundle 830 .getMessage("TrackLength"), 831 JmriJOptionPane.YES_NO_OPTION); 832 if (results == JmriJOptionPane.YES_OPTION) { 833 track.setLength(track.getLength() + 1000); 834 status = car.setLocation(location, track); 835 log.debug("Set track length status: {}", status); 836 if (askAutoIncreaseTrackLength) { 837 results = JmriJOptionPane.showConfirmDialog(null, Bundle 838 .getMessage("DoYouWantToAutoAdjustTrackLength"), 839 Bundle.getMessage("OnlyAskedOnce"), 840 JmriJOptionPane.YES_NO_OPTION); 841 if (results == JmriJOptionPane.YES_OPTION) { 842 autoAdjustTrackLength = true; 843 } 844 askAutoIncreaseTrackLength = false; 845 } 846 } else { 847 break; 848 } 849 } 850 } 851 if (!status.equals(Track.OKAY)) { 852 if (autoForceCar) { 853 car.setLocation(location, track, RollingStock.FORCE); // force 854 } else { 855 JmriJOptionPane.showMessageDialog(null, Bundle 856 .getMessage("CanNotSetCarAtLocation", 857 car.toString(), carType, carLocationName, carTrackName, 858 status), 859 Bundle.getMessage("rsCanNotLoc"), JmriJOptionPane.ERROR_MESSAGE); 860 int results = JmriJOptionPane.showConfirmDialog(null, Bundle 861 .getMessage("DoYouWantToForceCar", 862 car.toString(), carLocationName, carTrackName), 863 Bundle.getMessage("OverRide"), 864 JmriJOptionPane.YES_NO_OPTION); 865 if (results == JmriJOptionPane.YES_OPTION) { 866 car.setLocation(location, track, RollingStock.FORCE); // force 867 if (askAutoForceCar) { 868 results = JmriJOptionPane.showConfirmDialog(null, Bundle 869 .getMessage("DoYouWantToAutoForceCar"), 870 Bundle.getMessage("OnlyAskedOnce"), 871 JmriJOptionPane.YES_NO_OPTION); 872 if (results == JmriJOptionPane.YES_OPTION) { 873 autoForceCar = true; 874 } 875 askAutoForceCar = false; 876 } 877 } else { 878 break; 879 } 880 } 881 } 882 } 883 } else { 884 // log.debug("No location for car ("+carRoad+" 885 // "+carNumber+")"); 886 } 887 } else if (importKernel && inputLine.length == base + 3) { 888 carNumber = inputLine[base + 0].trim(); 889 carRoad = inputLine[base + 1].trim(); 890 String kernelName = inputLine[base + 2].trim(); 891 Car car = carManager.getByRoadAndNumber(carRoad, carNumber); 892 if (car != null) { 893 Kernel kernel = InstanceManager.getDefault(KernelManager.class).newKernel(kernelName); 894 car.setKernel(kernel); 895 carsAdded++; 896 } else { 897 log.info("Car number ({}) road ({}) does not exist!", carNumber, carRoad); // NOI18N 898 break; 899 } 900 } else if (!line.isEmpty()) { 901 log.info("Car import line {} missing attributes: {}", lineNum, line); 902 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("ImportMissingAttributes", 903 lineNum) + 904 NEW_LINE + 905 line + 906 NEW_LINE + 907 Bundle.getMessage("ImportMissingAttributes2"), 908 Bundle.getMessage("CarAttributeMissing"), 909 JmriJOptionPane.ERROR_MESSAGE); 910 break; 911 } 912 } 913 try { 914 in.close(); 915 } catch (IOException e) { 916 log.error("Import cars failed: {}", e.getLocalizedMessage()); 917 } 918 919 if (importOkay) { 920 JmriJOptionPane 921 .showMessageDialog(null, Bundle.getMessage("ImportCarsAdded", 922 carsAdded), Bundle.getMessage("SuccessfulImport"), 923 JmriJOptionPane.INFORMATION_MESSAGE); 924 } else { 925 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("ImportCarsAdded", 926 carsAdded), Bundle.getMessage("ImportFailed"), JmriJOptionPane.ERROR_MESSAGE); 927 } 928 929 // kill status panel 930 fstatus.dispose(); 931 } 932 933 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ImportCars.class); 934}