001package jmri.jmrit.operations.rollingstock.engines; 002 003import java.beans.PropertyChangeEvent; 004import java.util.*; 005 006import org.jdom2.Element; 007import org.slf4j.Logger; 008import org.slf4j.LoggerFactory; 009 010import jmri.*; 011import jmri.jmrit.operations.rollingstock.RollingStock; 012import jmri.jmrit.operations.rollingstock.RollingStockManager; 013import jmri.jmrit.operations.setup.OperationsSetupXml; 014import jmri.jmrit.operations.trains.Train; 015import jmri.jmrit.operations.trains.TrainManifestHeaderText; 016 017/** 018 * Manages the engines. 019 * 020 * @author Daniel Boudreau Copyright (C) 2008 021 */ 022public class EngineManager extends RollingStockManager<Engine> 023 implements InstanceManagerAutoDefault, InstanceManagerAutoInitialize { 024 025 public EngineManager() { 026 } 027 028 /** 029 * Finds an existing engine or creates a new engine if needed requires engine's 030 * road and number 031 * 032 * @param engineRoad The engine's road initials 033 * @param engineNumber The engine's road number 034 * 035 * @return new engine or existing engine 036 */ 037 @Override 038 public Engine newRS(String engineRoad, String engineNumber) { 039 Engine engine = getByRoadAndNumber(engineRoad, engineNumber); 040 if (engine == null) { 041 engine = new Engine(engineRoad, engineNumber); 042 register(engine); 043 } 044 return engine; 045 } 046 047 @Override 048 public void deregister(Engine engine) { 049 super.deregister(engine); 050 InstanceManager.getDefault(EngineManagerXml.class).setDirty(true); 051 } 052 053 /** 054 * Sort by engine model 055 * 056 * @return list of engines ordered by engine model 057 */ 058 public List<Engine> getByModelList() { 059 return getByList(getByRoadNameList(), BY_MODEL); 060 } 061 062 /** 063 * Sort by engine consist 064 * 065 * @return list of engines ordered by engine consist 066 */ 067 public List<Engine> getByConsistList() { 068 return getByList(getByRoadNameList(), BY_CONSIST); 069 } 070 071 public List<Engine> getByHpList() { 072 return getByList(getByModelList(), BY_HP); 073 } 074 075 // The special sort options for engines 076 private static final int BY_MODEL = 30; 077 private static final int BY_CONSIST = 31; 078 private static final int BY_HP = 32; 079 080 // add engine options to sort comparator 081 @Override 082 protected java.util.Comparator<Engine> getComparator(int attribute) { 083 switch (attribute) { 084 case BY_MODEL: 085 return (e1, e2) -> (e1.getModel().compareToIgnoreCase(e2.getModel())); 086 case BY_CONSIST: 087 return (e1, e2) -> (e1.getConsistName().compareToIgnoreCase(e2.getConsistName())); 088 case BY_HP: 089 return (e1, e2) -> (e1.getHpInteger() - e2.getHpInteger()); 090 default: 091 return super.getComparator(attribute); 092 } 093 } 094 095 /** 096 * return a list available engines (no assigned train) engines are ordered least 097 * recently moved to most recently moved. 098 * 099 * @param train The Train requesting this list. 100 * 101 * @return Ordered list of engines not assigned to a train 102 */ 103 public List<Engine> getAvailableTrainList(Train train) { 104 // now build list of available engines for this route 105 List<Engine> out = new ArrayList<>(); 106 // get engines by moves list 107 for (RollingStock rs : getByMovesList()) { 108 Engine engine = (Engine) rs; 109 if (engine.getTrack() != null && (engine.getTrain() == null || engine.getTrain() == train)) { 110 out.add(engine); 111 } 112 } 113 return out; 114 } 115 116 /** 117 * Returns a list of locos sorted by blocking number for a train. This returns a 118 * list of consisted locos in the order that they were entered in. 119 * 120 * @param train The Train requesting this list. 121 * @return A list of sorted locos. 122 */ 123 public List<Engine> getByTrainBlockingList(Train train) { 124 return getByList(super.getByTrainList(train), BY_BLOCKING); 125 } 126 127 /** 128 * Get a list of engine road names. 129 * 130 * @param model The string model name, can be NONE. 131 * 132 * @return List of engine road names. 133 */ 134 public List<String> getEngineRoadNames(String model) { 135 List<String> names = new ArrayList<>(); 136 Enumeration<String> en = _hashTable.keys(); 137 while (en.hasMoreElements()) { 138 Engine engine = getById(en.nextElement()); 139 if ((engine.getModel().equals(model) || model.equals(NONE)) && !names.contains(engine.getRoadName())) { 140 names.add(engine.getRoadName()); 141 } 142 } 143 java.util.Collections.sort(names); 144 return names; 145 } 146 147 int _commentLength = 0; 148 149 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( value="SLF4J_FORMAT_SHOULD_BE_CONST", 150 justification="I18N of Info Message") 151 public int getMaxCommentLength() { 152 if (_commentLength == 0) { 153 _commentLength = TrainManifestHeaderText.getStringHeader_Comment().length(); 154 String comment = ""; 155 Engine engineMax = null; 156 for (Engine engine : getList()) { 157 if (engine.getComment().length() > _commentLength) { 158 _commentLength = engine.getComment().length(); 159 comment = engine.getComment(); 160 engineMax = engine; 161 } 162 } 163 if (engineMax != null) { 164 log.info(Bundle.getMessage("InfoMaxComment", engineMax.toString(), comment, _commentLength)); 165 } 166 } 167 return _commentLength; 168 } 169 170 public void load(Element root) { 171 if (root.getChild(Xml.ENGINES) != null) { 172 List<Element> engines = root.getChild(Xml.ENGINES).getChildren(Xml.ENGINE); 173 log.debug("readFile sees {} engines", engines.size()); 174 for (Element e : engines) { 175 register(new Engine(e)); 176 } 177 } 178 } 179 180 /** 181 * Create an XML element to represent this Entry. This member has to remain 182 * synchronized with the detailed DTD in operations-engines.dtd. 183 * 184 * @param root The common Element for operations-engines.dtd. 185 * 186 */ 187 public void store(Element root) { 188 Element values; 189 root.addContent(values = new Element(Xml.ENGINES)); 190 // add entries 191 for (RollingStock rs : getByRoadNameList()) { 192 Engine eng = (Engine) rs; 193 values.addContent(eng.store()); 194 } 195 } 196 197 protected void setDirtyAndFirePropertyChange(String p, Object old, Object n) { 198 // Set dirty 199 InstanceManager.getDefault(EngineManagerXml.class).setDirty(true); 200 super.firePropertyChange(p, old, n); 201 } 202 203 @Override 204 public void propertyChange(PropertyChangeEvent evt) { 205 if (evt.getPropertyName().equals(Engine.COMMENT_CHANGED_PROPERTY)) { 206 _commentLength = 0; 207 } 208 super.propertyChange(evt); 209 } 210 211 private final static Logger log = LoggerFactory.getLogger(EngineManager.class); 212 213 @Override 214 public void initialize() { 215 InstanceManager.getDefault(OperationsSetupXml.class); // load setup 216 // create manager to load engines and their attributes 217 InstanceManager.getDefault(EngineManagerXml.class); 218 } 219}