001package jmri.jmrit.roster;
002
003import java.awt.Component;
004import java.awt.event.ActionEvent;
005import javax.swing.Icon;
006import javax.swing.JComboBox;
007import javax.swing.JOptionPane;
008import jmri.beans.BeanUtil;
009import jmri.jmrit.roster.rostergroup.RosterGroupSelector;
010import jmri.jmrit.roster.swing.RosterEntryComboBox;
011import jmri.util.FileUtil;
012import jmri.util.swing.JmriAbstractAction;
013import jmri.util.swing.WindowInterface;
014import org.slf4j.Logger;
015import org.slf4j.LoggerFactory;
016
017/**
018 * Remove a locomotive from the roster.
019 *
020 * <p>
021 * In case of error, this moves the definition file to a backup. This action
022 * posts a dialog box to select the loco to be deleted, and then posts an "are
023 * you sure" dialog box before acting.
024 *
025 * @author Bob Jacobsen Copyright (C) 2001, 2002
026 * @see jmri.jmrit.XmlFile
027 */
028public class DeleteRosterItemAction extends JmriAbstractAction {
029
030    public DeleteRosterItemAction(String s, WindowInterface wi) {
031        super(s, wi);
032    }
033
034    public DeleteRosterItemAction(String s, Icon i, WindowInterface wi) {
035        super(s, i, wi);
036    }
037
038    /**
039     * @param s   Name of this action, e.g. in menus
040     * @param who Component that action is associated with, used to ensure
041     *            proper position in of dialog boxes
042     */
043    public DeleteRosterItemAction(String s, Component who) {
044        super(s);
045        _who = who;
046    }
047    Component _who;
048
049    @Override
050    public void actionPerformed(ActionEvent event) {
051
052        Roster roster = Roster.getDefault();
053        String rosterGroup = Roster.getDefault().getDefaultRosterGroup();
054        RosterEntry[] entries;
055        // rosterGroup may legitimately be null
056        // but getProperty returns null if the property cannot be found, so
057        // we test that the property exists before attempting to get its value
058        if (BeanUtil.hasProperty(wi, RosterGroupSelector.SELECTED_ROSTER_GROUP)) {
059            rosterGroup = (String) BeanUtil.getProperty(wi, RosterGroupSelector.SELECTED_ROSTER_GROUP);
060            log.debug("selectedRosterGroup was {}", rosterGroup);
061        }
062        if (BeanUtil.hasProperty(wi, "selectedRosterEntries")) {
063            entries = (RosterEntry[]) BeanUtil.getProperty(wi, "selectedRosterEntries");
064            if (entries != null) {
065                log.debug("selectedRosterEntries found {} entries", entries.length);
066            } else {
067                log.debug("selectedRosterEntries left entries null");
068            }
069        } else {
070            entries = selectRosterEntry(rosterGroup);
071            if (entries.length > 0 ) {
072                log.debug("selectRosterEntry(rosterGroup) found {} entries", entries.length);
073            } else {
074                log.debug("selectRosterEntry(rosterGroup) found no entries");
075            }
076        }
077        if (entries == null || entries.length == 0) {
078            return;
079        }
080        // get parent object if there is one
081        //Component parent = null;
082        //if ( event.getSource() instanceof Component) parent = (Component)event.getSource();
083
084        // find the file for the selected entry
085        for (RosterEntry re : entries) {
086            String filename = roster.fileFromTitle(re.titleString());
087            String fullFilename = Roster.getDefault().getRosterFilesLocation() + filename;
088            log.debug("resolves to [{}], [{}]", filename, fullFilename);
089
090            // prompt for one last chance
091            log.debug("rosterGroup now {}", rosterGroup);
092            if (rosterGroup == null) {
093                if (!userOK(re.titleString(), filename, fullFilename)) {
094                    return;
095                }
096                // delete it from roster
097                roster.removeEntry(re);
098            } else {
099                String group = Roster.getRosterGroupProperty(rosterGroup);
100                log.debug("removing {} group from entry", group);
101                re.deleteAttribute(group);
102                re.updateFile();
103            }
104            Roster.getDefault().writeRoster();
105
106            // backup the file & delete it
107            if (rosterGroup == null) {
108                try {
109                    // ensure preferences will be found
110                    FileUtil.createDirectory(Roster.getDefault().getRosterFilesLocation());
111
112                    // move original file to backup
113                    LocoFile df = new LocoFile();   // need a dummy object to do this operation in next line
114                    df.makeBackupFile(Roster.getDefault().getRosterFilesLocation() + filename);
115
116                } catch (Exception ex) {
117                    log.error("error during locomotive file output", ex);
118                }
119            }
120        }
121
122    }
123
124    protected RosterEntry[] selectRosterEntry(String rosterGroup) {
125        RosterEntry[] entries = new RosterEntry[1];
126        // create a dialog to select the roster entry
127        JComboBox<?> selections = new RosterEntryComboBox(rosterGroup);
128        int retval = JOptionPane.showOptionDialog(_who,
129                Bundle.getMessage("CopyEntrySelectDialog"),
130                Bundle.getMessage("DeleteEntryTitle roster entry"),
131                JOptionPane.YES_NO_OPTION,
132                JOptionPane.INFORMATION_MESSAGE,
133                null,
134                new Object[] {Bundle.getMessage("ButtonCancel"), Bundle.getMessage("ButtonOK"), selections}, null);
135        log.debug("Dialog value {} selected {}:{}", retval, selections.getSelectedIndex(), selections.getSelectedItem()); // NOI18N
136        if (retval != 1) {
137            return entries; // empty
138        }
139        entries[0] = (RosterEntry) selections.getSelectedItem();
140        return entries;
141    }
142
143    /**
144     * Can provide some mechanism to prompt for user for one last chance to
145     * change his/her mind.
146     *
147     * @param entry Roster entry being operated on
148     * @param filename Just name of file
149     * @param fullFileName including path
150     * @return true if user says to continue
151     */
152    boolean userOK(String entry, String filename, String fullFileName) {
153        return (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(_who,
154                Bundle.getMessage("DeletePrompt", entry, fullFileName),
155                Bundle.getMessage("DeleteTitle", entry),
156                JOptionPane.YES_NO_OPTION));
157    }
158
159    // never invoked, because we overrode actionPerformed above
160    @Override
161    public jmri.util.swing.JmriPanel makePanel() {
162        throw new IllegalArgumentException("Should not be invoked");
163    }
164
165    // initialize logging
166    private final static Logger log = LoggerFactory.getLogger(DeleteRosterItemAction.class);
167
168}