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