001package jmri.jmrit.revhistory.configurexml; 002 003import java.util.ArrayList; 004 005import jmri.InstanceManager; 006import jmri.configurexml.LoadAndStorePreferences; 007import jmri.jmrit.revhistory.FileHistory; 008 009import org.jdom2.Element; 010 011/** 012 * Load/Store FileHistory objects. 013 * <p> 014 * This interacts somewhat differently with the ConfigureXML system. FileHistory 015 * objects are _not_ registed with the manager, but rather handled explicitly by 016 * them. The "load()" method is therefore a null-op here. 017 * 018 * @author Bob Jacobsen Copyright (c) 2010 019 */ 020public class FileHistoryXml extends jmri.configurexml.AbstractXmlAdapter { 021 022 /** 023 * Usual configurexml method, this one doesn't do anything because the 024 * content is explicitly loaded from the file 025 */ 026 @Override 027 public boolean load(Element shared, Element perNode) { 028 return true; 029 } 030 031 /** 032 * Load RevHistory from an element. 033 * 034 * <p> 035 * If no RevHistory already present in InstanceManager, creates one and adds 036 * this. 037 * <p> 038 * Then adds, instead of replacing, the history information 039 * @param e element to load. 040 * @return true when complete, false if unexpected. 041 */ 042 public boolean loadDirectly(Element e) { 043 if (!e.getName().equals("filehistory")) { 044 log.error("Unexpected element name: {}", e.getName()); 045 return false; 046 } 047 048 FileHistory rmain = jmri.InstanceManager.getDefault(FileHistory.class); 049 050 FileHistory r = loadFileHistory(e); 051 rmain.addOperation("Load", "", r); 052 053 return true; 054 } 055 056 static public FileHistory loadFileHistory(Element e) { 057 FileHistory r = new FileHistory(); 058 059 java.util.List<Element> list = e.getChildren("operation"); 060 for (int i = 0; i < list.size(); i++) { 061 loadOperation(r, list.get(i)); 062 } 063 return r; 064 } 065 066 static public void loadOperation(FileHistory r, Element e) { 067 Element s; 068 069 String type = null; 070 s = e.getChild("type"); 071 if (s != null) { 072 type = s.getText(); 073 } 074 075 String date = null; 076 s = e.getChild("date"); 077 if (s != null) { 078 date = s.getText(); 079 } 080 081 String filename = null; 082 s = e.getChild("filename"); 083 if (s != null) { 084 filename = s.getText(); 085 } 086 087 FileHistory filehistory = null; 088 s = e.getChild("filehistory"); 089 if (s != null) { 090 filehistory = loadFileHistory(s); 091 } 092 093 r.addOperation(type, date, filename, filehistory); 094 } 095 096 /** 097 * Create a set of configured objects from their XML description, using an 098 * auxiliary object. 099 * <p> 100 * For example, the auxilary object o might be a manager or GUI of some type 101 * that needs to be informed as each object is created. 102 * 103 * @param e Top-level XML element containing the description 104 * @param o Implementation-specific Object needed for the conversion 105 */ 106 @Override 107 public void load(Element e, Object o) { 108 throw new UnsupportedOperationException("Method not coded"); 109 } 110 111 /** 112 * Store the 113 * 114 * @param o The object to be recorded. Specific XmlAdapter implementations 115 * will require this to be of a specific type; that binding is done 116 * in ConfigXmlManager. 117 * @return The XML representation Element 118 */ 119 @Override 120 public Element store(Object o) { 121 return storeDirectly(o, ""); 122 } 123 124 static int defaultDepth = 5; 125 126 static public Element storeDirectly(Object o, String fileName) { 127 final FileHistory r = (FileHistory) o; 128 if (r == null) { 129 return null; // no file history object, not recording 130 } 131 var loadAndStorePreferences = InstanceManager.getDefault(LoadAndStorePreferences.class); 132 if (loadAndStorePreferences.isExcludeFileHistory()) { 133 return null; // writing of file history is suppressed 134 } 135 Element e = historyElement(r, defaultDepth); 136 137 // add one more element for this store 138 String name = fileName == null ? "" : fileName; 139 FileHistory.OperationMemo rev 140 = r.new OperationMemo() { 141 { 142 type = "Store"; 143 date = (new java.util.Date()).toString(); 144 filename = name; 145 history = null; 146 } 147 }; 148 149 e.addContent( 150 operationElement(rev, 10) 151 ); 152 // and return 153 return e; 154 } 155 156 static Element historyElement(FileHistory r, int depth) { 157 ArrayList<FileHistory.OperationMemo> list = r.getList(); 158 159 Element e = new Element("filehistory"); 160 161 for (int i = 0; i < list.size(); i++) { 162 Element operation = operationElement(list.get(i), depth); 163 e.addContent(operation); 164 } 165 166 return e; 167 } 168 169 static Element operationElement(FileHistory.OperationMemo r, int depth) { 170 Element rev = new Element("operation"); 171 172 Element revnumber = new Element("type"); 173 revnumber.addContent("" + r.type); 174 rev.addContent(revnumber); 175 176 Element date = new Element("date"); 177 date.addContent(r.date); 178 rev.addContent(date); 179 180 Element authorinitials = new Element("filename"); 181 authorinitials.addContent(r.filename); 182 rev.addContent(authorinitials); 183 184 if (r.history != null && depth >= 1) { 185 rev.addContent(historyElement(r.history, depth - 1)); 186 } 187 188 return rev; 189 } 190 191 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(FileHistoryXml.class); 192}