diff --git a/README.md b/README.md index de31b60..52e760a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,17 @@ A project for class "programming 2" at Baden-Wuerttemberg Cooperative State Univ ## Todo -- Implement CSVHandler to save CSV data - Highlight items with priority - Highlight items past due (and TodoList!) -- filter items (include/exclude done items) \ No newline at end of file +- filter items (include/exclude done items) + +## Dependencies + +- [Apache Commons Lang](https://commons.apache.org/proper/commons-lang/) +- [Apache Commons Validator](https://commons.apache.org/proper/commons-validator/) +- [Apache Commons Codec](https://commons.apache.org/proper/commons-codec/download_codec.cgi) + +or simply: + + cd ext + bash get-dependencies.sh \ No newline at end of file diff --git a/src/de/t_battermann/dhbw/todolist/CSVHandler.java b/src/de/t_battermann/dhbw/todolist/CSVHandler.java index ce653ff..3df9c91 100644 --- a/src/de/t_battermann/dhbw/todolist/CSVHandler.java +++ b/src/de/t_battermann/dhbw/todolist/CSVHandler.java @@ -1,33 +1,160 @@ package de.t_battermann.dhbw.todolist; -import java.io.File; -import java.io.IOException; +import com.opencsv.CSVParser; +import com.opencsv.CSVWriter; + +import java.io.*; +import java.nio.charset.Charset; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.GregorianCalendar; import java.util.Map; +import java.util.TreeMap; /** * Export the user data in a CSV file + * + * File format: + * USER,uuid,username,password,email + * TODOLIST,username,uuid,name,changeable + * TO DO,username,todolist,uuid,title,comment,dueDate,done,prio */ public class CSVHandler implements ExportHandler { - @Override - public void exportToFile(Map users, File filename) throws IOException { - // TODO: implement method - } - - @Override - public String exportToString(Map users) { - // TODO: implement method - return null; - } - - @Override - public Map importFromFile(File filename) throws IOException, InvalidDataException { - // TODO: implement method - return null; - } - - @Override - public Map importFromString(String str) throws InvalidDataException { - // TODO: implement method - return null; - } + /** + * Convert a map containing the users to a DOMSource containing XML + * + * @param users The users map + * @return String containing CSV + */ + private String doExport(Map users) { + StringWriter sw = new StringWriter(); + CSVWriter w = new CSVWriter(sw); + StringWriter s = new StringWriter(); + // date formatter + SimpleDateFormat format = new SimpleDateFormat(); + format.applyPattern("yyyyMMdd'T'HH:mm:ssZ"); + for( User user: users.values()) { + String userData[] = { "USER", user.getUuid(), user.getUsername(), user.getPassword(), user.getEmail() }; + w.writeNext(userData); + for( TodoList list: user.getTodoLists() ) { + String listData[] = { "TODOLIST", user.getUsername(), list.getUuid(), list.getName(), list.isChangeable() ? "true" : "false" }; + w.writeNext(listData); + for( Todo todo: list.getTodos() ) { + String todoData[] = { "TODO", user.getUsername(), list.getName(), todo.getUuid(), todo.getTitle(), todo.getComment(), + todo.getDueDate() == null ? "0" : format.format(todo.getDueDate().getTime()), todo.isDone() ? "true" : "false", todo.isPrio() ? "true" : "false" }; + w.writeNext(todoData); + } + } + } + return sw.toString(); + } + + @Override + public void exportToFile(Map users, File file) throws IOException { + FileWriter fw = new FileWriter(file); + BufferedWriter bw = new BufferedWriter(fw); + bw.write( doExport(users) ); + bw.close(); + } + + @Override + public String exportToString(Map users) { + return doExport(users); + } + + /** + * Get a date from a element + * + * @param date The String containing the date + * @return Either the date (if found) or null + */ + private Calendar stringToDate(String date) { + if ( date.equals("0") ) + return null; + SimpleDateFormat format = new SimpleDateFormat(); + format.applyPattern("yyyyMMdd'T'HH:mm:ssZ"); + try { + Calendar r = new GregorianCalendar(); + r.setTime(format.parse(date)); + return r; + } catch (ParseException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Helper function to convert the xml to a map containing the user data + * + * @param stream InputStream containing XML data + * @return The user object + * @throws IOException + * @throws InvalidDataException + */ + private Map doImport(InputStream stream) throws IOException, InvalidDataException { + BufferedReader r = new BufferedReader(new InputStreamReader(stream)); + CSVParser c = new CSVParser(); + String csv, line[]; + Map users = new TreeMap<>(); + while((csv = r.readLine()) != null) { + line = c.parseLine(csv); + switch( line[0] ) { + case "USER": + if ( line.length != 5 ) { + throw new InvalidDataException("Invalid user: line doesn’t contain 5 elements"); + }else if ( users.containsKey( line[2] ) ) { + throw new InvalidDataException("Invalid user: duplicate User!"); + }else { + User u = new User(line[1], line[2], line[3], line[4]); + users.put(line[2], u); + } + break; + case "TODOLIST": + if ( line.length != 5 ) { + throw new InvalidDataException("Invalid TodoList: line doesn’t contain 5 elements"); + } else if ( !users.containsKey(line[1]) ) { + throw new InvalidDataException("Invalid TodoList: User not found!"); + } else if ( users.get(line[1]).getTodoList(line[3]) != null) { + throw new InvalidDataException("Invalid TodoList: duplicate TodoList!"); + } else { + TodoList t = new TodoList(line[2],line[3],line[4].equals("true")); + users.get(line[1]).addTodoList(t); + } + break; + case "TODO": + if ( line.length != 9 ) { + throw new InvalidDataException("Invalid Todo: line doesn’t contain 9 elements" + line.length); + } else if ( !users.containsKey(line[1]) ) { + throw new InvalidDataException("Invalid Todo: User not found!"); + } else if ( users.get(line[1]).getTodoList(line[2]) == null) { + throw new InvalidDataException("Invalid Todo: TodoList not found!"); + } else { + Todo t = new Todo( line[3], line[4], line[5], stringToDate(line[6]), line[7].equals("true"), line[8].equals("true") ); + users.get(line[1]).getTodoList(line[2]).addTodo(t); + } + break; + default: + throw new InvalidDataException("Unexpected line identifier."); + } + } + return users; + } + + @Override + public Map importFromFile(File file) throws IOException, InvalidDataException { + InputStream inputStream = new FileInputStream(file); + return this.doImport(inputStream); + } + + @Override + public Map importFromString(String str) throws InvalidDataException { + try { + InputStream inputStream = new ByteArrayInputStream(str.getBytes(Charset.forName("UTF-8"))); + return this.doImport(inputStream); + } catch (IOException e) { + e.printStackTrace(); + return new TreeMap<>(); + } + } }