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