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