commit
36a73472ce
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module-library" exported="">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/ext/commons-codec-1.10/commons-codec-1.10.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library" exported="">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/ext/commons-validator-1.4.1/commons-validator-1.4.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" name="commons-codec" level="project" />
|
||||
<orderEntry type="library" name="commons-validator" level="project" />
|
||||
<orderEntry type="library" name="jfxrt" level="project" />
|
||||
</component>
|
||||
</module>
|
@ -0,0 +1,33 @@
|
||||
package de.t_battermann.dhbw.todolist;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Export the user data in a CSV file
|
||||
*/
|
||||
public class CSVHandler implements ExportHandler {
|
||||
@Override
|
||||
public void exportToFile(Map<String, User> users, File filename) throws IOException {
|
||||
// TODO: implement method
|
||||
}
|
||||
|
||||
@Override
|
||||
public String exportToString(Map<String, User> users) {
|
||||
// TODO: implement method
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, User> importFromFile(File filename) throws IOException, InvalidDataException {
|
||||
// TODO: implement method
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, User> importFromString(String str) throws InvalidDataException {
|
||||
// TODO: implement method
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package de.t_battermann.dhbw.todolist;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Interface for exporting/saving the data
|
||||
*/
|
||||
public interface ExportHandler {
|
||||
/**
|
||||
* Export to file.
|
||||
*
|
||||
* @param users A Map containing the users
|
||||
* @param filename Path to the file the data should be saved to
|
||||
*/
|
||||
void exportToFile(Map<String, User> users, File filename) throws IOException;
|
||||
|
||||
/**
|
||||
* Export to string.
|
||||
*
|
||||
* @param users the users
|
||||
* @return A String containing the data
|
||||
*/
|
||||
String exportToString(Map<String, User> users);
|
||||
|
||||
/**
|
||||
* Import from file.
|
||||
*
|
||||
* @param filename Path to the saved data
|
||||
* @return A Map containing the Users, username as index
|
||||
*/
|
||||
Map<String, User> importFromFile(File filename) throws IOException, InvalidDataException;
|
||||
|
||||
/**
|
||||
* Import from string.
|
||||
*
|
||||
* @param str A String containing the Data
|
||||
* @return A Map containing the User, username as index
|
||||
*/
|
||||
Map<String, User> importFromString(String str) throws InvalidDataException;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package de.t_battermann.dhbw.todolist;
|
||||
|
||||
/**
|
||||
* This exception is thrown when the imported data is not as expected.
|
||||
*/
|
||||
public class InvalidDataException extends Exception {
|
||||
public InvalidDataException() {
|
||||
}
|
||||
|
||||
public InvalidDataException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package de.t_battermann.dhbw.todolist;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class Main extends Application {
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception{
|
||||
new Controller(primaryStage);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
package de.t_battermann.dhbw.todolist;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This class represents a todo item containing all the data.
|
||||
*/
|
||||
public class Todo {
|
||||
private String uuid;
|
||||
private String title = "No title";
|
||||
private boolean done = false;
|
||||
private boolean prio = false;
|
||||
private String comment = "";
|
||||
private Calendar dueDate = null;
|
||||
|
||||
/**
|
||||
* Instantiates a new empty Todo item.
|
||||
*/
|
||||
public Todo() {
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Todo.
|
||||
*
|
||||
* @param uuid the uuid
|
||||
* @param title the title
|
||||
* @param comment the comment
|
||||
* @param dueDate the due date
|
||||
* @param done Is the item done?
|
||||
* @param prio Has the item high priority?
|
||||
*/
|
||||
protected Todo(String uuid, String title, String comment, Calendar dueDate, boolean done, boolean prio) {
|
||||
this.uuid = uuid;
|
||||
this.title = title;
|
||||
this.comment = comment;
|
||||
this.dueDate = dueDate;
|
||||
this.done = done;
|
||||
this.prio = prio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Todo.
|
||||
*
|
||||
* @param title the title
|
||||
* @param comment the comment
|
||||
*/
|
||||
public Todo(String title, String comment) {
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
this.title = title;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets uuid.
|
||||
*
|
||||
* @return the uuid
|
||||
*/
|
||||
public String getUuid() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets title.
|
||||
*
|
||||
* @return the title
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets title.
|
||||
*
|
||||
* @param title the title
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it done?
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets done.
|
||||
*
|
||||
* @param done the done
|
||||
*/
|
||||
public void setDone(boolean done) {
|
||||
this.done = done;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is prio.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean isPrio() {
|
||||
return prio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets prio.
|
||||
*
|
||||
* @param prio the prio
|
||||
*/
|
||||
public void setPrio(boolean prio) {
|
||||
this.prio = prio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets comment.
|
||||
*
|
||||
* @return the comment
|
||||
*/
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets comment.
|
||||
*
|
||||
* @param comment the comment
|
||||
*/
|
||||
public void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets due date.
|
||||
*
|
||||
* @return the due date
|
||||
*/
|
||||
public Calendar getDueDate() {
|
||||
return dueDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets due date.
|
||||
*
|
||||
* @param dueDate the due date
|
||||
*/
|
||||
public void setDueDate(Calendar dueDate) {
|
||||
this.dueDate = dueDate;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
SimpleDateFormat format = new SimpleDateFormat();
|
||||
format.applyPattern("yyyyMMdd'T'HH:mm:ssZ");
|
||||
return this.getDueDate() != null ? format.format(this.getDueDate().getTime()) : "00:00";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getTitle();
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
package de.t_battermann.dhbw.todolist;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class contains a todo list with all its items.
|
||||
*/
|
||||
public class TodoList {
|
||||
private String uuid = UUID.randomUUID().toString();
|
||||
private List<Todo> todos = new LinkedList<>();
|
||||
private String name;
|
||||
private boolean changeable;
|
||||
|
||||
/**
|
||||
* Instantiates a new Todo list.
|
||||
*
|
||||
* @param name the name
|
||||
*/
|
||||
public TodoList(String name) {
|
||||
this.changeable = true;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Todo list.
|
||||
*
|
||||
* @param name the name
|
||||
* @param changeable Can the name be changed?
|
||||
*/
|
||||
public TodoList(String name, boolean changeable) {
|
||||
this.changeable = changeable;
|
||||
this.name = name;
|
||||
this.initList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Todo list.
|
||||
*
|
||||
* @param uuid the uuid
|
||||
* @param name the name
|
||||
* @param changeable Can the name be changed?
|
||||
*/
|
||||
protected TodoList(String uuid, String name, boolean changeable) {
|
||||
this.uuid = uuid;
|
||||
this.todos = new LinkedList<>();
|
||||
this.name = name;
|
||||
this.changeable = changeable;
|
||||
}
|
||||
|
||||
private void initList() {
|
||||
this.todos.add(new Todo("Start using your TodoList", "Add, delete and modify entries."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets uuid.
|
||||
*
|
||||
* @return the uuid
|
||||
*/
|
||||
public String getUuid() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets name.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets name.
|
||||
*
|
||||
* @param name the name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
if (this.isChangeable())
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets todos.
|
||||
*
|
||||
* @return the todos
|
||||
*/
|
||||
public List<Todo> getTodos() {
|
||||
return todos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add todo.
|
||||
*
|
||||
* @param todo the todo
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean addTodo(Todo todo) {
|
||||
if (todos.contains(todo)) {
|
||||
return false;
|
||||
}
|
||||
todos.add(todo);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a todo item
|
||||
*
|
||||
* @param todo The Item to be deleted
|
||||
*/
|
||||
public void deleteTodo(Todo todo) {
|
||||
if (todos.contains(todo)) {
|
||||
todos.remove(todo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is changeable.
|
||||
*
|
||||
* @return true if the name can be changed
|
||||
*/
|
||||
public boolean isChangeable() {
|
||||
return changeable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getName();
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
package de.t_battermann.dhbw.todolist;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.validator.routines.EmailValidator;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class contains all the users data.
|
||||
*/
|
||||
public class User implements Serializable {
|
||||
private String username;
|
||||
private String email;
|
||||
private String password;
|
||||
private String uuid = UUID.randomUUID().toString();
|
||||
private List<TodoList> todoLists;
|
||||
|
||||
/**
|
||||
* Instantiates a new User.
|
||||
*
|
||||
* @param username the username
|
||||
* @param password the password
|
||||
*/
|
||||
public User(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = hashPassword(password);
|
||||
this.email = "";
|
||||
|
||||
todoLists = new LinkedList<>();
|
||||
TodoList tmp = new TodoList("Default", false);
|
||||
todoLists.add(tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new User.
|
||||
* Used to restore saved data
|
||||
*
|
||||
* @param uuid the uuid
|
||||
* @param username the username
|
||||
* @param hashedPassword the hashed password
|
||||
* @param email the email
|
||||
*/
|
||||
protected User(String uuid, String username, String hashedPassword, String email) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
this.password = hashedPassword;
|
||||
this.email = email;
|
||||
this.todoLists = new LinkedList<>();
|
||||
TodoList tmp = new TodoList("Default", false);
|
||||
todoLists.add(tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets username.
|
||||
*
|
||||
* @return the username
|
||||
*/
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets password.
|
||||
*
|
||||
* @return the password
|
||||
*/
|
||||
protected String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets uuid.
|
||||
*
|
||||
* @return the uuid
|
||||
*/
|
||||
public String getUuid() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets email.
|
||||
*
|
||||
* @return the email
|
||||
*/
|
||||
public String getEmail() {
|
||||
return this.email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets todo list.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the todo list
|
||||
*/
|
||||
public TodoList getTodoList(String name) {
|
||||
for(TodoList l: todoLists)
|
||||
if(l.getName().equals(name))
|
||||
return l;
|
||||
System.out.println("TodoList not found: " + name);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets todo lists.
|
||||
*
|
||||
* @return the todo lists
|
||||
*/
|
||||
public List<TodoList> getTodoLists() {
|
||||
return todoLists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check login data.
|
||||
*
|
||||
* @param password the password
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean checkLoginData(String password) {
|
||||
System.out.println("pw: " + password + " -> " + this.hashPassword(password));
|
||||
System.out.println("stored: " + this.password);
|
||||
return this.hashPassword(password).equals(this.password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Username: " + username + "\n"
|
||||
+ "eMail: " + email + "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a todo list.
|
||||
*
|
||||
* @param name the name for the new list
|
||||
* @return false if a list with the given name already exists
|
||||
*/
|
||||
public boolean addTodoList(String name) {
|
||||
return this.addTodoList(new TodoList(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add todo list.
|
||||
*
|
||||
* @param todoList the todo list
|
||||
* @return false if a list with the given name already exists
|
||||
*/
|
||||
public boolean addTodoList(TodoList todoList) {
|
||||
if ( this.getTodoList( todoList.getName()) == null ) {
|
||||
this.todoLists.add(todoList);
|
||||
return true;
|
||||
}
|
||||
System.out.println("A TodoList named '" + todoList.getName() + "' already exists!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the users password
|
||||
*
|
||||
* @param password the password (cleartext)
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = hashPassword(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets email.
|
||||
*
|
||||
* @param email the email
|
||||
* @return the email
|
||||
*/
|
||||
public boolean setEmail(String email) {
|
||||
if (User.checkEmail(email)) {
|
||||
this.email = email;
|
||||
return true;
|
||||
}
|
||||
System.out.println("Invalid eMail: '" + email + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a salted hash
|
||||
*
|
||||
* @param password the password to salt and hash
|
||||
* @return salted and hashed password
|
||||
*/
|
||||
private String hashPassword(String password) {
|
||||
return DigestUtils.sha256Hex(uuid + password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if eMail has correct syntax
|
||||
* @param email string containing a eMail address
|
||||
* @return true if valid syntax
|
||||
*/
|
||||
public static boolean checkEmail(String email) {
|
||||
return email.length() != 0 && EmailValidator.getInstance().isValid(email);
|
||||
}
|
||||
|
||||
public static boolean checkUsername(String username) {
|
||||
return username.matches("[a-zA-Z0-9_-]{3,}");
|
||||
}
|
||||
public static boolean checkPassword(String password) {
|
||||
return password.length() > 6 && password.matches(".*[A-Z].*") && password.matches(".*[a-z].*") && password.matches(".*[0-9].*");
|
||||
}
|
||||
}
|
@ -0,0 +1,286 @@
|
||||
package de.t_battermann.dhbw.todolist;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class implement the ExportHandler interface. It converts the data to XML and vice versa.
|
||||
*/
|
||||
public class XMLHandler implements ExportHandler {
|
||||
/**
|
||||
* Convert a map containing the users to a DOMSource containing XML
|
||||
*
|
||||
* @param users The users map
|
||||
* @return DOMSource containing XML
|
||||
*/
|
||||
private DOMSource doExport(Map<String, User> users) {
|
||||
try {
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
|
||||
Document doc = docBuilder.newDocument();
|
||||
Element rootElement = doc.createElement("todolistapp");
|
||||
doc.appendChild(rootElement);
|
||||
|
||||
for (User userEntry : users.values()) {
|
||||
Element user = doc.createElement("user");
|
||||
|
||||
Element username = doc.createElement("username");
|
||||
username.appendChild(doc.createTextNode(userEntry.getUsername()));
|
||||
user.appendChild(username);
|
||||
|
||||
Element password = doc.createElement("password");
|
||||
password.appendChild(doc.createTextNode(userEntry.getPassword()));
|
||||
user.appendChild(password);
|
||||
|
||||
Element password_salt = doc.createElement("uuid");
|
||||
password_salt.appendChild(doc.createTextNode(userEntry.getUuid()));
|
||||
user.appendChild(password_salt);
|
||||
|
||||
Element email = doc.createElement("email");
|
||||
email.appendChild(doc.createTextNode(userEntry.getEmail()));
|
||||
user.appendChild(email);
|
||||
|
||||
for (TodoList todoListEntry : userEntry.getTodoLists()) {
|
||||
Element list = doc.createElement("TodoList");
|
||||
list.setAttribute("changeable", todoListEntry.isChangeable() ? "true" : "false");
|
||||
|
||||
Element title = doc.createElement("name");
|
||||
title.appendChild(doc.createTextNode(todoListEntry.getName()));
|
||||
list.appendChild(title);
|
||||
|
||||
Element uuid = doc.createElement("uuid");
|
||||
uuid.appendChild(doc.createTextNode(todoListEntry.getUuid()));
|
||||
list.appendChild(uuid);
|
||||
|
||||
for (Todo entry : todoListEntry.getTodos()) {
|
||||
SimpleDateFormat format = new SimpleDateFormat();
|
||||
format.applyPattern("yyyyMMdd'T'HH:mm:ssZ");
|
||||
Element todo = doc.createElement("item");
|
||||
todo.setAttribute("prio", entry.isPrio() ? "true" : "false");
|
||||
todo.setAttribute("done", entry.isDone() ? "true" : "false");
|
||||
|
||||
Element todoTitle = doc.createElement("title");
|
||||
todoTitle.appendChild(doc.createTextNode(entry.getTitle()));
|
||||
todo.appendChild(todoTitle);
|
||||
|
||||
Element todoUuid = doc.createElement("uuid");
|
||||
todoUuid.appendChild(doc.createTextNode(entry.getUuid()));
|
||||
todo.appendChild(todoUuid);
|
||||
|
||||
Element comment = doc.createElement("comment");
|
||||
comment.appendChild(doc.createTextNode(entry.getComment()));
|
||||
todo.appendChild(comment);
|
||||
|
||||
if (entry.getDueDate() != null) {
|
||||
Element duedate = doc.createElement("duedate");
|
||||
duedate.appendChild(doc.createTextNode(format.format(entry.getDueDate().getTime())));
|
||||
todo.appendChild(duedate);
|
||||
} // if duedate
|
||||
list.appendChild(todo);
|
||||
} // for todos
|
||||
user.appendChild(list);
|
||||
} // for todoLists
|
||||
rootElement.appendChild(user);
|
||||
} // for users
|
||||
|
||||
return new DOMSource(doc);
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void exportToFile(Map<String, User> users, File file) {
|
||||
try {
|
||||
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
Transformer transformer = transformerFactory.newTransformer();
|
||||
DOMSource source = this.doExport(users);
|
||||
StreamResult result = new StreamResult(file);
|
||||
transformer.transform(source, result);
|
||||
} catch (TransformerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public String exportToString(Map<String, User> users) {
|
||||
try {
|
||||
StringWriter sw = new StringWriter();
|
||||
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
Transformer transformer = transformerFactory.newTransformer();
|
||||
DOMSource source = this.doExport(users);
|
||||
transformer.transform(source, new StreamResult(sw));
|
||||
return sw.toString();
|
||||
} catch (TransformerConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
} catch (TransformerException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string-element from a node
|
||||
*
|
||||
* @param node The node to be searched in
|
||||
* @param name The elements name
|
||||
* @return the desired string or empty string if not found
|
||||
*/
|
||||
private String elementGetString(Element node, String name) {
|
||||
NodeList nodes = node.getElementsByTagName(name);
|
||||
if (nodes.getLength() >= 1) {
|
||||
return nodes.item(0).getTextContent();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a boolean value from a attribute
|
||||
*
|
||||
* @param node The node to be searched in
|
||||
* @param name The attributes name
|
||||
* @param defaultValue if the attribute is not set use this value
|
||||
* @return either the value of the attribute or the default value if attribute not found
|
||||
*/
|
||||
private boolean elementGetBool(Element node, String name, boolean defaultValue) {
|
||||
if (node.hasAttribute(name)) {
|
||||
return node.getAttribute(name).compareTo("true") == 0;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a date from a element
|
||||
*
|
||||
* @param node The node to be searched in
|
||||
* @param name The elements name
|
||||
* @return Either the date (if found) or null
|
||||
*/
|
||||
private Calendar elementGetDate(Element node, String name) {
|
||||
SimpleDateFormat format = new SimpleDateFormat();
|
||||
format.applyPattern("yyyyMMdd'T'HH:mm:ssZ");
|
||||
NodeList nodes = node.getElementsByTagName(name);
|
||||
if (nodes.getLength() >= 1) {
|
||||
try {
|
||||
Calendar r = new GregorianCalendar();
|
||||
r.setTime(format.parse(nodes.item(0).getTextContent()));
|
||||
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<String, User> doImport(InputStream stream) throws IOException, InvalidDataException {
|
||||
// Temporary variables
|
||||
TreeMap<String, User> users = new TreeMap<>();
|
||||
User user;
|
||||
TodoList todoList;
|
||||
Todo todo;
|
||||
try {
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
|
||||
Document doc = docBuilder.parse(stream);
|
||||
doc.getDocumentElement().normalize();
|
||||
|
||||
// the actual import ...
|
||||
if (!"todolistapp".equals(doc.getDocumentElement().getNodeName())) {
|
||||
throw new InvalidDataException("Expected 'todolistapp' as root node");
|
||||
}
|
||||
|
||||
NodeList nUsers = doc.getElementsByTagName("user");
|
||||
for (int i = 0; i < nUsers.getLength(); i++) {
|
||||
Node nUser = nUsers.item(i);
|
||||
if (nUser.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element eUser = (Element) nUser;
|
||||
user = new User(
|
||||
this.elementGetString(eUser, "uuid"),
|
||||
this.elementGetString(eUser, "username"),
|
||||
this.elementGetString(eUser, "password"),
|
||||
this.elementGetString(eUser, "email")
|
||||
);
|
||||
NodeList nTodoLists = eUser.getElementsByTagName("TodoList");
|
||||
for (int j = 0; j < nTodoLists.getLength(); j++) {
|
||||
Node nTodoList = nTodoLists.item(j);
|
||||
if (nTodoList.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element eTodoList = (Element) nTodoList;
|
||||
todoList = new TodoList(
|
||||
this.elementGetString(eTodoList, "uuid"),
|
||||
this.elementGetString(eTodoList, "name"),
|
||||
this.elementGetBool(eTodoList, "changeable", true)
|
||||
);
|
||||
NodeList nTodos = eTodoList.getElementsByTagName("item");
|
||||
for (int k = 0; k < nTodos.getLength(); k++) {
|
||||
Node nTodo = nTodos.item(k);
|
||||
if (nTodo.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element eTodo = (Element) nTodo;
|
||||
// String uuid, String title, String comment, Calendar dueDate, boolean done, boolean prio
|
||||
todo = new Todo(
|
||||
this.elementGetString(eTodo, "uuid"),
|
||||
this.elementGetString(eTodo, "title"),
|
||||
this.elementGetString(eTodo, "comment"),
|
||||
this.elementGetDate(eTodo, "duedate"),
|
||||
this.elementGetBool(eTodo, "done", false),
|
||||
this.elementGetBool(eTodo, "prio", false)
|
||||
);
|
||||
todoList.addTodo(todo);
|
||||
}
|
||||
}
|
||||
user.addTodoList(todoList);
|
||||
}
|
||||
}
|
||||
users.put(user.getUsername(), user);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (ParserConfigurationException | SAXException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
public Map<String, User> importFromFile(File file) throws IOException, InvalidDataException {
|
||||
InputStream inputStream = new FileInputStream(file);
|
||||
return this.doImport(inputStream);
|
||||
}
|
||||
|
||||
public Map<String, User> 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<>();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.*?>
|
||||
<?import java.lang.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
|
||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="350.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8.0.45" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
<Accordion>
|
||||
<panes>
|
||||
<TitledPane id="loginPane" animated="false" text="Login">
|
||||
<content>
|
||||
<VBox prefHeight="300.0" prefWidth="100.0">
|
||||
<children>
|
||||
<GridPane hgap="5.0" vgap="5.0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="283.0" minWidth="10.0" prefWidth="159.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="419.0" minWidth="10.0" prefWidth="419.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Label text="Username:" />
|
||||
<Label text="Password:" GridPane.rowIndex="1" />
|
||||
<TextField id="loginUsername" GridPane.columnIndex="1" />
|
||||
<PasswordField id="loginPassword" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
</children>
|
||||
</GridPane>
|
||||
<Button id="loginButton" mnemonicParsing="false" prefHeight="25.0" prefWidth="482.0" text="Login" textAlignment="CENTER" VBox.vgrow="ALWAYS">
|
||||
<VBox.margin>
|
||||
<Insets top="5.0" />
|
||||
</VBox.margin>
|
||||
</Button>
|
||||
<Label id="labelHints" prefHeight="15.0" prefWidth="477.0" text="Please enter your credentials">
|
||||
<VBox.margin>
|
||||
<Insets top="10.0" />
|
||||
</VBox.margin>
|
||||
</Label>
|
||||
</children>
|
||||
</VBox>
|
||||
</content>
|
||||
</TitledPane>
|
||||
<TitledPane id="createNewUserPane" animated="false" text="Create new user">
|
||||
<content>
|
||||
<VBox prefHeight="300.0" prefWidth="100.0">
|
||||
<children>
|
||||
<GridPane hgap="5.0" prefHeight="156.0" prefWidth="478.0" vgap="5.0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="283.0" minWidth="10.0" prefWidth="159.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="419.0" minWidth="10.0" prefWidth="419.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Label text="Username:" />
|
||||
<Label text="Password:" GridPane.rowIndex="1" />
|
||||
<TextField id="registerUsername" GridPane.columnIndex="1" />
|
||||
<PasswordField id="registerPassword" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
<Label text="Password:" GridPane.rowIndex="2" />
|
||||
<Label text="eMail:" GridPane.rowIndex="3" />
|
||||
<Label text="eMail:" GridPane.rowIndex="4" />
|
||||
<PasswordField id="registerPasswordRepeat" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
||||
<TextField id="registerEmail" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||
<TextField id="registerEmailRepeat" GridPane.columnIndex="1" GridPane.rowIndex="4" />
|
||||
</children>
|
||||
</GridPane>
|
||||
<Button id="registerButton" mnemonicParsing="false" prefHeight="25.0" prefWidth="482.0" text="Login" textAlignment="CENTER" VBox.vgrow="ALWAYS">
|
||||
<VBox.margin>
|
||||
<Insets top="5.0" />
|
||||
</VBox.margin>
|
||||
</Button>
|
||||
<Label id="labelHintsCreateNewUser" prefHeight="15.0" prefWidth="477.0" text="Create a new user">
|
||||
<VBox.margin>
|
||||
<Insets top="10.0" />
|
||||
</VBox.margin>
|
||||
</Label>
|
||||
</children>
|
||||
</VBox>
|
||||
</content>
|
||||
</TitledPane>
|
||||
</panes>
|
||||
</Accordion>
|
||||
</children>
|
||||
</VBox>
|
@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.scene.image.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import java.lang.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
|
||||
<VBox id="vbox" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="550.0" prefWidth="750.0" xmlns="http://javafx.com/javafx/8.0.45" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
<ToolBar>
|
||||
<items>
|
||||
<Button id="menuSave" mnemonicParsing="false" text="Save" />
|
||||
<Button id="menuSaveAs" mnemonicParsing="false" text="Save as ..." />
|
||||
<Separator orientation="VERTICAL" />
|
||||
<Button id="menuChangePassword" mnemonicParsing="false" text="Cange password" />
|
||||
<Button id="MenuChangeEmail" mnemonicParsing="false" text="Change eMail" />
|
||||
<Button id="menuLogout" mnemonicParsing="false" text="Log out" />
|
||||
<Separator orientation="VERTICAL" />
|
||||
<Button id="menuClose" mnemonicParsing="false" text="Close" />
|
||||
</items>
|
||||
</ToolBar>
|
||||
<SplitPane dividerPositions="0.333" prefHeight="160.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
|
||||
<items>
|
||||
<VBox>
|
||||
<children>
|
||||
<ListView id="todoLists" VBox.vgrow="ALWAYS" />
|
||||
<ToolBar visible="false">
|
||||
<items>
|
||||
<TextField id="todoListNewName" />
|
||||
<Button id="todoListNewNameSave" mnemonicParsing="false" text="Save" />
|
||||
</items>
|
||||
</ToolBar>
|
||||
<ToolBar>
|
||||
<items>
|
||||
<Button mnemonicParsing="false" text="New" />
|
||||
<Button mnemonicParsing="false" text="Delete" />
|
||||
<Button mnemonicParsing="false" text="Edit" />
|
||||
</items>
|
||||
</ToolBar>
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0">
|
||||
<children>
|
||||
<ToolBar prefHeight="40.0" prefWidth="200.0">
|
||||
<items>
|
||||
<Button id="todoNew" mnemonicParsing="false" text="New" />
|
||||
<Button id="todoToggleDone" mnemonicParsing="false" text="(un)done" />
|
||||
<Button id="todoToggleStar" mnemonicParsing="false" text="(un)star" />
|
||||
<Button id="todoDelete" mnemonicParsing="false" text="delete" />
|
||||
<Separator orientation="VERTICAL" />
|
||||
<CheckBox id="todosShowDone" mnemonicParsing="false" text="show done" />
|
||||
</items>
|
||||
</ToolBar>
|
||||
<SplitPane dividerPositions="0.6" orientation="VERTICAL" VBox.vgrow="ALWAYS">
|
||||
<items>
|
||||
<ListView id="todos" prefHeight="200.0" prefWidth="200.0" />
|
||||
<ScrollPane vbarPolicy="ALWAYS">
|
||||
<content>
|
||||
<VBox>
|
||||
<children>
|
||||
<GridPane>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="ALWAYS" maxWidth="200.0" minWidth="10.0" prefWidth="105.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="309.0" minWidth="10.0" prefWidth="309.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" prefHeight="75.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="30.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Label text="Description" GridPane.rowIndex="1" />
|
||||
<Label text="Due date" GridPane.rowIndex="2" />
|
||||
<Label text="Title" />
|
||||
<TextField id="todoDetailTitle" GridPane.columnIndex="1" />
|
||||
<TextArea id="todoDetailDescription" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
<HBox prefHeight="100.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
|
||||
<children>
|
||||
<CheckBox id="todoDetailDueDate" mnemonicParsing="false" />
|
||||
<DatePicker id="todoDetailDate" disable="true" />
|
||||
<TextField id="todoDetailTime" disable="true" text="12:00" />
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
</GridPane>
|
||||
<Button id="todoDetailSave" mnemonicParsing="false" style="-fx-pref-width: 100%;" text="Save" VBox.vgrow="ALWAYS" />
|
||||
</children>
|
||||
</VBox>
|
||||
</content>
|
||||
</ScrollPane>
|
||||
</items>
|
||||
</SplitPane>
|
||||
</children>
|
||||
</VBox>
|
||||
</items>
|
||||
</SplitPane>
|
||||
<Label id="statusLine" text="TodoList" />
|
||||
</children>
|
||||
</VBox>
|
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.*?>
|
||||
<?import java.lang.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
|
||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="150.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8.0.45" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
<TitledPane animated="false" collapsible="false" prefHeight="75.0" text="Load saved data">
|
||||
<content>
|
||||
<HBox prefWidth="200.0">
|
||||
<children>
|
||||
<TextField id="openFilePath" prefHeight="26.0" prefWidth="346.0">
|
||||
<HBox.margin>
|
||||
<Insets right="5.0" />
|
||||
</HBox.margin>
|
||||
</TextField>
|
||||
<Button id="openFileButton" mnemonicParsing="false" prefHeight="26.0" prefWidth="127.0" text="Open file" />
|
||||
</children>
|
||||
</HBox>
|
||||
</content>
|
||||
</TitledPane>
|
||||
<TitledPane animated="false" collapsible="false" prefHeight="75.0" text="New file">
|
||||
<content>
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="0.0" prefWidth="498.0">
|
||||
<children>
|
||||
<Button id="openFileNew" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="473.0" text="Create new file" AnchorPane.bottomAnchor="1.0" AnchorPane.leftAnchor="1.0" AnchorPane.rightAnchor="1.0" AnchorPane.topAnchor="1.0" />
|
||||
</children></AnchorPane>
|
||||
</content>
|
||||
</TitledPane>
|
||||
</children>
|
||||
</VBox>
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.*?>
|
||||
<?import java.lang.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
|
||||
<TitledPane animated="false" collapsible="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" text="Save as ..." xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.45">
|
||||
<content>
|
||||
<HBox>
|
||||
<children>
|
||||
<TextField id="filename">
|
||||
<HBox.margin>
|
||||
<Insets right="5.0" />
|
||||
</HBox.margin>
|
||||
</TextField>
|
||||
<Button id="save" mnemonicParsing="false" text="Save" />
|
||||
</children>
|
||||
</HBox>
|
||||
</content>
|
||||
</TitledPane>
|
Loading…
Reference in new issue