001package jmri.jmrit.simpleclock.configurexml;
002
003import java.text.ParseException;
004import java.text.SimpleDateFormat;
005import java.util.Locale;
006import jmri.InstanceManager;
007import jmri.Timebase;
008import org.jdom2.Element;
009import org.slf4j.Logger;
010import org.slf4j.LoggerFactory;
011
012import static jmri.Timebase.ClockInitialRunState.DO_NOTHING;
013import static jmri.Timebase.ClockInitialRunState.DO_START;
014import static jmri.Timebase.ClockInitialRunState.DO_STOP;
015
016/**
017 * Handle XML persistance of SimpleTimebase objects.
018 *
019 * @author Bob Jacobsen Copyright (c) 2003, 2008, 2017
020 */
021public class SimpleTimebaseXml extends jmri.configurexml.AbstractXmlAdapter {
022
023    public SimpleTimebaseXml() {
024    }
025
026    /**
027     * Default implementation for storing the contents of a SimpleTimebase.
028     *
029     * @param o Object to start process, but not actually used
030     * @return Element containing the complete info
031     */
032    @Override
033    public Element store(Object o) {
034
035        Timebase clock = InstanceManager.getDefault(jmri.Timebase.class);
036
037        Element elem = new Element("timebase");
038        elem.setAttribute("class", this.getClass().getName());
039
040        elem.setAttribute("time", clock.getStartTime().toString());
041        elem.setAttribute("rate", "" + clock.userGetRate());
042        elem.setAttribute("startrate", "" + clock.getStartRate());
043        elem.setAttribute("run", (clock.getClockInitialRunState() == DO_START ? "yes" : "no"));
044        elem.setAttribute("master", (clock.getInternalMaster() ? "yes" : "no"));
045        if (!clock.getInternalMaster()) {
046            elem.setAttribute("mastername", clock.getMasterName());
047        }
048        elem.setAttribute("sync", (clock.getSynchronize() ? "yes" : "no"));
049        elem.setAttribute("correct", (clock.getCorrectHardware() ? "yes" : "no"));
050        elem.setAttribute("display", (clock.use12HourDisplay() ? "yes" : "no"));
051        elem.setAttribute("startstopped", (clock.getClockInitialRunState() == DO_STOP ? "yes" : "no"));
052        elem.setAttribute("startrunning", ((clock.getClockInitialRunState() == DO_START) ? "yes" : "no"));
053        elem.setAttribute("startsettime", (clock.getStartSetTime() ? "yes" : "no"));
054        elem.setAttribute("startclockoption", Integer.toString(
055                clock.getStartClockOption()));
056        elem.setAttribute("showbutton", (clock.getShowStopButton() ? "yes" : "no"));
057        elem.setAttribute("startsetrate", (clock.getSetRateAtStart() ? "yes" : "no"));
058
059        return elem;
060    }
061
062    @Override
063    public boolean load(Element shared, Element perNode) {
064        boolean result = true;
065        Timebase clock = InstanceManager.getDefault(jmri.Timebase.class);
066        String val, val2;
067        if (shared.getAttribute("master") != null) {
068            val = shared.getAttributeValue("master");
069            if (val.equals("yes")) {
070                clock.setInternalMaster(true, false);
071            }
072            if (val.equals("no")) {
073                clock.setInternalMaster(false, false);
074                if (shared.getAttribute("mastername") != null) {
075                    clock.setMasterName(shared.getAttributeValue("mastername"));
076                }
077            }
078        }
079        if (shared.getAttribute("sync") != null) {
080            val = shared.getAttributeValue("sync");
081            if (val.equals("yes")) {
082                clock.setSynchronize(true, false);
083            }
084            if (val.equals("no")) {
085                clock.setSynchronize(false, false);
086            }
087        }
088        if (shared.getAttribute("correct") != null) {
089            val = shared.getAttributeValue("correct");
090            if (val.equals("yes")) {
091                clock.setCorrectHardware(true, false);
092            }
093            if (val.equals("no")) {
094                clock.setCorrectHardware(false, false);
095            }
096        }
097        if (shared.getAttribute("display") != null) {
098            val = shared.getAttributeValue("display");
099            if (val.equals("yes")) {
100                clock.set12HourDisplay(true, false);
101            }
102            if (val.equals("no")) {
103                clock.set12HourDisplay(false, false);
104            }
105        }
106        if (shared.getAttribute("showbutton") != null) {
107            val = shared.getAttributeValue("showbutton");
108            if (val.equals("yes")) {
109                clock.setShowStopButton(true);
110            }
111            if (val.equals("no")) {
112                clock.setShowStopButton(false);
113            }
114        }
115        if ("yes".equals(shared.getAttributeValue("startrunning"))) {
116            clock.setRun(true);
117            clock.setClockInitialRunState(DO_START);
118        } else if ("yes".equals(shared.getAttributeValue("startstopped"))) {
119            clock.setRun(false);
120            clock.setClockInitialRunState(DO_STOP);
121        } else if (shared.getAttribute("startrunning") != null){
122            clock.setClockInitialRunState(DO_NOTHING);
123        } else {
124            // legacy XML
125            if (shared.getAttribute("run") != null) {
126                val = shared.getAttributeValue("run");
127                if (val.equals("yes")) {
128                    clock.setRun(true);
129                    clock.setClockInitialRunState(DO_START);
130                }
131                if (val.equals("no")) {
132                    clock.setRun(false);
133                    clock.setClockInitialRunState(DO_STOP);
134                }
135            }
136        }
137        if (shared.getAttribute("startsetrate") != null) {
138            val = shared.getAttributeValue("startsetrate");
139            clock.setSetRateAtStart(!val.equals("no"));
140        }
141        boolean hasRate = false;
142        if (shared.getAttribute("startrate") != null) {
143            try {
144                double r = shared.getAttribute("startrate").getDoubleValue();
145                clock.setStartRate(r);
146                hasRate = true;
147            } catch (org.jdom2.DataConversionException e2) {
148                log.error("Cannot convert start rate", e2);
149                result = false;
150            }
151        }
152        if (!hasRate && shared.getAttribute("rate") != null) {
153            try {
154                double r = shared.getAttribute("rate").getDoubleValue();
155                clock.setStartRate(r);
156                hasRate = true;
157            } catch (org.jdom2.DataConversionException e2) {
158                log.error("Cannot convert rate", e2);
159                result = false;
160            }
161        }
162        if (clock.getSetRateAtStart() && hasRate) {
163            try {
164                clock.userSetRate(clock.getStartRate());
165            } catch (jmri.TimebaseRateException e1) {
166                log.error("Cannot restore rate: {}", clock.getStartRate(), e1);
167                result = false;
168            }
169        }
170        if (shared.getAttribute("startsettime") != null) {
171            val = shared.getAttributeValue("startsettime");
172            if (val.equals("yes")) {
173                if (shared.getAttribute("time") != null) {
174                    val2 = shared.getAttributeValue("time");
175                    try {
176                        clock.setStartSetTime(true, format.parse(val2));
177                        clock.setTime(format.parse(val2));
178                    } catch (ParseException e) {
179                        // if non-invertable date format, just skip
180                        log.warn("Cannot set date using value stored in file: {}", val2);
181                        result = false;
182                    }
183                }
184            } else if (val.equals("no")) {
185                if (shared.getAttribute("time") != null) {
186                    val2 = shared.getAttributeValue("time");
187                    try {
188                        clock.setStartSetTime(false, format.parse(val2));
189                    } catch (ParseException e) {
190                        // if non-invertable date format, just skip
191                        log.warn("Cannot set date using value stored in file: {}", val2);
192                        result = false;
193                    }
194                }
195            }
196        } else if (shared.getAttribute("time") != null) {
197            // this only to preserve previous behavior for preexisting files
198            val2 = shared.getAttributeValue("time");
199            try {
200                clock.setStartSetTime(true, format.parse(val2));
201                clock.setTime(format.parse(val2));
202            } catch (ParseException e) {
203                // if non-invertable date format, just skip
204                log.warn("Cannot set date using value stored in file: {}", val2);
205                result = false;
206            }
207        }
208        if (shared.getAttribute("startclockoption") != null) {
209            int option = Integer.parseInt(shared.getAttribute(
210                    "startclockoption").getValue());
211            clock.setStartClockOption(option);
212            clock.initializeClock();
213        }
214        clock.initializeHardwareClock();
215        return result;
216    }
217
218    // Conversion format for dates created by Java Date.toString().
219    // The Locale needs to be always US, irrelevant from computer's and program's settings!
220    final SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
221
222    @Override
223    public int loadOrder() {
224        return jmri.Manager.TIMEBASE;
225    }
226
227    private final static Logger log = LoggerFactory.getLogger(SimpleTimebaseXml.class);
228
229}