diff --git a/doc/Note App Class Diagram.png b/doc/Note App Class Diagram.png
new file mode 100644
index 0000000..76db85f
Binary files /dev/null and b/doc/Note App Class Diagram.png differ
diff --git a/doc/NoteAppPrjReview.smproj b/doc/NoteAppPrjReview.smproj
new file mode 100644
index 0000000..f5387d6
Binary files /dev/null and b/doc/NoteAppPrjReview.smproj differ
diff --git a/doc/Project Review.pdf b/doc/Project Review.pdf
new file mode 100644
index 0000000..4289785
Binary files /dev/null and b/doc/Project Review.pdf differ
diff --git a/pom.xml b/pom.xml
index dd48a91..4a2bbfa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,6 +10,11 @@
21
+
+ com.itextpdf
+ itextpdf
+ 5.5.13.3
+
com.mailjet
mailjet-client
diff --git a/src/main/java/com/noteapp/common/service/CausedBySystemException.java b/src/main/java/com/noteapp/common/service/CausedBySystemException.java
new file mode 100644
index 0000000..028ec01
--- /dev/null
+++ b/src/main/java/com/noteapp/common/service/CausedBySystemException.java
@@ -0,0 +1,22 @@
+package com.noteapp.common.service;
+
+/**
+ * Đại diện cho các ngoại lệ gây ra bởi hệ thống NoteApp
+ * @author Nhóm 17
+ */
+public class CausedBySystemException extends NoteAppServiceException {
+ protected static final String DEFAULT_NOTIFY = "Caused by NoteApp System";
+
+ public CausedBySystemException(String message) {
+ super(DEFAULT_NOTIFY + message);
+ }
+
+ public CausedBySystemException(String message, Throwable cause) {
+ super(DEFAULT_NOTIFY + message, cause);
+ }
+
+ public CausedBySystemException(Throwable cause) {
+ super(DEFAULT_NOTIFY, cause);
+ }
+
+}
diff --git a/src/main/java/com/noteapp/common/service/CausedByUserException.java b/src/main/java/com/noteapp/common/service/CausedByUserException.java
new file mode 100644
index 0000000..922c5e6
--- /dev/null
+++ b/src/main/java/com/noteapp/common/service/CausedByUserException.java
@@ -0,0 +1,21 @@
+package com.noteapp.common.service;
+
+/**
+ * Đại diện cho các ngoại lệ gây ra bởi người dùng khi sử dụng hệ thống NoteApp
+ * @author Nhóm 17
+ */
+public class CausedByUserException extends NoteAppServiceException {
+
+ public CausedByUserException(String message) {
+ super(message);
+ }
+
+ public CausedByUserException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CausedByUserException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/src/main/java/com/noteapp/common/service/NoteAppService.java b/src/main/java/com/noteapp/common/service/NoteAppService.java
new file mode 100644
index 0000000..2ef3601
--- /dev/null
+++ b/src/main/java/com/noteapp/common/service/NoteAppService.java
@@ -0,0 +1,102 @@
+package com.noteapp.common.service;
+
+import com.noteapp.note.service.INoteService;
+import com.noteapp.note.service.IShareNoteService;
+import com.noteapp.note.service.io.FileIOService;
+import com.noteapp.user.service.IAdminService;
+import com.noteapp.user.service.IUserService;
+import com.noteapp.user.service.security.VerificationMailService;
+
+/**
+ * Cung cấp các service ở mức tổng quan của NoteApp System
+ * @author Nhóm 17
+ * @see IUserService
+ * @see IAdminService
+ * @see INoteService
+ * @see IShareNoteService
+ * @see VerificationMailService
+ * @see FileIOService
+ */
+public class NoteAppService {
+ private IUserService userService;
+ private IAdminService adminService;
+ private INoteService noteService;
+ private IShareNoteService shareNoteService;
+ private VerificationMailService verificationMailService;
+ private FileIOService fileIOService;
+
+ public NoteAppService() {
+ userService = null;
+ adminService = null;
+ noteService = null;
+ shareNoteService = null;
+ verificationMailService = null;
+ fileIOService = null;
+ }
+
+ public IUserService getUserService() throws NoteAppServiceException {
+ if (userService == null) {
+ throw new CausedBySystemException("Service has not inited!");
+ }
+ return userService;
+ }
+
+ public void setUserService(IUserService userService) {
+ this.userService = userService;
+ }
+
+ public IAdminService getAdminService() throws NoteAppServiceException {
+ if (adminService == null) {
+ throw new CausedBySystemException("Service has not inited!");
+ }
+ return adminService;
+ }
+
+ public void setAdminService(IAdminService adminService) {
+ this.adminService = adminService;
+ }
+
+ public INoteService getNoteService() throws NoteAppServiceException {
+ if (noteService == null) {
+ throw new CausedBySystemException("Service has not inited!");
+ }
+ return noteService;
+ }
+
+ public void setNoteService(INoteService noteService) {
+ this.noteService = noteService;
+ }
+
+ public IShareNoteService getShareNoteService() throws NoteAppServiceException {
+ if (shareNoteService == null) {
+ throw new CausedBySystemException("Service has not inited!");
+ }
+ return shareNoteService;
+ }
+
+ public void setShareNoteService(IShareNoteService shareNoteService) {
+ this.shareNoteService = shareNoteService;
+ }
+
+ public VerificationMailService getVerificationMailService() throws NoteAppServiceException {
+ if (verificationMailService == null) {
+ throw new CausedBySystemException("Service has not inited!");
+ }
+ return verificationMailService;
+ }
+
+ public void setVerificationMailService(VerificationMailService verificationMailService) {
+ this.verificationMailService = verificationMailService;
+ }
+
+ public FileIOService getFileIOService() throws NoteAppServiceException {
+ if (fileIOService == null) {
+ throw new CausedBySystemException("Service has not inited!");
+ }
+ return fileIOService;
+ }
+
+ public void setFileIOService(FileIOService fileIOService) {
+ this.fileIOService = fileIOService;
+ }
+}
diff --git a/src/main/java/com/noteapp/common/service/NoteAppServiceException.java b/src/main/java/com/noteapp/common/service/NoteAppServiceException.java
new file mode 100644
index 0000000..50e0037
--- /dev/null
+++ b/src/main/java/com/noteapp/common/service/NoteAppServiceException.java
@@ -0,0 +1,22 @@
+package com.noteapp.common.service;
+
+/**
+ * Đại diện cho tất cả các ngoại lệ có thể xảy ra khi sử dụng dịch vụ
+ * của hệ thống NoteApp
+ * @author Nhóm 17
+ */
+public class NoteAppServiceException extends Exception {
+
+ public NoteAppServiceException(String message) {
+ super(message);
+ }
+
+ public NoteAppServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public NoteAppServiceException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/src/main/java/com/noteapp/controller/AdminDashboardController.java b/src/main/java/com/noteapp/controller/AdminDashboardController.java
new file mode 100644
index 0000000..5371505
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/AdminDashboardController.java
@@ -0,0 +1,144 @@
+package com.noteapp.controller;
+
+import com.noteapp.common.service.NoteAppService;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.user.dao.AdminDAO;
+import com.noteapp.user.dao.UserDAO;
+import com.noteapp.user.service.AdminService;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.stage.Stage;
+
+/**
+ * Controller cho view Dashboard của Admin
+ * @author admin
+ */
+public class AdminDashboardController extends RequestServiceController implements Initable {
+ @FXML
+ private Button viewUsersButton;
+ @FXML
+ private TextField searchUserField;
+ @FXML
+ private VBox userCardLayout;
+ @FXML
+ private Button closeButton;
+ @FXML
+ private Button logoutButton;
+
+ private Map lockedStatusOfUsers;
+
+ @Override
+ public void init() {
+ noteAppService = new NoteAppService();
+ noteAppService.setAdminService(new AdminService(UserDAO.getInstance(), AdminDAO.getInstance()));
+ initView();
+ closeButton.setOnAction((ActionEvent event) -> {
+ close();
+ });
+ logoutButton.setOnAction((ActionEvent event) -> {
+ LoginController.open(stage);
+ });
+ viewUsersButton.setOnAction((ActionEvent event) -> {
+ initView();
+ });
+ searchUserField.setOnAction((ActionEvent event) -> {
+ searchUser();
+ });
+ }
+
+ protected void initView() {
+ try {
+ lockedStatusOfUsers = noteAppService.getAdminService().getAllLockedStatus();
+ loadUsers(lockedStatusOfUsers);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ private void saveLockedStatus(String username, boolean lockedStatus) {
+ try {
+ noteAppService.getAdminService().updateLockedStatus(username, lockedStatus);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ /**
+ * Tải thông tin về các User và trạng thái Locked của họ vào
+ * một danh sách có thể hiển thị trên màn hình
+ * @param lockedStatusOfUsers Một Map lưu giữ trạng thái Locked của mỗi User
+ * @see userCardLayout
+ * @see UserItemController
+ */
+ protected void loadUsers(Map lockedStatusOfUsers) {
+ userCardLayout.getChildren().clear();
+ if (lockedStatusOfUsers.isEmpty()) {
+ return;
+ }
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "UserItemView.fxml";
+ //Load từng user vào UserItemController
+ for (Map.Entry entry: lockedStatusOfUsers.entrySet()) {
+ String username = entry.getKey();
+ boolean isLocked = entry.getValue();
+ try {
+ UserItemController controller = new UserItemController();
+ HBox box = controller.loadFXML(filePath);
+ controller.setData(username, isLocked);
+ //Thêm action cho nút đổi trạng thái lock
+ controller.getChangeLockStatusButton().setOnAction((ActionEvent event) -> {
+ controller.changeLockedStatus();
+ String thisUsername = controller.getUsername();
+ boolean thisLockedStatus = controller.isLocked();
+ this.lockedStatusOfUsers.put(thisUsername, thisLockedStatus);
+ saveLockedStatus(thisUsername, thisLockedStatus);
+ });
+ userCardLayout.getChildren().add(box);
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can load user items");
+ }
+ }
+ }
+
+ /**
+ * Thực hiện tìm kiếm user có username chứa chuỗi được nhập vào
+ * {@link searchUserField} và load lại danh sách hiển thị những
+ * user khớp với yêu cầu
+ */
+ protected void searchUser() {
+ String searchText = searchUserField.getText();
+ Map searchUsers = new HashMap<>();
+ for (Map.Entry entry: lockedStatusOfUsers.entrySet()) {
+ String username = entry.getKey();
+ boolean isLocked = entry.getValue();
+ if (username.contains(searchText)) {
+ searchUsers.put(username, isLocked);
+ }
+ }
+ loadUsers(searchUsers);
+ }
+
+ /**
+ * Mở một giao diện Dashboard cho Admin
+ * @param stage Stage được truyền vào để chứa giao diện này
+ */
+ public static void open(Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "AdminDashboardView.fxml";
+ AdminDashboardController controller = new AdminDashboardController();
+ controller.setStage(stage);
+ controller.loadFXMLAndSetScene(filePath);
+ controller.init();
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open admin dashboard");
+ }
+ }
+}
diff --git a/src/main/java/com/noteapp/controller/DashboardController.java b/src/main/java/com/noteapp/controller/DashboardController.java
new file mode 100644
index 0000000..8b2f213
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/DashboardController.java
@@ -0,0 +1,678 @@
+package com.noteapp.controller;
+
+import com.noteapp.common.service.NoteAppService;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.note.dao.NoteBlockDAO;
+import com.noteapp.note.dao.NoteDAO;
+import com.noteapp.note.dao.NoteFilterDAO;
+import com.noteapp.note.dao.ShareNoteDAO;
+import com.noteapp.note.dao.SurveyBlockDAO;
+import com.noteapp.note.dao.TextBlockDAO;
+import com.noteapp.user.model.Email;
+import com.noteapp.note.model.Note;
+import com.noteapp.note.model.NoteBlock;
+import com.noteapp.note.model.NoteFilter;
+import com.noteapp.note.model.ShareNote;
+import com.noteapp.note.model.TextBlock;
+import com.noteapp.note.service.NoteService;
+import com.noteapp.user.model.User;
+import com.noteapp.note.service.ShareNoteService;
+import com.noteapp.user.dao.UserDAO;
+import com.noteapp.user.service.UserService;
+import java.io.IOException;
+import java.sql.Date;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.ButtonType;
+import javafx.scene.control.ChoiceDialog;
+import javafx.scene.control.Label;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.RadioButton;
+import javafx.scene.control.TextField;
+import javafx.scene.control.TextInputDialog;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.FlowPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+import javafx.stage.Stage;
+
+/**
+ * FXML Controller class cho Dashboard của User
+ * @author Nhóm 17
+ */
+public class DashboardController extends RequestServiceController implements Initable {
+ //Các thuộc tính FXML của form dashboard chung
+ @FXML
+ private BorderPane extraServiceScene;
+ @FXML
+ private VBox mainScene;
+ //Các thuộc tính chung
+ @FXML
+ private Label userLabel;
+ @FXML
+ private Button closeButton;
+ @FXML
+ private Button logoutButton;
+ @FXML
+ private Button backMainSceneButton;
+ @FXML
+ private Button myNotesButton;
+ @FXML
+ private Button myAccountButton;
+ @FXML
+ private Button homeButton;
+ //Các thuộc tính của myNotesScene
+ @FXML
+ private AnchorPane myNotesScene;
+ @FXML
+ private TextField searchNoteField;
+ @FXML
+ private VBox noteCardLayout;
+ @FXML
+ private Button createNoteButton;
+ @FXML
+ private Button deleteNoteButton;
+ //Các thuộc tính của myAccountScene
+ @FXML
+ private AnchorPane myAccountScene;
+ @FXML
+ private TextField usernameField;
+ @FXML
+ private PasswordField passwordField;
+ @FXML
+ private TextField emailAddressField;
+ @FXML
+ private TextField nameField;
+ @FXML
+ private TextField dayOfBirthField;
+ @FXML
+ private TextField monthOfBirthField;
+ @FXML
+ private TextField yearOfBirthField;
+ @FXML
+ private TextField schoolField;
+ @FXML
+ private RadioButton genderMale;
+ @FXML
+ private RadioButton genderFemale;
+ @FXML
+ private RadioButton genderOther;
+ @FXML
+ private Label errorEmailFieldLabel;
+ @FXML
+ private Label errorNameFieldLabel;
+ @FXML
+ private Label errorPasswordFieldLabel;
+ @FXML
+ private Label errorBirthdayFieldLabel;
+ @FXML
+ private Button changePasswordButton;
+ @FXML
+ private Button saveAccountButton;
+
+ @FXML
+ private FlowPane recentlyVisitedLayout;
+ @FXML
+ private AnchorPane homeScene;
+ @FXML
+ private StackPane stackLayout;
+
+ private User myUser;
+ private Note currentNote;
+ private List myNotes;
+ private List myReceivedNotes;
+ private List openedNotes;
+
+ @Override
+ public void init() {
+ noteAppService = new NoteAppService();
+ noteAppService.setUserService(new UserService(UserDAO.getInstance()));
+ noteAppService.setNoteService(new NoteService(NoteDAO.getInstance(), NoteFilterDAO.getInstance(),
+ NoteBlockDAO.getInstance(), TextBlockDAO.getInstance(), SurveyBlockDAO.getInstance()));
+ noteAppService.setShareNoteService(new ShareNoteService(ShareNoteDAO.getInstance(),
+ NoteDAO.getInstance(), NoteFilterDAO.getInstance(),
+ NoteBlockDAO.getInstance(), TextBlockDAO.getInstance(), SurveyBlockDAO.getInstance()));
+ initView();
+ closeButton.setOnAction((ActionEvent event) -> {
+ super.close();
+ });
+ //Switch
+ myNotesButton.setOnAction((ActionEvent event) -> {
+ changeSceneInExtraScene(myNotesButton);
+ try {
+ myNotes = noteAppService.getNoteService().getAll(myUser.getUsername());
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ myNotes = new ArrayList<>();
+ }
+ //Lấy tất cả các note được share tới myUser này
+ try {
+ myReceivedNotes = noteAppService.getShareNoteService().getAllReceived(myUser.getUsername());
+ } catch (NoteAppServiceException ex) {
+ myReceivedNotes = new ArrayList<>();
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ initMyNotesScene(myNotes, myReceivedNotes);
+ });
+ myAccountButton.setOnAction((ActionEvent event) -> {
+ changeSceneInExtraScene(myAccountButton);
+ initMyAccountScene(myUser);
+ });
+ homeButton.setOnAction((ActionEvent event) -> {
+ changeSceneInExtraScene(homeButton);
+ try {
+ myNotes = noteAppService.getNoteService().getAll(myUser.getUsername());
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ myNotes = new ArrayList<>();
+ }
+ initHomeScene(myNotes);
+ });
+ //My Note Scene
+ searchNoteField.setOnAction((ActionEvent event) -> {
+ searchNote();
+ });
+ createNoteButton.setOnAction((ActionEvent event) -> {
+ createNote();
+ });
+ deleteNoteButton.setOnAction((ActionEvent event) -> {
+ deleteNote();
+ });
+ //My Account Scene
+ changePasswordButton.setOnAction((ActionEvent event) -> {
+ changePassword();
+ });
+ saveAccountButton.setOnAction((ActionEvent event) -> {
+ saveAccount();
+ });
+
+ //Other
+ backMainSceneButton.setOnAction((ActionEvent event) -> {
+ if (currentNote.isDefaultValue()) {
+ showAlert(Alert.AlertType.ERROR, "No note has chosen!");
+ return;
+ }
+ if (!currentNote.isPubliced()) {
+ EditNoteController.open(myUser, currentNote, openedNotes, stage);
+ } else {
+ EditShareNoteController.open(myUser, (ShareNote) currentNote, openedNotes, stage);
+ }
+ });
+ logoutButton.setOnAction((ActionEvent event) -> {
+ LoginController.open(stage);
+ });
+ }
+
+ protected void initView() {
+ userLabel.setText(myUser.getName());
+ try {
+ myNotes = noteAppService.getNoteService().getAll(myUser.getUsername());
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ myNotes = new ArrayList<>();
+ }
+ initHomeScene(myNotes);
+ changeSceneInExtraScene(homeButton);
+ }
+
+ private void openNote(int noteId, Optional optional) {
+ if(optional.get() == ButtonType.OK) {
+ try {
+ currentNote = noteAppService.getNoteService().open(noteId);
+ if (!openedNotes.contains(currentNote)) {
+ openedNotes.add(currentNote);
+ }
+ if (currentNote.isPubliced()) {
+ currentNote = noteAppService.getShareNoteService().open(noteId, myUser.getUsername());
+ EditShareNoteController.open(myUser, (ShareNote) currentNote, openedNotes, stage);
+ } else {
+ EditNoteController.open(myUser, currentNote, openedNotes, stage);
+ }
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Khởi tạo Scene My Notes, chứa danh sách các Note mà User sở hữu hoặc các
+ * Note được chia sẻ tới User này
+ * @param notes Danh sách các Note mà User sở hữu
+ * @param shareNotes Danh sách các Note được chia sẻ tới User này
+ */
+ protected void initMyNotesScene(List notes, List shareNotes) {
+ //Làm sạch layout
+ noteCardLayout.getChildren().clear();
+ if(notes.isEmpty() || shareNotes.isEmpty()) {
+ return;
+ }
+ //Load các Note Card
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "NoteCardView.fxml";
+ for(int i=0; i < notes.size(); i++) {
+ //Load Note Card Layout
+ try {
+ //Thiết lập dữ liệu cho Note Card
+ NoteCardController controller = new NoteCardController();
+
+ HBox box = controller.loadFXML(filePath);
+ Note note = notes.get(i);
+ controller.setData(note);
+ //Xử lý khi nhấn vào note card
+ box.setOnMouseClicked((MouseEvent event) -> {
+ //Tạo thông báo và mở note nếu chọn OK
+ Optional optional = showAlert(Alert.AlertType.CONFIRMATION,
+ "Open " + controller.getHeader());
+ openNote(controller.getId(), optional);
+ });
+ //Thêm Note Card vào layout
+ noteCardLayout.getChildren().add(box);
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can load note!");
+ }
+ }
+ for(int i=0; i < shareNotes.size(); i++) {
+ //Load Note Card Layout
+ if (shareNotes.get(i).getAuthor().equals(myUser.getUsername())) {
+ continue;
+ }
+ try {
+ //Thiết lập dữ liệu cho Note Card
+ NoteCardController controller = new NoteCardController();
+
+ HBox box = controller.loadFXML(filePath);
+ controller.setData(shareNotes.get(i));
+ //Xử lý khi nhấn vào note card
+ box.setOnMouseClicked((MouseEvent event) -> {
+ //Tạo thông báo và mở note nếu chọn OK
+ Optional optional = showAlert(Alert.AlertType.CONFIRMATION,
+ "Open " + controller.getHeader());
+ openNote(controller.getId(), optional);
+ });
+ //Thêm Note Card vào layout
+ noteCardLayout.getChildren().add(box);
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can load note!");
+ }
+ }
+ }
+
+ /**
+ * Khởi tạo Scene Home
+ * @param recentlyNotes Các Note được truy cập gần nhất
+ */
+ protected void initHomeScene(List recentlyNotes) {
+ recentlyVisitedLayout.getChildren().clear();
+ if (recentlyNotes.isEmpty()) {
+ return;
+ }
+ if (recentlyNotes.size() > 3) {
+ recentlyNotes = recentlyNotes.subList(0, 3);
+ }
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "RecentlyNoteCardView.fxml";
+ for (Note note: recentlyNotes) {
+ try {
+ RecentlyNoteCardController controller = new RecentlyNoteCardController();
+ VBox box = controller.loadFXML(filePath);
+ controller.setNote(note);
+ box.setOnMouseClicked((event) -> {
+ Optional optional = showAlert(Alert.AlertType.CONFIRMATION,
+ "Open " + controller.getNote().getHeader());
+ openNote(controller.getNote().getId(), optional);
+ });
+ recentlyVisitedLayout.getChildren().add(box);
+ } catch (IOException ex) {
+ }
+ }
+ }
+
+ /**
+ * Khởi tạo scene hiển thị các thông tin của User
+ * @param user User đang đăng nhập
+ */
+ protected void initMyAccountScene(User user) {
+ //Thiết lập các thuộc tính
+ usernameField.setText(user.getUsername());
+ usernameField.setEditable(false);
+ passwordField.setText(user.getPassword());
+ emailAddressField.setText(user.getEmail().getAddress());
+ nameField.setText(user.getName());
+ schoolField.setText(user.getSchool());
+ dayOfBirthField.setText(String.valueOf(user.getBirthday().toLocalDate().getDayOfMonth()));
+ monthOfBirthField.setText(String.valueOf(user.getBirthday().toLocalDate().getMonthValue()));
+ yearOfBirthField.setText(String.valueOf(user.getBirthday().toLocalDate().getYear()));
+ switch(user.getGender()) {
+ case User.Gender.MALE -> {
+ genderMale.setSelected(true);
+ }
+ case User.Gender.FEMALE -> {
+ genderFemale.setSelected(true);
+ }
+ case User.Gender.OTHER -> {
+ genderOther.setSelected(true);
+ }
+ }
+ //Ẩn các error
+ errorEmailFieldLabel.setVisible(false);
+ errorBirthdayFieldLabel.setVisible(false);
+ errorNameFieldLabel.setVisible(false);
+ errorPasswordFieldLabel.setVisible(false);
+ }
+
+ public void setMyUser(User myUser) {
+ this.myUser = myUser;
+ }
+
+ public void setCurrentNote(Note currentNote) {
+ this.currentNote = currentNote;
+ }
+
+ public void setOpenedNotes(List openedNotes) {
+ this.openedNotes = openedNotes;
+ }
+
+ private boolean checkMatchSearchText(Note note, String searchText) {
+ if(note.getHeader().contains(searchText)) {
+ return true;
+ } else {
+ for(NoteFilter noteFilter: note.getFilters()) {
+ if(noteFilter.getFilter().contains(searchText)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tìm kiếm một note có header hoặc filter chứa văn bản
+ * đang được nhập vào trong field
+ * @see searchNoteField
+ */
+ protected void searchNote() {
+ //Lấy thông tin cần search
+ String searchText = searchNoteField.getText();
+ //Tạo list mới để chứa các note hợp lệ
+ List notes = new ArrayList<>();
+ List shareNotes = new ArrayList<>();
+ //Thêm các note hợp lệ vào list
+ for(Note newNote: myNotes) {
+ if (checkMatchSearchText(newNote, searchText)) {
+ notes.add(newNote);
+ }
+ }
+ for (ShareNote newShareNote: myReceivedNotes) {
+ if (checkMatchSearchText(newShareNote, searchText)) {
+ shareNotes.add(newShareNote);
+ }
+ }
+ //Load lại My Notes Scene
+ initMyNotesScene(notes, shareNotes);
+ }
+
+ protected void createNote() {
+ //Hiện dialog để nhập header cho Note mới
+ TextInputDialog dialog = new TextInputDialog();
+ dialog.setTitle("Create new note");
+ dialog.setHeaderText("Enter header for your new note");
+ //Lấy kết quả
+ Optional confirm = dialog.showAndWait();
+ //Xử lý kết quả khi nhấn OK
+ confirm.ifPresent(selectedHeader -> {
+ //Set dữ liệu cho note mới
+ Note newNote = new Note();
+ newNote.setAuthor(myUser.getUsername());
+ newNote.setHeader(selectedHeader);
+ newNote.getBlocks().add(
+ new TextBlock("EditHere", -1,
+ "B1", myUser.getUsername(), NoteBlock.BlockType.TEXT, 1));
+ newNote.setLastModifiedDate(Date.valueOf(LocalDate.now()));
+ //Tạo Note mới
+ try {
+ //Tạo thành công
+ newNote = noteAppService.getNoteService().create(newNote);
+ showAlert(Alert.AlertType.INFORMATION, "Successfully create " + newNote.getHeader());
+ //Thêm vào list và load lại
+ myNotes.add(newNote);
+ initMyNotesScene(myNotes, myReceivedNotes);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ });
+ }
+
+ protected void deleteNote() {
+ //Lấy list các header note
+ List myNotesHeader = new ArrayList<>();
+ for(Note note: myNotes){
+ myNotesHeader.add(note.getHeader());
+ }
+ //Hiện dialog để chọn note cần xóa
+ ChoiceDialog dialog = new ChoiceDialog<>(myNotesHeader.get(0), myNotesHeader);
+ dialog.setTitle("Delete Note");
+ dialog.setHeaderText("Choose note to delete");
+ //Lấy kết quả
+ Optional confirm = dialog.showAndWait();
+ //Xử lý kết quả khi nhấn OK
+ confirm.ifPresent(selectedHeader -> {
+ //Xóa Note được chọn
+ try {
+ //Xóa thành công
+ Note deletedNote = new Note();
+ for(Note note: myNotes) {
+ if(note.getHeader().equals(selectedHeader)) {
+ deletedNote = note;
+ }
+ }
+ noteAppService.getNoteService().delete(deletedNote.getId());
+ showAlert(Alert.AlertType.INFORMATION, "Successfully delete " + deletedNote.getHeader());
+ //Xóa khỏi list và load lại
+ myNotes.remove(deletedNote);
+ //Load lại My Notes Scene
+ initMyNotesScene(myNotes, myReceivedNotes);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ });
+ }
+
+ private void getPasswordFromField() {
+ if("".equals(passwordField.getText())) {
+ errorPasswordFieldLabel.setVisible(true);
+ }
+ myUser.setPassword(passwordField.getText());
+ }
+
+ private void getEmailFromField() {
+ Email email = new Email();
+ email.setAddress(emailAddressField.getText());
+ if(!email.checkAddress()) {
+ errorEmailFieldLabel.setVisible(true);
+ }
+ myUser.setEmail(email);
+ }
+
+ private void getBirthdayFromField() {
+ int dayOfBirth = -1;
+ int monthOfBirth = -1;
+ int yearOfBirth = -1;
+ if(dayOfBirthField.getText().matches("^[0-9]{1,2}$")) {
+ dayOfBirth = Integer.parseInt(dayOfBirthField.getText());
+ } else if("".equals(dayOfBirthField.getText())) {
+ dayOfBirth = LocalDate.now().getDayOfMonth();
+ } else {
+ errorBirthdayFieldLabel.setVisible(true);
+ }
+ if(monthOfBirthField.getText().matches("^[0-9]{1,2}$")) {
+ monthOfBirth = Integer.parseInt(monthOfBirthField.getText());
+ } else if("".equals(monthOfBirthField.getText())) {
+ monthOfBirth = LocalDate.now().getMonthValue();
+ } else {
+ errorBirthdayFieldLabel.setVisible(true);
+ }
+ if(yearOfBirthField.getText().matches("^[0-9]{4}$")) {
+ yearOfBirth = Integer.parseInt(yearOfBirthField.getText());
+ } else if("".equals(yearOfBirthField.getText())) {
+ yearOfBirth = LocalDate.now().getYear();
+ } else {
+ errorBirthdayFieldLabel.setVisible(true);
+ }
+ if(!errorBirthdayFieldLabel.isVisible()) {
+ myUser.setBirthday(Date.valueOf(LocalDate.of(yearOfBirth, monthOfBirth, dayOfBirth)));
+ }
+ }
+
+ private void getNameFromField() {
+ //Láy thông tin name
+ if("".equals(nameField.getText())) {
+ errorNameFieldLabel.setVisible(true);
+ }
+ myUser.setName(nameField.getText());
+ }
+
+ private void getGenderFromBox() {
+ if(genderMale.isSelected()) {
+ myUser.setGender(User.Gender.MALE);
+ } else if (genderFemale.isSelected()) {
+ myUser.setGender(User.Gender.FEMALE);
+ } else {
+ myUser.setGender(User.Gender.OTHER);
+ }
+ }
+
+ private boolean checkErrorAccountInfo() {
+ return errorNameFieldLabel.isVisible() || errorPasswordFieldLabel.isVisible()
+ || errorBirthdayFieldLabel.isVisible() || errorEmailFieldLabel.isVisible();
+ }
+
+ protected void saveAccount() {
+ errorEmailFieldLabel.setVisible(false);
+ errorBirthdayFieldLabel.setVisible(false);
+ errorNameFieldLabel.setVisible(false);
+ errorPasswordFieldLabel.setVisible(false);
+ //Lấy password
+ getPasswordFromField();
+ //Lấy Email
+ getEmailFromField();
+ //Lấy name
+ getNameFromField();
+ //Lấy school
+ myUser.setSchool(schoolField.getText());
+ //Lấy thông tin về birth
+ getBirthdayFromField();
+ //Lấy gender
+ getGenderFromBox();
+ //Kiểm tra xem có lỗi nào không
+ if(checkErrorAccountInfo()) {
+ return;
+ }
+ //Cập nhật User
+ try {
+ //Cập nhật thành công
+ noteAppService.getUserService().update(myUser);
+ showAlert(Alert.AlertType.INFORMATION, "Successfully update for " + myUser.getUsername());
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ protected void changePassword() {
+ //Hiện dialog để nhập mật khẩu cũ
+ TextInputDialog dialog = new TextInputDialog();
+ dialog.setTitle("Change Password");
+ dialog.setHeaderText("Enter your present password");
+ //Lấy kết quả
+ Optional confirm = dialog.showAndWait();
+ //Xử lý kết quả
+ confirm.ifPresent(password -> {
+ //Nếu nhập đúng thì cho phép nhập mật khẩu mới
+ if(password.equals(myUser.getPassword())) {
+ passwordField.setEditable(true);
+ }
+ });
+ }
+
+ /**
+ * Thay đổi Scene trên dashboard dựa vào việc nút nào đang được bấm
+ * @param button Nút được bấm
+ */
+ private void changeSceneInExtraScene(Button button) {
+ String pressedStyle = "-fx-background-color: #1a91b8";
+ String unPressedStyle = "-fx-background-color: transparent";
+ //init lại
+ myNotesButton.setStyle(unPressedStyle);
+ myNotesScene.setVisible(false);
+ myAccountButton.setStyle(unPressedStyle);
+ myAccountScene.setVisible(false);
+ homeButton.setStyle(unPressedStyle);
+ homeScene.setVisible(false);
+ //Press button được chọn và chuyển scene tương ứng
+ if (button == myNotesButton) {
+ myNotesButton.setStyle(pressedStyle);
+ myNotesScene.setVisible(true);
+ } else if (button == myAccountButton) {
+ myAccountButton.setStyle(pressedStyle);
+ myAccountScene.setVisible(true);
+ } else if (button == homeButton) {
+ homeButton.setStyle(pressedStyle);
+ homeScene.setVisible(true);
+ }
+ }
+
+ /**
+ * Mở một Dashboard cho User
+ * @param myUser User đã đăng nhập thành công
+ * @param stage Stage chứa Dashboard này
+ */
+ public static void open(User myUser, Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "DashboardView.fxml";
+
+ DashboardController controller = new DashboardController();
+
+ controller.setStage(stage);
+ controller.setMyUser(myUser);
+ controller.setCurrentNote(new Note());
+ controller.setOpenedNotes(new ArrayList<>());
+ controller.loadFXMLAndSetScene(filePath);
+ controller.init();
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open dashboard");
+ }
+ }
+
+ /**
+ * Mở một Dashboard cho User khi đang Edit
+ * @param myUser User đang trong phiên đăng nhập
+ * @param currentNote Note được edit hiện tại
+ * @param openedNotes Các Note đang được mở
+ * @param stage Stage chứa Dashboard này
+ */
+ public static void open(User myUser, Note currentNote, List openedNotes, Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "DashboardView.fxml";
+
+ DashboardController controller = new DashboardController();
+
+ controller.setStage(stage);
+ controller.setMyUser(myUser);
+ controller.setOpenedNotes(openedNotes);
+ controller.setCurrentNote(currentNote);
+ controller.loadFXMLAndSetScene(filePath);
+
+ controller.init();
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open dashboard");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/noteapp/controller/EditNoteController.java b/src/main/java/com/noteapp/controller/EditNoteController.java
new file mode 100644
index 0000000..05a05b9
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/EditNoteController.java
@@ -0,0 +1,670 @@
+package com.noteapp.controller;
+
+import com.noteapp.common.service.NoteAppService;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.note.dao.NoteBlockDAO;
+import com.noteapp.note.dao.NoteDAO;
+import com.noteapp.note.dao.NoteFilterDAO;
+import com.noteapp.note.dao.ShareNoteDAO;
+import com.noteapp.note.dao.SurveyBlockDAO;
+import com.noteapp.note.dao.TextBlockDAO;
+import com.noteapp.note.model.Note;
+import com.noteapp.note.model.NoteBlock;
+import com.noteapp.note.model.NoteFilter;
+import com.noteapp.note.model.ShareNote;
+import com.noteapp.note.model.SurveyBlock;
+import com.noteapp.note.model.TextBlock;
+import com.noteapp.note.service.NoteService;
+import com.noteapp.user.model.User;
+import com.noteapp.note.service.ShareNoteService;
+import com.noteapp.note.service.io.PdfIOService;
+import com.noteapp.user.dao.UserDAO;
+import com.noteapp.user.service.UserService;
+import java.io.File;
+import java.io.IOException;
+import java.sql.Date;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.Node;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.ButtonType;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Dialog;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.control.TextInputDialog;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.stage.DirectoryChooser;
+import javafx.stage.FileChooser;
+import javafx.stage.Stage;
+
+
+/**
+ * FXML Controller class cho trang Edit Note
+ * @author Nhóm 17
+ */
+public class EditNoteController extends RequestServiceController implements Initable {
+ //Các thuộc tính chung
+ @FXML
+ protected Label noteHeaderLabel;
+ @FXML
+ protected Button homeMenuButton;
+ @FXML
+ protected Button editMenuButton;
+ @FXML
+ protected HBox editBox;
+ //Các thuộc tính của edit Box
+ @FXML
+ protected Button saveNoteButton;
+ @FXML
+ protected Button openNoteButton;
+ @FXML
+ protected Button addFilterButton;
+ @FXML
+ protected Button addTextBlockButton;
+ @FXML
+ protected Button addSurveyBlockButton;
+ @FXML
+ protected Button shareButton;
+ @FXML
+ protected Button importFileButton;
+ @FXML
+ protected Button exportFileButton;
+ //Các thuộc tính còn lại
+ @FXML
+ protected VBox blocksLayout;
+ @FXML
+ protected GridPane filterGridLayout;
+ @FXML
+ protected Button closeButton;
+ @FXML
+ protected HBox openedNotesLayout;
+
+ protected User myUser;
+ protected Note myNote;
+ protected List textBlockControllers;
+ protected List surveyBlockControllers;
+ protected List openedNotes;
+
+ public void setMyUser(User myUser) {
+ this.myUser = myUser;
+ }
+
+ public void setMyNote(Note myNote) {
+ this.myNote = myNote;
+ }
+
+ public void setOpenedNotes(List openedNotes) {
+ this.openedNotes = openedNotes;
+ }
+
+ @Override
+ public void init() {
+ noteAppService = new NoteAppService();
+ noteAppService.setUserService(new UserService(UserDAO.getInstance()));
+ noteAppService.setNoteService(new NoteService(NoteDAO.getInstance(), NoteFilterDAO.getInstance(),
+ NoteBlockDAO.getInstance(), TextBlockDAO.getInstance(), SurveyBlockDAO.getInstance()));
+ noteAppService.setShareNoteService(new ShareNoteService(ShareNoteDAO.getInstance(),
+ NoteDAO.getInstance(), NoteFilterDAO.getInstance(),
+ NoteBlockDAO.getInstance(), TextBlockDAO.getInstance(), SurveyBlockDAO.getInstance()));
+ noteAppService.setFileIOService(new PdfIOService());
+ textBlockControllers = new ArrayList<>();
+ surveyBlockControllers = new ArrayList<>();
+ initView();
+ closeButton.setOnAction((ActionEvent event) -> {
+ close();
+ });
+ homeMenuButton.setOnAction((ActionEvent event) -> {
+ DashboardController.open(myUser, myNote, openedNotes, stage);
+ });
+ noteHeaderLabel.setOnMouseClicked((MouseEvent event) -> {
+ changeHeaderLabel();
+ });
+ saveNoteButton.setOnAction((ActionEvent event) -> {
+ saveMyNote();
+ });
+ addFilterButton.setOnAction((ActionEvent event) -> {
+ addFilter();
+ });
+ importFileButton.setOnAction((ActionEvent event) -> {
+ importFile();
+ });
+ exportFileButton.setOnAction((ActionEvent event) -> {
+ exportFile();
+ });
+ addTextBlockButton.setOnAction((ActionEvent event) -> {
+ TextBlock newBlock = new TextBlock();
+ int maxSize = Integer.max(textBlockControllers.size(), surveyBlockControllers.size());
+ newBlock.setOrder(maxSize + 1);
+ newBlock.setHeader("Block " + newBlock.getOrder() + " of " + myNote.getHeader());
+ newBlock.setEditor(myUser.getUsername());
+ newBlock.setContent("Edit here");
+ addBlock(newBlock);
+ });
+ addSurveyBlockButton.setOnAction((ActionEvent event) -> {
+ SurveyBlock newBlock = new SurveyBlock();
+ int maxSize = Integer.max(textBlockControllers.size(), surveyBlockControllers.size());
+ newBlock.setOrder(maxSize + 1);
+ newBlock.setHeader("SurveyBlock " + newBlock.getOrder() + " of " + myNote.getHeader());
+ newBlock.setEditor(myUser.getUsername());
+ addBlock(newBlock);
+ });
+ shareButton.setOnAction((ActionEvent event) -> {
+ shareMyNote();
+ });
+ }
+
+ protected void initView() {
+ noteHeaderLabel.setText(myNote.getHeader());
+ initOpenedNotes();
+ loadFilter(myNote.getFilters(), 8);
+ initBlock();
+ }
+
+ private void openNote(Note needOpenNote) {
+ if (needOpenNote.isPubliced()) {
+ try {
+ ShareNote needOpenShareNote = noteAppService.getShareNoteService().open(needOpenNote.getId(), myUser.getUsername());
+ EditShareNoteController.open(myUser, needOpenShareNote, openedNotes, stage);
+ } catch (NoteAppServiceException e) {
+ }
+ } else {
+ EditNoteController.open(myUser, needOpenNote, openedNotes, stage);
+ }
+
+ }
+
+ private void addOpenedNotesBox(Note openedNote) throws IOException {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "OpenedNoteCardView.fxml";
+ OpenedNoteCardController controller = new OpenedNoteCardController();
+ HBox box = controller.loadFXML(filePath);
+ controller.setNote(openedNote);
+ controller.setHeader(openedNote.getHeader());
+ controller.getRemoveNote().setOnMouseClicked((MouseEvent event) -> {
+ openedNotes.remove(controller.getNote());
+ initOpenedNotes();
+ });
+ box.getStyleClass().clear();
+ if (openedNote.getId() == myNote.getId()) {
+ box.getStyleClass().add("focused-opened-note-card");
+ } else {
+ box.getStyleClass().add("free-opened-note-card");
+ }
+ box.setOnMouseClicked((MouseEvent event) -> {
+ Note needOpenNote = controller.getNote();
+ openNote(needOpenNote);
+ });
+ openedNotesLayout.getChildren().add(box);
+
+ }
+
+ /**
+ * Khởi tạo các Note đang được mở, được truyền vào từ dashboard
+ * @see openNotesLayout
+ */
+ protected void initOpenedNotes() {
+ openedNotesLayout.getChildren().clear();
+
+ for (Note openedNote: openedNotes) {
+ try {
+ addOpenedNotesBox(openedNote);
+ } catch (IOException ex) {
+ }
+ }
+ }
+
+ /**
+ * Khởi tạo các block của Note này, các Block được truyền vào từ CSDL
+ * @see #addBlock(TextBlock)
+ * @see #addBlock(SurveyBlock)
+ */
+ protected void initBlock() {
+ blocksLayout.getChildren().clear();
+ List blocks = myNote.getBlocks();
+ for(int i=0; i myNotes = noteAppService.getNoteService().getAll(myUser.getUsername());
+ for(Note note: myNotes) {
+ if(note.getHeader().equals(newNoteHeader)) {
+ showAlert(Alert.AlertType.ERROR, "This header exist");
+ return true;
+ }
+ }
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ return false;
+ }
+
+ protected void changeHeaderLabel() {
+ //Mở dialog
+ TextInputDialog inputDialog = new TextInputDialog();
+ inputDialog.setTitle("Change header for " + myNote.getHeader());
+ inputDialog.setHeaderText("Input your new header");
+ //Lấy kết quả và xử lý
+ Optional confirm = inputDialog.showAndWait();
+ confirm.ifPresent(newNoteHeader -> {
+ if (checkExistHeader(newNoteHeader)) return;
+ noteHeaderLabel.setText(newNoteHeader);
+ });
+ }
+
+ /**
+ * Lưu Note hiện tại đang chỉnh sửa vào CSDL và thông báo lỗi nếu không lưu được.
+ * Phương thức này sẽ reset dữ liệu của các block và lấy lại dữ liệu trên
+ * trang edit hiện tại.
+ */
+ protected void saveMyNote() {
+ myNote.setHeader(noteHeaderLabel.getText());
+ myNote.setLastModifiedDate(Date.valueOf(LocalDate.now()));
+ myNote.getBlocks().clear();
+ for(int i=0; i> dialog = new Dialog<>();
+ dialog.setTitle("Share your note");
+ dialog.setWidth(400);
+
+ dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
+ TextField receiverField = new TextField();
+ receiverField.setPrefWidth(350);
+ receiverField.setPromptText("Input username of receiver!");
+
+ ComboBox shareTypeComboBox = new ComboBox<>();
+ shareTypeComboBox.getItems().addAll("Read only", "Can edit");
+ shareTypeComboBox.setPrefWidth(350);
+
+ GridPane grid = new GridPane();
+ grid.setHgap(10); grid.setVgap(10);
+ grid.add(receiverField, 0, 0);
+ grid.add(shareTypeComboBox, 0, 1);
+
+ dialog.getDialogPane().setContent(grid);
+
+ dialog.setResultConverter(dialogButton -> {
+ List results = new ArrayList<>();
+ if (dialogButton == ButtonType.OK) {
+ results.add(receiverField.getText());
+ results.add(shareTypeComboBox.getSelectionModel().getSelectedItem());
+ }
+ return results;
+ });
+
+ dialog.showAndWait().ifPresent(result -> {
+ if (result.size() <= 1) return;
+ ShareNote.ShareType shareType;
+ if (result.get(1).equals("Can edit")) {
+ shareType = ShareNote.ShareType.CAN_EDIT;
+ } else {
+ shareType = ShareNote.ShareType.READ_ONLY;
+ }
+ String receiver = result.get(0);
+ boolean isExistReceiver = false;
+ try {
+ isExistReceiver = noteAppService.getUserService().isUser(receiver);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ if (!isExistReceiver) {
+ showAlert(Alert.AlertType.ERROR, "Receiver is not exist!");
+ return;
+ }
+ boolean isLocked = false;
+ try {
+ isLocked = noteAppService.getUserService().checkLocked(receiver);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ if (isLocked) {
+ showAlert(Alert.AlertType.ERROR, "Your account is locked!");
+ }
+ try {
+ noteAppService.getShareNoteService().share(myNote, receiver, shareType);
+ showAlert(Alert.AlertType.INFORMATION, "Successfully share!");
+ ShareNote shareNote = noteAppService.getShareNoteService().open(myNote.getId(), myUser.getUsername());
+ EditShareNoteController.open(myUser, shareNote, stage);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ });
+ }
+
+ protected void addBlock(TextBlock newTextBlock) {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "TextBlockView.fxml";
+ try {
+ TextBlockController controller = new TextBlockController();
+
+ VBox box = controller.loadFXML(filePath);
+ controller.init();
+ controller.setTextBlock(newTextBlock);
+ controller.setNoteId(myNote.getId());
+ controller.setText(newTextBlock.getContent());
+ controller.setHeader(newTextBlock.getHeader());
+
+ controller.getDeleteButton().setOnAction((ActionEvent event) -> {
+ int idxToDelete = controller.getTextBlock().getOrder()-1;
+ blocksLayout.getChildren().remove(idxToDelete);
+ myNote.getBlocks().remove(idxToDelete);
+ textBlockControllers.remove(idxToDelete);
+ });
+
+ controller.getUpButton().setOnAction((ActionEvent event) -> {
+ int order = controller.getTextBlock().getOrder();
+ if (order <= 1) return;
+ swapOrder(order - 1, order);
+
+ //Swap
+ Node temp = blocksLayout.getChildren().get(order - 1);
+ blocksLayout.getChildren().remove(order - 1);
+ blocksLayout.getChildren().add(order - 2, temp);
+ });
+
+ controller.getDownButton().setOnAction((ActionEvent event) -> {
+ int order = controller.getTextBlock().getOrder();
+ if (order >= blocksLayout.getChildren().size()) return;
+ swapOrder(order, order + 1);
+
+ //Swap
+ Node temp = blocksLayout.getChildren().get(order);
+ blocksLayout.getChildren().remove(order);
+ blocksLayout.getChildren().add(order - 1, temp);
+ });
+
+ controller.getBlockHeader().setOnMouseClicked((MouseEvent event) -> {
+ TextInputDialog dialog = new TextInputDialog();
+ dialog.setHeaderText("Input your new header");
+
+ dialog.showAndWait().ifPresent(newHeader -> {
+ controller.setHeader(newHeader);
+ controller.getTextBlock().setHeader(newHeader);
+ });
+
+ });
+
+ blocksLayout.getChildren().add(box);
+ textBlockControllers.add(controller);
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't load text block!");
+ }
+ }
+
+ protected void addBlock(SurveyBlock newSurveyBlock) {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "SurveyBlockView.fxml";
+ try {
+ SurveyBlockController controller = new SurveyBlockController();
+
+ VBox box = controller.loadFXML(filePath);
+ controller.init();
+ controller.setSurveyBlock(newSurveyBlock);
+ controller.setNoteId(myNote.getId());
+ controller.setHeader(newSurveyBlock.getHeader());
+ controller.loadItems();
+
+ controller.getDeleteButton().setOnAction((ActionEvent event) -> {
+ int idxToDelete = controller.getSurveyBlock().getOrder()-1;
+ blocksLayout.getChildren().remove(idxToDelete);
+ myNote.getBlocks().remove(idxToDelete);
+ surveyBlockControllers.remove(idxToDelete);
+ });
+
+ controller.getUpButton().setOnAction((ActionEvent event) -> {
+ int order = controller.getSurveyBlock().getOrder();
+ if (order <= 1) return;
+ swapOrder(order - 1, order);
+
+ //Swap
+ Node temp = blocksLayout.getChildren().get(order - 1);
+ blocksLayout.getChildren().remove(order - 1);
+ blocksLayout.getChildren().add(order - 2, temp);
+ });
+
+ controller.getDownButton().setOnAction((ActionEvent event) -> {
+ int order = controller.getSurveyBlock().getOrder();
+ if (order >= blocksLayout.getChildren().size()) return;
+ swapOrder(order, order + 1);
+
+ //Swap
+ Node temp = blocksLayout.getChildren().get(order);
+ blocksLayout.getChildren().remove(order);
+ blocksLayout.getChildren().add(order - 1, temp);
+ });
+
+ controller.getBlockHeader().setOnMouseClicked((MouseEvent event) -> {
+ TextInputDialog dialog = new TextInputDialog();
+ dialog.setHeaderText("Input your new header");
+
+ dialog.showAndWait().ifPresent(newHeader -> {
+ controller.setHeader(newHeader);
+ controller.getSurveyBlock().setHeader(newHeader);
+ });
+ });
+
+ blocksLayout.getChildren().add(box);
+ surveyBlockControllers.add(controller);
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't load survey block!");
+ }
+ }
+
+ protected void addFilter() {
+ //Hiện Dialog để nhập filter mới
+ TextInputDialog inputDialog = new TextInputDialog();
+ inputDialog.setTitle("Add filter for " + myNote.getHeader());
+ inputDialog.setHeaderText("Enter your new filter");
+ //Lấy kết quả
+ Optional confirm = inputDialog.showAndWait();
+ //Xử lý kết quả khi nhấn OK
+ confirm.ifPresent(newFilterStr -> {
+ NoteFilter newFilter = new NoteFilter(newFilterStr);
+ //Thiết lập và add tất cả các filter cũ
+ if(myNote.getFilters().contains(newFilter)) {
+ //Nếu filter đã tồn tại thì thông báo lỗi
+ showAlert(Alert.AlertType.ERROR, "Exist Filter");
+ } else {
+ //Thêm filter vào list
+ myNote.getFilters().add(newFilter);
+ //Load lại filter GUI
+ loadFilter(myNote.getFilters(), 8);
+ }
+ });
+ }
+
+ /**
+ * Load các filter của note này và hiển thị lên màn hình
+ * @param filters Các NoteFilter cần hiển thị
+ * @param maxColEachRow Số lượng filter lớn nhất ở mỗi hàng
+ */
+ protected void loadFilter(List filters, int maxColEachRow) {
+ int column = 0;
+ int row = 0;
+ //Làm sạch filter layout
+ filterGridLayout.getChildren().clear();
+ if(filters.isEmpty()) {
+ return;
+ }
+ //Thiết lập khoảng cách giữa các filter
+ filterGridLayout.setHgap(8);
+ filterGridLayout.setVgap(8);
+ //Thiết lập filter layout
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "NoteFiltersView.fxml";
+ try {
+ for(int i = 0; i < filters.size(); i++) {
+ NoteFiltersController controller = new NoteFiltersController();
+ HBox hbox = controller.loadFXML(filePath);
+ //Thiết lập dữ liệu cho filter
+ controller.setData(filters.get(i).getFilter());
+ controller.getRemoveFilterView().setOnMouseClicked(event -> {
+ myNote.getFilters().remove(new NoteFilter(controller.getFilter()));
+ loadFilter(myNote.getFilters(), 8);
+ });
+ //Chuyển hàng
+ if(column == maxColEachRow){
+ column = 0;
+ row++;
+ }
+ //Thêm filter vừa tạo vào layout
+ filterGridLayout.add(hbox, column++, row);
+ }
+ } catch (IOException e) {
+ showAlert(Alert.AlertType.ERROR, "Can't load filter!");
+ }
+ }
+
+ /**
+ * Hàm trợ giúp việc thay đổi thứ tự giữa các block
+ * @param firstOrder order của block thứ nhất
+ * @param secondOrder order của block thứ hai
+ */
+ protected void swapOrder(int firstOrder, int secondOrder) {
+ for (TextBlockController controller: textBlockControllers) {
+ if (controller.getTextBlock().getOrder() == firstOrder) {
+ controller.getTextBlock().setOrder(secondOrder);
+ } else if (controller.getTextBlock().getOrder() == secondOrder) {
+ controller.getTextBlock().setOrder(firstOrder);
+ }
+ }
+
+ for (SurveyBlockController controller: surveyBlockControllers) {
+ if (controller.getSurveyBlock().getOrder() == firstOrder) {
+ controller.getSurveyBlock().setOrder(secondOrder);
+ } else if (controller.getSurveyBlock().getOrder() == secondOrder) {
+ controller.getSurveyBlock().setOrder(firstOrder);
+ }
+ }
+ }
+
+ protected void importFile() {
+ //Tạo directory chooser
+ FileChooser fileChooser = new FileChooser();
+ fileChooser.setTitle("Choose dir to export file");
+ File file = fileChooser.showOpenDialog(stage);
+ if (file == null) {
+ return;
+ }
+
+ try {
+ Note importedNote = noteAppService.getFileIOService().importNote(file.getPath());
+ myNote.setBlocks(importedNote.getBlocks());
+ initView();
+ showAlert(Alert.AlertType.INFORMATION, "Successfully import.");
+ } catch (NoteAppServiceException | IOException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ protected void exportFile() {
+ //Tạo directory chooser
+ DirectoryChooser directoryChooser = new DirectoryChooser();
+ directoryChooser.setTitle("Choose dir to export file");
+ File dir = directoryChooser.showDialog(stage);
+ if (dir == null) {
+ return;
+ }
+ //Export ra tên file tương ứng
+ String pdfFileName = myNote.getHeader() + "_" + myNote.getAuthor() + ".pdf";
+ try {
+ noteAppService.getFileIOService().outputNote(dir + "\\" + pdfFileName, myNote);
+ showAlert(Alert.AlertType.INFORMATION, "Successfully export.");
+ } catch (NoteAppServiceException | IOException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ /**
+ * Mở một trang edit note
+ * @param myUser User sở hữu Note
+ * @param myNote Note được mở
+ * @param stage Stage chứa trang edit này
+ */
+ public static void open(User myUser, Note myNote, Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "EditNoteView.fxml";
+
+ EditNoteController controller = new EditNoteController();
+
+ controller.setStage(stage);
+ controller.setMyUser(myUser);
+ controller.setMyNote(myNote);
+ controller.setOpenedNotes(new ArrayList<>());
+ controller.loadFXMLAndSetScene(filePath);
+ controller.init();
+ //Set scene cho stage và show
+
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open edit.");
+ }
+ }
+
+ /**
+ * Mở một trang edit note với thông tin về các note đang được mở
+ * @param myUser User sở hữu các note này
+ * @param myNote Note đang được edit
+ * @param openedNotes Các Note đang được mở
+ * @param stage Stage chứa trang edit này
+ */
+ public static void open(User myUser, Note myNote, List openedNotes, Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "EditNoteView.fxml";
+
+ EditNoteController controller = new EditNoteController();
+
+ controller.setStage(stage);
+ controller.setMyUser(myUser);
+ controller.setMyNote(myNote);
+ controller.setOpenedNotes(openedNotes);
+ controller.loadFXMLAndSetScene(filePath);
+ controller.init();
+ //Set scene cho stage và show
+
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open edit.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/noteapp/controller/EditShareNoteController.java b/src/main/java/com/noteapp/controller/EditShareNoteController.java
new file mode 100644
index 0000000..8fc2736
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/EditShareNoteController.java
@@ -0,0 +1,455 @@
+package com.noteapp.controller;
+
+import com.noteapp.common.service.NoteAppServiceException;
+import static com.noteapp.controller.Controller.showAlert;
+import com.noteapp.note.model.Note;
+import com.noteapp.note.model.NoteBlock;
+import com.noteapp.note.model.ShareNote;
+import com.noteapp.note.model.SurveyBlock;
+import com.noteapp.note.model.TextBlock;
+import com.noteapp.user.model.User;
+import java.io.File;
+import java.io.IOException;
+import java.sql.Date;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Timer;
+import java.util.TimerTask;
+import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.scene.Node;
+import javafx.scene.control.Alert;
+import javafx.scene.control.ButtonType;
+import javafx.scene.control.TextInputDialog;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.VBox;
+import javafx.stage.DirectoryChooser;
+import javafx.stage.Stage;
+
+/**
+ * Controller cho trang edit một note được chia sẻ giữa nhiều người
+ * @author Nhóm 17
+ */
+public class EditShareNoteController extends EditNoteController {
+ private Map> othersTextBlockById;
+ private Map> othersSurveyBlockById;
+
+ private ShareNote myShareNote;
+ private Timer updateTimer;
+ private TimerTask updateTimerTask;
+
+ private boolean needReload;
+
+ public void setMyShareNote(ShareNote myShareNote) {
+ this.myShareNote = myShareNote;
+ }
+
+ @Override
+ public void init() {
+ needReload = false;
+ super.init();
+ }
+
+ @Override
+ protected void initView() {
+ noteHeaderLabel.setText(myShareNote.getHeader());
+ initOpenedNotes();
+ loadFilter(myNote.getFilters(), 8);
+ this.initBlock();
+ }
+
+ @Override
+ protected void initBlock() {
+ blocksLayout.getChildren().clear();
+ textBlockControllers.clear();
+ surveyBlockControllers.clear();
+ List blocks = myShareNote.getBlocks();
+ Map> otherEditorBlocks = myShareNote.getOtherEditorBlocks();
+ othersTextBlockById = new HashMap<>();
+ othersSurveyBlockById = new HashMap<>();
+
+ getBlocksById(otherEditorBlocks);
+
+ for(int i=0; i btnType = showAlert(Alert.AlertType.WARNING, "You need to reload.");
+ reload();
+ }
+ myShareNote = noteAppService.getShareNoteService().open(myShareNote.getId(), myShareNote.getEditor());
+ noteHeaderLabel.setText(myShareNote.getHeader());
+ loadFilter(myShareNote.getFilters(), 8);
+ Map> otherEditorBlocks = myShareNote.getOtherEditorBlocks();
+ getBlocksById(otherEditorBlocks);
+ updateTextBlock();
+ updateSurveyBlock();
+ }
+
+ /**
+ * Cài đặt trang edit tự động cập nhật dữ liệu về các block được chỉnh sửa
+ * bởi các user khác. Trong trường hợp thứ tự của các block bị thay đổi, hoặc
+ * header của một block nào đó bị thay đổi, ứng dụng sẽ yêu cầu User reload lại
+ * trang edit này.
+ * @see #reload()
+ * @see #updateTextBlock()
+ * @see #updateSurveyBlock()
+ */
+ public void setOnAutoUpdate() {
+ updateTimer = new Timer();
+ updateTimerTask = new TimerTask() {
+ @Override
+ public void run() {
+ Platform.runLater(() -> {
+ try {
+ autoUpdate();
+
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.WARNING, "Can't update!");
+ }
+ });
+ }
+ };
+ updateTimer.scheduleAtFixedRate(updateTimerTask, 2000, 4000);
+ }
+
+ @Override
+ protected void addBlock(TextBlock newTextBlock) {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "TextBlockView.fxml";
+ try {
+ int blockId = newTextBlock.getId();
+ TextBlockController controller = new TextBlockController();
+
+ VBox box = controller.loadFXML(filePath);
+ controller.init();
+ controller.setTextBlock(newTextBlock);
+ if (othersTextBlockById.containsKey(blockId)) {
+ controller.setOtherEditors(othersTextBlockById.get(blockId));
+ }
+ controller.setNoteId(myNote.getId());
+ controller.setText(newTextBlock.getContent());
+ controller.setHeader(newTextBlock.getHeader());
+ controller.initOtherEditComboBox();
+
+ controller.getDeleteButton().setOnAction((ActionEvent event) -> {
+ int idxToDelete = controller.getTextBlock().getOrder()-1;
+ blocksLayout.getChildren().remove(idxToDelete);
+ myNote.getBlocks().remove(idxToDelete);
+ textBlockControllers.remove(idxToDelete);
+ });
+ controller.getSwitchToOtherButton().setOnAction((ActionEvent event) -> {
+ String otherEditor = controller.getOtherEditor();
+ TextBlock otherTextBlock = new TextBlock();
+ for (TextBlock block: othersTextBlockById.get(blockId)) {
+ if (block.getEditor().equals(otherEditor)) {
+ otherTextBlock = block;
+ break;
+ }
+ }
+ controller.setText(otherTextBlock.getContent());
+ });
+ controller.getUpButton().setOnAction((ActionEvent event) -> {
+ int order = controller.getTextBlock().getOrder();
+ if (order <= 1) return;
+ swapOrder(order - 1, order);
+
+ //Swap
+ Node temp = blocksLayout.getChildren().get(order - 1);
+ blocksLayout.getChildren().remove(order - 1);
+ blocksLayout.getChildren().add(order - 2, temp);
+ });
+
+ controller.getDownButton().setOnAction((ActionEvent event) -> {
+ int order = controller.getTextBlock().getOrder();
+ if (order >= blocksLayout.getChildren().size()) return;
+ swapOrder(order, order + 1);
+
+ //Swap
+ Node temp = blocksLayout.getChildren().get(order);
+ blocksLayout.getChildren().remove(order);
+ blocksLayout.getChildren().add(order - 1, temp);
+ });
+
+ controller.getBlockHeader().setOnMouseClicked((MouseEvent event) -> {
+ TextInputDialog dialog = new TextInputDialog();
+ dialog.setHeaderText("Input your new header");
+
+ dialog.showAndWait().ifPresent(newHeader -> {
+ controller.setHeader(newHeader);
+ controller.getTextBlock().setHeader(newHeader);
+ });
+
+ });
+
+ blocksLayout.getChildren().add(box);
+ textBlockControllers.add(controller);
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't load text block!");
+ }
+ }
+
+ @Override
+ protected void addBlock(SurveyBlock newSurveyBlock) {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "SurveyBlockView.fxml";
+ try {
+ int blockId = newSurveyBlock.getId();
+ SurveyBlockController controller = new SurveyBlockController();
+
+ VBox box = controller.loadFXML(filePath);
+ controller.init();
+ controller.setSurveyBlock(newSurveyBlock);
+ if (othersSurveyBlockById.containsKey(blockId)) {
+ controller.setOtherEditors(othersSurveyBlockById.get(blockId));
+ }
+ controller.setNoteId(myNote.getId());
+ controller.setHeader(newSurveyBlock.getHeader());
+ controller.loadItems();
+
+ controller.getDeleteButton().setOnAction((ActionEvent event) -> {
+ int idxToDelete = controller.getSurveyBlock().getOrder()-1;
+ blocksLayout.getChildren().remove(idxToDelete);
+ myNote.getBlocks().remove(idxToDelete);
+ surveyBlockControllers.remove(idxToDelete);
+ });
+
+ controller.getUpButton().setOnAction((ActionEvent event) -> {
+ int order = controller.getSurveyBlock().getOrder();
+ if (order <= 1) return;
+ swapOrder(order - 1, order);
+
+ //Swap
+ Node temp = blocksLayout.getChildren().get(order - 1);
+ blocksLayout.getChildren().remove(order - 1);
+ blocksLayout.getChildren().add(order - 2, temp);
+ });
+
+ controller.getDownButton().setOnAction((ActionEvent event) -> {
+ int order = controller.getSurveyBlock().getOrder();
+ if (order >= blocksLayout.getChildren().size()) return;
+ swapOrder(order, order + 1);
+
+ //Swap
+ Node temp = blocksLayout.getChildren().get(order);
+ blocksLayout.getChildren().remove(order);
+ blocksLayout.getChildren().add(order - 1, temp);
+ });
+
+ controller.getBlockHeader().setOnMouseClicked((MouseEvent event) -> {
+ TextInputDialog dialog = new TextInputDialog();
+ dialog.setHeaderText("Input your new header");
+
+ dialog.showAndWait().ifPresent(newHeader -> {
+ controller.setHeader(newHeader);
+ controller.getSurveyBlock().setHeader(newHeader);
+ });
+ });
+
+ blocksLayout.getChildren().add(box);
+ surveyBlockControllers.add(controller);
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't load survey block!");
+ }
+ }
+
+ @Override
+ protected void saveMyNote() {
+ myShareNote.setHeader(noteHeaderLabel.getText());
+ myShareNote.setLastModifiedDate(Date.valueOf(LocalDate.now()));
+ myShareNote.getBlocks().clear();
+ for(int i=0; i> otherEditorBlocks) {
+ othersTextBlockById = new HashMap<>();
+ othersSurveyBlockById = new HashMap<>();
+
+ for(Map.Entry> entry: otherEditorBlocks.entrySet()) {
+ int blockId = entry.getKey();
+ List others = entry.getValue();
+
+ for(int i = 0; i < others.size(); i++) {
+ if(others.get(i).getBlockType() == NoteBlock.BlockType.TEXT) {
+ if (!othersTextBlockById.containsKey(blockId)) {
+ othersTextBlockById.put(blockId, new ArrayList<>());
+ }
+ othersTextBlockById.get(blockId).add((TextBlock) others.get(i));
+ } else {
+ if (!othersSurveyBlockById.containsKey(blockId)) {
+ othersSurveyBlockById.put(blockId, new ArrayList<>());
+ }
+ othersSurveyBlockById.get(blockId).add((SurveyBlock) others.get(i));
+ }
+ }
+ }
+ }
+
+ protected void updateTextBlock() {
+ for (int i = 0; i < textBlockControllers.size(); i++) {
+ TextBlock thisBlock = textBlockControllers.get(i).getTextBlock();
+ List otherEditors = othersTextBlockById.get(thisBlock.getId());
+ for (TextBlock otherEditor: otherEditors) {
+ if (!otherEditor.getHeader().equals(thisBlock.getHeader())) {
+ needReload = true;
+ break;
+ }
+ if (otherEditor.getOrder() != thisBlock.getOrder()) {
+ needReload = true;
+ break;
+ }
+ }
+
+ textBlockControllers.get(i).updateOtherEditors(otherEditors);
+ textBlockControllers.get(i).initOtherEditComboBox();
+ }
+ }
+
+ protected void updateSurveyBlock() {
+ for (int i = 0; i < surveyBlockControllers.size(); i++) {
+ SurveyBlock thisBlock = surveyBlockControllers.get(i).getSurveyBlock();
+ List otherEditors = othersSurveyBlockById.get(thisBlock.getId());
+ for (SurveyBlock otherEditor: otherEditors) {
+ if (!otherEditor.getHeader().equals(thisBlock.getHeader())) {
+ needReload = true;
+ break;
+ }
+ if (otherEditor.getOrder() != thisBlock.getOrder()) {
+ needReload = true;
+ break;
+ }
+ }
+ surveyBlockControllers.get(i).setOtherEditors(otherEditors);
+ surveyBlockControllers.get(i).loadItems();
+ }
+ }
+
+ protected NoteBlock getBlock(int order) {
+ for (TextBlockController textBlockController: textBlockControllers) {
+ if (textBlockController.getTextBlock().getOrder() == order) {
+ return textBlockController.getTextBlock();
+ }
+ }
+ for (SurveyBlockController surveyBlockController: surveyBlockControllers) {
+ if (surveyBlockController.getSurveyBlock().getOrder() == order) {
+ return surveyBlockController.getSurveyBlock();
+ }
+ }
+ return new NoteBlock();
+ }
+
+ @Override
+ protected void exportFile() {
+ //Tạo directory chooser
+ DirectoryChooser directoryChooser = new DirectoryChooser();
+ directoryChooser.setTitle("Choose dir to export file");
+ File dir = directoryChooser.showDialog(stage);
+ if (dir == null) {
+ return;
+ }
+ //Export ra tên file tương ứng
+ String pdfFileName = myNote.getHeader() + "_" + myShareNote.getAuthor() + ".pdf";
+ try {
+ noteAppService.getFileIOService().outputNote(dir + "\\" + pdfFileName, myShareNote);
+ showAlert(Alert.AlertType.INFORMATION, "Successfully export.");
+ } catch (NoteAppServiceException | IOException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ /**
+ * Mở một trang edit cho một note được chia sẻ giữa nhiều người
+ * @param myUser User đang trong phiên đăng nhập
+ * @param myShareNote Một Note được mở và được chia sẻ tới User này
+ * @param stage Stage chứa trang edit này
+ */
+ public static void open(User myUser, ShareNote myShareNote, Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "EditNoteView.fxml";
+ EditShareNoteController controller = new EditShareNoteController();
+ controller.setStage(stage);
+ controller.setMyUser(myUser);
+ controller.setMyNote(myShareNote);
+ controller.setMyShareNote(myShareNote);
+ controller.setOpenedNotes(new ArrayList<>());
+ controller.loadFXMLAndSetScene(filePath);
+ controller.init();
+ controller.setOnAutoUpdate();
+ //Set scene cho stage và show
+
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open view");
+ }
+ }
+
+ /**
+ * Mở một trang edit cho một note được chia sẻ giữa nhiều người
+ * @param myUser User đang trong phiên đăng nhập
+ * @param myShareNote Một Note được mở và được chia sẻ tới User này
+ * @param openedNotes Các Note đang được mở hiện tại
+ * @param stage Stage chứa trang edit này
+ */
+ public static void open(User myUser, ShareNote myShareNote, List openedNotes, Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "EditNoteView.fxml";
+ EditShareNoteController controller = new EditShareNoteController();
+
+ controller.setStage(stage);
+ controller.setMyUser(myUser);
+ controller.setMyNote(myShareNote);
+ controller.setMyShareNote(myShareNote);
+ controller.setOpenedNotes(openedNotes);
+ controller.loadFXMLAndSetScene(filePath);
+ controller.init();
+ controller.setOnAutoUpdate();
+ //Set scene cho stage và show
+
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open edit.");
+ }
+ }
+}
diff --git a/src/main/java/com/noteapp/controller/Initable.java b/src/main/java/com/noteapp/controller/Initable.java
new file mode 100644
index 0000000..4219a00
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/Initable.java
@@ -0,0 +1,15 @@
+package com.noteapp.controller;
+
+/**
+ * Yêu cầu các class kế thừa nó phải khởi tạo qua một phương thức
+ * trước khi sử dụng
+ * @author admin
+ */
+public interface Initable {
+ /**
+ * Phương thức khởi tạo các giá trị, thuộc tính cần thiết
+ * và thiết lập các action event khi bấm vào các đối tượng
+ * hiển thị trên view
+ */
+ public abstract void init();
+}
diff --git a/src/main/java/com/noteapp/controller/LoginController.java b/src/main/java/com/noteapp/controller/LoginController.java
new file mode 100644
index 0000000..816c133
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/LoginController.java
@@ -0,0 +1,110 @@
+package com.noteapp.controller;
+
+import com.noteapp.common.service.NoteAppService;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.user.dao.AdminDAO;
+import com.noteapp.user.dao.UserDAO;
+import com.noteapp.user.model.User;
+import com.noteapp.user.service.AdminService;
+import com.noteapp.user.service.UserService;
+import java.io.IOException;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.TextField;
+import javafx.scene.input.MouseEvent;
+import javafx.stage.Stage;
+
+/**
+ * FXML Controller class cho trang Login
+ * @author Nhóm 17
+ */
+public class LoginController extends RequestServiceController implements Initable {
+ //Các thuộc tính FXML
+ @FXML
+ private Button loginButton;
+ @FXML
+ private PasswordField passwordField;
+ @FXML
+ private TextField usernameField;
+ @FXML
+ private Label registerLabel;
+ @FXML
+ private Button closeButton;
+ @FXML
+ private Label forgotPasswordLabel;
+
+ @Override
+ public void init() {
+ noteAppService = new NoteAppService();
+ noteAppService.setUserService(new UserService(UserDAO.getInstance()));
+ noteAppService.setAdminService(new AdminService(UserDAO.getInstance(), AdminDAO.getInstance()));
+ loginButton.setOnAction((ActionEvent event) -> {
+ login();
+ });
+ closeButton.setOnAction((ActionEvent event) -> {
+ close();
+ });
+ registerLabel.setOnMouseClicked((MouseEvent event) -> {
+ RegisterController.open(stage);
+ });
+ forgotPasswordLabel.setOnMouseClicked((MouseEvent event) -> {
+ ResetPasswordController.open(stage);
+ });
+ }
+
+ /**
+ * Kiểm tra username và password của User thông qua các field
+ * và tiến hành chuyển vào trang dashboard tương ứng nếu đăng nhập thành công
+ * @see usernameField
+ * @see passwordField
+ */
+ protected void login() {
+ //Lấy username và password
+ String username = usernameField.getText();
+ String password = passwordField.getText();
+
+ //Kiểm tra thông tin đăng nhập
+ try {
+ boolean isAdmin = noteAppService.getAdminService().isAdmin(username);
+ if (!isAdmin) {
+ User user = noteAppService.getUserService().checkUser(username, password);
+ showAlert(Alert.AlertType.INFORMATION, "Successfully Login");
+ //Mở Dashboard của user này
+ DashboardController.open(user, stage);
+ } else {
+ noteAppService.getAdminService().checkAdmin(username, password);
+ showAlert(Alert.AlertType.INFORMATION, "Successfully Login");
+ //Mở Dashboard của user này
+ AdminDashboardController.open(stage);
+ }
+
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ /**
+ * Mở một trang đăng nhập
+ * @param stage Stage chứa trang đăng nhập này
+ */
+ public static void open(Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "LoginView.fxml";
+
+ LoginController controller = new LoginController();
+
+ controller.setStage(stage);
+ controller.loadFXMLAndSetScene(filePath);
+ controller.init();
+ //Set scene cho stage và show
+
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open login");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/noteapp/controller/RegisterController.java b/src/main/java/com/noteapp/controller/RegisterController.java
new file mode 100644
index 0000000..f6cb92c
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/RegisterController.java
@@ -0,0 +1,300 @@
+package com.noteapp.controller;
+
+import com.noteapp.common.service.NoteAppService;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.user.dao.UserDAO;
+import com.noteapp.user.model.Email;
+import com.noteapp.user.model.User;
+import com.noteapp.user.service.UserService;
+import com.noteapp.user.service.security.MailjetSevice;
+import com.noteapp.user.service.security.SixNumCodeGenerator;
+import com.noteapp.user.service.security.VerificationMailService;
+import java.io.IOException;
+import java.sql.Date;
+import java.time.LocalDate;
+import java.util.Optional;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.ButtonType;
+import javafx.scene.control.Label;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.RadioButton;
+import javafx.scene.control.TextField;
+import javafx.scene.control.TextInputDialog;
+import javafx.scene.input.MouseEvent;
+import javafx.stage.Stage;
+
+/**
+ * FXML Controller class cho trang Register
+ *
+ * @author Nhóm 17
+ */
+public class RegisterController extends RequestServiceController implements Initable {
+ //Các thuộc tính FXML
+ @FXML
+ private TextField nameField;
+ @FXML
+ private PasswordField passwordField;
+ @FXML
+ private Button registerButton;
+ @FXML
+ private TextField schoolField;
+ @FXML
+ private TextField usernameField;
+ @FXML
+ private TextField dayOfBirthField;
+ @FXML
+ private TextField monthOfBirthField;
+ @FXML
+ private TextField yearOfBirthField;
+ @FXML
+ private RadioButton genderMale;
+ @FXML
+ private RadioButton genderFemale;
+ @FXML
+ private RadioButton genderOther;
+ @FXML
+ private TextField emailAddressField;
+ @FXML
+ private TextField emailNameField;
+ @FXML
+ private Label errorNameFieldLabel;
+ @FXML
+ private Label errorUsernameFieldLabel;
+ @FXML
+ private Label errorPasswordFieldLabel;
+ @FXML
+ private Label errorBirthdayFieldLabel;
+ @FXML
+ private Label errorEmailFieldLabel;
+ @FXML
+ private Label backLoginLabel;
+ @FXML
+ private Button closeButton;
+
+ private User newUser;
+
+ @Override
+ public void init() {
+ noteAppService = new NoteAppService();
+ noteAppService.setUserService(new UserService(UserDAO.getInstance()));
+ initView();
+ registerButton.setOnAction((ActionEvent event) -> {
+ register();
+ });
+ closeButton.setOnAction((ActionEvent event) -> {
+ close();
+ });
+ backLoginLabel.setOnMouseClicked((MouseEvent event) -> {
+ LoginController.open(stage);
+ });
+ }
+
+ protected void initView() {
+ //Ẩn các error label
+ errorNameFieldLabel.setVisible(false);
+ errorUsernameFieldLabel.setVisible(false);
+ errorPasswordFieldLabel.setVisible(false);
+ errorEmailFieldLabel.setVisible(false);
+ errorBirthdayFieldLabel.setVisible(false);
+
+ //Thiết lập lựa chọn mặc định cho gender
+ genderOther.setSelected(true);
+
+ }
+
+ private void getPasswordFromField() {
+ if("".equals(passwordField.getText())) {
+ errorPasswordFieldLabel.setVisible(true);
+ }
+ newUser.setPassword(passwordField.getText());
+ }
+
+ private void getEmailFromField() {
+ Email email = new Email();
+ email.setAddress(emailAddressField.getText());
+ if(!email.checkAddress()) {
+ errorEmailFieldLabel.setVisible(true);
+ }
+ newUser.setEmail(email);
+ }
+
+ private void getBirthdayFromField() {
+ int dayOfBirth = -1;
+ int monthOfBirth = -1;
+ int yearOfBirth = -1;
+ if(dayOfBirthField.getText().matches("^[0-9]{1,2}$")) {
+ dayOfBirth = Integer.parseInt(dayOfBirthField.getText());
+ } else if("".equals(dayOfBirthField.getText())) {
+ dayOfBirth = LocalDate.now().getDayOfMonth();
+ } else {
+ errorBirthdayFieldLabel.setVisible(true);
+ }
+ if(monthOfBirthField.getText().matches("^[0-9]{1,2}$")) {
+ monthOfBirth = Integer.parseInt(monthOfBirthField.getText());
+ } else if("".equals(monthOfBirthField.getText())) {
+ monthOfBirth = LocalDate.now().getMonthValue();
+ } else {
+ errorBirthdayFieldLabel.setVisible(true);
+ }
+ if(yearOfBirthField.getText().matches("^[0-9]{4}$")) {
+ yearOfBirth = Integer.parseInt(yearOfBirthField.getText());
+ } else if("".equals(yearOfBirthField.getText())) {
+ yearOfBirth = LocalDate.now().getYear();
+ } else {
+ errorBirthdayFieldLabel.setVisible(true);
+ }
+ if(!errorBirthdayFieldLabel.isVisible()) {
+ newUser.setBirthday(Date.valueOf(LocalDate.of(yearOfBirth, monthOfBirth, dayOfBirth)));
+ }
+ }
+ private void getNameFromField() {
+ //Láy thông tin name
+ if("".equals(nameField.getText())) {
+ errorNameFieldLabel.setVisible(true);
+ }
+ newUser.setName(nameField.getText());
+ }
+
+ private void getUsernameFromField() {
+ if("".equals(usernameField.getText())) {
+ errorUsernameFieldLabel.setVisible(true);
+ }
+ newUser.setUsername(usernameField.getText());
+ }
+
+ private void getGenderFromBox() {
+ if(genderMale.isSelected()) {
+ newUser.setGender(User.Gender.MALE);
+ } else if (genderFemale.isSelected()) {
+ newUser.setGender(User.Gender.FEMALE);
+ } else {
+ newUser.setGender(User.Gender.OTHER);
+ }
+ }
+
+ private boolean checkErrorAccountInfo() {
+ return errorNameFieldLabel.isVisible() || errorPasswordFieldLabel.isVisible()
+ || errorBirthdayFieldLabel.isVisible() || errorEmailFieldLabel.isVisible()
+ || errorUsernameFieldLabel.isVisible();
+ }
+ /**
+ * Tiến hành lấy dữ liệu từ các field tương ứng để set dữ liệu cho {@link User},
+ * thông qua đó thêm User này vào CSDL
+ */
+ protected void register() {
+ initView();
+ //Thiết lập các thuộc tính cho new user
+ newUser = new User();
+ //Láy thông tin name
+ getNameFromField();
+ //Lấy username
+ getUsernameFromField();
+ //Lấy password
+ getPasswordFromField();
+ //Lấy school
+ newUser.setSchool(schoolField.getText());
+ //Lấy thông tin về birth
+ getBirthdayFromField();
+ //Lấy gender
+ getGenderFromBox();
+ //Lấy email
+ getEmailFromField();
+ //Kiểm tra xem có lỗi nào không
+ if(checkErrorAccountInfo()) {
+ return;
+ }
+ if (!checkVerifyEmail()) {
+ return;
+ }
+ createUser(newUser);
+ }
+
+ private boolean checkVerifyEmail() {
+ VerificationMailService.CodeStatus codeStatus = verifyEmail();
+ switch (codeStatus) {
+ case EXPIRED -> {
+ showAlert(Alert.AlertType.ERROR, "This code is expired!");
+ }
+ case FALSE -> {
+ showAlert(Alert.AlertType.ERROR, "This code is false!");
+ }
+ case TRUE -> {
+ return true;
+ }
+ }
+ return true;
+ }
+
+ private void createUser(User newUser) {
+ try {
+ //Tạo User mới thành công
+ noteAppService.getUserService().create(newUser);
+ showAlert(Alert.AlertType.INFORMATION, "Successfully create");
+ Optional optional = showAlert(Alert.AlertType.CONFIRMATION, "Back to Login");
+ if(optional.get() == ButtonType.OK) {
+ //Quay về trang đăng nhập
+ LoginController.open(stage);
+ }
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ /**
+ * Xác thực một Email bằng cách gửi code về địa chỉ được nhập trong field
+ * @return Một {@link VerificationMailService.CodeStatus} miêu tả trạng thái
+ * của Code được nhập vào dialog
+ * @see emailAddressField
+ */
+ private VerificationMailService.CodeStatus verifyEmail() {
+ try {
+ Email toEmail = new Email();
+ toEmail.setAddress(emailAddressField.getText());
+ toEmail.setName(emailNameField.getText());
+ noteAppService.setVerificationMailService(new VerificationMailService(new MailjetSevice(),
+ new SixNumCodeGenerator()));
+ noteAppService.getVerificationMailService().sendCode(toEmail);
+
+ TextInputDialog dialog = new TextInputDialog();
+ dialog.setTitle("VERIFY CODE HAS SENT TO YOUR EMAIL");
+ dialog.setHeaderText("Enter your verification code");
+ //Lấy kết quả
+ Optional confirm = dialog.showAndWait();
+ confirm.ifPresent(inputCode -> {
+ try {
+ noteAppService.getVerificationMailService().checkCode(inputCode);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ });
+ return noteAppService.getVerificationMailService().getCodeStatus();
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ return VerificationMailService.CodeStatus.FALSE;
+ }
+ }
+
+ /**
+ * Mở trang register
+ * @param stage Stage chứa trang register này
+ */
+ public static void open(Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "RegisterView.fxml";
+
+ RegisterController controller = new RegisterController();
+
+ controller.setStage(stage);
+ controller.loadFXMLAndSetScene(filePath);
+ controller.init();
+ //Set scene cho stage và show
+
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open register");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/noteapp/controller/RequestServiceController.java b/src/main/java/com/noteapp/controller/RequestServiceController.java
new file mode 100644
index 0000000..378bed9
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/RequestServiceController.java
@@ -0,0 +1,12 @@
+package com.noteapp.controller;
+
+import com.noteapp.common.service.NoteAppService;
+
+/**
+ * Một class đại diện cho các controller yêu cầu sử dụng dịch vụ của
+ * hệ thống NoteApp
+ * @author Nhóm 17
+ */
+public abstract class RequestServiceController extends Controller {
+ protected NoteAppService noteAppService;
+}
diff --git a/src/main/java/com/noteapp/controller/ResetPasswordController.java b/src/main/java/com/noteapp/controller/ResetPasswordController.java
new file mode 100644
index 0000000..eeac03c
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/ResetPasswordController.java
@@ -0,0 +1,157 @@
+package com.noteapp.controller;
+
+import com.noteapp.common.service.NoteAppService;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.user.dao.UserDAO;
+import com.noteapp.user.model.Email;
+import com.noteapp.user.service.UserService;
+import com.noteapp.user.service.security.MailjetSevice;
+import com.noteapp.user.service.security.SixNumCodeGenerator;
+import com.noteapp.user.service.security.VerificationMailService;
+import java.io.IOException;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.TextField;
+import javafx.scene.input.MouseEvent;
+import javafx.stage.Stage;
+
+/**
+ * Một Controller cho trang cấp lại mật khẩu mới
+ * @author Nhóm 17
+ */
+public class ResetPasswordController extends RequestServiceController implements Initable {
+ @FXML
+ private Button closeButton;
+ @FXML
+ private Button confirmPasswordButton;
+ @FXML
+ private Label errorUsernameFieldLabel;
+ @FXML
+ private PasswordField passwordField;
+ @FXML
+ private Button sendCodeButton;
+ @FXML
+ private TextField usernameField;
+ @FXML
+ private TextField verificationCodeField;
+ @FXML
+ private Button verifyCodeButton;
+ @FXML
+ private Label backLoginLabel;
+
+ @Override
+ public void init() {
+ noteAppService = new NoteAppService();
+ noteAppService.setUserService(new UserService(UserDAO.getInstance()));
+ initScene();
+ closeButton.setOnAction((ActionEvent event) -> {
+ close();
+ });
+ sendCodeButton.setOnAction((ActionEvent event) -> {
+ sendCode();
+ });
+ verifyCodeButton.setOnAction((ActionEvent event) -> {
+ checkVerifyCode();
+ });
+ confirmPasswordButton.setOnAction((ActionEvent event) -> {
+ resetPassword();
+ });
+ backLoginLabel.setOnMouseClicked((MouseEvent event) -> {
+ LoginController.open(stage);
+ });
+ }
+
+ protected void initScene() {
+ errorUsernameFieldLabel.setVisible(false);
+ verificationCodeField.setEditable(false);
+ passwordField.setEditable(false);
+ }
+
+ /**
+ * Gửi một verify code tới email của User có username được nhập vào field,
+ * nếu user tồn tại và đã gửi email thì mở khóa field để nhập code
+ */
+ protected void sendCode() {
+ String username = usernameField.getText();
+ if("".equals(username)) {
+ errorUsernameFieldLabel.setVisible(true);
+ return;
+ } else {
+ errorUsernameFieldLabel.setVisible(false);
+ }
+ try {
+ Email vefiryEmail = noteAppService.getUserService().getVerificationEmail(username);
+ noteAppService.setVerificationMailService(new VerificationMailService(new MailjetSevice(),
+ new SixNumCodeGenerator()));
+ noteAppService.getVerificationMailService().sendCode(vefiryEmail);
+ verificationCodeField.setEditable(true);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ /**
+ * Kiểm tra code xác thực được nhập vào từ người dùng.
+ * Nếu code đúng thì mở khóa field để nhập password mới
+ */
+ protected void checkVerifyCode() {
+ if(!verificationCodeField.isEditable()) {
+ return;
+ }
+ try {
+ String inputCode = verificationCodeField.getText();
+ noteAppService.getVerificationMailService().checkCode(inputCode);
+ VerificationMailService.CodeStatus codeStatus = noteAppService.getVerificationMailService().getCodeStatus();
+ switch (codeStatus) {
+ case EXPIRED -> {
+ showAlert(Alert.AlertType.ERROR, "This code is expired!");
+ }
+ case FALSE -> {
+ showAlert(Alert.AlertType.ERROR, "This code is false!");
+ }
+ case TRUE -> {
+ showAlert(Alert.AlertType.INFORMATION, "Please input your new password below");
+ passwordField.setEditable(true);
+ }
+ }
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ protected void resetPassword() {
+ if(!passwordField.isEditable()) {
+ return;
+ }
+ String username = usernameField.getText();
+ try {
+ noteAppService.getUserService().updatePassword(username, passwordField.getText());
+ initScene();
+ showAlert(Alert.AlertType.INFORMATION, "Successfully reset.");
+ LoginController.open(stage);
+ } catch (NoteAppServiceException ex) {
+ showAlert(Alert.AlertType.ERROR, ex.getMessage());
+ }
+ }
+
+ public static void open(Stage stage) {
+ try {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "ResetPasswordView.fxml";
+
+ ResetPasswordController controller = new ResetPasswordController();
+
+ controller.setStage(stage);
+ controller.loadFXMLAndSetScene(filePath);
+ controller.init();
+ //Set scene cho stage và show
+
+ controller.showFXML();
+ } catch (IOException ex) {
+ showAlert(Alert.AlertType.ERROR, "Can't open reset Password");
+ }
+ }
+}
diff --git a/src/main/java/com/noteapp/controller/SurveyBlockController.java b/src/main/java/com/noteapp/controller/SurveyBlockController.java
new file mode 100644
index 0000000..fa9071c
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/SurveyBlockController.java
@@ -0,0 +1,213 @@
+package com.noteapp.controller;
+
+import com.noteapp.note.model.SurveyBlock;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextInputDialog;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+
+/**
+ * Một class Controller để hiển thị một SurveyBlock lên trang edit
+ * @author Nhóm 17
+ * @see EditNoteController
+ */
+public class SurveyBlockController extends Controller implements Initable {
+ @FXML
+ private Label blockHeader;
+ @FXML
+ private Label changeNotify;
+ @FXML
+ private VBox itemsLayout;
+ @FXML
+ private Button addItemButton;
+ @FXML
+ private Button deleteButton;
+ @FXML
+ private Button upButton;
+ @FXML
+ private Button downButton;
+
+ private int noteId;
+ private SurveyBlock surveyBlock;
+ private List otherEditors;
+ private List itemsController;
+
+ @Override
+ public void init() {
+ noteId = -1;
+ surveyBlock = new SurveyBlock();
+ otherEditors = new ArrayList<>();
+ itemsController = new ArrayList<>();
+ changeNotify.setVisible(false);
+
+ addItemButton.setOnAction((ActionEvent event) -> {
+ addItem();
+ });
+ }
+
+ private void loadItem(String choice, boolean isVoted) throws IOException {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "SurveyItemView.fxml";
+ SurveyItemController controller = new SurveyItemController();
+ HBox box = controller.loadFXML(filePath);
+ controller.init();
+ controller.setChoice(choice);
+
+ int numVoted = 0;
+ if (isVoted) {
+ numVoted += 1;
+ }
+
+ for (SurveyBlock otherEditor: otherEditors) {
+ boolean otherVoted = otherEditor.getSurveyMap().get(choice);
+ if (otherVoted) {
+ numVoted += 1;
+ }
+ }
+ controller.getVotedRatioButton().setSelected(isVoted);
+ controller.setNum(numVoted);
+ controller.getVotedRatioButton().setOnAction((ActionEvent event) -> {
+ boolean radioVoted = controller.getVotedRatioButton().isSelected();
+ controller.setVoted(radioVoted);
+ surveyBlock.getSurveyMap().put(choice, radioVoted);
+ });
+ List others = new ArrayList<>();
+ for (SurveyBlock otherBlock: otherEditors) {
+ if (otherBlock.getSurveyMap().get(choice)) {
+ others.add(otherBlock.getEditor());
+ }
+ }
+ controller.setOther(others);
+ itemsController.add(controller);
+ itemsLayout.getChildren().add(box);
+ }
+
+ /**
+ * Load các choice vào danh sách các choice
+ * @see SurveyItemController
+ * @see itemsLayout
+ */
+ public void loadItems() {
+ itemsController.clear();
+ itemsLayout.getChildren().clear();
+
+ if (surveyBlock.getSurveyMap().isEmpty()) {
+ return;
+ }
+ for (Map.Entry entry: surveyBlock.getSurveyMap().entrySet()) {
+ String choice = entry.getKey();
+ boolean isVoted = entry.getValue();
+ try {
+ loadItem(choice, isVoted);
+ } catch (IOException ex) {
+ System.err.println(ex.getMessage());
+ }
+ }
+ }
+
+ private void addNewItem(String newChoice) throws IOException {
+ String filePath = Controller.DEFAULT_FXML_RESOURCE + "SurveyItemView.fxml";
+ SurveyItemController controller = new SurveyItemController();
+ HBox box = controller.loadFXML(filePath);
+
+ controller.init();
+ controller.setChoice(newChoice);
+ controller.getDeleteChoiceButton().setOnAction((ActionEvent event) -> {
+ String deletedChoice = controller.getChoice();
+ int deletedIdx = -1;
+ for (int i = 0; i < itemsController.size(); i++) {
+ if (deletedChoice.equals(itemsController.get(i).getChoice())) {
+ deletedIdx = i;
+ break;
+ }
+ }
+ itemsController.remove(deletedIdx);
+ itemsLayout.getChildren().remove(deletedIdx);
+ surveyBlock.getSurveyMap().remove(deletedChoice);
+ });
+ controller.getVotedRatioButton().setOnAction((ActionEvent event) -> {
+ boolean radioVoted = controller.getVotedRatioButton().isSelected();
+ controller.setVoted(radioVoted);
+ });
+ itemsController.add(controller);
+ itemsLayout.getChildren().add(box);
+ }
+
+ protected void addItem() {
+ TextInputDialog inputDialog = new TextInputDialog();
+ inputDialog.setTitle("Add a choice to survey");
+ inputDialog.setHeaderText("Input your new choice");
+ //Lấy kết quả và xử lý
+ Optional confirm = inputDialog.showAndWait();
+ confirm.ifPresent(newChoice -> {
+ //Lấy tất cả các Note của myUser
+ try {
+ addNewItem(newChoice);
+ } catch (IOException ex) {
+ System.err.println(ex.getMessage());
+ }
+ });
+ }
+
+
+ public String getHeader() {
+ return blockHeader.getText();
+ }
+
+ public void setHeader(String header) {
+ blockHeader.setText(header);
+ }
+
+ public int getNoteId() {
+ return noteId;
+ }
+
+ public void setNoteId(int noteId) {
+ this.noteId = noteId;
+ }
+
+ public Label getBlockHeader() {
+ return blockHeader;
+ }
+
+ public SurveyBlock getSurveyBlock() {
+ surveyBlock.getSurveyMap().clear();
+ for (int i = 0; i < itemsController.size(); i++) {
+ String choice = itemsController.get(i).getChoice();
+ boolean isVoted = itemsController.get(i).getVoted();
+ surveyBlock.getSurveyMap().put(choice, isVoted);
+ }
+ return surveyBlock;
+ }
+
+ public void setSurveyBlock(SurveyBlock surveyBlock) {
+ this.surveyBlock = surveyBlock;
+ }
+
+ public List getOtherEditors() {
+ return otherEditors;
+ }
+
+ public void setOtherEditors(List otherEditors) {
+ this.otherEditors = otherEditors;
+ }
+
+ public Button getDeleteButton() {
+ return deleteButton;
+ }
+
+ public Button getUpButton() {
+ return upButton;
+ }
+
+ public Button getDownButton() {
+ return downButton;
+ }
+}
diff --git a/src/main/java/com/noteapp/controller/SurveyItemController.java b/src/main/java/com/noteapp/controller/SurveyItemController.java
new file mode 100644
index 0000000..b7a5761
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/SurveyItemController.java
@@ -0,0 +1,83 @@
+package com.noteapp.controller;
+
+import java.util.List;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.RadioButton;
+
+/**
+ * Một class Controller để hiển thị các lựa chọn trong một Survey Block
+ * @author Nhóm 17
+ * @see SurveyBlockController
+ */
+public class SurveyItemController extends Controller implements Initable {
+ @FXML
+ private Label choice;
+ @FXML
+ private RadioButton voted;
+ @FXML
+ private Button deleteChoiceButton;
+ @FXML
+ private Label num;
+ @FXML
+ private Label other;
+
+ @Override
+ public void init() {
+ voted.setSelected(false);
+ num.setText("0");
+ other.setText("No one");
+ }
+
+ public void setChoice(String choice) {
+ this.choice.setText(choice);
+ }
+
+ public String getChoice() {
+ return choice.getText();
+ }
+
+ public int getNum() {
+ return Integer.parseInt(num.getText());
+ }
+
+ public void setNum(int num) {
+ this.num.setText(String.valueOf(num));
+ }
+
+ public void setOther(List others) {
+ if (others.isEmpty()) {
+ other.setText("No one");
+ return;
+ }
+ String otherStr = "";
+ for (String otherVoted: others) {
+ otherStr += otherVoted + ", ";
+ }
+ other.setText(otherStr.substring(0, otherStr.length() - 2));
+ }
+
+ public boolean getVoted() {
+ return voted.isSelected();
+ }
+
+ public void setVoted(boolean isVoted) {
+ voted.setSelected(isVoted);
+ int nowNum = getNum();
+ if (isVoted) {
+ nowNum++;
+ } else {
+ nowNum--;
+ }
+ setNum(nowNum);
+ }
+
+ public Button getDeleteChoiceButton() {
+ return deleteChoiceButton;
+ }
+
+ public RadioButton getVotedRatioButton() {
+ return voted;
+ }
+}
diff --git a/src/main/java/com/noteapp/controller/TextBlockController.java b/src/main/java/com/noteapp/controller/TextBlockController.java
new file mode 100644
index 0000000..c6f2909
--- /dev/null
+++ b/src/main/java/com/noteapp/controller/TextBlockController.java
@@ -0,0 +1,200 @@
+package com.noteapp.controller;
+
+import com.noteapp.note.model.TextBlock;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextArea;
+import javafx.scene.layout.Region;
+
+/**
+ * Một Controller để hiển thị một Text Block lên trang Edit
+ * @author Nhóm 17
+ * @see EditNoteController
+ */
+public class TextBlockController extends Controller implements Initable {
+ @FXML
+ private TextArea editableText;
+ @FXML
+ private Button deleteButton;
+ @FXML
+ private ComboBox otherEditComboBox;
+ @FXML
+ private Label blockHeader;
+ @FXML
+ private Button returnToYoursButton;
+ @FXML
+ private Button switchToOtherButton;
+ @FXML
+ private Label changeNotify;
+ @FXML
+ private Button upButton;
+ @FXML
+ private Button downButton;
+
+ private int noteId;
+ private TextBlock textBlock;
+ private List otherEditors;
+
+ @Override
+ public void init() {
+ noteId = -1;
+ textBlock = new TextBlock();
+
+ returnToYoursButton.setOnAction((ActionEvent event) -> {
+ returnToYourContent();
+ });
+ otherEditComboBox.setPromptText("Other edit by");
+ changeNotify.setText("");
+ }
+
+ public void initOtherEditComboBox() {
+ otherEditComboBox.getItems().clear();
+ otherEditComboBox.setPromptText("Other edit by");
+ if(otherEditors.isEmpty()) {
+ return;
+ }
+ for(TextBlock otherEditor: otherEditors) {
+ otherEditComboBox.getItems().add(otherEditor.getEditor());
+ }
+ }
+
+ public void setHeader(String header) {
+ blockHeader.setText(header);
+ }
+
+ public void setNoteId(int noteId) {
+ this.noteId = noteId;
+ }
+
+ public void setTextBlock(TextBlock textBlock) {
+ this.textBlock = textBlock;
+ }
+
+ public void setOtherEditors(List otherEditors) {
+ this.otherEditors = otherEditors;
+ }
+
+ /**
+ * Cập nhật trạng thái của các phiên bản chỉnh sửa bởi các editor
+ * khác với của block này
+ * @param otherEditors Một list các phiên bản khác của Block này
+ * được chỉnh sửa bởi các editor khác
+ */
+ public void updateOtherEditors(List otherEditors) {
+ List hadModifiedEditor = new ArrayList<>();
+ for (TextBlock oldBlock: this.otherEditors) {
+ for (TextBlock newBlock: otherEditors) {
+ boolean sameEditor = oldBlock.getEditor().equals(newBlock.getEditor());
+ boolean sameContent = oldBlock.getContent().equals(newBlock.getContent());
+ if (sameEditor && (!sameContent)) {
+ hadModifiedEditor.add(newBlock.getEditor());
+ }
+ }
+ }
+
+ setChangeNotify(hadModifiedEditor);
+ this.otherEditors = otherEditors;
+ }
+
+ public Button getDeleteButton() {
+ return deleteButton;
+ }
+
+ public Button getUpButton() {
+ return upButton;
+ }
+
+ public Button getDownButton() {
+ return downButton;
+ }
+
+ public ComboBox getOtherEditComboBox() {
+ return otherEditComboBox;
+ }
+
+ public Button getReturnToYoursButton() {
+ return returnToYoursButton;
+ }
+
+ public Button getSwitchToOtherButton() {
+ return switchToOtherButton;
+ }
+
+ public int getNoteId() {
+ return noteId;
+ }
+
+ public TextBlock getTextBlock() {
+ return textBlock;
+ }
+
+ public List getOtherEditors() {
+ return otherEditors;
+ }
+
+ public String getOtherEditor() {
+ return otherEditComboBox.getSelectionModel().getSelectedItem();
+ }
+
+ public String getText() {
+ return editableText.getText();
+ }
+
+ public void setText(String text) {
+ editableText.setText(text);
+ }
+
+ public void returnToYourContent() {
+ editableText.setText(textBlock.getContent());
+ }
+
+ public Label getBlockHeader() {
+ return blockHeader;
+ }
+
+ /**
+ * Thay đổi thông báo nếu có editor nào khác vừa chỉnh sửa block
+ * @param hadModifiedEditors Những editor vừa chỉnh sửa block này
+ */
+ public void setChangeNotify(List hadModifiedEditors) {
+ if(hadModifiedEditors.isEmpty()) {
+ changeNotify.setText("");
+ return;
+ }
+ String notify = "";
+ for(String str: hadModifiedEditors) {
+ notify += str + ", ";
+ }
+ notify += "has modified their editor";
+ changeNotify.setText(notify);
+ changeNotify.setPrefWidth(Region.USE_COMPUTED_SIZE);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 47 * hash + Objects.hashCode(this.textBlock);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final TextBlockController other = (TextBlockController) obj;
+ return Objects.equals(this.textBlock, other.textBlock);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/noteapp/note/service/INoteService.java b/src/main/java/com/noteapp/note/service/INoteService.java
new file mode 100644
index 0000000..b65cf0f
--- /dev/null
+++ b/src/main/java/com/noteapp/note/service/INoteService.java
@@ -0,0 +1,58 @@
+package com.noteapp.note.service;
+
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.note.model.Note;
+import java.util.List;
+
+/**
+ *
+ * @author admin
+ */
+public interface INoteService {
+ /**
+ * Tạo một {@link Note} mới và lưu vào trong CSDL
+ * @param newNote Note mới cần tạo
+ * @return Note vừa được tạo thành công
+ * @throws NoteAppServiceException Xảy ra khi Note đã tồn tại, hoặc các
+ * thao tác với CSDL bị lỗi
+ */
+ Note create(Note newNote) throws NoteAppServiceException;
+
+ /**
+ * Xóa một Note đã tồn tại trong CSDL
+ * @param noteId id của Note cần xóa
+ * @return Note vừa được xóa thành công
+ * @throws NoteAppServiceException Xảy ra khi các thao tác tương ứng với CSDL
+ * bị lỗi
+ */
+ Note delete(int noteId) throws NoteAppServiceException;
+
+ /**
+ * Lấy tất cả các Note thuộc quyền sở hữu của User
+ * @param author username của User sở hữu các Note này
+ * @return Một List các Note thuộc quyền của User này nếu thành công
+ * @throws NoteAppServiceException Xảy ra khi các thao tác với CSDL liên quan
+ * bị lỗi
+ */
+ List getAll(String author) throws NoteAppServiceException;
+
+ /**
+ * Mở một Note, cụ thể là lấy tất cả các dữ liệu liên quan tới một Note từ
+ * các CSDL Note, NoteFilter, NoteBlock, TextBlock, SurveyBlock và trả về
+ * @param noteId id của Note cần mở
+ * @return Note được mở thành công
+ * @throws NoteAppServiceException Xảy ra khi các thao tác với các CSDL liên quan bị lỗi
+ */
+ Note open(int noteId) throws NoteAppServiceException;
+
+ /**
+ * Lưu một Note, bản chất là cập nhật các thông tin của một Note vào các
+ * CSDL tương ứng. Nếu Note chưa tồn tại thì tnos sẽ được tạo mới và đưa
+ * vào các CSDL tương ứng.
+ * @param note Note cần lưu
+ * @return Note sau khi được cập nhật hoặc tạo mới thành công
+ * @throws NoteAppServiceException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ */
+ Note save(Note note) throws NoteAppServiceException;
+}
diff --git a/src/main/java/com/noteapp/note/service/IShareNoteService.java b/src/main/java/com/noteapp/note/service/IShareNoteService.java
new file mode 100644
index 0000000..d8a27fc
--- /dev/null
+++ b/src/main/java/com/noteapp/note/service/IShareNoteService.java
@@ -0,0 +1,43 @@
+package com.noteapp.note.service;
+
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.note.model.Note;
+import com.noteapp.note.model.ShareNote;
+import java.util.List;
+
+/**
+ *
+ * @author admin
+ */
+public interface IShareNoteService {
+ /**
+ * Chia sẻ một Note tới một người chỉnh sửa khác theo một trong hai loại
+ * (chỉ đọc hoặc có thể chỉnh sửa)
+ * @param note Note cần được chia sẻ
+ * @param editor username của người nhận Note này
+ * @param shareType Loại chia sẻ (Chỉ đọc hoặc có thể Edit)
+ * @return Một ShareNote (một Note được chia sẻ giữa nhiều người)
+ * @throws NoteAppServiceException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ */
+ ShareNote share(Note note, String editor, ShareNote.ShareType shareType) throws NoteAppServiceException;
+
+ /**
+ * Mở một Note được chia sẻ (ShareNote)
+ * @param noteId id của Note cần mở
+ * @param editor username là người chỉnh sửa phiên bản Note này
+ * @return Một ShareNote được mở thành công
+ * @throws NoteAppServiceException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ */
+ ShareNote open(int noteId, String editor) throws NoteAppServiceException;
+
+ /**
+ * Lấy tất cả các ShareNote được chia sẻ tới người chỉnh sửa này
+ * @param editor username của User
+ * @return Một List các ShareNote là các Note được chia sẻ tới User này
+ * @throws NoteAppServiceException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ */
+ List getAllReceived(String editor) throws NoteAppServiceException;
+}
diff --git a/src/main/java/com/noteapp/note/service/NoteService.java b/src/main/java/com/noteapp/note/service/NoteService.java
index 416de50..0c26ee4 100644
--- a/src/main/java/com/noteapp/note/service/NoteService.java
+++ b/src/main/java/com/noteapp/note/service/NoteService.java
@@ -2,6 +2,13 @@
import com.noteapp.common.dao.DAOException;
import com.noteapp.common.dao.NotExistDataException;
+<<<<<<< Updated upstream
+=======
+import com.noteapp.common.service.CausedBySystemException;
+import com.noteapp.common.service.CausedByUserException;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.note.dao.IConcreateBlockDAO;
+>>>>>>> Stashed changes
import com.noteapp.note.dao.INoteBlockDAO;
import com.noteapp.note.dao.INoteDAO;
import com.noteapp.note.dao.INoteFilterDAO;
@@ -40,6 +47,7 @@ public NoteService() {
}
+<<<<<<< Updated upstream
/**
* Lấy các thể hiện tương ứng cho các DAO
*/
@@ -66,15 +74,26 @@ protected void getInstanceOfDAO() {
*/
public Note create(Note newNote) throws NoteServiceException {
getInstanceOfDAO();
+=======
+ private void checkNullDAO() throws NoteAppServiceException {
+ if (noteDAO == null || noteFilterDAO == null) {
+ throw new CausedBySystemException("DAO is null!");
+ }
+ }
+
+ @Override
+ public Note create(Note newNote) throws NoteAppServiceException {
+ checkNullDAO();
+>>>>>>> Stashed changes
int noteId = newNote.getId();
//Kiểm tra note đã tồn tại hay chưa
try {
noteDAO.get(noteId);
- throw new NoteServiceException("Already exist note!");
+ throw new CausedByUserException("Already exist note!");
} catch (NotExistDataException nedExByGet) {
//Nếu chưa tồn tại thì tiếp tục
} catch (DAOException exByGet) {
- throw new NoteServiceException(exByGet.getMessage(), exByGet.getCause());
+ throw new CausedBySystemException(exByGet.getMessage(), exByGet.getCause());
}
try {
//Thêm các trường thông tin cơ bản vào CSDL Note
@@ -91,10 +110,11 @@ public Note create(Note newNote) throws NoteServiceException {
//Mở Note và trả về
return this.open(newNote.getId());
} catch (DAOException exByCreate) {
- throw new NoteServiceException(exByCreate.getMessage(), exByCreate.getCause());
+ throw new CausedBySystemException(exByCreate.getMessage(), exByCreate.getCause());
}
}
+<<<<<<< Updated upstream
/**
* Xóa một Note đã tồn tại trong CSDL
* @param noteId id của Note cần xóa
@@ -107,6 +127,11 @@ public Note create(Note newNote) throws NoteServiceException {
*/
public Note delete(int noteId) throws NoteServiceException {
getInstanceOfDAO();
+=======
+ @Override
+ public Note delete(int noteId) throws NoteAppServiceException {
+ checkNullDAO();
+>>>>>>> Stashed changes
try {
//Lấy Note bằng cách mở
Note deletedNote = this.open(noteId);
@@ -114,10 +139,11 @@ public Note delete(int noteId) throws NoteServiceException {
noteDAO.delete(noteId);
return deletedNote;
} catch (DAOException exByGetAndDelete) {
- throw new NoteServiceException(exByGetAndDelete.getMessage(), exByGetAndDelete.getCause());
+ throw new CausedBySystemException(exByGetAndDelete.getMessage(), exByGetAndDelete.getCause());
}
}
+<<<<<<< Updated upstream
/**
* Lấy tất cả các Note thuộc quyền sở hữu của User
* @param author username của User sở hữu các Note này
@@ -130,6 +156,11 @@ public Note delete(int noteId) throws NoteServiceException {
*/
public List getAll(String author) throws NoteServiceException {
getInstanceOfDAO();
+=======
+ @Override
+ public List getAll(String author) throws NoteAppServiceException {
+ checkNullDAO();
+>>>>>>> Stashed changes
try {
List notes = noteDAO.getAll(author);
List returnNotes = new ArrayList<>();
@@ -138,10 +169,11 @@ public List getAll(String author) throws NoteServiceException {
}
return returnNotes;
} catch (DAOException exByGetAll) {
- throw new NoteServiceException(exByGetAll.getMessage(), exByGetAll.getCause());
+ throw new CausedBySystemException(exByGetAll.getMessage(), exByGetAll.getCause());
}
}
+<<<<<<< Updated upstream
/**
* Mở một Note, cụ thể là lấy tất cả các dữ liệu liên quan tới một Note từ
* các CSDL Note, NoteFilter, NoteBlock, TextBlock, SurveyBlock và trả về
@@ -155,6 +187,11 @@ public List getAll(String author) throws NoteServiceException {
*/
public Note open(int noteId) throws NoteServiceException {
getInstanceOfDAO();
+=======
+ @Override
+ public Note open(int noteId) throws NoteAppServiceException {
+ checkNullDAO();
+>>>>>>> Stashed changes
try {
//Lấy các thông tin cơ bản
Note note = noteDAO.get(noteId);
@@ -165,6 +202,7 @@ public Note open(int noteId) throws NoteServiceException {
note.setBlocks(noteBlocks);
return note;
} catch (DAOException exByGet) {
+<<<<<<< Updated upstream
exByGet.printStackTrace();
throw new NoteServiceException(exByGet.getMessage(), exByGet.getCause());
}
@@ -187,6 +225,15 @@ public Note open(int noteId) throws NoteServiceException {
*/
public Note save(Note note) throws NoteServiceException {
getInstanceOfDAO();
+=======
+ throw new CausedBySystemException(exByGet.getMessage(), exByGet.getCause());
+ }
+ }
+
+ @Override
+ public Note save(Note note) throws NoteAppServiceException {
+ checkNullDAO();
+>>>>>>> Stashed changes
int noteId = note.getId();
//Kiểm tra note đã tồn tại chưa
try {
@@ -195,7 +242,7 @@ public Note save(Note note) throws NoteServiceException {
//Nếu chưa tồn tại thì tạo note mới
return this.create(note);
} catch (DAOException exByGet) {
- throw new NoteServiceException(exByGet.getMessage(), exByGet.getCause());
+ throw new CausedBySystemException(exByGet.getMessage(), exByGet.getCause());
}
try {
//Cập nhật các thông tin cơ bản vào CSDL Note
@@ -210,8 +257,12 @@ public Note save(Note note) throws NoteServiceException {
saveBlocks(note.getId(), note.getBlocks());
return note;
} catch (DAOException exByUpdate) {
+<<<<<<< Updated upstream
exByUpdate.printStackTrace();
throw new NoteServiceException(exByUpdate.getMessage(), exByUpdate.getCause());
+=======
+ throw new CausedBySystemException(exByUpdate.getMessage(), exByUpdate.getCause());
+>>>>>>> Stashed changes
}
}
diff --git a/src/main/java/com/noteapp/note/service/NoteServiceException.java b/src/main/java/com/noteapp/note/service/NoteServiceException.java
deleted file mode 100644
index 12860b1..0000000
--- a/src/main/java/com/noteapp/note/service/NoteServiceException.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.noteapp.note.service;
-
-/**
- * Một ngoại lệ cho các dịch vụ liên quan tới Note
- * @author Nhóm 17
- */
-public class NoteServiceException extends Exception {
-
- public NoteServiceException(String message) {
- super(message);
- }
-
- public NoteServiceException(String message, Throwable cause) {
- super(message, cause);
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/noteapp/note/service/ShareNoteService.java b/src/main/java/com/noteapp/note/service/ShareNoteService.java
new file mode 100644
index 0000000..d119d9e
--- /dev/null
+++ b/src/main/java/com/noteapp/note/service/ShareNoteService.java
@@ -0,0 +1,147 @@
+package com.noteapp.note.service;
+
+import com.noteapp.common.dao.DAOException;
+import com.noteapp.common.dao.NotExistDataException;
+import com.noteapp.common.service.CausedBySystemException;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.note.dao.IConcreateBlockDAO;
+import com.noteapp.note.dao.INoteBlockDAO;
+import com.noteapp.note.dao.INoteDAO;
+import com.noteapp.note.dao.INoteFilterDAO;
+import com.noteapp.note.dao.IShareNoteDAO;
+import com.noteapp.note.model.Note;
+import com.noteapp.note.model.NoteBlock;
+import com.noteapp.note.model.ShareNote;
+import com.noteapp.note.model.SurveyBlock;
+import com.noteapp.note.model.TextBlock;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Cung cấp các dịch vụ liên quan tới Note được chia sẻ (ShareNote)
+ * @author Nhóm 17
+ * @see IUserDAO
+ * @see IShareNoteDAO
+ */
+public class ShareNoteService implements IShareNoteService {
+ protected IShareNoteDAO shareNoteDAO;
+ protected SupportedNoteBlockService blockService;
+ protected INoteService noteService;
+
+ public ShareNoteService(IShareNoteDAO shareNoteDAO, INoteDAO noteDAO, INoteFilterDAO noteFilterDAO, INoteBlockDAO noteBlockDAO, IConcreateBlockDAO textBlockDAO, IConcreateBlockDAO surveyBlockDAO) {
+ this.shareNoteDAO = shareNoteDAO;
+ noteService = new NoteService(noteDAO, noteFilterDAO, noteBlockDAO, textBlockDAO, surveyBlockDAO);
+ blockService = new SupportedNoteBlockService(noteBlockDAO, textBlockDAO, surveyBlockDAO);
+ }
+
+ public void setBlockService(SupportedNoteBlockService blockService) {
+ this.blockService = blockService;
+ }
+
+ public void setNoteService(INoteService noteService) {
+ this.noteService = noteService;
+ }
+
+ public void setShareNoteDAO(IShareNoteDAO shareNoteDAO) {
+ this.shareNoteDAO = shareNoteDAO;
+ }
+
+ private void checkNullDAO() throws NoteAppServiceException {
+ if (shareNoteDAO == null) {
+ throw new CausedBySystemException("DAO is null!");
+ }
+ }
+
+ @Override
+ public ShareNote share(Note note, String editor, ShareNote.ShareType shareType) throws NoteAppServiceException {
+ checkNullDAO();
+ //Set các thông tin của note cho shareNote
+ int noteId = note.getId();
+ ShareNote shareNote = new ShareNote();
+ shareNote.setNote(note);
+ //Kiểm tra xem Note đã được chia sẻ hay chưa
+ try {
+ //Nếu có thì chỉ cần update và open nó
+ shareNoteDAO.get(noteId, editor);
+ shareNoteDAO.update(shareNote);
+ return this.open(note.getId(), editor);
+ } catch (NotExistDataException ex1) {
+ //Nếu không thì cần tạo mới trong CSDL
+ } catch (DAOException ex2) {
+ throw new CausedBySystemException(ex2.getMessage(), ex2.getCause());
+ }
+ //Kiểm tra note của User đã được chia sẻ cho người khác hay chưa
+ try {
+ //Nếu có thì chỉ cần update và open nó
+ shareNoteDAO.get(noteId, note.getAuthor());
+ } catch (NotExistDataException ex1) {
+ shareNote.setShareType(ShareNote.ShareType.CAN_EDIT);
+ shareNote.setEditor(note.getAuthor());
+ try {
+ shareNoteDAO.create(shareNote);
+ } catch (DAOException ex3) {
+ throw new CausedBySystemException(ex3.getMessage(), ex3.getCause());
+ }
+ } catch (DAOException ex2) {
+ throw new CausedBySystemException(ex2.getMessage(), ex2.getCause());
+ }
+ try {
+ //Tạo ShareNote mới
+ shareNote.setEditor(editor);
+ shareNote.setShareType(shareType);
+ //Sao lưu các Block của tác giả sang người chỉnh sửa khác
+ List authorBlocks = note.getBlocks();
+ for(NoteBlock noteBlock: authorBlocks) {
+ NoteBlock thisEditorBlock = noteBlock;
+ blockService.createOtherVersion(thisEditorBlock, shareNote.getEditor());
+ }
+ shareNoteDAO.create(shareNote);
+ note.setPubliced(true);
+ noteService.save(note);
+ return this.open(shareNote.getId(), shareNote.getEditor());
+ } catch (DAOException ex) {
+ throw new CausedBySystemException(ex.getMessage(), ex.getCause());
+ }
+ }
+
+ @Override
+ public ShareNote open(int noteId, String editor) throws NoteAppServiceException {
+ checkNullDAO();
+ //Trước hết mở Note
+ Note note = noteService.open(noteId);
+ //Mở phiên bản Note của editor
+ try {
+ ShareNote shareNote = shareNoteDAO.get(noteId, editor);
+ shareNote.setNote(note);
+ //Lấy và phân loại block nào của editor này và cái nào của editor khác
+ List blocks = blockService.getAll(noteId);
+ List thisEditorBlocks = new ArrayList<>();
+ for(NoteBlock noteBlock: blocks) {
+ if(editor.equals(noteBlock.getEditor())) {
+ thisEditorBlocks.add(noteBlock);
+ } else {
+ shareNote.addOtherEditorBlock(noteBlock);
+ }
+ }
+ shareNote.setBlocks(thisEditorBlocks);
+ return shareNote;
+ } catch (DAOException ex) {
+ throw new CausedBySystemException(ex.getMessage(), ex.getCause());
+ }
+ }
+
+ @Override
+ public List getAllReceived(String editor) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ List shareNotes = shareNoteDAO.getAll(editor);
+ List receivedNotes = new ArrayList<>();
+ for(ShareNote shareNote: shareNotes) {
+ receivedNotes.add(this.open(shareNote.getId(), editor));
+ }
+ return receivedNotes;
+ } catch (DAOException ex) {
+ throw new CausedBySystemException(ex.getMessage(), ex.getCause());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/noteapp/note/service/SupportedNoteBlockService.java b/src/main/java/com/noteapp/note/service/SupportedNoteBlockService.java
new file mode 100644
index 0000000..5eb1363
--- /dev/null
+++ b/src/main/java/com/noteapp/note/service/SupportedNoteBlockService.java
@@ -0,0 +1,279 @@
+package com.noteapp.note.service;
+
+import com.noteapp.common.dao.DAOException;
+import com.noteapp.common.service.CausedBySystemException;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.note.dao.IConcreateBlockDAO;
+import com.noteapp.note.dao.INoteBlockDAO;
+import com.noteapp.note.model.NoteBlock;
+import static com.noteapp.note.model.NoteBlock.BlockType.SURVEY;
+import static com.noteapp.note.model.NoteBlock.BlockType.TEXT;
+import com.noteapp.note.model.SurveyBlock;
+import com.noteapp.note.model.TextBlock;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author admin
+ */
+public class SupportedNoteBlockService {
+ protected INoteBlockDAO noteBlockDAO;
+ protected IConcreateBlockDAO textBlockDAO;
+ protected IConcreateBlockDAO surveyBlockDAO;
+
+ protected SupportedNoteBlockService(INoteBlockDAO noteBlockDAO, IConcreateBlockDAO textBlockDAO, IConcreateBlockDAO surveyBlockDAO) {
+ this.noteBlockDAO = noteBlockDAO;
+ this.textBlockDAO = textBlockDAO;
+ this.surveyBlockDAO = surveyBlockDAO;
+ }
+
+ protected void setNoteBlockDAO(INoteBlockDAO noteBlockDAO) {
+ this.noteBlockDAO = noteBlockDAO;
+ }
+
+ protected void setTextBlockDAO(IConcreateBlockDAO textBlockDAO) {
+ this.textBlockDAO = textBlockDAO;
+ }
+
+ protected void setSurveyBlockDAO(IConcreateBlockDAO surveyBlockDAO) {
+ this.surveyBlockDAO = surveyBlockDAO;
+ }
+
+ private void checkNullDAO() throws NoteAppServiceException {
+ if (noteBlockDAO == null || textBlockDAO == null || surveyBlockDAO == null) {
+ throw new CausedBySystemException("DAO is null!");
+ }
+ }
+
+ private List getTextBlocks(NoteBlock noteBlock) throws DAOException {
+ List returnBlocks = new ArrayList<>();
+ List textBlocks = textBlockDAO.getAll(noteBlock.getId());
+ for(TextBlock textBlock: textBlocks) {
+ textBlock.setNoteBlock(noteBlock);
+ returnBlocks.add(textBlock);
+ }
+ return returnBlocks;
+ }
+
+ private TextBlock getTextBlock(NoteBlock noteBlock, String editor) throws DAOException {
+ List textBlocks = textBlockDAO.getAll(noteBlock.getId());
+ for(TextBlock textBlock: textBlocks) {
+ if(editor.equals(textBlock.getEditor())) {
+ textBlock.setNoteBlock(noteBlock);
+ return textBlock;
+ }
+ }
+ throw new DAOException("Not found!");
+ }
+
+ private List getSurveyBlocks(NoteBlock noteBlock) throws DAOException {
+ List returnBlocks = new ArrayList<>();
+ List surveyBlocks = surveyBlockDAO.getAll(noteBlock.getId());
+ for(SurveyBlock surveyBlock: surveyBlocks) {
+ surveyBlock.setNoteBlock(noteBlock);
+ returnBlocks.add(surveyBlock);
+ }
+ return returnBlocks;
+ }
+
+ private SurveyBlock getSurveyBlock(NoteBlock noteBlock, String editor) throws DAOException {
+ List surveyBlocks = surveyBlockDAO.getAll(noteBlock.getId());
+ for(SurveyBlock surveyBlock: surveyBlocks) {
+ if(editor.equals(surveyBlock.getEditor())) {
+ surveyBlock.setNoteBlock(noteBlock);
+ return surveyBlock;
+ }
+ }
+ throw new DAOException("Not found!");
+ }
+
+ /**
+ * Lấy tất cả các block của một Note
+ * @param noteId id của Note chứa các block cần lấy
+ * @return Một List các block của note đó (bao gồm cả các phiên bản tương
+ * ứng của block)
+ * @throws DAOException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ * @see INoteBlockDAO#getAll(int)
+ * @see ITextBlockDAO#getAll(int)
+ * @see ISurveyBlockDAO#getAll(int)
+ * @see TextBlock
+ * @see SurveyBlock
+ */
+ protected List getAll(int noteId) throws DAOException, NoteAppServiceException {
+ checkNullDAO();
+ //Lấy các thông tin cơ bản của block trước
+ List noteBlocks = noteBlockDAO.getAll(noteId);
+ List returnBlocks = new ArrayList<>();
+ //Dựa vào kiểu của block mà quyết định gọi DAO nào để lấy các phiên bản tương ứng
+ for(NoteBlock noteBlock: noteBlocks) {
+ switch (noteBlock.getBlockType()) {
+ case TEXT -> {
+ returnBlocks.addAll(getTextBlocks(noteBlock));
+ }
+ case SURVEY -> {
+ returnBlocks.addAll(getSurveyBlocks(noteBlock));
+ }
+ }
+ }
+ return returnBlocks;
+ }
+
+ /**
+ * Lấy tất cả các block của một Note với một phiên bản chỉnh sửa của một User
+ * @param noteId id của Note chứa các block cần lấy
+ * @param editor username của chủ phiên bản chỉnh sửa này
+ * @return Một List các NoteBlock của phiên bản Note tương ứng
+ * @throws DAOException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ * @see INoteBlockDAO#getAll(int)
+ * @see ITextBlockDAO#getAll(int)
+ * @see ISurveyBlockDAO#getAll(int)
+ * @see #getAll(int)
+ * @see TextBlock
+ * @see SurveyBlock
+ */
+ protected List getAll(int noteId, String editor) throws DAOException, NoteAppServiceException {
+ checkNullDAO();
+ List noteBlocks = noteBlockDAO.getAll(noteId);
+ List returnBlocks = new ArrayList<>();
+ for(NoteBlock noteBlock: noteBlocks) {
+ switch (noteBlock.getBlockType()) {
+ case TEXT -> {
+ returnBlocks.add(getTextBlock(noteBlock, editor));
+ }
+
+ case SURVEY -> {
+ returnBlocks.add(getSurveyBlock(noteBlock, editor));
+ }
+ }
+ }
+ return returnBlocks;
+ }
+
+ /**
+ * Tạo một block mới và lưu vào các CSDL tương ứng (NoteBlock, TextBlock, SurveyBlock)
+ * @param noteId id của Note chứa mà block chuẩn bị tạo thuộc về
+ * @param newBlock NoteBlock cần được tạo
+ * @throws DAOException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ * @see INoteBlockDAO#create(int, NoteBlock)
+ * @see ITextBlockDAO#create(TextBlock)
+ * @see ISurveyBlockDAO#create(SurveyBlock)
+ * @see TextBlock
+ * @see SurveyBlock
+ */
+ protected void create(int noteId, NoteBlock newBlock) throws DAOException, NoteAppServiceException {
+ checkNullDAO();
+ newBlock = noteBlockDAO.create(noteId, newBlock);
+ switch (newBlock.getBlockType()) {
+ case TEXT -> {
+ TextBlock newTextBlock = (TextBlock) newBlock;
+ textBlockDAO.create(newTextBlock);
+ }
+ case SURVEY -> {
+ SurveyBlock newSurveyBlock = (SurveyBlock) newBlock;
+ surveyBlockDAO.create(newSurveyBlock);
+ }
+ }
+ }
+
+ protected void createOtherVersion(NoteBlock noteBlock, String otherEditor) throws DAOException, NoteAppServiceException {
+ checkNullDAO();
+ noteBlock.setEditor(otherEditor);
+ switch (noteBlock.getBlockType()) {
+ case TEXT -> {
+ TextBlock newTextBlock = (TextBlock) noteBlock;
+ textBlockDAO.create(newTextBlock);
+ }
+ case SURVEY -> {
+ SurveyBlock newSurveyBlock = (SurveyBlock) noteBlock;
+ surveyBlockDAO.create(newSurveyBlock);
+ }
+ }
+ }
+
+ /**
+ * Cập nhật một NoteBlock trong một Note
+ * @param noteId id của Note chứa NoteBlock cần cập nhật
+ * @param needUpdateBlock NoteBlock cần cập nhật
+ * @throws DAOException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ * @see INoteBlockDAO#update(int, NoteBlock)
+ * @see ITextBlockDAO#update(TextBlock)
+ * @see ISurveyBlockDAO#update(SurveyBlock)
+ * @see TextBlock
+ * @see SurveyBlock
+ */
+ protected void update(int noteId, NoteBlock needUpdateBlock) throws DAOException, NoteAppServiceException {
+ checkNullDAO();
+ noteBlockDAO.update(noteId, needUpdateBlock);
+ switch (needUpdateBlock.getBlockType()) {
+ case TEXT -> {
+ TextBlock needUpdateTextBlock = (TextBlock) needUpdateBlock;
+ textBlockDAO.update(needUpdateTextBlock);
+ }
+ case SURVEY -> {
+ SurveyBlock needUpdateSurveyBlock = (SurveyBlock) needUpdateBlock;
+ surveyBlockDAO.update(needUpdateSurveyBlock);
+ }
+ }
+ }
+
+ /**
+ * Xóa một NoteBlock nào đó
+ * @param blockId id của block cần xóa
+ * @throws DAOException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ */
+ protected void delete(int blockId) throws DAOException, NoteAppServiceException {
+ checkNullDAO();
+ noteBlockDAO.delete(blockId);
+ }
+
+ /**
+ * Lưu một số các blocks của một Note vào CSDL tương ứng
+ * @param noteId id của Note chứa các blocks cần lưu
+ * @param noteBlocks các block cần lưu
+ * @throws DAOException Xảy ra khi các thao tác với CSDL tương ứng
+ * bị lỗi
+ * @see #getAll(int, String)
+ * @see #create(int, NoteBlock)
+ * @see #update(int, NoteBlock)
+ * @see #delete(int)
+ * @see TextBlock
+ * @see SurveyBlock
+ */
+ protected void save(int noteId, List noteBlocks) throws DAOException, NoteAppServiceException {
+ //Lấy các block của phiên bản note này
+ String editor = noteBlocks.get(0).getEditor();
+ List blocksInDB = this.getAll(noteId, editor);
+ //Phân loại các note vào loại cần tạo mới, cần cập nhật, cần xóa
+ List newBlocks = new ArrayList<>();
+ List needUpdateBlocks = new ArrayList<>();
+ List deletedBlocks = new ArrayList<>();
+ for(NoteBlock noteBlock: noteBlocks) {
+ if(blocksInDB.contains(noteBlock)) {
+ needUpdateBlocks.add(noteBlock);
+ } else {
+ newBlocks.add(noteBlock);
+ }
+ }
+ for(NoteBlock noteBlock: blocksInDB) {
+ if(!noteBlocks.contains(noteBlock)) {
+ deletedBlocks.add(noteBlock);
+ }
+ }
+ //Thực hiện dịch vụ tương ứng với từng loại
+ for(NoteBlock newBlock: newBlocks) {
+ this.create(noteId, newBlock);
+ }
+ for(NoteBlock needUpdateBlock: needUpdateBlocks) {
+ this.update(noteId, needUpdateBlock);
+ }
+ for(NoteBlock deletedBlock: deletedBlocks) {
+ this.delete(deletedBlock.getId());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/noteapp/note/service/io/FileIOService.java b/src/main/java/com/noteapp/note/service/io/FileIOService.java
new file mode 100644
index 0000000..a167b8f
--- /dev/null
+++ b/src/main/java/com/noteapp/note/service/io/FileIOService.java
@@ -0,0 +1,36 @@
+package com.noteapp.note.service.io;
+
+import com.noteapp.note.model.Note;
+import com.noteapp.note.model.ShareNote;
+import java.io.IOException;
+
+/**
+ *
+ * @author admin
+ */
+public interface FileIOService {
+
+ /**
+ * Nhập dữ liệu từ một file vào một Note
+ * @param inputFileDir Đường dẫn tới file chứa dữ liệu vào
+ * @return Một Note chứa dữ liệu được đoc
+ * @throws IOException Việc đọc dữ liệu bị lỗi
+ */
+ Note importNote(String inputFileDir) throws IOException;
+
+ /**
+ * Xuất dữ liệu từ một Note ra một file
+ * @param outputFileDir Đường dẫn tới file chứa dữ liệu ra
+ * @param outputNote Một Note chứa dữ liệu cần xuất
+ * @throws IOException Việc đọc dữ liệu bị lỗi
+ */
+ void outputNote(String outputFileDir, Note outputNote) throws IOException;
+
+ /**
+ * Xuất dữ liệu từ một Note ra một file
+ * @param outputFileDir Đường dẫn tới file chứa dữ liệu ra
+ * @param outputNote Một Note được chia sẻ chứa dữ liệu cần xuất
+ * @throws IOException Việc đọc dữ liệu bị lỗi
+ */
+ void outputNote(String outputFileDir, ShareNote outputNote) throws IOException;
+}
diff --git a/src/main/java/com/noteapp/note/service/io/PdfExportService.java b/src/main/java/com/noteapp/note/service/io/PdfExportService.java
new file mode 100644
index 0000000..c083781
--- /dev/null
+++ b/src/main/java/com/noteapp/note/service/io/PdfExportService.java
@@ -0,0 +1,139 @@
+package com.noteapp.note.service.io;
+
+import com.itextpdf.text.Chapter;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.FontFactory;
+import com.itextpdf.text.PageSize;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.Phrase;
+import com.itextpdf.text.Section;
+import com.itextpdf.text.pdf.PdfPCell;
+import com.itextpdf.text.pdf.PdfPTable;
+import com.itextpdf.text.pdf.PdfWriter;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.util.List;
+
+/**
+ *
+ * @author admin
+ */
+public class PdfExportService {
+ private final Document document;
+ private Chapter allElements;
+
+ /**
+ * Khởi tạo một Service giúp export ra định dạng file .pdf sử dụng api của itextpdf
+ * @param outputFileDir Đường dẫn tới file cần ghi
+ * @param header Đầu đề của file cần ghi
+ * @throws FileNotFoundException Khi không tìm thấy đường dẫn để ghi file
+ * @throws DocumentException Khi không thể ghi header vào file
+ * @see PageSize
+ */
+ public PdfExportService(String outputFileDir, String header) throws FileNotFoundException, DocumentException {
+ document = new Document(PageSize.A4, 50, 30, 30, 30);
+ PdfWriter.getInstance(document, new FileOutputStream(outputFileDir));
+ document.open();
+ setHeaderOfFile(header);
+ }
+
+ /**
+ * Khởi tạo một Service giúp export ra định dạng file .pdf sử dụng api của itextpdf
+ * @param pageSize Size của mỗi page, có thể là A0->A10, etc.
+ * @param marginLeft Độ rộng lề trái
+ * @param marginRight Độ rộng lề phải
+ * @param marginTop Độ rộng lề trên
+ * @param marginBottom Độ rộng lề dưới
+ * @param outputFileDir Đường dẫn tới file cần ghi
+ * @param header Đầu đề của file cần ghi
+ * @throws FileNotFoundException Khi không tìm thấy đường dẫn để ghi file
+ * @throws DocumentException Khi không thể ghi header vào file
+ * @see PageSize
+ */
+ public PdfExportService(float marginLeft, float marginRight, float marginTop, float marginBottom, String outputFileDir, String header) throws FileNotFoundException, DocumentException {
+ document = new Document(PageSize.A4, marginLeft, marginRight, marginTop, marginBottom);
+ PdfWriter.getInstance(document, new FileOutputStream(outputFileDir));
+ document.open();
+ setHeaderOfFile(header);
+ }
+
+ protected final void setHeaderOfFile(String fileHeader) {
+ Font headerFont = FontFactory.getFont(FontFactory.HELVETICA, 25, Font.BOLD);
+ Paragraph fileHeaderParagraph = new Paragraph(fileHeader, headerFont);
+ allElements = new Chapter(fileHeaderParagraph, 0);
+ allElements.setNumberDepth(0);
+ }
+
+ /**
+ * Thêm một đoạn text dạng Paragraph và có header vào file document đã khởi tạo
+ * @param header header của đoạn text
+ * @param content nội dung của đoạn text
+ */
+ public void writeText(String header, String content) {
+ //Thiết lập định dạng và nội dung cho header dưới dạng 1 section
+ Font headerFont = FontFactory.getFont(FontFactory.TIMES_ROMAN, 15, Font.BOLDITALIC);
+ Paragraph headerOfSection = new Paragraph(header, headerFont);
+ Section thisBlock = allElements.addSection(headerOfSection);
+ thisBlock.setNumberDepth(0);
+ //Thêm nội dung vào section
+ Paragraph newParagraph = new Paragraph(content);
+ thisBlock.add(newParagraph);
+ }
+
+ /**
+ * Thêm một bảng vào document
+ * @param header tiêu đề của bảng
+ * @param columns danh sách tiêu đề của các cột
+ * @param datas một list 2 chiều lưu giữ data theo từng hàng
+ */
+ public void writeTable(String header, List columns, List> datas) {
+ //Thiết lập định dạng và nội dung cho header dưới dạng 1 section
+ Font headerFont = FontFactory.getFont(FontFactory.TIMES_ROMAN, 15, Font.BOLDITALIC);
+ Paragraph headerOfSection = new Paragraph(header, headerFont);
+ Section thisBlock = allElements.addSection(headerOfSection);
+ thisBlock.setNumberDepth(0);
+ //Thêm một bảng
+ int numCols = columns.size();
+ PdfPTable table = new PdfPTable(numCols);
+ table.setSpacingBefore(25);
+ table.setSpacingAfter(25);
+ //Thêm các cột
+ for (String column: columns) {
+ Font columnHeaderFont = FontFactory.getFont(FontFactory.TIMES_ROMAN, 13, Font.BOLD);
+ PdfPCell newCell = new PdfPCell(new Phrase(column, columnHeaderFont));
+ table.addCell(newCell);
+ }
+ //Tìm số hàng cần thiết
+ int numRows = datas.size();
+ //Duyệt từng hàng để thêm dữ liệu, nếu có một cột bị hết dữ liệu thì sẽ thêm chuỗi rỗng
+ for (int i = 0; i < numRows; i++) {
+ for (int j = 0; j < numCols; j++) {
+ try {
+ table.addCell(datas.get(i).get(j));
+ } catch (IndexOutOfBoundsException e) {
+ table.addCell("");
+ }
+ }
+ }
+ thisBlock.add(table);
+ }
+
+ /**
+ * Kết thúc việc ghi dữ liệu ra file .pdf. Bạn phải gọi phương thức này
+ * để việc ghi dữ liệu được hoàn tất, nếu không, có thể dẫn tới trường
+ * hợp không được ghi thành công.
+ * @return {@code true} nếu quá trình ghi dữ liệu được hoàn thành,
+ * {@code false} nếu ngược lại
+ */
+ public boolean endWrite() {
+ try {
+ document.add(allElements);
+ document.close();
+ return true;
+ } catch (DocumentException e) {
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/com/noteapp/note/service/io/PdfIOService.java b/src/main/java/com/noteapp/note/service/io/PdfIOService.java
new file mode 100644
index 0000000..7e8c25e
--- /dev/null
+++ b/src/main/java/com/noteapp/note/service/io/PdfIOService.java
@@ -0,0 +1,152 @@
+package com.noteapp.note.service.io;
+
+import com.itextpdf.text.DocumentException;
+import com.noteapp.note.model.Note;
+import com.noteapp.note.model.NoteBlock;
+import com.noteapp.note.model.ShareNote;
+import com.noteapp.note.model.SurveyBlock;
+import com.noteapp.note.model.TextBlock;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @author admin
+ */
+public class PdfIOService implements FileIOService {
+ private PdfImportService importService;
+ private PdfExportService exportService;
+
+ @Override
+ public Note importNote(String inputFileDir) throws IOException {
+ //Khởi tạo import service
+ importService = new PdfImportService(inputFileDir);
+ //Tạo note và đọc header, đọc mỗi page để lấy dữ liệu
+ Note note = new Note();
+ note.setHeader(inputFileDir);
+ List blocks = importService.readTextEachPage();
+ //Lấy mỗi block là dữ liệu ở một page và thêm vào Note
+ for (int i = 0; i < blocks.size(); i++) {
+ TextBlock newTextBlock = new TextBlock();
+ newTextBlock.setOrder(i + 1);
+ newTextBlock.setHeader("page " + String.valueOf(i + 1));
+ newTextBlock.setContent(blocks.get(i));
+ note.getBlocks().add(newTextBlock);
+ }
+ return note;
+ }
+
+ @Override
+ public void outputNote(String outputFileDir, Note outputNote) throws IOException {
+ //Khởi tạo export service
+ try {
+ exportService = new PdfExportService(outputFileDir, outputNote.getHeader());
+ //Thực hiện duyệt các block và lưu trữ dạng dữ liệu tương ứng
+ for (NoteBlock block: outputNote.getBlocks()) {
+ if (block.getBlockType() == NoteBlock.BlockType.TEXT) {
+ exportService.writeText(block.getHeader(), ((TextBlock) block).getContent());
+ } else {
+ List columns = new ArrayList<>();
+ columns.add("choice");
+ columns.add("your vote");
+ List> datas = getTableDataFromSurvey(((SurveyBlock) block));
+ exportService.writeTable(block.getHeader(), columns, datas);
+ }
+ }
+ exportService.endWrite();
+ } catch (DocumentException ex) {
+ throw new IOException(ex.getCause());
+ }
+ }
+
+ @Override
+ public void outputNote(String outputFileDir, ShareNote outputNote) throws IOException {
+ //Khởi tạo export service
+ try {
+ exportService = new PdfExportService(outputFileDir, outputNote.getHeader());
+ //Thực hiện duyệt các block và lưu trữ dạng dữ liệu tương ứng
+ for (NoteBlock block: outputNote.getBlocks()) {
+ if (block.getBlockType() == NoteBlock.BlockType.TEXT) {
+ exportService.writeText(block.getHeader(), ((TextBlock) block).getContent());
+ } else {
+ List columns = new ArrayList<>();
+ columns.add("choice");
+ columns.add("your vote");
+ columns.add("total vote");
+ columns.add("other vote");
+ List> datas = getTableDataFromSurvey((SurveyBlock) block, outputNote.getOtherEditorBlocks());
+ exportService.writeTable(block.getHeader(), columns, datas);
+ }
+ }
+ exportService.endWrite();
+ } catch (DocumentException ex) {
+ throw new IOException(ex.getCause());
+ }
+ }
+
+ protected List> getTableDataFromSurvey(SurveyBlock surveyBlock) {
+ List> datas = new ArrayList<>();
+ for (Map.Entry entry: surveyBlock.getSurveyMap().entrySet()) {
+ List newRow = new ArrayList<>();
+ newRow.add(entry.getKey());
+ newRow.add(String.valueOf(entry.getValue()));
+ datas.add(newRow);
+ }
+ return datas;
+ }
+
+ protected List> getTableDataFromSurvey(SurveyBlock surveyBlock, Map> otherEditors) {
+ List> datas = new ArrayList<>();
+ for (Map.Entry entry: surveyBlock.getSurveyMap().entrySet()) {
+ //Lấy choice và your vote
+ List newRow = new ArrayList<>();
+ String choice = entry.getKey();
+ boolean isVoted = entry.getValue();
+ int numVoted = 0;
+ newRow.add(choice);
+
+ if (isVoted) {
+ newRow.add("yes");
+ numVoted += 1;
+ } else {
+ newRow.add("no");
+ }
+ //Lấy số lượng và vote của các editor khác
+ List otherSurveyBlocks = findOthersBlocks(surveyBlock, otherEditors);
+ List others = new ArrayList<>();
+ for (SurveyBlock otherSurveyBlock: otherSurveyBlocks) {
+ if (otherSurveyBlock.getSurveyMap().get(choice)) {
+ numVoted += 1;
+ others.add(otherSurveyBlock.getEditor());
+ }
+ }
+
+ newRow.add(String.valueOf(numVoted));
+ newRow.add(convertOthers(others));
+
+ datas.add(newRow);
+ }
+ return datas;
+ }
+
+ protected String convertOthers(List others) {
+ String otherStr = "";
+ for (String otherVoted: others) {
+ otherStr += otherVoted + ", ";
+ }
+ return otherStr;
+ }
+
+ protected List findOthersBlocks(NoteBlock noteBlock, Map> otherEditors) {
+ List res = new ArrayList<>();
+ if (noteBlock.getBlockType() == NoteBlock.BlockType.TEXT) {
+ return res;
+ }
+ for (NoteBlock block: otherEditors.get(noteBlock.getId())) {
+ res.add((SurveyBlock) block);
+ }
+ return res;
+ }
+}
diff --git a/src/main/java/com/noteapp/note/service/io/PdfImportService.java b/src/main/java/com/noteapp/note/service/io/PdfImportService.java
new file mode 100644
index 0000000..c805453
--- /dev/null
+++ b/src/main/java/com/noteapp/note/service/io/PdfImportService.java
@@ -0,0 +1,62 @@
+package com.noteapp.note.service.io;
+
+import com.itextpdf.text.pdf.PdfReader;
+import com.itextpdf.text.pdf.parser.PdfTextExtractor;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author admin
+ */
+public class PdfImportService {
+ private final PdfReader pdfReader;
+
+ /**
+ * Khởi tạo một service đọc file .pdf bằng api của itextpdf
+ * @param inputFileDir Đường dẫn tới file cần đọc
+ * @throws IOException Khi file không tồn tại hoặc việc đọc file bị lỗi
+ */
+ public PdfImportService(String inputFileDir) throws IOException {
+ this.pdfReader = new PdfReader(inputFileDir);
+ }
+
+ /**
+ * Đọc dữ liệu dạng văn bản từ file .pdf ở một trang xác định
+ * @param page số thứ tự của trang cần đọc
+ * @return Dữ liệu dạng văn bản được đọc trong trang này
+ * @throws IOException nếu việc đọc dữ liệu bị lỗi
+ */
+ public String readTextAtPage(int page) throws IOException {
+ return PdfTextExtractor.getTextFromPage(pdfReader, page);
+ }
+
+ /**
+ * Đọc dữ liệu dạng văn bản từ file .pdf
+ * @return Dữ liệu dạng văn bản được đọc
+ * @throws IOException nếu việc đọc dữ liệu bị lỗi
+ */
+ public String readText() throws IOException {
+ int numOfPages = pdfReader.getNumberOfPages();
+ String res = "";
+ for (int i = 1; i <= numOfPages; i++) {
+ res += readTextAtPage(i);
+ }
+ return res;
+ }
+
+ /**
+ * Đọc dữ liệu dạng văn bản từ file .pdf
+ * @return Trả về một List lưu giữ dữ liệu ở mỗi trang
+ * @throws IOException nếu việc đọc dữ liệu bị lỗi
+ */
+ public List readTextEachPage() throws IOException {
+ int numOfPages = pdfReader.getNumberOfPages();
+ List res = new ArrayList<>();
+ for (int i = 1; i <= numOfPages; i++) {
+ res.add(readTextAtPage(i));
+ }
+ return res;
+ }
+}
diff --git a/src/main/java/com/noteapp/user/service/AdminService.java b/src/main/java/com/noteapp/user/service/AdminService.java
new file mode 100644
index 0000000..61b5afb
--- /dev/null
+++ b/src/main/java/com/noteapp/user/service/AdminService.java
@@ -0,0 +1,99 @@
+package com.noteapp.user.service;
+
+import com.noteapp.common.dao.DAOException;
+import com.noteapp.common.dao.NotExistDataException;
+import com.noteapp.common.service.CausedBySystemException;
+import com.noteapp.common.service.CausedByUserException;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.user.dao.IAdminDAO;
+import com.noteapp.user.dao.IUserDAO;
+import com.noteapp.user.model.Admin;
+import com.noteapp.user.model.User;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @author admin
+ */
+public class AdminService implements IAdminService {
+ protected IUserDAO userDAO;
+ protected IAdminDAO adminDAO;
+
+ public AdminService(IUserDAO userDAO, IAdminDAO adminDAO) {
+ this.userDAO = userDAO;
+ this.adminDAO = adminDAO;
+ }
+
+ public void setUserDAO(IUserDAO userDAO) {
+ this.userDAO = userDAO;
+ }
+
+ public void setAdminDAO(IAdminDAO adminDAO) {
+ this.adminDAO = adminDAO;
+ }
+
+ private void checkNullDAO() throws NoteAppServiceException {
+ if (adminDAO == null || userDAO == null) {
+ throw new CausedBySystemException("DAO is null!");
+ }
+ }
+
+ @Override
+ public boolean isAdmin(String username) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ adminDAO.get(username);
+ return true;
+ } catch (NotExistDataException ex1) {
+ return false;
+ } catch (DAOException ex2) {
+ throw new CausedBySystemException(ex2.getMessage(), ex2.getCause());
+ }
+ }
+
+ @Override
+ public Admin checkAdmin(String username, String password) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ //Lấy tài khoản
+ Admin admin = adminDAO.get(username);
+ //Kiểm tra mật khẩu
+ if(password.equals(admin.getPassword())) {
+ return admin;
+ } else {
+ throw new CausedByUserException("Password is false!");
+ }
+ } catch (DAOException exByGet) {
+ throw new CausedBySystemException(exByGet.getMessage(), exByGet.getCause());
+ }
+ }
+
+ @Override
+ public Map getAllLockedStatus() throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ List users = userDAO.getAll();
+ Map lockedStatus = new HashMap<>();
+ for (User user: users) {
+ lockedStatus.put(user.getUsername(), user.isLocked());
+ }
+ return lockedStatus;
+ } catch (DAOException ex) {
+ throw new CausedBySystemException(ex.getMessage(), ex.getCause());
+ }
+ }
+
+ @Override
+ public void updateLockedStatus(String username, boolean lockedStatus) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ User user = userDAO.get(username);
+ user.setLocked(lockedStatus);
+ userDAO.update(user);
+ } catch (DAOException ex) {
+ throw new CausedBySystemException(ex.getMessage(), ex.getCause());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/noteapp/user/service/IAdminService.java b/src/main/java/com/noteapp/user/service/IAdminService.java
new file mode 100644
index 0000000..a016186
--- /dev/null
+++ b/src/main/java/com/noteapp/user/service/IAdminService.java
@@ -0,0 +1,47 @@
+package com.noteapp.user.service;
+
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.user.model.Admin;
+import java.util.Map;
+
+/**
+ *
+ * @author admin
+ */
+public interface IAdminService {
+
+ /**
+ * Kiểm tra xem một tên đăng nhập có phải là admin hay không
+ * @param username username cần kiểm tra
+ * @return {@code true} nếu đây là một {@link Admin}, {@code false} nếu ngược lại
+ * @throws NoteAppServiceException Xảy ra khi các câu lệnh không thể
+ * thực hiện do kết nối tới CSDL
+ */
+ public boolean isAdmin(String username) throws NoteAppServiceException;
+
+ /**
+ * Kiểm tra tài khoản và mật khẩu để đăng nhập
+ * @param username username được nhập
+ * @param password password được nhập
+ * @return Các thông tin của Admin nếu tài khoản và mật khẩu đúng
+ * @throws NoteAppServiceException Xảy ra khi (1) Admin không tồn tại,
+ * (2) password sai, (3) Việc thực thi các câu lệnh lỗi
+ */
+ Admin checkAdmin(String username, String password) throws NoteAppServiceException;
+
+ /**
+ * Lất tất cả các thông tin bị khóa quyền hay không của các user
+ * @return Một Map chứa username và trạng thái khóa tương ứng của
+ * các {@link User}
+ * @throws NoteAppServiceException Xảy ra khi các câu lệnh bị lỗi
+ */
+ public Map getAllLockedStatus() throws NoteAppServiceException;
+
+ /**
+ * Cập nhật trạng thái khóa của một user
+ * @param username username của {@link User} cần cập nhật
+ * @param lockedStatus trạng thái khóa cần cập nhật của User
+ * @throws NoteAppServiceException Xảy ra khi các câu lệnh bị lỗi
+ */
+ void updateLockedStatus(String username, boolean lockedStatus) throws NoteAppServiceException;
+}
diff --git a/src/main/java/com/noteapp/user/service/IUserService.java b/src/main/java/com/noteapp/user/service/IUserService.java
new file mode 100644
index 0000000..e84c185
--- /dev/null
+++ b/src/main/java/com/noteapp/user/service/IUserService.java
@@ -0,0 +1,66 @@
+package com.noteapp.user.service;
+
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.user.model.Email;
+import com.noteapp.user.model.User;
+
+/**
+ *
+ * @author admin
+ */
+public interface IUserService {
+
+ boolean isUser(String username) throws NoteAppServiceException;
+
+ /**
+ * Tạo một {@link User} mới và lưu và CSDL, đồng thời trả lại User vừa tạo
+ * @param newUser User cần tạo
+ * @return User được tạo thành công.
+ * @throws NoteAppServiceException Xảy ra khi (1) User đã tồn tại,
+ * (2) Các câu lệnh không thể thực hiện do kết nối tới CSDL
+ */
+ User create(User newUser) throws NoteAppServiceException;
+
+ /**
+ * Kiểm tra tài khoản và mật khẩu để đăng nhập
+ * @param username username được nhập
+ * @param password password được nhập
+ * @return Các thông tin của User nếu tài khoản và mật khẩu đúng
+ * @throws NoteAppServiceException Xảy ra khi (1) User không tồn tại,
+ * (2) password sai, (3) Việc thực thi các câu lệnh lỗi
+ */
+ User checkUser(String username, String password) throws NoteAppServiceException;
+
+ /**
+ * Kiểm tra xem một user có bị khóa quyền không?
+ * @param username username của {@link User} cần kiểm tra
+ * @return {@code true} nếu User này bị khóa, {@code false} nếu ngược lại
+ * @throws NoteAppServiceException Xảy ra khi các câu lệnh bị lỗi
+ */
+ boolean checkLocked(String username) throws NoteAppServiceException;
+
+ /**
+ * Cập nhật mật khẩu của User
+ * @param username username của user
+ * @param newPassword password mới của user
+ * @throws NoteAppServiceException Xảy ra khi (1) User không tồn tại,
+ * (2) Các câu lệnh bị lỗi
+ */
+ void updatePassword(String username, String newPassword) throws NoteAppServiceException;
+
+ /**
+ * Cập nhật các thông tin của user
+ * @param user User cần cập nhật
+ * @return User sau khi cập nhật
+ * @throws NoteAppServiceException Xảy ra khi câu lệnh hoặc kết nối bị lỗi
+ */
+ User update(User user) throws NoteAppServiceException;
+
+ /**
+ * Lấy địa chỉ email xác thực của User
+ * @param username username của User cần lấy
+ * @return Một {@link Email} chứa địa chỉ email xác thực của User
+ * @throws NoteAppServiceException Xảy ra khi không thể lấy dữ liệu của User
+ */
+ Email getVerificationEmail(String username) throws NoteAppServiceException;
+}
diff --git a/src/main/java/com/noteapp/user/service/UserService.java b/src/main/java/com/noteapp/user/service/UserService.java
new file mode 100644
index 0000000..6543b1e
--- /dev/null
+++ b/src/main/java/com/noteapp/user/service/UserService.java
@@ -0,0 +1,132 @@
+package com.noteapp.user.service;
+
+import com.noteapp.common.dao.DAOException;
+import com.noteapp.common.dao.NotExistDataException;
+import com.noteapp.common.service.CausedBySystemException;
+import com.noteapp.common.service.CausedByUserException;
+import com.noteapp.common.service.NoteAppServiceException;
+import com.noteapp.user.dao.IUserDAO;
+import com.noteapp.user.model.Email;
+import com.noteapp.user.model.User;
+
+/**
+ * Cung cấp các service liên quan tới User
+ * @author Nhóm 17
+ * @see IUserDAO
+ * @see User
+ */
+public class UserService implements IUserService {
+ protected IUserDAO userDAO;
+
+ public UserService(IUserDAO userDAO) {
+ this.userDAO = userDAO;
+ }
+
+ public void setUserDAO(IUserDAO userDAO) {
+ this.userDAO = userDAO;
+ }
+
+ private void checkNullDAO() throws NoteAppServiceException {
+ if (userDAO == null) {
+ throw new CausedBySystemException("DAO is null!");
+ }
+ }
+
+ @Override
+ public boolean isUser(String username) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ userDAO.get(username);
+ return true;
+ } catch (NotExistDataException ex1) {
+ return false;
+ } catch (DAOException ex2) {
+ throw new CausedBySystemException(ex2.getMessage(), ex2.getCause());
+ }
+ }
+
+ @Override
+ public User create(User newUser) throws NoteAppServiceException {
+ checkNullDAO();
+ String username = newUser.getUsername();
+ //Kiểm tra đã tồn tại user hay chưa
+ try {
+ userDAO.get(username);
+ throw new CausedByUserException("This user is already exist!");
+ } catch (NotExistDataException nedExForGet) {
+ //Nếu chưa thì tiếp tục
+ } catch (DAOException exByGet) {
+ throw new CausedBySystemException(exByGet.getMessage(), exByGet.getCause());
+ }
+ //Tạo User mới và trả về
+ try {
+ return userDAO.create(newUser);
+ } catch (DAOException exByCreate) {
+ throw new CausedBySystemException(exByCreate.getMessage());
+ }
+ }
+
+ @Override
+ public User checkUser(String username, String password) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ //Lấy tài khoản
+ User user = userDAO.get(username);
+ //Kiểm tra mật khẩu
+ if(password.equals(user.getPassword())) {
+ return user;
+ } else {
+ throw new CausedByUserException("Password is false!");
+ }
+ } catch (DAOException exByGet) {
+ throw new CausedBySystemException(exByGet.getMessage(), exByGet.getCause());
+ }
+ }
+
+ @Override
+ public boolean checkLocked(String username) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ //Lấy tài khoản
+ User user = userDAO.get(username);
+ //Kiểm tra mật khẩu
+ return user.isLocked();
+ } catch (DAOException exByGet) {
+ throw new CausedBySystemException(exByGet.getMessage(), exByGet.getCause());
+ }
+ }
+
+ @Override
+ public void updatePassword(String username, String newPassword) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ User user = userDAO.get(username);
+ user.setPassword(newPassword);
+ userDAO.update(user);
+ } catch (DAOException ex) {
+ throw new CausedBySystemException(ex.getMessage(), ex.getCause());
+ }
+ }
+
+ @Override
+ public User update(User user) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ userDAO.update(user);
+ return user;
+ } catch (DAOException exByUpdate) {
+ throw new CausedBySystemException(exByUpdate.getMessage());
+ }
+ }
+
+ @Override
+ public Email getVerificationEmail(String username) throws NoteAppServiceException {
+ checkNullDAO();
+ try {
+ User user = userDAO.get(username);
+ return user.getEmail();
+ } catch (DAOException exByGet) {
+ throw new CausedBySystemException(exByGet.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index af66ab9..a1b08ee 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -6,6 +6,7 @@
requires com.mailjet.api;
requires org.json;
requires okhttp3;
+ requires itextpdf;
opens com.noteapp to javafx.fxml;
exports com.noteapp;
diff --git a/src/main/resources/com/noteapp/view/EditNoteView.fxml b/src/main/resources/com/noteapp/view/EditNoteView.fxml
new file mode 100644
index 0000000..dfe0b33
--- /dev/null
+++ b/src/main/resources/com/noteapp/view/EditNoteView.fxml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/com/noteapp/view/TextBlockView.fxml b/src/main/resources/com/noteapp/view/TextBlockView.fxml
new file mode 100644
index 0000000..80400a1
--- /dev/null
+++ b/src/main/resources/com/noteapp/view/TextBlockView.fxml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/target/classes/com/noteapp/common/service/CausedBySystemException.class b/target/classes/com/noteapp/common/service/CausedBySystemException.class
new file mode 100644
index 0000000..7e28083
Binary files /dev/null and b/target/classes/com/noteapp/common/service/CausedBySystemException.class differ
diff --git a/target/classes/com/noteapp/common/service/CausedByUserException.class b/target/classes/com/noteapp/common/service/CausedByUserException.class
new file mode 100644
index 0000000..7e3d95c
Binary files /dev/null and b/target/classes/com/noteapp/common/service/CausedByUserException.class differ
diff --git a/target/classes/com/noteapp/common/service/NoteAppService.class b/target/classes/com/noteapp/common/service/NoteAppService.class
new file mode 100644
index 0000000..47a1a3f
Binary files /dev/null and b/target/classes/com/noteapp/common/service/NoteAppService.class differ
diff --git a/target/classes/com/noteapp/common/service/NoteAppServiceException.class b/target/classes/com/noteapp/common/service/NoteAppServiceException.class
new file mode 100644
index 0000000..5f9610b
Binary files /dev/null and b/target/classes/com/noteapp/common/service/NoteAppServiceException.class differ
diff --git a/target/classes/com/noteapp/controller/AdminDashboardController.class b/target/classes/com/noteapp/controller/AdminDashboardController.class
new file mode 100644
index 0000000..0448c5e
Binary files /dev/null and b/target/classes/com/noteapp/controller/AdminDashboardController.class differ
diff --git a/target/classes/com/noteapp/controller/DashboardController$1.class b/target/classes/com/noteapp/controller/DashboardController$1.class
new file mode 100644
index 0000000..f6e0bf4
Binary files /dev/null and b/target/classes/com/noteapp/controller/DashboardController$1.class differ
diff --git a/target/classes/com/noteapp/controller/DashboardController.class b/target/classes/com/noteapp/controller/DashboardController.class
new file mode 100644
index 0000000..46b57ab
Binary files /dev/null and b/target/classes/com/noteapp/controller/DashboardController.class differ
diff --git a/target/classes/com/noteapp/controller/EditNoteController.class b/target/classes/com/noteapp/controller/EditNoteController.class
new file mode 100644
index 0000000..73b71bd
Binary files /dev/null and b/target/classes/com/noteapp/controller/EditNoteController.class differ
diff --git a/target/classes/com/noteapp/controller/EditShareNoteController$1.class b/target/classes/com/noteapp/controller/EditShareNoteController$1.class
new file mode 100644
index 0000000..dc77e51
Binary files /dev/null and b/target/classes/com/noteapp/controller/EditShareNoteController$1.class differ
diff --git a/target/classes/com/noteapp/controller/EditShareNoteController.class b/target/classes/com/noteapp/controller/EditShareNoteController.class
new file mode 100644
index 0000000..249717d
Binary files /dev/null and b/target/classes/com/noteapp/controller/EditShareNoteController.class differ
diff --git a/target/classes/com/noteapp/controller/LoginController.class b/target/classes/com/noteapp/controller/LoginController.class
new file mode 100644
index 0000000..6ff3054
Binary files /dev/null and b/target/classes/com/noteapp/controller/LoginController.class differ
diff --git a/target/classes/com/noteapp/controller/RegisterController$1.class b/target/classes/com/noteapp/controller/RegisterController$1.class
new file mode 100644
index 0000000..9c694f8
Binary files /dev/null and b/target/classes/com/noteapp/controller/RegisterController$1.class differ
diff --git a/target/classes/com/noteapp/controller/RegisterController.class b/target/classes/com/noteapp/controller/RegisterController.class
new file mode 100644
index 0000000..9df055e
Binary files /dev/null and b/target/classes/com/noteapp/controller/RegisterController.class differ
diff --git a/target/classes/com/noteapp/controller/ResetPasswordController$1.class b/target/classes/com/noteapp/controller/ResetPasswordController$1.class
new file mode 100644
index 0000000..782ce6e
Binary files /dev/null and b/target/classes/com/noteapp/controller/ResetPasswordController$1.class differ
diff --git a/target/classes/com/noteapp/controller/ResetPasswordController.class b/target/classes/com/noteapp/controller/ResetPasswordController.class
new file mode 100644
index 0000000..e7b162b
Binary files /dev/null and b/target/classes/com/noteapp/controller/ResetPasswordController.class differ
diff --git a/target/classes/com/noteapp/controller/SurveyBlockController.class b/target/classes/com/noteapp/controller/SurveyBlockController.class
new file mode 100644
index 0000000..5f1b0cc
Binary files /dev/null and b/target/classes/com/noteapp/controller/SurveyBlockController.class differ
diff --git a/target/classes/com/noteapp/note/service/INoteService.class b/target/classes/com/noteapp/note/service/INoteService.class
new file mode 100644
index 0000000..935e27b
Binary files /dev/null and b/target/classes/com/noteapp/note/service/INoteService.class differ
diff --git a/target/classes/com/noteapp/note/service/IShareNoteService.class b/target/classes/com/noteapp/note/service/IShareNoteService.class
new file mode 100644
index 0000000..66aacf6
Binary files /dev/null and b/target/classes/com/noteapp/note/service/IShareNoteService.class differ
diff --git a/target/classes/com/noteapp/note/service/NoteService.class b/target/classes/com/noteapp/note/service/NoteService.class
new file mode 100644
index 0000000..399388d
Binary files /dev/null and b/target/classes/com/noteapp/note/service/NoteService.class differ
diff --git a/target/classes/com/noteapp/note/service/ShareNoteService.class b/target/classes/com/noteapp/note/service/ShareNoteService.class
new file mode 100644
index 0000000..99c026d
Binary files /dev/null and b/target/classes/com/noteapp/note/service/ShareNoteService.class differ
diff --git a/target/classes/com/noteapp/note/service/SupportedNoteBlockService$1.class b/target/classes/com/noteapp/note/service/SupportedNoteBlockService$1.class
new file mode 100644
index 0000000..cabffe1
Binary files /dev/null and b/target/classes/com/noteapp/note/service/SupportedNoteBlockService$1.class differ
diff --git a/target/classes/com/noteapp/note/service/SupportedNoteBlockService.class b/target/classes/com/noteapp/note/service/SupportedNoteBlockService.class
new file mode 100644
index 0000000..e01d35b
Binary files /dev/null and b/target/classes/com/noteapp/note/service/SupportedNoteBlockService.class differ
diff --git a/target/classes/com/noteapp/note/service/io/FileIOService.class b/target/classes/com/noteapp/note/service/io/FileIOService.class
new file mode 100644
index 0000000..e84b279
Binary files /dev/null and b/target/classes/com/noteapp/note/service/io/FileIOService.class differ
diff --git a/target/classes/com/noteapp/note/service/io/PdfExportService.class b/target/classes/com/noteapp/note/service/io/PdfExportService.class
new file mode 100644
index 0000000..a79c074
Binary files /dev/null and b/target/classes/com/noteapp/note/service/io/PdfExportService.class differ
diff --git a/target/classes/com/noteapp/note/service/io/PdfIOService.class b/target/classes/com/noteapp/note/service/io/PdfIOService.class
new file mode 100644
index 0000000..ea33d05
Binary files /dev/null and b/target/classes/com/noteapp/note/service/io/PdfIOService.class differ
diff --git a/target/classes/com/noteapp/note/service/io/PdfImportService.class b/target/classes/com/noteapp/note/service/io/PdfImportService.class
new file mode 100644
index 0000000..6c59dba
Binary files /dev/null and b/target/classes/com/noteapp/note/service/io/PdfImportService.class differ
diff --git a/target/classes/com/noteapp/user/service/AdminService.class b/target/classes/com/noteapp/user/service/AdminService.class
new file mode 100644
index 0000000..273b55c
Binary files /dev/null and b/target/classes/com/noteapp/user/service/AdminService.class differ
diff --git a/target/classes/com/noteapp/user/service/IAdminService.class b/target/classes/com/noteapp/user/service/IAdminService.class
new file mode 100644
index 0000000..f40a58c
Binary files /dev/null and b/target/classes/com/noteapp/user/service/IAdminService.class differ
diff --git a/target/classes/com/noteapp/user/service/IUserService.class b/target/classes/com/noteapp/user/service/IUserService.class
new file mode 100644
index 0000000..eb111b1
Binary files /dev/null and b/target/classes/com/noteapp/user/service/IUserService.class differ
diff --git a/target/classes/com/noteapp/user/service/UserService.class b/target/classes/com/noteapp/user/service/UserService.class
new file mode 100644
index 0000000..b0551a4
Binary files /dev/null and b/target/classes/com/noteapp/user/service/UserService.class differ
diff --git a/target/classes/com/noteapp/view/EditNoteView.fxml b/target/classes/com/noteapp/view/EditNoteView.fxml
new file mode 100644
index 0000000..dfe0b33
--- /dev/null
+++ b/target/classes/com/noteapp/view/EditNoteView.fxml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/target/classes/com/noteapp/view/TextBlockView.fxml b/target/classes/com/noteapp/view/TextBlockView.fxml
new file mode 100644
index 0000000..80400a1
--- /dev/null
+++ b/target/classes/com/noteapp/view/TextBlockView.fxml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
index 7d9f81e..a78d1dc 100644
--- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
+++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
@@ -4,12 +4,22 @@ com\noteapp\controller\BlockController.class
com\noteapp\model\datatransfer\ShareNote$ShareType.class
com\noteapp\model\datatransfer\ShareNote.class
com\noteapp\controller\RegisterController.class
+<<<<<<< Updated upstream
com\noteapp\dataaccess\ShareNoteDataAccess.class
+=======
+com\noteapp\user\service\security\MailjetSevice.class
+com\noteapp\note\model\NoteBlock$BlockType.class
+com\noteapp\user\dao\AdminDAO.class
+com\noteapp\common\dao\sql\ISQLReader.class
+com\noteapp\note\model\ShareNote.class
+com\noteapp\common\dao\DAOException.class
+>>>>>>> Stashed changes
com\noteapp\controller\Controller.class
com\noteapp\controller\NoteFiltersController.class
com\noteapp\model\datatransfer\User.class
com\noteapp\NoteLite.class
com\noteapp\controller\LoginController.class
+<<<<<<< Updated upstream
com\noteapp\dataaccess\ShareNoteDataAccess$SingletonHelper.class
com\noteapp\model\datatransfer\BaseDataTransferModel.class
com\noteapp\dataaccess\connection\DatabaseConnection.class
@@ -63,4 +73,99 @@ com\noteapp\dataaccess\NoteBlockDataAccess.class
com\noteapp\model\datatransfer\NoteFilter.class
com\noteapp\dataaccess\NoteDataAccess.class
com\noteapp\dataaccess\NotExistDataException.class
+=======
+com\noteapp\note\dao\NoteFilterDAO.class
+com\noteapp\note\service\io\PdfImportService.class
+com\noteapp\note\service\ShareNoteService.class
+com\noteapp\controller\EditShareNoteController.class
+com\noteapp\user\dao\IAdminDAO.class
+com\noteapp\user\model\User.class
+com\noteapp\note\service\SupportedNoteBlockService$1.class
+com\noteapp\user\model\Email.class
+com\noteapp\user\service\security\SixNumCodeGenerator.class
+com\noteapp\user\dao\UserDAO$SingletonHelper.class
+com\noteapp\common\dao\NotExistDataException.class
+com\noteapp\note\dao\TextBlockDAO$QueriesType.class
+com\noteapp\controller\RegisterController$1.class
+com\noteapp\common\service\NoteAppServiceException.class
+com\noteapp\note\dao\INoteBlockDAO.class
+com\noteapp\note\dao\NoteDAO$SingletonHelper.class
+com\noteapp\note\service\INoteService.class
+com\noteapp\common\dao\FailedExecuteException.class
+com\noteapp\controller\ResetPasswordController$1.class
+com\noteapp\user\service\AdminService.class
+com\noteapp\NoteApp.class
+module-info.class
+com\noteapp\note\dao\SurveyBlockDAO$SingletonHelper.class
+com\noteapp\user\dao\AbstractUserDAO.class
+com\noteapp\note\service\SupportedNoteBlockService.class
+com\noteapp\common\dao\BasicDAO.class
+com\noteapp\note\dao\TextBlockDAO$SingletonHelper.class
+com\noteapp\note\dao\ShareNoteDAO$SingletonHelper.class
+com\noteapp\note\dao\NoteFilterDAO$SingletonHelper.class
+com\noteapp\user\dao\UserDAO$ColumnName.class
+com\noteapp\user\service\security\VerificationMailService.class
+com\noteapp\note\model\TextBlock.class
+com\noteapp\common\service\CausedBySystemException.class
+com\noteapp\controller\AdminDashboardController.class
+com\noteapp\note\dao\IShareNoteDAO.class
+com\noteapp\note\dao\AbstractNoteDAO.class
+com\noteapp\controller\RecentlyNoteCardController.class
+com\noteapp\user\model\Admin.class
+com\noteapp\note\model\NoteBlock.class
+com\noteapp\user\service\UserService.class
+com\noteapp\user\model\AbstractUser.class
+com\noteapp\controller\DashboardController$1.class
+com\noteapp\note\dao\TextBlockDAO.class
+com\noteapp\controller\TextBlockController.class
+com\noteapp\note\dao\NoteFilterDAO$QueriesType.class
+com\noteapp\controller\InitableController.class
+com\noteapp\user\dao\AdminDAO$ColumnName.class
+com\noteapp\note\model\SurveyBlock.class
+com\noteapp\user\service\IAdminService.class
+com\noteapp\note\service\io\FileIOService.class
+com\noteapp\note\service\IShareNoteService.class
+com\noteapp\note\dao\INoteDAO.class
+com\noteapp\note\dao\SurveyBlockDAO.class
+com\noteapp\note\dao\INoteFilterDAO.class
+com\noteapp\note\service\io\PdfIOService.class
+com\noteapp\note\dao\NoteDAO$QueriesType.class
+com\noteapp\note\dao\ShareNoteDAO$QueriesType.class
+com\noteapp\note\dao\TextBlockDAO$ColumnName.class
+com\noteapp\controller\DashboardController.class
+com\noteapp\controller\SurveyBlockController.class
+com\noteapp\note\dao\NoteBlockDAO$QueriesType.class
+com\noteapp\user\dao\AdminDAO$QueriesType.class
+com\noteapp\note\model\Note.class
+com\noteapp\common\service\CausedByUserException.class
+com\noteapp\common\dao\connection\MySQLDatabaseConnection.class
+com\noteapp\note\dao\ShareNoteDAO$ColumnName.class
+com\noteapp\note\dao\SurveyBlockDAO$QueriesType.class
+com\noteapp\note\service\io\PdfExportService.class
+com\noteapp\controller\ResetPasswordController.class
+com\noteapp\user\service\IUserService.class
+com\noteapp\note\service\NoteService.class
+com\noteapp\user\model\User$Gender.class
+com\noteapp\note\dao\NoteFilterDAO$ColumnName.class
+com\noteapp\controller\SurveyItemController.class
+com\noteapp\note\dao\NoteDAO$ColumnName.class
+com\noteapp\note\dao\SurveyBlockDAO$ColumnName.class
+com\noteapp\user\dao\UserDAO.class
+com\noteapp\common\dao\connection\SQLDatabaseConnection.class
+com\noteapp\note\model\NoteFilter.class
+com\noteapp\common\dao\DAOKeyException.class
+com\noteapp\note\model\ShareNote$ShareType.class
+com\noteapp\controller\UserItemController.class
+com\noteapp\note\dao\NoteBlockDAO.class
+com\noteapp\note\dao\NoteDAO.class
+com\noteapp\common\dao\sql\SQLReader.class
+com\noteapp\controller\EditShareNoteController$1.class
+com\noteapp\note\dao\IConcreateBlockDAO.class
+com\noteapp\note\dao\NoteBlockDAO$ColumnName.class
+com\noteapp\controller\EditNoteController.class
+com\noteapp\note\dao\NoteBlockDAO$SingletonHelper.class
+com\noteapp\user\dao\AdminDAO$SingletonHelper.class
+com\noteapp\common\service\NoteAppService.class
+com\noteapp\note\dao\ShareNoteDAO.class
+>>>>>>> Stashed changes
com\noteapp\controller\NoteCardController.class
diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
index 9bff5e3..b25911e 100644
--- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
+++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
@@ -1,3 +1,4 @@
+<<<<<<< Updated upstream
F:\NoteMaven\src\main\java\com\noteapp\App.java
F:\NoteMaven\src\main\java\com\noteapp\controller\BlockController.java
F:\NoteMaven\src\main\java\com\noteapp\dataaccess\ShareNoteDataAccess.java
@@ -49,3 +50,82 @@ F:\NoteMaven\src\main\java\com\noteapp\controller\EditNoteViewController.java
F:\NoteMaven\src\main\java\com\noteapp\model\datatransfer\NoteFilter.java
F:\NoteMaven\src\main\java\com\noteapp\service\CollectionServerService.java
F:\NoteMaven\src\main\java\com\noteapp\NoteLite.java
+=======
+F:\NoteApp\src\main\java\com\noteapp\common\dao\sql\ISQLReader.java
+F:\NoteApp\src\main\java\com\noteapp\user\service\IAdminService.java
+F:\NoteApp\src\main\java\com\noteapp\controller\OpenedNoteCardController.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\SurveyBlockDAO.java
+F:\NoteApp\src\main\java\com\noteapp\user\model\AbstractUser.java
+F:\NoteApp\src\main\java\com\noteapp\user\service\AdminService.java
+F:\NoteApp\src\main\java\com\noteapp\common\service\CausedByUserException.java
+F:\NoteApp\src\main\java\com\noteapp\controller\LoginController.java
+F:\NoteApp\src\main\java\com\noteapp\user\dao\IUserDAO.java
+F:\NoteApp\src\main\java\com\noteapp\note\model\SurveyBlock.java
+F:\NoteApp\src\main\java\com\noteapp\user\dao\AbstractUserDAO.java
+F:\NoteApp\src\main\java\com\noteapp\common\dao\sql\SQLReader.java
+F:\NoteApp\src\main\java\com\noteapp\common\service\NoteAppServiceException.java
+F:\NoteApp\src\main\java\com\noteapp\controller\EditNoteController.java
+F:\NoteApp\src\main\java\com\noteapp\note\model\Note.java
+F:\NoteApp\src\main\java\com\noteapp\user\service\security\MailService.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\NoteDAO.java
+F:\NoteApp\src\main\java\com\noteapp\common\service\NoteAppService.java
+F:\NoteApp\src\main\java\com\noteapp\user\dao\IAdminDAO.java
+F:\NoteApp\src\main\java\com\noteapp\common\service\CausedBySystemException.java
+F:\NoteApp\src\main\java\com\noteapp\controller\SurveyBlockController.java
+F:\NoteApp\src\main\java\com\noteapp\note\model\NoteFilter.java
+F:\NoteApp\src\main\java\com\noteapp\NoteApp.java
+F:\NoteApp\src\main\java\com\noteapp\common\dao\NotExistDataException.java
+F:\NoteApp\src\main\java\com\noteapp\controller\Controller.java
+F:\NoteApp\src\main\java\com\noteapp\controller\UserItemController.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\INoteFilterDAO.java
+F:\NoteApp\src\main\java\com\noteapp\user\model\Email.java
+F:\NoteApp\src\main\java\com\noteapp\controller\InitableController.java
+F:\NoteApp\src\main\java\com\noteapp\note\service\io\PdfIOService.java
+F:\NoteApp\src\main\java\com\noteapp\user\model\Admin.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\INoteDAO.java
+F:\NoteApp\src\main\java\com\noteapp\note\model\NoteBlock.java
+F:\NoteApp\src\main\java\module-info.java
+F:\NoteApp\src\main\java\com\noteapp\common\dao\DAOException.java
+F:\NoteApp\src\main\java\com\noteapp\note\service\INoteService.java
+F:\NoteApp\src\main\java\com\noteapp\note\service\SupportedNoteBlockService.java
+F:\NoteApp\src\main\java\com\noteapp\common\dao\connection\SQLDatabaseConnection.java
+F:\NoteApp\src\main\java\com\noteapp\user\service\security\VerificationCodeGenerator.java
+F:\NoteApp\src\main\java\com\noteapp\user\model\User.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\TextBlockDAO.java
+F:\NoteApp\src\main\java\com\noteapp\user\dao\UserDAO.java
+F:\NoteApp\src\main\java\com\noteapp\note\service\io\PdfImportService.java
+F:\NoteApp\src\main\java\com\noteapp\user\service\security\SixNumCodeGenerator.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\IShareNoteDAO.java
+F:\NoteApp\src\main\java\com\noteapp\common\dao\FailedExecuteException.java
+F:\NoteApp\src\main\java\com\noteapp\controller\EditShareNoteController.java
+F:\NoteApp\src\main\java\com\noteapp\controller\NoteFiltersController.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\NoteBlockDAO.java
+F:\NoteApp\src\main\java\com\noteapp\note\model\ShareNote.java
+F:\NoteApp\src\main\java\com\noteapp\user\service\UserService.java
+F:\NoteApp\src\main\java\com\noteapp\user\service\security\MailjetSevice.java
+F:\NoteApp\src\main\java\com\noteapp\controller\ResetPasswordController.java
+F:\NoteApp\src\main\java\com\noteapp\controller\RecentlyNoteCardController.java
+F:\NoteApp\src\main\java\com\noteapp\user\service\IUserService.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\AbstractNoteDAO.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\ShareNoteDAO.java
+F:\NoteApp\src\main\java\com\noteapp\controller\SurveyItemController.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\IConcreateBlockDAO.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\INoteBlockDAO.java
+F:\NoteApp\src\main\java\com\noteapp\user\service\security\VerificationMailService.java
+F:\NoteApp\src\main\java\com\noteapp\controller\TextBlockController.java
+F:\NoteApp\src\main\java\com\noteapp\note\dao\NoteFilterDAO.java
+F:\NoteApp\src\main\java\com\noteapp\common\dao\connection\MySQLDatabaseConnection.java
+F:\NoteApp\src\main\java\com\noteapp\note\service\io\PdfExportService.java
+F:\NoteApp\src\main\java\com\noteapp\controller\RegisterController.java
+F:\NoteApp\src\main\java\com\noteapp\controller\DashboardController.java
+F:\NoteApp\src\main\java\com\noteapp\note\service\ShareNoteService.java
+F:\NoteApp\src\main\java\com\noteapp\note\service\IShareNoteService.java
+F:\NoteApp\src\main\java\com\noteapp\common\dao\BasicDAO.java
+F:\NoteApp\src\main\java\com\noteapp\common\dao\DAOKeyException.java
+F:\NoteApp\src\main\java\com\noteapp\note\model\TextBlock.java
+F:\NoteApp\src\main\java\com\noteapp\controller\AdminDashboardController.java
+F:\NoteApp\src\main\java\com\noteapp\note\service\NoteService.java
+F:\NoteApp\src\main\java\com\noteapp\note\service\io\FileIOService.java
+F:\NoteApp\src\main\java\com\noteapp\user\dao\AdminDAO.java
+F:\NoteApp\src\main\java\com\noteapp\controller\NoteCardController.java
+>>>>>>> Stashed changes