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}