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