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