001package jmri.jmrit.operations.trains.manualtrainbuilder;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006import jmri.InstanceManager;
007import jmri.beans.PropertyChangeSupport;
008import jmri.jmrit.operations.locations.*;
009import jmri.jmrit.operations.routes.RouteLocation;
010import jmri.jmrit.operations.routes.RouteManager;
011import jmri.jmrit.operations.trains.TrainManagerXml;
012import jmri.jmrit.operations.trains.schedules.TrainSchedule;
013import jmri.jmrit.operations.trains.schedules.TrainScheduleManager;
014
015/**
016 * Represents one manual build item of a manual build.
017 *
018 * @author Daniel Boudreau Copyright (C) 2026
019 */
020public class TrainManualBuildItem extends PropertyChangeSupport {
021
022    public static final String NONE = ""; // NOI18N
023
024    protected String _id = NONE;
025    protected int _sequenceId = 0; // used to determine order in the manual build
026    protected String _type = NONE; // the type of car
027    protected String _road = NONE; // the car road
028    protected String _load = NONE; // the car load
029    protected RouteLocation _routeLocation = null; // car route location
030    protected Track _trackLocation = null;// car location track
031    protected Location _destination = null; // car destination
032    protected Track _trackDestination = null;// car destination track
033    protected String _trainScheduleId = NONE; // which day of the week to pickup car
034    protected int _count = 1;
035    protected boolean _warn = false; // when true issue warning
036    protected boolean _fail = false; // when true issue build failure
037    protected boolean _remove = false; // when true issue build failure
038
039    public static final String TRAIN_SCHEDULE_CHANGED_PROPERTY = "trainScheduleProteryId"; // NOI18N
040    public static final String TYPE_CHANGED_PROPERTY = "manualItemType"; // NOI18N
041    public static final String ROAD_CHANGED_PROPERTY = "manualItemRoad"; // NOI18N
042    public static final String LOAD_CHANGED_PROPERTY = "manualItemLoad"; // NOI18N
043    public static final String ROUTE_LOCATION_CHANGED_PROPERTY = "manualItemRouteLocation"; // NOI18N
044    public static final String LOCATION_TRACK_CHANGED_PROPERTY = "manualItemLocationTrack"; // NOI18N
045    public static final String DESTINATION_CHANGED_PROPERTY = "manualItemDestination"; // NOI18N
046    public static final String DESTINATION_TRACK_CHANGED_PROPERTY = "manualItemDestinationTrack"; // NOI18N
047    public static final String COUNT_CHANGED_PROPERTY = "manualItemCount"; // NOI18N
048    public static final String WARN_CHANGED_PROPERTY = "manualItemWarn"; // NOI18N
049    public static final String FAIL_CHANGED_PROPERTY = "manualItemFail"; // NOI18N
050    public static final String REMOVE_CHANGED_PROPERTY = "manualItemRemove"; // NOI18N
051    public static final String DISPOSE = "manualItemDispose"; // NOI18N
052
053    /**
054     * @param id ManualItem string id
055     */
056    public TrainManualBuildItem(String id) {
057        log.debug("New manual build item id: {}", id);
058        _id = id;
059    }
060
061    public String getId() {
062        return _id;
063    }
064
065    public int getSequenceId() {
066        return _sequenceId;
067    }
068
069    public void setSequenceId(int sequence) {
070        // property change not needed
071        _sequenceId = sequence;
072    }
073
074    public String getTypeName() {
075        return _type;
076    }
077
078    /**
079     * Sets the type of car requested.
080     *
081     * @param type The car type requested.
082     */
083    public void setTypeName(String type) {
084        String old = _type;
085        _type = type;
086        setDirtyAndFirePropertyChange(TYPE_CHANGED_PROPERTY, old, type);
087    }
088
089    public String getTrainScheduleId() {
090        return _trainScheduleId;
091    }
092
093    public String getTrainScheduleName() {
094        String name = NONE;
095        TrainSchedule sch = InstanceManager.getDefault(TrainScheduleManager.class)
096                .getScheduleById(getTrainScheduleId());
097        if (sch != null) {
098            name = sch.getName();
099        }
100        return name;
101    }
102
103    public void setTrainScheduleId(String id) {
104        String old = _trainScheduleId;
105        _trainScheduleId = id;
106        setDirtyAndFirePropertyChange(TRAIN_SCHEDULE_CHANGED_PROPERTY, old, id);
107    }
108
109    public String getRoadName() {
110        return _road;
111    }
112
113    /**
114     * Sets the requested car road name.
115     *
116     * @param road The car road requested.
117     */
118    public void setRoadName(String road) {
119        String old = _road;
120        _road = road;
121        setDirtyAndFirePropertyChange(ROAD_CHANGED_PROPERTY, old, road);
122    }
123
124    /**
125     * Sets the car load requested.
126     *
127     * @param load The load name requested.
128     */
129    public void setLoadName(String load) {
130        String old = _load;
131        _load = load;
132        setDirtyAndFirePropertyChange(LOAD_CHANGED_PROPERTY, old, load);
133    }
134
135    public String getLoadName() {
136        return _load;
137    }
138
139    public RouteLocation getRouteLocation() {
140        return _routeLocation;
141    }
142
143    public void setRouteLocation(RouteLocation rl) {
144        RouteLocation old = _routeLocation;
145        _routeLocation = rl;
146        setDirtyAndFirePropertyChange(ROUTE_LOCATION_CHANGED_PROPERTY, old, rl);
147    }
148
149    public String getLocationName() {
150        if (_routeLocation != null) {
151            return _routeLocation.getName();
152        }
153        return NONE;
154    }
155
156    public String getRouteLocationId() {
157        if (_routeLocation != null) {
158            return _routeLocation.getId();
159        }
160        return NONE;
161    }
162
163    public Track getLocationTrack() {
164        return _trackLocation;
165    }
166
167    public void setLocationTrack(Track track) {
168        Track old = _trackLocation;
169        _trackLocation = track;
170        setDirtyAndFirePropertyChange(LOCATION_TRACK_CHANGED_PROPERTY, old, track);
171    }
172
173    public String getLocationTrackName() {
174        if (_trackLocation != null) {
175            return _trackLocation.getName();
176        }
177        return NONE;
178    }
179
180    public String getLocationTrackId() {
181        if (_trackLocation != null) {
182            return _trackLocation.getId();
183        }
184        return NONE;
185    }
186
187    public Location getDestination() {
188        return _destination;
189    }
190
191    public void setDestination(Location destination) {
192        Location old = _destination;
193        _destination = destination;
194        setDirtyAndFirePropertyChange(DESTINATION_CHANGED_PROPERTY, old, destination);
195    }
196
197    public String getDestinationName() {
198        if (_destination != null) {
199            return _destination.getName();
200        }
201        return NONE;
202    }
203
204    public String getDestinationId() {
205        if (_destination != null) {
206            return _destination.getId();
207        }
208        return NONE;
209    }
210
211    public Track getDestinationTrack() {
212        return _trackDestination;
213    }
214
215    public void setDestinationTrack(Track track) {
216        Track old = _trackDestination;
217        _trackDestination = track;
218        setDirtyAndFirePropertyChange(DESTINATION_TRACK_CHANGED_PROPERTY, old, track);
219    }
220
221    public String getDestinationTrackName() {
222        if (_trackDestination != null) {
223            return _trackDestination.getName();
224        }
225        return NONE;
226    }
227
228    public String getDestinationTrackId() {
229        if (_trackDestination != null) {
230            return _trackDestination.getId();
231        }
232        return NONE;
233    }
234    
235    public int getCount() {
236        return _count;
237    }
238
239    public void setCount(int count) {
240        int old = _count;
241        _count = count;
242        setDirtyAndFirePropertyChange(COUNT_CHANGED_PROPERTY, old, count);
243    }
244    
245    public boolean isWarnEnabled() {
246        return _warn;
247    }
248    
249    public void setWarnEnabled(boolean warn) {
250        boolean old = _warn;
251        _warn = warn;
252        setDirtyAndFirePropertyChange(WARN_CHANGED_PROPERTY, old, warn);
253    }
254    
255    public boolean isFailEnabled() {
256        return _fail;
257    }
258    
259    public void setFailEnabled(boolean fail) {
260        boolean old = _fail;
261        _fail = fail;
262        setDirtyAndFirePropertyChange(FAIL_CHANGED_PROPERTY, old, fail);
263    }
264    
265    public boolean isRemoveEnabled() {
266        return _remove;
267    }
268    
269    public void setRemoveEnabled(boolean fail) {
270        boolean old = _remove;
271        _remove = fail;
272        setDirtyAndFirePropertyChange(REMOVE_CHANGED_PROPERTY, old, fail);
273    }
274    
275    protected void setDirtyAndFirePropertyChange(String p, Object old, Object n) {
276        InstanceManager.getDefault(TrainManagerXml.class).setDirty(true);
277        firePropertyChange(p, old, n);
278    }
279
280    public void copyManualBuildItem(TrainManualBuildItem mbi) {
281        setCount(mbi.getCount());
282        setTypeName(mbi.getTypeName());
283        setLoadName(mbi.getLoadName());
284        setRoadName(mbi.getRoadName());
285        setRouteLocation(mbi.getRouteLocation());
286        setLocationTrack(mbi.getLocationTrack());
287        setDestination(mbi.getDestination());
288        setDestinationTrack(mbi.getDestinationTrack());
289        setTrainScheduleId(mbi.getTrainScheduleId());
290        setFailEnabled(mbi.isFailEnabled());
291        setWarnEnabled(mbi.isWarnEnabled());
292    }
293
294    public void dispose() {
295        firePropertyChange(DISPOSE, null, DISPOSE);
296    }
297
298    /**
299     * Construct this Entry from XML. This member has to remain synchronized
300     * with the detailed DTD in operations-config.xml
301     *
302     * @param e Consist XML element
303     */
304    public TrainManualBuildItem(org.jdom2.Element e) {
305        org.jdom2.Attribute a;
306        if ((a = e.getAttribute(Xml.ID)) != null) {
307            _id = a.getValue();
308        } else {
309            log.warn("no id attribute in Schedule Item element when reading operations");
310        }
311        if ((a = e.getAttribute(Xml.SEQUENCE_ID)) != null) {
312            _sequenceId = Integer.parseInt(a.getValue());
313        }
314        if ((a = e.getAttribute(Xml.TRAIN_SCHEDULE_ID)) != null) {
315            _trainScheduleId = a.getValue();
316        }
317        if ((a = e.getAttribute(Xml.TYPE)) != null) {
318            _type = a.getValue();
319        }
320        if ((a = e.getAttribute(Xml.ROAD)) != null) {
321            _road = a.getValue();
322        }
323        if ((a = e.getAttribute(Xml.LOAD)) != null) {
324            _load = a.getValue();
325        }
326        if ((a = e.getAttribute(Xml.ROUTE_LOCATION_ID)) != null) {
327            _routeLocation = InstanceManager.getDefault(RouteManager.class).getRouteLocationById(a.getValue());
328        }
329        if ((a = e.getAttribute(Xml.LOC_TRACK_ID)) != null && _routeLocation != null) {
330            _trackLocation = _routeLocation.getLocation().getTrackById(a.getValue());
331        }
332        if ((a = e.getAttribute(Xml.DESTINATION_ID)) != null) {
333            _destination = InstanceManager.getDefault(LocationManager.class).getLocationById(a.getValue());
334        }
335        if ((a = e.getAttribute(Xml.DEST_TRACK_ID)) != null && _destination != null) {
336            _trackDestination = _destination.getTrackById(a.getValue());
337        }
338        if ((a = e.getAttribute(Xml.COUNT)) != null) {
339            _count = Integer.parseInt(a.getValue());
340        }
341        if ((a = e.getAttribute(Xml.WARN)) != null) {
342            _warn = a.getValue().equals(Xml.TRUE);
343        }
344        if ((a = e.getAttribute(Xml.FAIL)) != null) {
345            _fail = a.getValue().equals(Xml.TRUE);
346        }
347        if ((a = e.getAttribute(Xml.REMOVE)) != null) {
348            _remove = a.getValue().equals(Xml.TRUE);
349        }
350    }
351
352    /**
353     * Create an XML element to represent this Entry. This member has to remain
354     * synchronized with the detailed DTD in operations-config.xml.
355     *
356     * @return Contents in a JDOM Element
357     */
358    public org.jdom2.Element store() {
359        org.jdom2.Element e = new org.jdom2.Element(Xml.MANUAL_BUILD_ITEM);
360        e.setAttribute(Xml.ID, getId());
361        e.setAttribute(Xml.SEQUENCE_ID, Integer.toString(getSequenceId()));
362        e.setAttribute(Xml.TRAIN_SCHEDULE_ID, getTrainScheduleId());
363        e.setAttribute(Xml.TYPE, getTypeName());
364        e.setAttribute(Xml.ROAD, getRoadName());
365        e.setAttribute(Xml.LOAD, getLoadName());
366        if (!getRouteLocationId().equals(NONE)) {
367            e.setAttribute(Xml.ROUTE_LOCATION_ID, getRouteLocationId());
368        }
369        if (!getLocationTrackId().equals(NONE)) {
370            e.setAttribute(Xml.LOC_TRACK_ID, getLocationTrackId());
371        }
372        if (!getDestinationId().equals(NONE)) {
373            e.setAttribute(Xml.DESTINATION_ID, getDestinationId());
374        }
375        if (!getDestinationTrackId().equals(NONE)) {
376            e.setAttribute(Xml.DEST_TRACK_ID, getDestinationTrackId());
377        }
378        e.setAttribute(Xml.COUNT, Integer.toString(getCount()));
379        e.setAttribute(Xml.WARN, isWarnEnabled() ? Xml.TRUE : Xml.FALSE);
380        e.setAttribute(Xml.FAIL, isFailEnabled() ? Xml.TRUE : Xml.FALSE);
381        e.setAttribute(Xml.REMOVE, isRemoveEnabled() ? Xml.TRUE : Xml.FALSE);
382        return e;
383    }
384
385    private static final Logger log = LoggerFactory.getLogger(TrainManualBuildItem.class);
386
387}