package teamnotepad;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.jdbc.JdbcConnectionSource;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.SecureRandom;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import teamnotepad.entities.*;
/**
*
* @author User
*/
public class TeamNotepadModel {
private final String authFilePath = "user.auth";
private final String connectionString = "jdbc:mysql://localhost/teamnotepad";
private final String userName = "root";
private final String userPass = "";
public TeamNotepadModel() {
try {
setupDatabase();
} catch (SQLException ex) {
System.out.println("SQL EXCEPTION");
}
}
public TeamNotepadModel(boolean ommitDBCreation){}
private void setupDatabase() throws SQLException {
ConnectionSource connectionSource = null;
try {
connectionSource = new JdbcConnectionSource(connectionString, userName, userPass);
TableUtils.createTableIfNotExists(connectionSource, NotesSuite.class);
TableUtils.createTableIfNotExists(connectionSource, User.class);
TableUtils.createTableIfNotExists(connectionSource, Note.class);
} catch (Exception ex) {
System.err.println("Exception: " + ex.getMessage() + "\n");
ex.printStackTrace();
} finally {
if (connectionSource != null) {
connectionSource.close();
}
}
}
public void createNotesSuite(User owner, String title) throws Exception {
if (!isNotesSuiteTitleValid(title)) {
throw new Exception("Incorrect title");
}
Dao<NotesSuite, Integer> notesSuiteDao;
ConnectionSource connectionSource = null;
try {
connectionSource = new JdbcConnectionSource(connectionString, userName, userPass);
notesSuiteDao = DaoManager.createDao(connectionSource, NotesSuite.class);
NotesSuite newNotesSuite = new NotesSuite(owner, title);
notesSuiteDao.create(newNotesSuite);
int id = newNotesSuite.getId();
System.out.println("Created: " + id);
} catch (SQLException ex) {
System.err.println("Exception: " + ex.getMessage());
ex.printStackTrace();
} finally {
if (connectionSource != null) {
connectionSource.close();
}
}
}
public List<NotesSuite> getNotesSuites(User owner) {
Dao<NotesSuite, Integer> notesSuitesDao;
ConnectionSource connectionSource = null;
List<NotesSuite> notesSuites = null;
try {
connectionSource = new JdbcConnectionSource(connectionString, userName, userPass);
notesSuitesDao = DaoManager.createDao(connectionSource, NotesSuite.class);
QueryBuilder<NotesSuite, Integer> queryBuilder = notesSuitesDao.queryBuilder();
queryBuilder.where().eq(NotesSuite.OWNER_FIELD_NAME, owner);
notesSuites = notesSuitesDao.query(queryBuilder.prepare());
connectionSource.close();
} catch (SQLException ex) {
System.err.println("Exception: " + ex.getMessage());
ex.printStackTrace();
}
return notesSuites;
}
public boolean createNote(Note note) {
Dao<Note, Integer> notesDao;
ConnectionSource connectionSource = null;
try {
connectionSource = new JdbcConnectionSource(connectionString, userName, userPass);
notesDao = DaoManager.createDao(connectionSource, Note.class);
notesDao.create(note);
connectionSource.close();
} catch (SQLException ex) {
System.err.println("Exception: " + ex.getMessage());
ex.printStackTrace();
return false;
}
return true;
}
public boolean updateNote(Note note) {
Dao<Note, Integer> notesDao;
ConnectionSource connectionSource = null;
try {
connectionSource = new JdbcConnectionSource(connectionString, userName, userPass);
notesDao = DaoManager.createDao(connectionSource, Note.class);
notesDao.update(note);
connectionSource.close();
} catch (SQLException ex) {
System.err.println("Exception: " + ex.getMessage());
ex.printStackTrace();
return false;
}
return true;
}
public User getCurrentUserByAuthFile() {
User user = null;
try {
File authFile = new File(authFilePath);
if (authFile.exists()) {
String token = getTokenFromAuthFile();
return getUserByToken(token);
}
} catch (Exception ex) {
System.err.println("ex: " + ex.getMessage());
}
return user;
}
private String getTokenFromAuthFile() throws IOException {
return new String(Files.readAllBytes(Paths.get(authFilePath)), StandardCharsets.UTF_8);
}
private User getUserByToken(String token) {
Dao<User, Integer> usersDao;
ConnectionSource connectionSource;
User user = null;
try {
connectionSource = new JdbcConnectionSource(connectionString, userName, userPass);
usersDao = DaoManager.createDao(connectionSource, User.class);
QueryBuilder<User, Integer> queryBuilder = usersDao.queryBuilder();
queryBuilder.where().like(User.TOKEN_FIELD_NAME, token);
user = usersDao.queryForFirst(queryBuilder.prepare());
connectionSource.close();
} catch (SQLException ex) {
System.err.println("Exception: " + ex.getMessage());
ex.printStackTrace();
}
return user;
}
private void generateAndSaveUserToken(User user) {
if (user != null) {
Dao<User, Integer> usersDao;
ConnectionSource connectionSource;
try {
connectionSource = new JdbcConnectionSource(connectionString, userName, userPass);
usersDao = DaoManager.createDao(connectionSource, User.class);
String token = generateUserAuthToken();
user.setToken(token);
usersDao.update(user);
saveUserAuthFile(token);
connectionSource.close();
} catch (SQLException ex) {
System.err.println("Exception: " + ex.getMessage());
ex.printStackTrace();
} catch (Exception ex) {
System.err.println("Exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
public String generateUserAuthToken() {
SecureRandom random = new SecureRandom();
return new BigInteger(512, random).toString(36);
}
private void saveUserAuthFile(String token) throws Exception {
try (PrintWriter writer = new PrintWriter(authFilePath, "UTF-8")) {
writer.print(token);
}
}
public boolean isNotesSuiteTitleValid(String title) {
return (title.length() > 4 && title.length() < 129);
}
User loginUser(String login, String password, boolean rememberUser) {
Dao<User, Integer> usersDao;
ConnectionSource connectionSource;
User user = null;
try {
connectionSource = new JdbcConnectionSource(connectionString, userName, userPass);
usersDao = DaoManager.createDao(connectionSource, User.class);
QueryBuilder<User, Integer> queryBuilder = usersDao.queryBuilder();
queryBuilder.where().like(User.LOGIN_FIELD_NAME, login).and().like(User.PASSWORD_FIELD_NAME, password);
user = usersDao.queryForFirst(queryBuilder.prepare());
connectionSource.close();
} catch (SQLException ex) {
System.err.println("Exception: " + ex.getMessage());
ex.printStackTrace();
}
if (rememberUser) {
generateAndSaveUserToken(user);
}
return user;
}
User registerUser(String login, String fullName, String password) {
User newUser = new User(login, fullName, password);
Dao<User, Integer> usersDao;
ConnectionSource connectionSource = null;
User user = null;
try {
connectionSource = new JdbcConnectionSource(connectionString, userName, userPass);
usersDao = DaoManager.createDao(connectionSource, User.class);
QueryBuilder<User, Integer> queryBuilder = usersDao.queryBuilder();
queryBuilder.where().like(User.LOGIN_FIELD_NAME, login).countOf();
if (usersDao.countOf(queryBuilder.prepare()) > 0) {
connectionSource.close();
return null;
}
usersDao.create(newUser);
connectionSource.close();
} catch (SQLException ex) {
System.err.println("Exception: " + ex.getMessage());
ex.printStackTrace();
}
return newUser;
}
public List<SerializedNotesSuite> getRemoteNotesSuites(String address, int port) throws IOException {
String input;
int charRead;
StringWriter stringWriter = new StringWriter();
try (
Socket socket = new Socket(address, port);
BufferedReader inputReader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
while((charRead = inputReader.read()) != -1){
stringWriter.write(charRead);
}
}
input = stringWriter.toString();
stringWriter.close();
return deserializeNotesSuite(input);
}
public void shareNotesSuite(User owner, final int port) throws Exception {
System.out.println("Sharing NotesSuite on port: " + port);
ServerSocket serverSocket;
serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
System.out.println("Sending notes in a second");
try (PrintWriter outputWriter = new PrintWriter(clientSocket.getOutputStream(), true)) {
outputWriter.write(serializeLocalNotesSuite(owner));
}
System.out.println("Sending notes finished");
clientSocket.close();
serverSocket.close();
System.out.println("Closed");
}
private String serializeLocalNotesSuite(User owner) throws Exception {
List<NotesSuite> notesSuites = getNotesSuites(owner);
String retval = "";
StringWriter writer = new StringWriter();
writer.write("[");
for(int i=0; i< notesSuites.size(); i++){
writer.write(serializeNotesSuite(notesSuites.get(i)));
if(i < notesSuites.size() - 1)
writer.write(", ");
}
writer.write("]");
return writer.toString();
}
private String serializeNotesSuite(NotesSuite suite) throws Exception{
StringWriter writer = new StringWriter();
writer.write("{\"title\": \"" + suite.getTitle() + "\", ");
writer.write("\"notes\": [");
for(int i=0; i< suite.getNotes().length; i++){
writer.write(serializeNote(suite.getNotes()[i]));
if(i < suite.getNotes().length - 1)
writer.write(", ");
}
writer.write("]}");
return writer.toString();
}
public String serializeNote(Note note){
StringWriter writer = new StringWriter();
writer.write("{\"title\": \"" + note.getTitle() + "\", ");
writer.write("\"content\": \"" + note.getContent() + "\"}");
return writer.toString();
}
private List<SerializedNotesSuite> deserializeNotesSuite(String serialized) throws IOException {
System.out.println("Begin serializing");
List<SerializedNotesSuite> notesSuites = fromJSON(new TypeReference<List<SerializedNotesSuite>>() {}, serialized);
//ArrayList<SerializedNotesSuite> notesSuites = new ArrayList<SerializedNotesSuite>();
System.out.println("End serializing");
return notesSuites;
}
public static <T> T fromJSON(final TypeReference<T> type, final String json) throws IOException{
T data = null;
ObjectMapper mapper = new ObjectMapper();
data = mapper.readValue(json, type);
return data;
}
}