001package jmri.jmrit.operations.locations; 002 003import java.util.ArrayList; 004import java.util.List; 005 006import org.slf4j.Logger; 007import org.slf4j.LoggerFactory; 008 009import jmri.beans.Bean; 010 011/** 012 * Represents a pool of tracks that share their length. 013 * 014 * @author Daniel Boudreau Copyright (C) 2011 015 * @author Gregory Madsen Copyright (C) 2012 016 * 017 */ 018public class Pool extends Bean { 019 020 public static final String LISTCHANGE_CHANGED_PROPERTY = "poolListChange"; // NOI18N 021 public static final String DISPOSE = "poolDispose"; // NOI18N 022 023 private final static Logger log = LoggerFactory.getLogger(Pool.class); 024 025 // stores tracks for this pool 026 protected List<Track> _tracks = new ArrayList<>(); 027 028 protected String _id = ""; 029 030 public String getId() { 031 return _id; 032 } 033 034 protected String _name = ""; 035 036 public String getName() { 037 return _name; 038 } 039 040 public void setName(String name) { 041 String old = _name; 042 _name = name; 043 this.propertyChangeSupport.firePropertyChange("Name", old, name); 044 } 045 046 /** 047 * The number of tracks in this pool. 048 * 049 * @return the number of tracks in this pool. 050 */ 051 public int getSize() { 052 return _tracks.size(); 053 } 054 055 // for combo boxes 056 @Override 057 public String toString() { 058 return _name; 059 } 060 061 public Pool(String id, String name) { 062 super(false); 063 log.debug("New pool ({}) id: {}", name, id); 064 _name = name; 065 _id = id; 066 } 067 068 public void dispose() { 069 firePropertyChange(DISPOSE, null, DISPOSE); 070 } 071 072 /** 073 * Adds a track to this pool 074 * 075 * @param track to be added. 076 */ 077 public void add(Track track) { 078 if (!_tracks.contains(track)) { 079 080 int oldSize = _tracks.size(); 081 _tracks.add(track); 082 083 firePropertyChange(LISTCHANGE_CHANGED_PROPERTY, oldSize, _tracks.size()); 084 } 085 } 086 087 /** 088 * Removes a track from this pool 089 * 090 * @param track to be removed. 091 */ 092 public void remove(Track track) { 093 if (_tracks.contains(track)) { 094 095 int oldSize = _tracks.size(); 096 _tracks.remove(track); 097 098 firePropertyChange(LISTCHANGE_CHANGED_PROPERTY, oldSize, _tracks.size()); 099 } 100 } 101 102 public List<Track> getTracks() { 103 // Return a copy to protect the internal list 104 return new ArrayList<>(_tracks); 105 } 106 107 public int getTotalLengthTracks() { 108 return getTracks().stream().map(track -> track.getLength()).reduce(0, Integer::sum); 109 } 110 111 public int getMaxLengthTrack(Track track) { 112 int length = getTotalLengthTracks(); 113 for (Track t : getTracks()) { 114 if (t == track) { 115 continue; 116 } 117 length = length - t.getMinimumLength(); 118 } 119 return length; 120 } 121 122 /** 123 * Request track length from one of the other tracks in this pool. Other 124 * tracks in the same pool may have their length shortened or lengthened by 125 * this operation. 126 * 127 * @param track the track requesting additional length 128 * @param length the length of rolling stock 129 * @return true if successful 130 */ 131 public boolean requestTrackLength(Track track, int length) { 132 // only request enough length for the rolling stock to fit 133 int additionalLength = track.getUsedLength() + track.getReserved() + length - track.getLength(); 134 135 for (Track t : getTracks()) { 136 // note that the reserved track length can be either positive or negative 137 if (t != track) { 138 if (t.getUsedLength() + t.getReserved() + additionalLength <= t.getLength() 139 && t.getLength() - additionalLength >= t.getMinimumLength()) { 140 log.debug("Pool ({}) increasing track ({}) length ({}) decreasing ({})", getName(), 141 track.getName(), additionalLength, t.getName()); // NOI18N 142 t.setLength(t.getLength() - additionalLength); 143 track.setLength(track.getLength() + additionalLength); 144 return true; 145 } else { 146 // steal whatever isn't being used by this track 147 int available = t.getLength() - (t.getUsedLength() + t.getReserved()); 148 int min = t.getLength() - t.getMinimumLength(); 149 if (min < available) { 150 available = min; 151 } 152 if (available > 0) { 153 // adjust track lengths and reduce the additional length needed 154 log.debug("Pool ({}) incremental increase for track ({}) length ({}) decreasing ({})", 155 getName(), track.getName(), available, t.getName()); // NOI18N 156 t.setLength(t.getLength() - available); 157 track.setLength(track.getLength() + available); 158 additionalLength = additionalLength - available; 159 } 160 } 161 } 162 } 163 return false; 164 } 165}