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