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