001package jmri.jmrit.logix;
002
003import java.util.HashMap;
004import java.util.Iterator;
005import java.util.Map;
006import java.util.Map.Entry;
007
008import jmri.InstanceManager;
009import jmri.implementation.AbstractShutDownTask;
010import jmri.jmrit.roster.Roster;
011import jmri.jmrit.roster.RosterEntry;
012import jmri.jmrit.roster.RosterSpeedProfile;
013import org.slf4j.Logger;
014import org.slf4j.LoggerFactory;
015
016/**
017 *
018 * Allows user to decide if (and which) SpeedProfiles to write to the Roster at
019 * the end of a session. Locos running warrants have had their speeds measured
020 * and this new data may or may not be merged into any existing SpeedProfiles in
021 * the Roster.
022 *
023 * @author Pete cressman Copyright (C) 2017
024 */
025public class WarrantShutdownTask extends AbstractShutDownTask {
026
027    HashMap<String, Boolean> _mergeCandidates;
028    HashMap<String, RosterSpeedProfile> _mergeProfiles;
029    Map<String, Map<Integer, Boolean>> _anomalies;
030    
031    /**
032     * Constructor specifies the warning message and action to take
033     *
034     * @param name the name of the task (used in logs)
035     */
036    public WarrantShutdownTask(String name) {
037        super(name);
038    }
039
040    /**
041     * {@inheritDoc}
042     */
043    @Override
044    public Boolean call() {
045        WarrantPreferences preferences = WarrantPreferences.getDefault();
046        switch (preferences.getShutdown()) {
047            case MERGE_ALL:
048                if (makeMergeCandidates()) {
049                    if (_anomalies != null && _anomalies.size() > 0) {
050                        makeMergeWindow();
051                    }
052                    setDoRun(true);
053                }
054                break;
055            case PROMPT:
056                if (makeMergeCandidates()) {
057                    makeMergeWindow();
058                    setDoRun(true);
059                }
060                break;
061            case NO_MERGE:
062                // do nothing
063                break;
064            default:
065                log.warn("No choice made for warrant shutdown");
066                break;
067        }
068        return true;
069    }
070
071    /**
072     * {@inheritDoc}
073     */
074    @Override
075    public void run() {
076        if (isDoRun()) {
077            merge();
078        }
079    }
080
081    private boolean makeMergeCandidates() {
082        WarrantManager manager = InstanceManager.getDefault(WarrantManager.class);
083        _mergeProfiles = manager.getMergeProfiles();
084        if (_mergeProfiles == null || _mergeProfiles.isEmpty()) {
085            return false;
086        }
087        _anomalies = new HashMap<>();
088        _mergeCandidates = new HashMap<>();
089        Iterator<java.util.Map.Entry<String, RosterSpeedProfile>> iter = _mergeProfiles.entrySet().iterator();
090        while (iter.hasNext()) {
091            java.util.Map.Entry<String, RosterSpeedProfile> entry = iter.next();
092            Map<Integer, Boolean> anomaly = MergePrompt.validateSpeedProfile(entry.getValue());
093            if (anomaly != null && anomaly.size() > 0) {
094                _anomalies.put(entry.getKey(), anomaly);
095            }
096            String rosterId = entry.getKey();
097            if (Roster.getDefault().getEntryForId(rosterId) != null) {
098                _mergeCandidates.put(rosterId, true);
099            }
100        }
101        if (_mergeCandidates.isEmpty()) {
102            return false;
103        }
104        return true;
105    }
106
107    private void makeMergeWindow() {
108        new MergePrompt(Bundle.getMessage("MergeTitle"), _mergeCandidates, _anomalies);
109    }
110
111    private void merge() {
112        for (Entry<String, Boolean> entry : _mergeCandidates.entrySet()) {
113            if (entry.getValue()) {
114                String id = entry.getKey();
115                RosterEntry rosterEntry = Roster.getDefault().entryFromTitle(id);
116                if (rosterEntry != null) {
117                    rosterEntry.setSpeedProfile(_mergeProfiles.get(id));
118                    log.debug("Write SpeedProfile to Roster. id= {}", id);
119                } else {
120                    log.debug("Unable to Write SpeedProfile to Roster. No RosterEntry for {}", id);
121                }
122            } else {
123                log.debug("SpeedProfile not merged to Roster. id= {}", entry.getKey());
124            }
125        }
126        Roster.getDefault().writeRoster();
127    }
128
129    private static final Logger log = LoggerFactory.getLogger(WarrantShutdownTask.class);
130
131}