001package jmri.configurexml;
002
003import java.io.File;
004import java.io.FileNotFoundException;
005import java.io.IOException;
006import jmri.jmrit.XmlFile;
007import jmri.util.FileUtil;
008import org.jdom2.Document;
009import org.jdom2.Element;
010import org.jdom2.JDOMException;
011
012/**
013 * Load and store scale xml data files.
014 * <p>
015 * Custom changes to scale information result in the scale data being stored
016 * at the user files location.  Subsequent scale data loading uses the custom
017 * data file.  The default scale data file is part of the JMRI distribution.
018 * @author Dave Sand Copyright (C) 2018
019 * @since 4.13.6
020 */
021public class ScaleConfigXML {
022
023    public static boolean doStore() {
024        ScaleXmlFile x = new ScaleXmlFile();
025        File file = x.getStoreFile();
026        if (file == null) {
027            log.warn("Unable to create local scale file");
028            return false;
029        }
030
031        // Create root element
032        Element root = new Element("scale-data");  // NOI18N
033        root.setAttribute("noNamespaceSchemaLocation",  // NOI18N
034                "http://jmri.org/xml/schema/scale.xsd",  // NOI18N
035                org.jdom2.Namespace.getNamespace("xsi",
036                        "http://www.w3.org/2001/XMLSchema-instance"));  // NOI18N
037        Document doc = new Document(root);
038        Element values;
039
040        root.addContent(values = new Element("scales"));  // NOI18N
041        for (jmri.Scale scale : jmri.ScaleManager.getScales()) {
042            Element e = new Element("scale");  // NOI18N
043            e.addContent(new Element("scale_name").addContent(scale.getScaleName()));  // NOI18N
044            e.addContent(new Element("user_name").addContent(scale.getUserName()));  // NOI18N
045            e.addContent(new Element("scale_ratio").addContent(Double.toString(scale.getScaleRatio())));  // NOI18N
046            values.addContent(e);
047        }
048
049        try {
050            x.writeXML(file, doc);
051        } catch (FileNotFoundException ex) {
052            log.error("File not found when writing", ex);  // NOI18N
053            return false;
054        } catch (IOException ex) {
055            log.error("IO Exception when writing", ex);  // NOI18N
056            return false;
057        }
058
059        return true;
060    }
061
062    public static boolean doLoad() {
063        ScaleXmlFile x = new ScaleXmlFile();
064        File file = x.getLoadFile();
065
066        // Find root
067        Element root;
068        try {
069            root = x.rootFromFile(file);
070            if (root == null) {
071                log.debug("File could not be read");  // NOI18N
072                return false;
073            }
074
075            Element scales = root.getChild("scales");  // NOI18N
076            if (scales == null) {
077                log.error("Unable to find a scale entry");  // NOI18N
078                return false;
079            }
080            for (Element scale : scales.getChildren("scale")) {  // NOI18N
081                Element scale_name = scale.getChild("scale_name");  // NOI18N
082                String scaleName = (scale_name == null) ? "" : scale_name.getValue();
083                Element user_name = scale.getChild("user_name");  // NOI18N
084                String userName = (user_name == null) ? "" : user_name.getValue();
085                Element scale_ratio = scale.getChild("scale_ratio");  // NOI18N
086                double scaleRatio = (scale_ratio == null) ? 1.0 : Double.parseDouble(scale_ratio.getValue());
087
088                jmri.ScaleManager.addScale(scaleName, userName, scaleRatio);
089            }
090
091        } catch (JDOMException ex) {
092            log.error("File invalid", ex);  // NOI18N
093            return false;
094        } catch (IOException ex) {
095            log.error("Error reading file", ex);  // NOI18N
096            return false;
097        }
098
099        return true;
100    }
101
102    private static class ScaleXmlFile extends XmlFile {
103        private static String prodPath = FileUtil.getProgramPath() + "resources/scales/";  // NOI18N
104        private static String userPath = FileUtil.getUserFilesPath() + "resources/scales/";  // NOI18N
105        private static String fileName = "ScaleData.xml";  // NOI18N
106
107        public static String getStoreFileName() {
108            return userPath + fileName;
109        }
110
111        public File getStoreFile() {
112            File chkdir = new File(userPath);
113            if (!chkdir.exists()) {
114                if (!chkdir.mkdirs()) {
115                    return null;
116                }
117            }
118            File file = findFile(getStoreFileName());
119            if (file == null) {
120                log.info("Create new scale file");  // NOI18N
121                file = new File(getStoreFileName());
122            } else {
123                try {
124                    FileUtil.rotate(file, 4, "bup");  // NOI18N
125                } catch (IOException ex) {
126                    log.warn("Rotate failed, reverting to xml backup");  // NOI18N
127                    makeBackupFile(getStoreFileName());
128                }
129            }
130            return file;
131        }
132
133        public File getLoadFile() {
134            File file = findFile(userPath + fileName);
135            if (file == null) {
136                file = findFile(prodPath + fileName);
137            }
138            return file;
139        }
140    }
141
142    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ScaleConfigXML.class);
143}