001package jmri.configurexml;
002
003import java.io.File;
004import java.util.Set;
005import java.awt.Component;
006import java.awt.event.ActionEvent;
007
008import javax.annotation.CheckForNull;
009import javax.annotation.Nonnull;
010import javax.swing.JFileChooser;
011
012import jmri.ConfigureManager;
013import jmri.InstanceManager;
014import jmri.jmrit.logixng.LogixNGPreferences;
015import jmri.JmriException;
016import jmri.jmrit.display.Editor;
017import jmri.jmrit.display.EditorManager;
018import jmri.jmrit.logixng.LogixNG_Manager;
019import jmri.util.swing.JmriJOptionPane;
020
021/**
022 * Load configuration information from an XML file.
023 * <p>
024 * The file context for this is the "config" file chooser.
025 * <p>
026 * This will load whatever information types are present in the file. See
027 * {@link jmri.ConfigureManager} for information on the various types of
028 * information stored in configuration files.
029 *
030 * @author Bob Jacobsen Copyright (C) 2002
031 * @see jmri.jmrit.XmlFile
032 */
033public class LoadXmlConfigAction extends LoadStoreBaseAction {
034
035    public LoadXmlConfigAction() {
036        this("Open Data File ...");  // NOI18N
037    }
038
039    public LoadXmlConfigAction(String s) {
040        super(s);
041    }
042
043    @Override
044    public void actionPerformed(ActionEvent e) {
045        loadFile(getConfigFileChooser(), JmriJOptionPane.findWindowForObject( e == null ? null : e.getSource()));
046    }
047
048    /**
049     * Load a File from a given JFileChooser.
050     * @param fileChooser {@link JFileChooser} to use for file selection
051     * @param component a Component which has called the File Chooser.
052     * @return true if successful
053     */
054    protected boolean loadFile(@Nonnull JFileChooser fileChooser, @CheckForNull Component component ) {
055        Set<Editor> editors = InstanceManager.getDefault(EditorManager.class).getAll();
056        if (!editors.isEmpty()) {
057            InstanceManager.getDefault(jmri.UserPreferencesManager.class).showWarningMessage(
058                    Bundle.getMessage("DuplicateLoadTitle"), Bundle.getMessage("DuplicateLoadMessage"),  // NOI18N
059                    "jmri.jmrit.display.EditorManager",  "skipDupLoadDialog", false, true);  //NOI18N
060            InstanceManager.getDefault(jmri.UserPreferencesManager.class).setPreferenceItemDetails(
061                    "jmri.jmrit.display.EditorManager", "skipDupLoadDialog", Bundle.getMessage("DuplicateLoadSkip"));  // NOI18N
062        }
063
064        boolean results = false;
065        File file = getFile(fileChooser, component);
066        if (file != null) {
067            log.info("Loading selected file: {}", file); // NOI18N
068            try {
069                ConfigureManager cm = InstanceManager.getNullableDefault(jmri.ConfigureManager.class);
070                if (cm == null) {
071                    log.error("Failed to get default configure manager");  // NOI18N
072                } else {
073                    results = cm.load(file);
074
075                    // If LogixNGs aren't setup, the actions and expressions will not
076                    // be stored if the user stores the tables and panels. So we need
077                    // to try to setup LogixNGs even if the loading failed.
078                    LogixNG_Manager logixNG_Manager = InstanceManager.getDefault(LogixNG_Manager.class);
079                    logixNG_Manager.setupAllLogixNGs();
080
081                    if (results) {
082                        // insure logix etc fire up
083                        InstanceManager.getDefault(jmri.LogixManager.class).activateAllLogixs();
084                        InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager.class).initializeLayoutBlockPaths();
085
086                        if (InstanceManager.getDefault(LogixNGPreferences.class).getStartLogixNGOnStartup()
087                                && logixNG_Manager.isStartLogixNGsOnLoad()) {
088                            logixNG_Manager.activateAllLogixNGs();
089                        }
090                    }
091                }
092            } catch (JmriException e) {
093                log.error("Unhandled problem in loadFile", e);  // NOI18N
094            }
095        } else {
096            results = true;   // We assume that as the file is null then the user has clicked cancel.
097        }
098        return results;
099    }
100
101    /**
102     * Get the File from a given JFileChooser.
103     * @return the selected File.
104     * @deprecated use {@link #getFile(JFileChooser fileChooser, Component component)}
105     * @param fileChooser the JFileChooser for the file.
106     */
107    @CheckForNull
108    @Deprecated (since="5.7.8",forRemoval=true)
109    public static File getFile(@Nonnull JFileChooser fileChooser) {
110        return getFile(fileChooser, null);
111    }
112
113    /**
114     * Get the File from an Open File JFileChooser.
115     * If a Component is provided, this helps the JFileChooser to not get stuck
116     * behind an Always On Top Window.
117     * @param fileChooser the FileChooser to get from.
118     * @param component a Component within a JFrame / Window / Popup Menu,
119     *                  or the JFrame or Window itself.
120     * @return the File, may be null if none selected.
121     */
122    @CheckForNull
123    public static File getFile(@Nonnull JFileChooser fileChooser, @CheckForNull Component component) {
124        fileChooser.setDialogType(javax.swing.JFileChooser.OPEN_DIALOG);
125        return getFileCustom(fileChooser, component);
126    }
127
128    /**
129     * @return the selected File.
130     * @deprecated use {@link #getFile(JFileChooser fileChooser, Component component)}
131     * @param fileChooser the FileChooser to get from.
132     */
133    @CheckForNull
134    @Deprecated (since="5.7.8",forRemoval=true)
135    public static File getFileCustom(@Nonnull JFileChooser fileChooser) {
136        return getFileCustom(fileChooser, null);
137    }
138
139    /**
140     * Get the File from a JFileChooser.
141     * If a Component is provided, this helps the JFileChooser to not get stuck
142     * behind an Always On Top Window.
143     * @param fileChooser the FileChooser to get from.
144     * @param component a Component within a JFrame / Window / Popup Menu,
145     *                  or the JFrame or Window itself.
146     * @return the File, may be null if none selected.
147     */
148    @CheckForNull
149    public static File getFileCustom(@Nonnull JFileChooser fileChooser, @CheckForNull Component component){
150        fileChooser.rescanCurrentDirectory();
151        int retVal = fileChooser.showDialog(component, Bundle.getMessage("MenuItemLoad"));  // NOI18N
152        if (retVal != JFileChooser.APPROVE_OPTION) {
153            return null;  // give up if no file selected
154        }
155        log.debug("Open file: {}", fileChooser.getSelectedFile().getPath());
156        return fileChooser.getSelectedFile();
157    }
158
159    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoadXmlConfigAction.class);
160
161}