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