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