package de.saring.sportstracker.storage; import java.io.File; import java.io.IOException; import java.time.LocalDateTime; import java.util.ArrayList; import org.jdom2.Document; import org.jdom2.Element; import de.saring.sportstracker.core.STException; import de.saring.sportstracker.core.STExceptionID; import de.saring.sportstracker.data.Note; import de.saring.sportstracker.data.NoteList; /** * This class is for reading or writing a NoteList object from or to a XML file. * * @author Stefan Saring * @version 1.0 */ public class XMLNoteList { /** * The XSD filename with the structure of the note list. */ private static final String XSD_NOTES = "notes.xsd"; /** * Reads the note list from the specified XML file. * Returns an empty list when the file doesn't exists yet. * * @param source name of the XML file to read from * @return the created NoteList * @throws STException thrown on read problems */ public NoteList readNoteList(String source) throws STException { try { // return an empty list if the file doesn't exists yet File fSource = new File(source); if (!fSource.exists()) { return new NoteList(); } // create JDOM Document from XML with XSD validation Document document = XMLUtils.getJDOMDocument(fSource, XSD_NOTES); ArrayList<Note> tempNotes = new ArrayList<>(); // get root element and read all the contained notes Element eNoteList = document.getRootElement(); eNoteList.getChildren("note").forEach(eNote -> tempNotes.add(readNote(eNote))); NoteList noteList = new NoteList(); noteList.clearAndAddAll(tempNotes); return noteList; } catch (Exception e) { throw new STException(STExceptionID.XMLSTORAGE_READ_NOTE_LIST, "Failed to read note list from XML file '" + source + "' ...", e); } } /** * Reads the data from the specified note element and returns the created * Note object. * * @param eNote note JDOM element * @return the created Note object */ private Note readNote(Element eNote) { Note note = new Note(Integer.parseInt(eNote.getChildText("id"))); note.setComment(eNote.getChildText("text")); // get and convert date (format already checked by XSD schema) String strDate = eNote.getChildText("date"); try { note.setDateTime(LocalDateTime.parse(strDate, XMLUtils.DATE_TIME_FORMAT)); } catch (Exception e) { throw new IllegalArgumentException("Failed to parse note with ID '" + note.getId() + "', the date format '" + strDate + "' is not valid!"); } return note; } /** * Writes the NoteList to the specified XML file. * * @param noteList the NoteList to store * @param destination name of xml file to write to * @throws STException thrown on store problems */ public void storeNoteList(NoteList noteList, String destination) throws STException { // create JDOM element with all notes Element eNoteList = createNoteListElement(noteList); // write the element to XML file try { XMLUtils.writeXMLFile(eNoteList, destination); } catch (IOException e) { throw new STException(STExceptionID.XMLSTORAGE_STORE_NOTE_LIST, "Failed to write note list to XML file '" + destination + "' ...", e); } } /** * Creates the "note-list" element with all notes for the specified * note list. * * @param noteList the NoteList to store * @return the created Element */ private Element createNoteListElement(NoteList noteList) { Element eNoteList = new Element("note-list"); noteList.forEach(note -> { Element eNote = new Element("note"); eNoteList.addContent(eNote); XMLUtils.addElement(eNote, "id", String.valueOf(note.getId())); XMLUtils.addElement(eNote, "date", note.getDateTime().format(XMLUtils.DATE_TIME_FORMAT)); XMLUtils.addElement(eNote, "text", note.getComment()); }); return eNoteList; } }