001package jmri.managers.configurexml;
002
003import java.lang.reflect.Constructor;
004import java.lang.reflect.InvocationTargetException;
005import java.util.List;
006import javax.swing.SortOrder;
007import jmri.InstanceManager;
008import jmri.swing.JmriJTablePersistenceManager;
009import org.jdom2.Element;
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013/**
014 * Read XML persistence data for the now removed
015 * jmri.managers.DefaultUserMessagePreferences class so that the current
016 * {@link jmri.UserPreferencesManager} can use it.
017 */
018public class DefaultUserMessagePreferencesXml extends jmri.configurexml.AbstractXmlAdapter {
019
020    public DefaultUserMessagePreferencesXml() {
021        super();
022    }
023
024    /**
025     * Default implementation for storing the contents of a User Messages
026     * Preferences
027     *
028     * @param o Object to store, but not really used, because info to be stored
029     *          comes from the DefaultUserMessagePreferences
030     * @return Element containing the complete info
031     */
032    @Override
033    public Element store(Object o) {
034        // nothing to do, since this class exists only to load older preferences if they exist
035        return null;
036    }
037
038    public void setStoreElementClass(Element messages) {
039        messages.setAttribute("class", "jmri.managers.configurexml.DefaultUserMessagePreferencesXml");
040    }
041
042    @Override
043    public void load(Element element, Object o) {
044        log.error("Invalid method called");
045    }
046
047    @Override
048    public boolean load(Element shared, Element perNode) {
049        // ensure the master object exists
050        jmri.UserPreferencesManager p = jmri.InstanceManager.getDefault(jmri.UserPreferencesManager.class);
051        p.setLoading();
052
053        List<Element> settingList = shared.getChildren("setting");
054
055        for (Element set : settingList) {
056            String name = set.getText();
057            p.setSimplePreferenceState(name, true);
058        }
059
060        List<Element> comboList = shared.getChildren("comboBoxLastValue");
061
062        for (Element cmb : comboList) {
063            List<Element> comboItem = cmb.getChildren("comboBox");
064            for (int x = 0; x < comboItem.size(); x++) {
065                String combo = comboItem.get(x).getAttribute("name").getValue();
066                String setting = comboItem.get(x).getAttribute("lastSelected").getValue();
067                p.setComboBoxLastSelection(combo, setting);
068            }
069        }
070
071        List<Element> classList = shared.getChildren("classPreferences");
072        for (Element cls : classList) {
073            List<Element> multipleList = cls.getChildren("multipleChoice");
074            String strClass = cls.getAttribute("class").getValue();
075            for (Element mul : multipleList) {
076                List<Element> multiItem = mul.getChildren("option");
077                for (Element muli : multiItem) {
078                    String item = muli.getAttribute("item").getValue();
079                    int value = 0x00;
080                    try {
081                        value = muli.getAttribute("value").getIntValue();
082                    } catch (org.jdom2.DataConversionException e) {
083                        log.error("failed to convert positional attribute");
084                    }
085                    p.setMultipleChoiceOption(strClass, item, value);
086                }
087            }
088
089            List<Element> preferenceList = cls.getChildren("reminderPrompts");
090            for (Element pref : preferenceList) {
091                List<Element> reminderBoxes = pref.getChildren("reminder");
092                for (Element rem : reminderBoxes) {
093                    String name = rem.getText();
094                    p.setPreferenceState(strClass, name, true);
095                }
096            }
097        }
098
099        List<Element> windowList = shared.getChildren("windowDetails");
100        for (Element win : windowList) {
101            String strClass = win.getAttribute("class").getValue();
102            p.setWindowLocation(strClass,
103                    new java.awt.Point(extractCoord(win, "locX"), extractCoord(win, "locY")));
104            p.setWindowSize(strClass,
105                    new java.awt.Dimension(extractCoord(win, "width"), extractCoord(win, "height")));
106
107            Element prop = win.getChild("properties");
108            if (prop != null) {
109                for (Object next : prop.getChildren("property")) {
110                    Element e = (Element) next;
111
112                    try {
113                        Class<?> cl;
114                        Constructor<?> ctor;
115                        // create key object
116                        String key = e.getChild("key").getText();
117
118                        // create value object
119                        Object value = null;
120                        if (e.getChild("value") != null) {
121                            cl = Class.forName(e.getChild("value").getAttributeValue("class"));
122                            ctor = cl.getConstructor(new Class<?>[]{String.class});
123                            value = ctor.newInstance(new Object[]{e.getChild("value").getText()});
124                        }
125
126                        // store
127                        p.setProperty(strClass, key, value);
128                    } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
129                        log.error("Error loading properties", ex);
130                    }
131                }
132            }
133        }
134
135        List<Element> tablesList = shared.getChildren("tableDetails");
136        InstanceManager.getOptionalDefault(JmriJTablePersistenceManager.class).ifPresent((jtpm) -> {
137            for (Element tables : tablesList) {
138                List<Element> tableList = tables.getChildren("table");
139                for (Element table : tableList) {
140                    String strTableName = table.getAttribute("name").getValue();
141                    // if this table is already persisted, do not try to persist it again
142                    // this can happen if profile preferences have only been partly migrated
143                    if (!jtpm.isPersistenceDataRetained(strTableName)) {
144                        List<Element> columnList = table.getChildren("column");
145                        for (Element column : columnList) {
146                            String strColumnName = column.getAttribute("name").getValue();
147                            int order = -1;
148                            int width = -1;
149                            SortOrder sort = SortOrder.UNSORTED;
150                            boolean hidden = false;
151                            if (column.getChild("order") != null) {
152                                order = Integer.parseInt(column.getChild("order").getText());
153                            }
154                            if (column.getChild("width") != null) {
155                                width = Integer.parseInt(column.getChild("width").getText());
156                            }
157                            if (column.getChild("sortOrder") != null) {
158                                sort = SortOrder.valueOf(column.getChild("sortOrder").getText());
159                                // before 4.3.5 we used "sort" save column sort state
160                            } else if (column.getChild("sort") != null) {
161                                switch (Integer.parseInt(column.getChild("sort").getText())) {
162                                    case 1: // old sort scheme used 1 for ascending
163                                        sort = SortOrder.ASCENDING;
164                                        break;
165                                    case -1: // old sort scheme used -1 for descending
166                                        sort = SortOrder.DESCENDING;
167                                        break;
168                                    default:
169                                        break;
170                                }
171                            }
172                            if (column.getChild("hidden") != null && column.getChild("hidden").getText().equals("yes")) {
173                                hidden = true;
174                            }
175
176                            setTableColumnPreferences(jtpm, strTableName, strColumnName, order, width, sort, hidden);
177                        }
178                    }
179                }
180            }
181        });
182        p.finishLoading();
183        return true;
184    }
185
186    private int extractCoord(Element win, String name) {
187        List<Element> locList = win.getChildren(name);
188        double coord = 0.0;
189        for (Element loc : locList) {
190            try {
191                coord = Double.parseDouble(loc.getText());
192            } catch (NumberFormatException e) {
193                log.error("failed to convert positional attribute");
194            }
195        }
196        return (int) coord;
197    }
198
199    private void setTableColumnPreferences(JmriJTablePersistenceManager jtpm, String table, String column, int order, int width, SortOrder sort, boolean hidden) {
200    }
201    
202    private final static Logger log = LoggerFactory.getLogger(DefaultUserMessagePreferencesXml.class);
203
204}