001package jmri.jmrit.operations.locations.tools; 002 003import java.awt.*; 004import java.io.IOException; 005import java.text.MessageFormat; 006import java.util.List; 007 008import javax.swing.*; 009 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013import jmri.InstanceManager; 014import jmri.jmrit.operations.OperationsFrame; 015import jmri.jmrit.operations.locations.*; 016import jmri.jmrit.operations.locations.schedules.*; 017import jmri.jmrit.operations.rollingstock.cars.*; 018import jmri.jmrit.operations.rollingstock.engines.EngineTypes; 019import jmri.jmrit.operations.routes.Route; 020import jmri.jmrit.operations.routes.RouteManager; 021import jmri.jmrit.operations.setup.Control; 022import jmri.jmrit.operations.setup.Setup; 023import jmri.jmrit.operations.trains.Train; 024import jmri.jmrit.operations.trains.TrainManager; 025import jmri.jmrit.operations.trains.trainbuilder.TrainCommon; 026import jmri.util.davidflanagan.HardcopyWriter; 027 028/** 029 * Frame to print a summary of the Location Roster contents 030 * <p> 031 * This uses the older style printing, for compatibility with Java 1.1.8 in 032 * Macintosh MRJ 033 * 034 * @author Bob Jacobsen Copyright (C) 2003 035 * @author Dennis Miller Copyright (C) 2005 036 * @author Daniel Boudreau Copyright (C) 2008, 2011, 2012, 2014, 2022, 2023 037 */ 038public class PrintLocationsFrame extends OperationsFrame { 039 040 static final String FORM_FEED = "\f"; // NOI18N 041 static final String TAB = "\t"; // NOI18N 042 static final int TAB_LENGTH = 10; 043 static final String SPACES_2 = " "; 044 static final String SPACES_3 = " "; 045 static final String SPACES_4 = " "; 046 047 static final int MAX_NAME_LENGTH = Control.max_len_string_location_name; 048 049 JCheckBox printLocations = new JCheckBox(Bundle.getMessage("PrintLocations")); 050 JCheckBox printSchedules = new JCheckBox(Bundle.getMessage("PrintSchedules")); 051 JCheckBox printComments = new JCheckBox(Bundle.getMessage("PrintComments")); 052 JCheckBox printDetails = new JCheckBox(Bundle.getMessage("PrintDetails")); 053 JCheckBox printAnalysis = new JCheckBox(Bundle.getMessage("PrintAnalysis")); 054 JCheckBox printErrorAnalysis = new JCheckBox(Bundle.getMessage("PrintErrorAnalysis")); 055 056 JButton okayButton = new JButton(Bundle.getMessage("ButtonOK")); 057 058 LocationManager lmanager = InstanceManager.getDefault(LocationManager.class); 059 CarTypes cts = InstanceManager.getDefault(CarTypes.class); 060 CarLoads cls = InstanceManager.getDefault(CarLoads.class); 061 CarRoads crs = InstanceManager.getDefault(CarRoads.class); 062 063 boolean _isPreview; 064 Location _location; 065 066 private int charactersPerLine = 70; 067 068 HardcopyWriter writer; 069 070 public PrintLocationsFrame(boolean isPreview, Location location) { 071 super(); 072 _isPreview = isPreview; 073 _location = location; 074 075 // create panel 076 JPanel pPanel = new JPanel(); 077 pPanel.setLayout(new GridBagLayout()); 078 pPanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PrintOptions"))); 079 addItemLeft(pPanel, printLocations, 0, 0); 080 addItemLeft(pPanel, printSchedules, 0, 3); 081 addItemLeft(pPanel, printComments, 0, 5); 082 addItemLeft(pPanel, printDetails, 0, 7); 083 addItemLeft(pPanel, printAnalysis, 0, 9); 084 addItemLeft(pPanel, printErrorAnalysis, 0, 11); 085 086 // set defaults 087 printLocations.setSelected(true); 088 printSchedules.setSelected(false); 089 printComments.setSelected(false); 090 printDetails.setSelected(false); 091 printAnalysis.setSelected(false); 092 printErrorAnalysis.setSelected(false); 093 094 // add tool tips 095 JPanel pButtons = new JPanel(); 096 pButtons.setLayout(new GridBagLayout()); 097 pButtons.add(okayButton); 098 addButtonAction(okayButton); 099 100 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 101 getContentPane().add(pPanel); 102 getContentPane().add(pButtons); 103 setPreferredSize(null); 104 if (_isPreview) { 105 setTitle(Bundle.getMessage("MenuItemPreview")); 106 } else { 107 setTitle(Bundle.getMessage("MenuItemPrint")); 108 } 109 initMinimumSize(new Dimension(Control.panelWidth300, Control.panelHeight250)); 110 } 111 112 @Override 113 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 114 setVisible(false); 115 printLocations(); 116 } 117 118 private void printLocations() { 119 // prevent NPE on close 120 if (!printLocations.isSelected() && 121 !printSchedules.isSelected() && 122 !printComments.isSelected() && 123 !printDetails.isSelected() && 124 !printAnalysis.isSelected() && 125 !printErrorAnalysis.isSelected()) { 126 return; 127 } 128 // obtain a HardcopyWriter 129 String title = Bundle.getMessage("TitleLocationsTable"); 130 if (_location != null) { 131 title = _location.getName(); 132 } 133 try (HardcopyWriter writer = 134 new HardcopyWriter(new Frame(), title, Control.reportFontSize, .5, .5, .5, .5, _isPreview)) { 135 136 this.writer = writer; 137 138 charactersPerLine = writer.getCharactersPerLine(); 139 140 // print locations? 141 if (printLocations.isSelected()) { 142 printLocationsSelected(); 143 } 144 // print schedules? 145 if (printSchedules.isSelected()) { 146 printSchedulesSelected(); 147 } 148 if (printComments.isSelected()) { 149 printCommentsSelected(); 150 } 151 // print detailed report? 152 if (printDetails.isSelected()) { 153 printDetailsSelected(); 154 } 155 // print analysis? 156 if (printAnalysis.isSelected()) { 157 printAnalysisSelected(); 158 } 159 if (printErrorAnalysis.isSelected()) { 160 printErrorAnalysisSelected(); 161 } 162 } catch (HardcopyWriter.PrintCanceledException ex) { 163 log.debug("Print canceled"); 164 } catch (IOException we) { 165 log.error("Error printing PrintLocationAction: {}", we.getLocalizedMessage()); 166 } 167 } 168 169 // Loop through the Roster, printing as needed 170 private void printLocationsSelected() throws IOException { 171 List<Location> locations = lmanager.getLocationsByNameList(); 172 int totalLength = 0; 173 int usedLength = 0; 174 int numberRS = 0; 175 int numberCars = 0; 176 int numberEngines = 0; 177 // header 178 String s = Bundle.getMessage("Location") + 179 TAB + 180 TAB + 181 TAB + 182 Bundle.getMessage("Length") + 183 " " + 184 Bundle.getMessage("Used") + 185 TAB + 186 Bundle.getMessage("RS") + 187 TAB + 188 Bundle.getMessage("Cars") + 189 TAB + 190 Bundle.getMessage("Engines") + 191 TAB + 192 Bundle.getMessage("Pickups") + 193 " " + 194 Bundle.getMessage("Drop") + 195 NEW_LINE; 196 writer.write(s); 197 for (Location location : locations) { 198 if (_location != null && location != _location) { 199 continue; 200 } 201 // location name, track length, used, number of RS, scheduled pick 202 // ups and drops 203 s = padOutString(location.getName(), MAX_NAME_LENGTH) + 204 TAB + 205 " " + 206 Integer.toString(location.getLength()) + 207 TAB + 208 Integer.toString(location.getUsedLength()) + 209 TAB + 210 Integer.toString(location.getNumberRS()) + 211 TAB + 212 Integer.toString(location.getNumberCars()) + 213 TAB + 214 Integer.toString(location.getNumberEngines()) + 215 TAB + 216 Integer.toString(location.getPickupRS()) + 217 TAB + 218 Integer.toString(location.getDropRS()) + 219 NEW_LINE; 220 writer.write(s); 221 222 if (location.getDivision() != null) { 223 writer.write(SPACES_3 + Bundle.getMessage("Division") + ": " + location.getDivisionName() + NEW_LINE); 224 } 225 226 totalLength += location.getLength(); 227 usedLength += location.getUsedLength(); 228 numberRS += location.getNumberRS(); 229 230 List<Track> yards = location.getTracksByNameList(Track.YARD); 231 if (yards.size() > 0) { 232 // header 233 writer.write(SPACES_3 + Bundle.getMessage("YardName") + NEW_LINE); 234 for (Track yard : yards) { 235 writer.write(getTrackString(yard)); 236 numberCars += yard.getNumberCars(); 237 numberEngines += yard.getNumberEngines(); 238 } 239 } 240 241 List<Track> spurs = location.getTracksByNameList(Track.SPUR); 242 if (spurs.size() > 0) { 243 // header 244 writer.write(SPACES_3 + Bundle.getMessage("SpurName") + NEW_LINE); 245 for (Track spur : spurs) { 246 writer.write(getTrackString(spur)); 247 numberCars += spur.getNumberCars(); 248 numberEngines += spur.getNumberEngines(); 249 } 250 } 251 252 List<Track> interchanges = location.getTracksByNameList(Track.INTERCHANGE); 253 if (interchanges.size() > 0) { 254 // header 255 writer.write(SPACES_3 + Bundle.getMessage("InterchangeName") + NEW_LINE); 256 for (Track interchange : interchanges) { 257 writer.write(getTrackString(interchange)); 258 numberCars += interchange.getNumberCars(); 259 numberEngines += interchange.getNumberEngines(); 260 } 261 } 262 263 List<Track> stagingTracks = location.getTracksByNameList(Track.STAGING); 264 if (stagingTracks.size() > 0) { 265 // header 266 writer.write(SPACES_3 + Bundle.getMessage("StagingName") + NEW_LINE); 267 for (Track staging : stagingTracks) { 268 writer.write(getTrackString(staging)); 269 numberCars += staging.getNumberCars(); 270 numberEngines += staging.getNumberEngines(); 271 } 272 } 273 writer.write(NEW_LINE); 274 } 275 276 // summary 277 s = MessageFormat 278 .format(Bundle.getMessage("TotalLengthMsg"), 279 new Object[]{Integer.toString(totalLength), Integer.toString(usedLength), 280 totalLength > 0 ? Integer.toString(usedLength * 100 / totalLength) : 0}) + 281 NEW_LINE; 282 writer.write(s); 283 s = MessageFormat 284 .format(Bundle.getMessage("TotalRollingMsg"), 285 new Object[]{Integer.toString(numberRS), Integer.toString(numberCars), 286 Integer.toString(numberEngines)}) + 287 NEW_LINE; 288 writer.write(s); 289 // are there trains en route, then some cars and engines not counted! 290 if (numberRS != numberCars + numberEngines) { 291 s = Bundle.getMessage("NoteRSMsg", Integer.toString(numberRS - (numberCars + numberEngines))) + NEW_LINE; 292 writer.write(s); 293 } 294 if (printSchedules.isSelected() || 295 printComments.isSelected() || 296 printDetails.isSelected() || 297 printAnalysis.isSelected() || 298 printErrorAnalysis.isSelected()) { 299 writer.write(FORM_FEED); 300 } 301 } 302 303 private void printSchedulesSelected() throws IOException { 304 List<Location> locations = lmanager.getLocationsByNameList(); 305 String s = padOutString(Bundle.getMessage("Schedules"), MAX_NAME_LENGTH) + 306 " " + 307 Bundle.getMessage("Location") + 308 " - " + 309 Bundle.getMessage("SpurName") + 310 NEW_LINE; 311 writer.write(s); 312 List<Schedule> schedules = InstanceManager.getDefault(ScheduleManager.class).getSchedulesByNameList(); 313 for (Schedule schedule : schedules) { 314 for (Location location : locations) { 315 if (_location != null && location != _location) { 316 continue; 317 } 318 List<Track> spurs = location.getTracksByNameList(Track.SPUR); 319 for (Track spur : spurs) { 320 if (spur.getScheduleId().equals(schedule.getId())) { 321 // pad out schedule name 322 s = padOutString(schedule.getName(), 323 MAX_NAME_LENGTH) + " " + location.getName() + " - " + spur.getName(); 324 String status = spur.checkScheduleValid(); 325 if (!status.equals(Schedule.SCHEDULE_OKAY)) { 326 StringBuffer buf = new StringBuffer(s); 327 for (int m = s.length(); m < 63; m++) { 328 buf.append(" "); 329 } 330 s = buf.toString(); 331 if (s.length() > 63) { 332 s = s.substring(0, 63); 333 } 334 s = s + TAB + status; 335 } 336 s = s + NEW_LINE; 337 writer.write(s); 338 // show the schedule's mode 339 s = padOutString("", MAX_NAME_LENGTH) + 340 SPACES_3 + 341 Bundle.getMessage("ScheduleMode") + 342 ": " + 343 spur.getScheduleModeName() + 344 NEW_LINE; 345 writer.write(s); 346 // show alternate track if there's one 347 if (spur.getAlternateTrack() != null) { 348 s = padOutString("", MAX_NAME_LENGTH) + 349 SPACES_3 + 350 Bundle.getMessage("AlternateTrackName", spur.getAlternateTrack().getName()) + 351 NEW_LINE; 352 writer.write(s); 353 } 354 // show custom loads from staging if not 100% 355 if (spur.getReservationFactor() != 100) { 356 s = padOutString("", MAX_NAME_LENGTH) + 357 SPACES_3 + 358 Bundle.getMessage("PercentageStaging", 359 spur.getReservationFactor()) + 360 NEW_LINE; 361 writer.write(s); 362 } 363 } 364 } 365 } 366 } 367 // now show the contents of each schedule 368 for (Schedule schedule : schedules) { 369 writer.write(FORM_FEED); 370 s = schedule.getName() + NEW_LINE; 371 writer.write(s); 372 373 for (ScheduleItem si : schedule.getItemsBySequenceList()) { 374 s = padOutString(Bundle.getMessage("Type"), cts.getMaxNameLength() + 1) + 375 padOutString(Bundle.getMessage("Receive"), cls.getMaxNameLength() + 1) + 376 padOutString(Bundle.getMessage("Ship"), cls.getMaxNameLength() + 1) + 377 padOutString(Bundle.getMessage("Destination"), lmanager.getMaxLocationNameLength() + 1) + 378 Bundle.getMessage("Track") + 379 NEW_LINE; 380 writer.write(s); 381 s = padOutString(si.getTypeName(), cts.getMaxNameLength() + 1) + 382 padOutString(si.getReceiveLoadName(), cls.getMaxNameLength() + 1) + 383 padOutString(si.getShipLoadName(), cls.getMaxNameLength() + 1) + 384 padOutString(si.getDestinationName(), lmanager.getMaxLocationNameLength() + 1) + 385 si.getDestinationTrackName() + 386 NEW_LINE; 387 writer.write(s); 388 389 s = padOutString("", cts.getMaxNameLength() + 1) + 390 padOutString(Bundle.getMessage("Random"), Bundle.getMessage("Random").length() + 1) + 391 padOutString(Bundle.getMessage("Delivery"), Bundle.getMessage("Delivery").length() + 1) + 392 padOutString(Bundle.getMessage("Road"), crs.getMaxNameLength() + 1) + 393 padOutString(Bundle.getMessage("Pickup"), Bundle.getMessage("Delivery").length() + 1) + 394 Bundle.getMessage("Wait") + 395 NEW_LINE; 396 writer.write(s); 397 398 s = padOutString("", cts.getMaxNameLength() + 1) + 399 padOutString(si.getRandom(), Bundle.getMessage("Random").length() + 1) + 400 padOutString(si.getSetoutTrainScheduleName(), Bundle.getMessage("Delivery").length() + 1) + 401 padOutString(si.getRoadName(), crs.getMaxNameLength() + 1) + 402 padOutString(si.getPickupTrainScheduleName(), Bundle.getMessage("Delivery").length() + 1) + 403 si.getWait() + 404 NEW_LINE; 405 writer.write(s); 406 } 407 } 408 if (printComments.isSelected() || 409 printDetails.isSelected() || 410 printAnalysis.isSelected() || 411 printErrorAnalysis.isSelected()) { 412 writer.write(FORM_FEED); 413 } 414 } 415 416 private void printCommentsSelected() throws IOException { 417 String s = Bundle.getMessage("PrintComments") + NEW_LINE + NEW_LINE; 418 writer.write(s); 419 List<Location> locations = lmanager.getLocationsByNameList(); 420 for (Location location : locations) { 421 if (_location != null && location != _location) { 422 continue; 423 } 424 s = location.getName() + NEW_LINE; 425 writer.write(s); 426 s = SPACES_3 + location.getComment() + NEW_LINE; 427 writer.write(s); 428 for (Track track : location.getTracksByNameList(null)) { 429 if (!track.getComment().equals(Track.NONE) || 430 !track.getCommentBoth().equals(Track.NONE) || 431 !track.getCommentPickup().equals(Track.NONE) || 432 !track.getCommentSetout().equals(Track.NONE)) { 433 s = SPACES_2 + track.getName() + NEW_LINE; 434 writer.write(s); 435 if (!track.getComment().equals(Track.NONE)) { 436 s = SPACES_4 + track.getComment() + NEW_LINE; 437 writer.write(s); 438 } 439 if (!track.getCommentBoth().equals(Track.NONE)) { 440 s = SPACES_3 + Bundle.getMessage("CommentBoth") + ":" + NEW_LINE; 441 writer.write(s); 442 s = SPACES_4 + track.getCommentBoth() + NEW_LINE; 443 writer.write(s); 444 } 445 if (!track.getCommentPickup().equals(Track.NONE)) { 446 s = SPACES_3 + Bundle.getMessage("CommentPickup") + ":" + NEW_LINE; 447 writer.write(s); 448 s = SPACES_4 + track.getCommentPickup() + NEW_LINE; 449 writer.write(s); 450 } 451 if (!track.getCommentSetout().equals(Track.NONE)) { 452 s = SPACES_3 + Bundle.getMessage("CommentSetout") + ":" + NEW_LINE; 453 writer.write(s); 454 s = SPACES_4 + track.getCommentSetout() + NEW_LINE; 455 writer.write(s); 456 } 457 } 458 } 459 } 460 if (printDetails.isSelected() || printAnalysis.isSelected() || printErrorAnalysis.isSelected()) { 461 writer.write(FORM_FEED); 462 } 463 } 464 465 private void printDetailsSelected() throws IOException { 466 List<Location> locations = lmanager.getLocationsByNameList(); 467 String s = Bundle.getMessage("DetailedReport") + NEW_LINE; 468 writer.write(s); 469 for (Location location : locations) { 470 if (_location != null && location != _location) { 471 continue; 472 } 473 String name = location.getName(); 474 // services train direction 475 int dir = location.getTrainDirections(); 476 s = NEW_LINE + name + getDirection(dir); 477 writer.write(s); 478 479 // division 480 if (location.getDivision() != null) { 481 s = SPACES_3 + Bundle.getMessage("Division") + ": " + location.getDivisionName() + NEW_LINE; 482 writer.write(s); 483 } 484 485 // services car and engine types 486 s = getLocationTypes(location); 487 writer.write(s); 488 489 List<Track> spurs = location.getTracksByNameList(Track.SPUR); 490 if (spurs.size() > 0) { 491 s = SPACES_3 + Bundle.getMessage("SpurName") + NEW_LINE; 492 writer.write(s); 493 printTrackInfo(location, spurs); 494 } 495 496 List<Track> yards = location.getTracksByNameList(Track.YARD); 497 if (yards.size() > 0) { 498 s = SPACES_3 + Bundle.getMessage("YardName") + NEW_LINE; 499 writer.write(s); 500 printTrackInfo(location, yards); 501 } 502 503 List<Track> interchanges = location.getTracksByNameList(Track.INTERCHANGE); 504 if (interchanges.size() > 0) { 505 s = SPACES_3 + Bundle.getMessage("InterchangeName") + NEW_LINE; 506 writer.write(s); 507 printTrackInfo(location, interchanges); 508 } 509 510 List<Track> staging = location.getTracksByNameList(Track.STAGING); 511 if (staging.size() > 0) { 512 s = SPACES_3 + Bundle.getMessage("StagingName") + NEW_LINE; 513 writer.write(s); 514 printTrackInfo(location, staging); 515 } 516 } 517 if (printAnalysis.isSelected() || printErrorAnalysis.isSelected()) { 518 writer.write(FORM_FEED); 519 } 520 } 521 522 private final boolean showStaging = true; 523 524 private void printAnalysisSelected() throws IOException { 525 CarManager carManager = InstanceManager.getDefault(CarManager.class); 526 List<Location> locations = lmanager.getLocationsByNameList(); 527 List<Car> cars = carManager.getByLocationList(); 528 String[] carTypes = cts.getNames(); 529 530 String s = Bundle.getMessage("TrackAnalysis") + NEW_LINE; 531 writer.write(s); 532 533 // print the car type being analyzed 534 for (String type : carTypes) { 535 // get the total length for a given car type 536 int numberOfCars = 0; 537 int totalTrackLength = 0; 538 for (Car car : cars) { 539 if (car.getTypeName().equals(type) && car.getLocation() != null) { 540 numberOfCars++; 541 totalTrackLength += car.getTotalLength(); 542 } 543 } 544 writer.write(Bundle.getMessage("NumberTypeLength", 545 numberOfCars, type, totalTrackLength, Setup.getLengthUnit().toLowerCase()) + 546 NEW_LINE); 547 // don't bother reporting when the number of cars for a given type 548 // is zero. Round up percentage used by a car type. 549 if (numberOfCars > 0) { 550 // spurs 551 writer.write(SPACES_3 + 552 Bundle.getMessage("SpurTrackThatAccept", type) + 553 NEW_LINE); 554 int trackLength = getTrackLengthAcceptType(locations, type, Track.SPUR); 555 if (trackLength > 0) { 556 writer.write(SPACES_3 + 557 Bundle.getMessage("TotalLengthSpur", type, trackLength, Setup.getLengthUnit().toLowerCase(), 558 Math.ceil((double) 100 * totalTrackLength / trackLength)) + 559 NEW_LINE); 560 } else { 561 writer.write(SPACES_3 + Bundle.getMessage("None") + NEW_LINE); 562 } 563 // yards 564 writer.write(SPACES_3 + 565 Bundle.getMessage("YardTrackThatAccept", type) + 566 NEW_LINE); 567 trackLength = getTrackLengthAcceptType(locations, type, Track.YARD); 568 if (trackLength > 0) { 569 writer.write(SPACES_3 + 570 Bundle.getMessage("TotalLengthYard", type, trackLength, Setup.getLengthUnit().toLowerCase(), 571 Math.ceil((double) 100 * totalTrackLength / trackLength)) + 572 NEW_LINE); 573 } else { 574 writer.write(SPACES_3 + Bundle.getMessage("None") + NEW_LINE); 575 } 576 // interchanges 577 writer.write(SPACES_3 + 578 Bundle.getMessage("InterchangesThatAccept", type) + 579 NEW_LINE); 580 trackLength = getTrackLengthAcceptType(locations, type, Track.INTERCHANGE); 581 if (trackLength > 0) { 582 writer.write(SPACES_3 + 583 Bundle.getMessage("TotalLengthInterchange", 584 type, trackLength, Setup.getLengthUnit().toLowerCase(), 585 Math.ceil((double) 100 * totalTrackLength / trackLength)) + 586 NEW_LINE); 587 } else { 588 writer.write(SPACES_3 + Bundle.getMessage("None") + NEW_LINE); 589 } 590 // staging 591 if (showStaging) { 592 writer.write(SPACES_3 + 593 Bundle.getMessage("StageTrackThatAccept", type) + 594 NEW_LINE); 595 trackLength = getTrackLengthAcceptType(locations, type, Track.STAGING); 596 if (trackLength > 0) { 597 writer.write(SPACES_3 + 598 Bundle.getMessage("TotalLengthStage", 599 type, trackLength, Setup.getLengthUnit().toLowerCase(), 600 Math.ceil((double) 100 * totalTrackLength / trackLength)) + 601 NEW_LINE); 602 } else { 603 writer.write(SPACES_3 + Bundle.getMessage("None") + NEW_LINE); 604 } 605 } 606 } 607 } 608 if (printErrorAnalysis.isSelected()) { 609 writer.write(FORM_FEED); 610 } 611 } 612 613 private void printErrorAnalysisSelected() throws IOException { 614 writer.write(Bundle.getMessage("TrackErrorAnalysis") + NEW_LINE); 615 boolean foundError = false; 616 for (Location location : lmanager.getLocationsByNameList()) { 617 if (_location != null && location != _location) { 618 continue; 619 } 620 writer.write(location.getName() + NEW_LINE); 621 for (Track track : location.getTracksByNameList(null)) { 622 if (!track.checkPickups().equals(Track.PICKUP_OKAY)) { 623 writer.write(TAB + track.checkPickups() + NEW_LINE); 624 foundError = true; 625 } 626 } 627 } 628 if (!foundError) { 629 writer.write(Bundle.getMessage("NoErrors")); 630 } 631 } 632 633 private int getTrackLengthAcceptType(List<Location> locations, String carType, 634 String trackType) 635 throws IOException { 636 int trackLength = 0; 637 for (Location location : locations) { 638 if (_location != null && location != _location) { 639 continue; 640 } 641 List<Track> tracks = location.getTracksByNameList(trackType); 642 for (Track track : tracks) { 643 if (track.isTypeNameAccepted(carType)) { 644 trackLength = trackLength + track.getLength(); 645 writer.write(SPACES_3 + 646 SPACES_3 + 647 Bundle.getMessage("LocationTrackLength", 648 location.getName(), track.getName(), track.getLength(), 649 Setup.getLengthUnit().toLowerCase()) + 650 NEW_LINE); 651 } 652 } 653 } 654 return trackLength; 655 } 656 657 private String getTrackString(Track track) { 658 String s = TAB + 659 padOutString(track.getName(), Control.max_len_string_track_name) + 660 " " + 661 Integer.toString(track.getLength()) + 662 TAB + 663 Integer.toString(track.getUsedLength()) + 664 TAB + 665 Integer.toString(track.getNumberRS()) + 666 TAB + 667 Integer.toString(track.getNumberCars()) + 668 TAB + 669 Integer.toString(track.getNumberEngines()) + 670 TAB + 671 Integer.toString(track.getPickupRS()) + 672 TAB + 673 Integer.toString(track.getDropRS()) + 674 NEW_LINE; 675 return s; 676 } 677 678 private String getDirection(int dir) { 679 if ((Setup.getTrainDirection() & dir) == 0) { 680 return " " + Bundle.getMessage("LocalOnly") + NEW_LINE; 681 } 682 StringBuffer direction = new StringBuffer(" " + Bundle.getMessage("ServicedByTrain") + " "); 683 if ((Setup.getTrainDirection() & dir & Location.NORTH) == Location.NORTH) { 684 direction.append(Bundle.getMessage("North") + " "); 685 } 686 if ((Setup.getTrainDirection() & dir & Location.SOUTH) == Location.SOUTH) { 687 direction.append(Bundle.getMessage("South") + " "); 688 } 689 if ((Setup.getTrainDirection() & dir & Location.EAST) == Location.EAST) { 690 direction.append(Bundle.getMessage("East") + " "); 691 } 692 if ((Setup.getTrainDirection() & dir & Location.WEST) == Location.WEST) { 693 direction.append(Bundle.getMessage("West") + " "); 694 } 695 direction.append(NEW_LINE); 696 return direction.toString(); 697 } 698 699 private void printTrackInfo(Location location, List<Track> tracks) { 700 for (Track track : tracks) { 701 try { 702 String s = TAB + 703 track.getName() + 704 getDirection(location.getTrainDirections() & track.getTrainDirections()); 705 writer.write(s); 706 printIsAlternate(track); 707 writer.write(getTrackCarTypes(track)); 708 writer.write(getTrackEngineTypes(track)); 709 writer.write(getTrackRoads(track)); 710 writer.write(getTrackLoads(track)); 711 writer.write(getTrackShipLoads(track)); 712 writer.write(getCarOrder(track)); 713 writer.write(getSetOutTrains(track)); 714 writer.write(getPickUpTrains(track)); 715 writer.write(getDestinations(track)); 716 writer.write(getTrackInfo(track)); 717 writer.write(getSpurInfo(track)); 718 writer.write(getSchedule(track)); 719 writer.write(getStagingInfo(track)); 720 printIsQuickService(track); 721 writer.write(NEW_LINE); 722 } catch (IOException we) { 723 log.error("Error printing PrintLocationAction: {}", we.getLocalizedMessage()); 724 } 725 } 726 } 727 728 private String getLocationTypes(Location location) { 729 StringBuffer buf = new StringBuffer(TAB + TAB + Bundle.getMessage("TypesServiced") + NEW_LINE + TAB + TAB); 730 int charCount = 0; 731 int typeCount = 0; 732 733 for (String type : cts.getNames()) { 734 if (location.acceptsTypeName(type)) { 735 typeCount++; 736 charCount += type.length() + 2; 737 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 738 buf.append(NEW_LINE + TAB + TAB); 739 charCount = type.length() + 2; 740 } 741 buf.append(type + ", "); 742 } 743 } 744 745 for (String type : InstanceManager.getDefault(EngineTypes.class).getNames()) { 746 if (location.acceptsTypeName(type)) { 747 typeCount++; 748 charCount += type.length() + 2; 749 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 750 buf.append(NEW_LINE + TAB + TAB); 751 charCount = type.length() + 2; 752 } 753 buf.append(type + ", "); 754 } 755 } 756 if (buf.length() > 2) { 757 buf.setLength(buf.length() - 2); // remove trailing separators 758 } 759 // does this location accept all types? 760 if (typeCount == cts.getNames().length + InstanceManager.getDefault(EngineTypes.class).getNames().length) { 761 buf = new StringBuffer(TAB + TAB + Bundle.getMessage("LocationAcceptsAllTypes")); 762 } 763 buf.append(NEW_LINE); 764 return buf.toString(); 765 } 766 767 private String getTrackCarTypes(Track track) { 768 StringBuffer buf = 769 new StringBuffer(TAB + TAB + Bundle.getMessage("CarTypesServicedTrack") + NEW_LINE + TAB + TAB); 770 int charCount = 0; 771 int typeCount = 0; 772 773 for (String type : cts.getNames()) { 774 if (track.isTypeNameAccepted(type)) { 775 typeCount++; 776 charCount += type.length() + 2; 777 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 778 buf.append(NEW_LINE + TAB + TAB); 779 charCount = type.length() + 2; 780 } 781 buf.append(type + ", "); 782 } 783 } 784 if (buf.length() > 2) { 785 buf.setLength(buf.length() - 2); // remove trailing separators 786 } 787 // does this track accept all types? 788 if (typeCount == cts.getNames().length) { 789 buf = new StringBuffer(TAB + TAB + Bundle.getMessage("TrackAcceptsAllCarTypes")); 790 } 791 buf.append(NEW_LINE); 792 return buf.toString(); 793 } 794 795 private String getTrackEngineTypes(Track track) { 796 StringBuffer buf = 797 new StringBuffer(TAB + TAB + Bundle.getMessage("EngineTypesServicedTrack") + NEW_LINE + TAB + TAB); 798 int charCount = 0; 799 int typeCount = 0; 800 801 for (String type : InstanceManager.getDefault(EngineTypes.class).getNames()) { 802 if (track.isTypeNameAccepted(type)) { 803 typeCount++; 804 charCount += type.length() + 2; 805 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 806 buf.append(NEW_LINE + TAB + TAB); 807 charCount = type.length() + 2; 808 } 809 buf.append(type + ", "); 810 } 811 } 812 if (buf.length() > 2) { 813 buf.setLength(buf.length() - 2); // remove trailing separators 814 } 815 // does this track accept all types? 816 if (typeCount == InstanceManager.getDefault(EngineTypes.class).getNames().length) { 817 buf = new StringBuffer(TAB + TAB + Bundle.getMessage("TrackAcceptsAllEngTypes")); 818 } 819 buf.append(NEW_LINE); 820 return buf.toString(); 821 } 822 823 private String getTrackRoads(Track track) { 824 if (track.getRoadOption().equals(Track.ALL_ROADS)) { 825 return TAB + TAB + Bundle.getMessage("AcceptsAllRoads") + NEW_LINE; 826 } 827 828 String op = Bundle.getMessage("RoadsServicedTrack"); 829 if (track.getRoadOption().equals(Track.EXCLUDE_ROADS)) { 830 op = Bundle.getMessage("ExcludeRoadsTrack"); 831 } 832 833 StringBuffer buf = new StringBuffer(TAB + TAB + op + NEW_LINE + TAB + TAB); 834 int charCount = 0; 835 836 for (String road : track.getRoadNames()) { 837 charCount += road.length() + 2; 838 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 839 buf.append(NEW_LINE + TAB + TAB); 840 charCount = road.length() + 2; 841 } 842 buf.append(road + ", "); 843 } 844 if (buf.length() > 2) { 845 buf.setLength(buf.length() - 2); // remove trailing separators 846 } 847 buf.append(NEW_LINE); 848 return buf.toString(); 849 } 850 851 private String getTrackLoads(Track track) { 852 if (track.getLoadOption().equals(Track.ALL_LOADS)) { 853 return TAB + TAB + Bundle.getMessage("AcceptsAllLoads") + NEW_LINE; 854 } 855 856 String op = Bundle.getMessage("LoadsServicedTrack"); 857 if (track.getLoadOption().equals(Track.EXCLUDE_LOADS)) { 858 op = Bundle.getMessage("ExcludeLoadsTrack"); 859 } 860 861 StringBuffer buf = new StringBuffer(TAB + TAB + op + NEW_LINE + TAB + TAB); 862 int charCount = 0; 863 864 for (String load : track.getLoadNames()) { 865 charCount += load.length() + 2; 866 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 867 buf.append(NEW_LINE + TAB + TAB); 868 charCount = load.length() + 2; 869 } 870 buf.append(load + ", "); 871 } 872 if (buf.length() > 2) { 873 buf.setLength(buf.length() - 2); // remove trailing separators 874 } 875 buf.append(NEW_LINE); 876 return buf.toString(); 877 } 878 879 private String getTrackShipLoads(Track track) { 880 // only staging has the ship load control 881 if (!track.isStaging()) { 882 return ""; 883 } 884 if (track.getShipLoadOption().equals(Track.ALL_LOADS)) { 885 return TAB + TAB + Bundle.getMessage("ShipsAllLoads") + NEW_LINE; 886 } 887 String op = Bundle.getMessage("LoadsShippedTrack"); 888 if (track.getShipLoadOption().equals(Track.EXCLUDE_LOADS)) { 889 op = Bundle.getMessage("ExcludeLoadsShippedTrack"); 890 } 891 892 StringBuffer buf = new StringBuffer(TAB + TAB + op + NEW_LINE + TAB + TAB); 893 int charCount = 0; 894 895 for (String load : track.getShipLoadNames()) { 896 charCount += load.length() + 2; 897 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 898 buf.append(NEW_LINE + TAB + TAB); 899 charCount = load.length() + 2; 900 } 901 buf.append(load + ", "); 902 } 903 if (buf.length() > 2) { 904 buf.setLength(buf.length() - 2); // remove trailing separators 905 } 906 buf.append(NEW_LINE); 907 return buf.toString(); 908 } 909 910 private String getCarOrder(Track track) { 911 // only yards and interchanges have the car order option 912 if (track.isSpur() || track.isStaging() || track.getServiceOrder().equals(Track.NORMAL)) { 913 return ""; 914 } 915 if (track.getServiceOrder().equals(Track.FIFO)) { 916 return TAB + TAB + Bundle.getMessage("TrackPickUpOrderFIFO") + NEW_LINE; 917 } 918 return TAB + TAB + Bundle.getMessage("TrackPickUpOrderLIFO") + NEW_LINE; 919 } 920 921 private String getSetOutTrains(Track track) { 922 if (track.getDropOption().equals(Track.ANY)) { 923 return TAB + TAB + Bundle.getMessage("SetOutAllTrains") + NEW_LINE; 924 } 925 StringBuffer buf; 926 int charCount = 0; 927 String[] ids = track.getDropIds(); 928 if (track.getDropOption().equals(Track.TRAINS) || track.getDropOption().equals(Track.EXCLUDE_TRAINS)) { 929 String trainType = Bundle.getMessage("TrainsSetOutTrack"); 930 if (track.getDropOption().equals(Track.EXCLUDE_TRAINS)) { 931 trainType = Bundle.getMessage("ExcludeTrainsSetOutTrack"); 932 } 933 buf = new StringBuffer(TAB + TAB + trainType + NEW_LINE + TAB + TAB); 934 for (String id : ids) { 935 Train train = InstanceManager.getDefault(TrainManager.class).getTrainById(id); 936 if (train == null) { 937 log.info("Could not find a train for id: {} track ({})", id, track.getName()); 938 continue; 939 } 940 charCount += train.getName().length() + 2; 941 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 942 buf.append(NEW_LINE + TAB + TAB); 943 charCount = train.getName().length() + 2; 944 } 945 buf.append(train.getName() + ", "); 946 } 947 } else { 948 String routeType = Bundle.getMessage("RoutesSetOutTrack"); 949 if (track.getDropOption().equals(Track.EXCLUDE_ROUTES)) { 950 routeType = Bundle.getMessage("ExcludeRoutesSetOutTrack"); 951 } 952 buf = new StringBuffer(TAB + TAB + routeType + NEW_LINE + TAB + TAB); 953 for (String id : ids) { 954 Route route = InstanceManager.getDefault(RouteManager.class).getRouteById(id); 955 if (route == null) { 956 log.info("Could not find a route for id: {} location ({}) track ({})", id, 957 track.getLocation().getName(), track.getName()); // NOI18N 958 continue; 959 } 960 charCount += route.getName().length() + 2; 961 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 962 buf.append(NEW_LINE + TAB + TAB); 963 charCount = route.getName().length() + 2; 964 } 965 buf.append(route.getName() + ", "); 966 } 967 } 968 if (buf.length() > 2) { 969 buf.setLength(buf.length() - 2); // remove trailing separators 970 } 971 buf.append(NEW_LINE); 972 return buf.toString(); 973 } 974 975 private String getPickUpTrains(Track track) { 976 if (track.getPickupOption().equals(Track.ANY)) { 977 return TAB + TAB + Bundle.getMessage("PickUpAllTrains") + NEW_LINE; 978 } 979 StringBuffer buf; 980 int charCount = 0; 981 String[] ids = track.getPickupIds(); 982 if (track.getPickupOption().equals(Track.TRAINS) || track.getPickupOption().equals(Track.EXCLUDE_TRAINS)) { 983 String trainType = Bundle.getMessage("TrainsPickUpTrack"); 984 if (track.getPickupOption().equals(Track.EXCLUDE_TRAINS)) { 985 trainType = Bundle.getMessage("ExcludeTrainsPickUpTrack"); 986 } 987 buf = new StringBuffer(TAB + TAB + trainType + NEW_LINE + TAB + TAB); 988 for (String id : ids) { 989 Train train = InstanceManager.getDefault(TrainManager.class).getTrainById(id); 990 if (train == null) { 991 log.info("Could not find a train for id: {} track ({})", id, track.getName()); 992 continue; 993 } 994 charCount += train.getName().length() + 2; 995 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 996 buf.append(NEW_LINE + TAB + TAB); 997 charCount = train.getName().length() + 2; 998 } 999 buf.append(train.getName() + ", "); 1000 } 1001 } else { 1002 String routeType = Bundle.getMessage("RoutesPickUpTrack"); 1003 if (track.getPickupOption().equals(Track.EXCLUDE_ROUTES)) { 1004 routeType = Bundle.getMessage("ExcludeRoutesPickUpTrack"); 1005 } 1006 buf = new StringBuffer(TAB + TAB + routeType + NEW_LINE + TAB + TAB); 1007 for (String id : ids) { 1008 Route route = InstanceManager.getDefault(RouteManager.class).getRouteById(id); 1009 if (route == null) { 1010 log.info("Could not find a route for id: {} location ({}) track ({})", id, 1011 track.getLocation().getName(), track.getName()); // NOI18N 1012 continue; 1013 } 1014 charCount += route.getName().length() + 2; 1015 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 1016 buf.append(NEW_LINE + TAB + TAB); 1017 charCount = route.getName().length() + 2; 1018 } 1019 buf.append(route.getName() + ", "); 1020 } 1021 } 1022 if (buf.length() > 2) { 1023 buf.setLength(buf.length() - 2); // remove trailing separators 1024 } 1025 buf.append(NEW_LINE); 1026 return buf.toString(); 1027 } 1028 1029 private String getDestinations(Track track) { 1030 StringBuffer buf = new StringBuffer(); 1031 if (track.isOnlyCarsWithFinalDestinationEnabled()) { 1032 buf.append(TAB + TAB + Bundle.getMessage("OnlyCarsWithFD")); 1033 buf.append(NEW_LINE); 1034 } 1035 if (track.getDestinationOption().equals(Track.ALL_DESTINATIONS)) { 1036 return buf.toString(); 1037 } 1038 String op = Bundle.getMessage( 1039 "AcceptOnly") + " " + track.getDestinationListSize() + " " + Bundle.getMessage("Destinations") + ":"; 1040 if (track.getDestinationOption().equals(Track.EXCLUDE_DESTINATIONS)) { 1041 op = Bundle.getMessage("Exclude") + 1042 " " + 1043 (lmanager.getNumberOfLocations() - track.getDestinationListSize()) + 1044 " " + 1045 Bundle.getMessage("Destinations") + 1046 ":"; 1047 } 1048 buf.append(TAB + TAB + op + NEW_LINE + TAB + TAB); 1049 String[] destIds = track.getDestinationIds(); 1050 int charCount = 0; 1051 for (String id : destIds) { 1052 Location location = lmanager.getLocationById(id); 1053 if (location == null) { 1054 continue; 1055 } 1056 charCount += location.getName().length() + 2; 1057 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 1058 buf.append(NEW_LINE + TAB + TAB); 1059 charCount = location.getName().length() + 2; 1060 } 1061 buf.append(location.getName() + ", "); 1062 } 1063 if (buf.length() > 2) { 1064 buf.setLength(buf.length() - 2); // remove trailing separators 1065 } 1066 buf.append(NEW_LINE); 1067 return buf.toString(); 1068 } 1069 1070 private String getTrackInfo(Track track) { 1071 if (track.getPool() != null) { 1072 StringBuffer buf = 1073 new StringBuffer(TAB + TAB + Bundle.getMessage("Pool") + ": " + track.getPoolName() + NEW_LINE); 1074 return buf.toString(); 1075 } 1076 return ""; 1077 } 1078 1079 private String getSchedule(Track track) { 1080 // only spurs have schedules 1081 if (!track.isSpur() || track.getSchedule() == null) { 1082 return ""; 1083 } 1084 StringBuffer buf = new StringBuffer(TAB + 1085 TAB + 1086 Bundle.getMessage("TrackScheduleName", track.getScheduleName()) + 1087 NEW_LINE); 1088 if (track.getAlternateTrack() != null) { 1089 buf.append(TAB + 1090 TAB + 1091 Bundle.getMessage("AlternateTrackName", 1092 track.getAlternateTrack().getName()) + 1093 NEW_LINE); 1094 } 1095 if (track.getReservationFactor() != 100) { 1096 buf.append(TAB + 1097 TAB + 1098 Bundle.getMessage("PercentageStaging", 1099 track.getReservationFactor()) + 1100 NEW_LINE); 1101 } 1102 return buf.toString(); 1103 } 1104 1105 private void printIsAlternate(Track track) throws IOException { 1106 if (track.isAlternate()) { 1107 writer.write(TAB + TAB + Bundle.getMessage("AlternateTrack") + NEW_LINE); 1108 } 1109 } 1110 1111 private void printIsQuickService(Track track) throws IOException { 1112 if (track.isQuickServiceEnabled()) { 1113 writer.write(TAB + TAB + Bundle.getMessage("QuickService") + NEW_LINE); 1114 } 1115 } 1116 1117 private String getSpurInfo(Track track) { 1118 if (!track.isSpur()) { 1119 return ""; 1120 } 1121 1122 StringBuffer buf = new StringBuffer(); 1123 1124 if (track.isHoldCarsWithCustomLoadsEnabled()) { 1125 buf.append(TAB + TAB + Bundle.getMessage("HoldCarsWithCustomLoads") + NEW_LINE); 1126 } 1127 if (track.isDisableLoadChangeEnabled()) { 1128 buf.append(TAB + TAB + Bundle.getMessage("DisableLoadChange") + NEW_LINE); 1129 } 1130 return buf.toString(); 1131 } 1132 1133 private String getStagingInfo(Track track) { 1134 if (!track.isStaging()) { 1135 return ""; 1136 } 1137 1138 StringBuffer buf = new StringBuffer(); 1139 1140 if (track.isLoadSwapEnabled() || track.isLoadEmptyEnabled()) { 1141 buf.append(TAB + SPACES_3 + Bundle.getMessage("OptionalLoads") + NEW_LINE); 1142 if (track.isLoadSwapEnabled()) { 1143 buf.append(TAB + TAB + Bundle.getMessage("SwapCarLoads") + NEW_LINE); 1144 } 1145 if (track.isLoadEmptyEnabled()) { 1146 buf.append(TAB + TAB + Bundle.getMessage("EmptyDefaultCarLoads") + NEW_LINE); 1147 } 1148 } 1149 1150 if (track.isRemoveCustomLoadsEnabled() || 1151 track.isAddCustomLoadsEnabled() || 1152 track.isAddCustomLoadsAnySpurEnabled() || 1153 track.isAddCustomLoadsAnyStagingTrackEnabled()) { 1154 buf.append(TAB + SPACES_3 + Bundle.getMessage("OptionalCustomLoads") + NEW_LINE); 1155 if (track.isRemoveCustomLoadsEnabled()) { 1156 buf.append(TAB + TAB + Bundle.getMessage("EmptyCarLoads") + NEW_LINE); 1157 } 1158 if (track.isAddCustomLoadsEnabled()) { 1159 buf.append(TAB + TAB + Bundle.getMessage("LoadCarLoads") + NEW_LINE); 1160 } 1161 if (track.isAddCustomLoadsAnySpurEnabled()) { 1162 buf.append(TAB + TAB + Bundle.getMessage("LoadAnyCarLoads") + NEW_LINE); 1163 } 1164 if (track.isAddCustomLoadsAnyStagingTrackEnabled()) { 1165 buf.append(TAB + TAB + Bundle.getMessage("LoadsStaging") + NEW_LINE); 1166 } 1167 } 1168 1169 if (track.isBlockCarsEnabled()) { 1170 buf.append(TAB + SPACES_3 + Bundle.getMessage("OptionalBlocking") + NEW_LINE); 1171 buf.append(TAB + TAB + Bundle.getMessage("BlockCars") + NEW_LINE); 1172 } 1173 return buf.toString(); 1174 } 1175 1176 private String padOutString(String s, int length) { 1177 return TrainCommon.padAndTruncate(s, length); 1178 } 1179 1180 private final static Logger log = LoggerFactory.getLogger(PrintLocationsFrame.class); 1181}