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