001package jmri.jmrit.operations.trains.schedules;
002
003import java.util.ArrayList;
004import java.util.List;
005import jmri.InstanceManager;
006import jmri.beans.PropertyChangeSupport;
007import jmri.jmrit.operations.setup.Control;
008import jmri.jmrit.operations.trains.TrainManagerXml;
009import org.jdom2.Element;
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013/**
014 * Represents a schedule for trains. For example, can be a day of the week. Useful when
015 * determining which trains to build and run.
016 *
017 * @author Daniel Boudreau Copyright (C) 2010
018 */
019public class TrainSchedule extends PropertyChangeSupport {
020    
021    public static final String NONE = "";
022    public static final String ANY = "ANY"; // allow cars to be picked up any day of the week NOI18N
023
024    public static final String NAME_CHANGED_PROPERTY = "trainScheduleName"; // NOI18N
025    public static final String SCHEDULE_CHANGED_PROPERTY = "trainScheduleChanged"; // NOI18N
026
027    protected String _id = NONE;
028    protected String _name = NONE;
029    protected String _comment = NONE;
030    protected List<String> _trainIds = new ArrayList<>();
031
032    public TrainSchedule(String id, String name) {
033        log.debug("New train schedule ({}) id: {}", name, id);
034        _name = name;
035        _id = id;
036    }
037
038    public String getId() {
039        return _id;
040    }
041
042    public void setName(String name) {
043        String old = _name;
044        _name = name;
045        if (!old.equals(name)) {
046            setDirtyAndFirePropertyChange(NAME_CHANGED_PROPERTY, old, name);
047        }
048    }
049
050    // for combo boxes
051    @Override
052    public String toString() {
053        return _name;
054    }
055
056    public String getName() {
057        return _name;
058    }
059
060    public void setComment(String comment) {
061        String old = _comment;
062        _comment = comment;
063        if (!old.equals(comment)) {
064            setDirtyAndFirePropertyChange("AddTrainScheduleComment", old, comment); // NOI18N
065        }
066    }
067
068    public String getComment() {
069        return _comment;
070    }
071
072    /**
073     * Adds the train id for a train that needs to be built
074     * @param id The train id
075     */
076    public void addTrainId(String id) {
077        if (!_trainIds.contains(id)) {
078            _trainIds.add(id);
079            setDirtyAndFirePropertyChange(SCHEDULE_CHANGED_PROPERTY, null, id);
080        }
081    }
082
083    /**
084     * Removes the train id for a train that needs to be built
085     * @param id The train id
086     */
087    public void removeTrainId(String id) {
088        _trainIds.remove(id);
089        setDirtyAndFirePropertyChange(SCHEDULE_CHANGED_PROPERTY, id, null);
090    }
091
092    /**
093     * Used to determine if train is to be built using this schedule
094     * @param id the id of the train to be tested
095     * @return true if this train's build enable should be set
096     */
097    public boolean containsTrainId(String id) {
098        return _trainIds.contains(id);
099    }
100
101    /**
102     * Construct this Entry from XML. This member has to remain synchronized
103     * with the detailed DTD in operations-trains.xml
104     *
105     * @param e Consist XML element
106     */
107    public TrainSchedule(Element e) {
108        org.jdom2.Attribute a;
109        if ((a = e.getAttribute(Xml.ID)) != null) {
110            _id = a.getValue();
111        } else {
112            log.warn("no id attribute in schedule element when reading operations");
113        }
114        if ((a = e.getAttribute(Xml.NAME)) != null) {
115            _name = a.getValue();
116        }
117        if ((a = e.getAttribute(Xml.COMMENT)) != null) {
118            _comment = a.getValue();
119        }
120        if ((a = e.getAttribute(Xml.TRAIN_IDS)) != null) {
121            String ids = a.getValue();
122            String[] trainIds = ids.split(",");
123            for (String id : trainIds) {
124                _trainIds.add(id);
125            }
126//    log.debug("Train schedule " + getName() + " trainIds: " + ids);
127        }
128    }
129
130    /**
131     * Create an XML element to represent this Entry. This member has to remain
132     * synchronized with the detailed DTD in operations-config.xml.
133     *
134     * @return Contents in a JDOM Element
135     */
136    public Element store() {
137        Element e = new org.jdom2.Element(Xml.SCHEDULE);
138        e.setAttribute(Xml.ID, getId());
139        e.setAttribute(Xml.NAME, getName());
140        if (!getComment().equals(NONE)) {
141            e.setAttribute(Xml.COMMENT, getComment());
142        }
143        // store train ids
144        StringBuilder buf = new StringBuilder();
145        for (String id : _trainIds) {
146            buf.append(id + ",");
147        }
148        e.setAttribute(Xml.TRAIN_IDS, buf.toString());
149        return e;
150    }
151
152    public void propertyChange(java.beans.PropertyChangeEvent e) {
153        if (Control.SHOW_PROPERTY) {
154            log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e
155                    .getNewValue());
156        }
157    }
158
159    protected void setDirtyAndFirePropertyChange(String p, Object old, Object n) {
160        InstanceManager.getDefault(TrainManagerXml.class).setDirty(true);
161        firePropertyChange(p, old, n);
162    }
163
164    private final static Logger log = LoggerFactory.getLogger(TrainSchedule.class);
165
166}