001package jmri.jmrit.operations; 002 003import java.io.*; 004 005import org.jdom2.JDOMException; 006import org.slf4j.Logger; 007import org.slf4j.LoggerFactory; 008 009import jmri.InstanceManager; 010import jmri.jmrit.XmlFile; 011import jmri.jmrit.operations.locations.LocationManagerXml; 012import jmri.jmrit.operations.rollingstock.cars.CarManagerXml; 013import jmri.jmrit.operations.rollingstock.engines.EngineManagerXml; 014import jmri.jmrit.operations.routes.RouteManagerXml; 015import jmri.jmrit.operations.setup.OperationsSetupXml; 016import jmri.jmrit.operations.trains.TrainManagerXml; 017import jmri.util.FileUtil; 018 019/** 020 * Loads and stores the operation setup using xml files. 021 * 022 * @author Daniel Boudreau Copyright (C) 2008 023 */ 024public abstract class OperationsXml extends XmlFile { 025 026 /** 027 * Store the all of the operation train objects in the default place, 028 * including making a backup if needed 029 */ 030 public void writeOperationsFile() { 031 createFile(getDefaultOperationsFilename(), true); // make backup 032 try { 033 writeFile(getDefaultOperationsFilename()); 034 } catch (IOException e) { 035 log.error("Exception while writing operation file, may not be complete: {}", e.getLocalizedMessage()); 036 } 037 } 038 039 protected void load() { 040 try { 041 readFile(getDefaultOperationsFilename()); 042 } catch (IOException | JDOMException e) { 043 log.error("Exception during operations file reading: {}", e.getLocalizedMessage()); 044 } 045 } 046 047 protected File createFile(String fullPathName) { 048 return createFile(fullPathName, false); // no backup 049 } 050 051 protected File createFile(String fullPathName, boolean backupFile) { 052 if (backupFile) { 053 makeBackupFile(fullPathName); 054 } 055 File file = null; 056 try { 057 if (!checkFile(fullPathName)) { 058 // log.debug("File "+fullPathName+ " does not exist, creating it"); 059 // The file does not exist, create it before writing 060 file = new File(fullPathName); 061 File parentDir = file.getParentFile(); 062 if (!parentDir.exists()) { 063 if (!parentDir.mkdir()) { 064 log.error("Directory wasn't created"); 065 } 066 } 067 if (file.createNewFile()) { 068 log.debug("File created {}", fullPathName); 069 } 070 } else { 071 file = new File(fullPathName); 072 } 073 } catch (IOException e) { 074 log.error("Exception while creating operations file, may not be complete: {}", e.getLocalizedMessage()); 075 } 076 return file; 077 } 078 079 protected void createDirectory(String fullPathName) { 080 if (!checkFile(fullPathName)) { 081 File file = new File(fullPathName); 082 File parentDir = file.getParentFile(); 083 if (!parentDir.exists()) { 084 if (!parentDir.mkdir()) { 085 log.error("Directory wasn't created"); 086 } 087 } 088 if (file.mkdirs()) { 089 log.debug("Directory created {}", fullPathName); 090 } 091 } 092 } 093 094 protected void writeFile(String filename) throws FileNotFoundException, IOException { 095 log.error("writeFile not overridden"); 096 } 097 098 /** 099 * @param filename The string file name. 100 * @throws org.jdom2.JDOMException Due to XML parsing error 101 * @throws java.io.IOException Due to trouble accessing named file 102 */ 103 abstract public void readFile(String filename) throws org.jdom2.JDOMException, java.io.IOException; 104 105 private boolean dirty = false; 106 107 public void setDirty(boolean b) { 108 dirty = b; 109 } 110 111 public boolean isDirty() { 112 return dirty; 113 } 114 115 public void writeFileIfDirty() { 116 if (isDirty()) { 117 writeOperationsFile(); 118 } 119 } 120 121 public String getDefaultOperationsFilename() { 122 return getFileLocation() + getOperationsDirectoryName() + File.separator + getOperationsFileName(); 123 } 124 125 public static void setOperationsDirectoryName(String name) { 126 operationsDirectoryName = name; 127 } 128 129 public static String getOperationsDirectoryName() { 130 return operationsDirectoryName; 131 } 132 133 private static String operationsDirectoryName = "operations"; // NOI18N 134 135 public void setOperationsFileName(String name) { 136 operationsFileName = name; 137 } 138 139 public String getOperationsFileName() { 140 return operationsFileName; 141 } 142 143 private String operationsFileName = "DefaultOperations.xml"; // should be overridden // NOI18N 144 145 /** 146 * Absolute path to location of Operations files. 147 * <p> 148 * Default is in the user's files path, but can be set to anything. 149 * 150 * @return The string path name. 151 * 152 * @see jmri.util.FileUtil#getUserFilesPath() 153 */ 154 public static String getFileLocation() { 155 return fileLocation; 156 } 157 158 /** 159 * Set path to location of Operations files. 160 * <p> 161 * Default is in the user's files path, but can be set to anything. 162 * 163 * @param location path to file, including trailing file separator. 164 */ 165 public static void setFileLocation(String location) { 166 fileLocation = location; 167 } 168 169 private static String fileLocation = FileUtil.getUserFilesPath(); 170 171 /** 172 * Checks name for the file control characters: 173 * 174 * @param name The string to check for a valid file name. 175 * @return true if name is okay, false if name contains a control character. 176 */ 177 public static boolean checkFileName(String name) { 178 if (name.contains(".") || name.contains("<") || name.contains(">") // NOI18N 179 || name.contains(":") || name.contains("\"") || name.contains("\\") // NOI18N 180 || name.contains("/") || name.contains("|") || name.contains("?") // NOI18N 181 || name.contains("*")) { // NOI18N 182 return false; 183 } 184 return true; 185 } 186 187 /** 188 * Saves operation files that have been modified. 189 */ 190 public static void save() { 191 InstanceManager.getDefault(OperationsSetupXml.class).writeFileIfDirty(); 192 InstanceManager.getDefault(LocationManagerXml.class).writeFileIfDirty(); // Need to save "moves" for track location 193 InstanceManager.getDefault(RouteManagerXml.class).writeFileIfDirty(); // Only if user used setX&Y 194 InstanceManager.getDefault(CarManagerXml.class).writeFileIfDirty(); // save train assignments 195 InstanceManager.getDefault(EngineManagerXml.class).writeFileIfDirty(); // save train assignments 196 InstanceManager.getDefault(TrainManagerXml.class).writeFileIfDirty(); // save train changes 197 } 198 199 /** 200 * Checks to see if any operations files are dirty 201 * 202 * @return True if any operations parameters have been modified. 203 */ 204 public static boolean areFilesDirty() { 205 return InstanceManager.getDefault(OperationsSetupXml.class).isDirty() 206 || InstanceManager.getDefault(LocationManagerXml.class).isDirty() 207 || InstanceManager.getDefault(RouteManagerXml.class).isDirty() 208 || InstanceManager.getDefault(CarManagerXml.class).isDirty() 209 || InstanceManager.getDefault(EngineManagerXml.class).isDirty() 210 || InstanceManager.getDefault(TrainManagerXml.class).isDirty(); 211 } 212 213 private final static Logger log = LoggerFactory.getLogger(OperationsXml.class); 214 215}