diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 000000000..69d41be32 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 000000000..aa00ffab7 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 000000000..0f4669960 --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 000000000..0abcc97ca --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 8c4770018..80e0be14b 100644 --- a/README.md +++ b/README.md @@ -1,181 +1,63 @@ -# Lab 5: Logout - -## Preamble - -In the current homework, you added code to the login use case to save the currently-logged-in -user by saving the user in the Data Access Layer. You also added a unit test for this. - -In this lab, you will complete a logout use case as a team. You will also begin to discuss your project -and the use cases that need to be implemented. - -We have created all the Clean Architecture classes necessary for the logout use case. - -By Friday, your team will submit: -- your completed lab code [for credit] -- a draft of your project blueprint proposal. [required, but not for credit] - -# Phase 2 [for credit] -_(recall, Phase 1 was your solo task of adding the storage of the currently-logged-in user)_ - -## Task 0: Fork this repo on GitHub -**To get started, one team member should fork this repo on GitHub and share it with the team. -All of you should then clone it.** - -* * * - -Suggested logistics: One of you should invite the others to collaborate on their fork of the -original repo on GitHub. You can do this in your repo on GitHub under `Settings -> Collaborators`. -This will allow you to push branches to a common repo and then use pull requests to contribute -your code and review. To prevent others from pushing directly to the main branch, -we recommend you set branch protection rules on GitHub. Below are how the settings might look if you -add branch protection rules: - -![image of branch protection rules for main with the -requirement of two approvers to merge in pull requests. -](images/branch_protection_rules.png) - -* * * - -Open the project in IntelliJ and make sure you can successfully run `app/Main.java`. -Note: you may need to set the Project SDK in the `Project Structure...` menu, and possibly -also manually link the Maven project, as you did in Phase 1. - -## Task 1: Understanding the Program - -You may notice that we have refactored the CA engine code _slightly_ since Phase 1, but the -way we build the engine is drastically different: we have switched from using Factories to -using the Builder design pattern, which we'll be discussing in lecture soon. - -Open up `app.Main` and read it as a team. -- What are the Views and what are the current Use Cases? -- Which Uses Cases are triggered from each View? -- Which version of the DAO is `app.Main` using? - -The major change since Phase 1 is that we have added the `app.AppBuilder` class which makes -it easier to understand how our CA engine is being constructed — it also makes `app.Main` nice and concise! -- Why do all those `addX` methods end in `return this;`? - -Run the program and make sure the signup and login Use Cases work. - -Currently, you'll notice that the "Log Out" button still doesn't actually log you out. It's time to fix -that button, which is part of the `LoggedInView`. -We have created all the classes for you, but some of the code is missing. -As a team, your task is to fill in the missing code so that the Logout Use Case is implemented. -**The next part of the readme describes how your team will do this.** - -* * * - -**Your team will know when you are done when:** - -- Clicking the "Log Out" button takes the user back to the Login View when you use the program. -- The provided `LogoutInteractorTest` test passes. - -The "Log Out" button is an instance variable in class `LoggedInVew`. Go find it. -Also look at the `interface_adapter.change_password.LoggedInViewModel`, which contains any -data showing on the `LoggedInVew`. +# CSC207 Group Project * * * -## Task 2: Dividing up the work +## Group 108 - Translator Program -There are `TODO` comments left in the files -Recall that you can use the TODO tool window to conveniently pull up a complete list. +* * * -Once the TODOs are all complete, the "Log Out" button _should_ work! - -As a team, split up the TODOs (see below) between the members of your team. - -There are TODOs in seven of the files. -Make sure each member has at least one TODO which they will be responsible for completing. -If your team prefers to work in pairs, that is fine too. Your individual branches -will not be graded for this — only the final, working version. - -The TODOs are summarized below (by file) to help your team decide how to split them up: +**Team Members:** +- Sean Yin (GitHub Username: PikachuSean) +- Haoxuan Qiu (GitHub Username: Kaguya-kyuu) +- Doran Wang (GitHub Username: Wang20030509) +- Charles Cai (GitHub Username: charles0504) * * * -- `Main.java` +**Domain:** Translation generation and management - - [ ] TODO: add the Logout Use Case to the app using the appBuilder +**Software Specification:** +The program allows users to translate between several languages. Users can create and sign in to accounts, allowing users to bookmark translations and view their translation history. Users can submit feedback on translations they think are inaccurate and can suggest a better translation. -* * * +**User Stories:** +1. Bob creates and signs in to an account for the translation app. He translates a sentence from one language to another and receives a translation from the app. (Team story) -- `LoggedInView.java` (tip: refer to the other views for similar code) +2. Bob is a student in a language class. His teacher has created a class account for all the students to use, and he wants to see the translations that his teacher displayed in class. He signs in to the class account, and he views the translation history. (Ericka) - - [ ] TODO: save the logout controller in the instance variable. - - [ ] TODO: execute the logout use case through the Controller +3. Bob is a user of the translation app. He translates a sentence from one language to another. He finds the translation inaccurate and decides to submit a suggestion for a better translation. After some time, the suggestion is accepted by the developers of the app and now the app displays the new suggested translation. (Sean) -* * * - -- `LogoutController.java` (tip: refer to the other controllers for similar code) +4. Bob is studying a second language. Sometimes he wants to be able to save his translation result for future review. So he decides to bookmark it so he can see it later by accessing his bookmarked translations. (Doran) - - [ ] TODO: Save the interactor in the instance variable. - - [ ] TODO: run the use case interactor for the logout use case +5. Bob is sick and tired of google translate so he decided to find a better translator. He found this amazing translator called (our app name). He finds out there is a create account/sign in function which is always ignored on translator apps. He decided to create an account and found out there are so many useful functions! He translated a long paragraph that he will be working on for a few days. Unfortunately, he forgot to bookmark it, but he looks through his translation history to find it and bookmarks it from there so he can come back to it within a few clicks. (Charles) -* * * +**Proposed Entities for the Domain:** -- `LogoutInputData.java` (should be done with the LogoutInteractor TODOs below) +Translator +- String inputLanguage +- String outputLanguage +- String inputText +- String translatedText - - [ ] TODO: save the current username in an instance variable and add a getter. +History +- User currentUser +- List translationHistory -- `LogoutInteractor.java` (tip: refer to `ChangePasswordInteractor.java` for similar code) +Bookmark +- User currentUser +- List bookmarkedTranslations - - [ ] TODO: save the DAO and Presenter in the instance variables. - - [ ] TODO: implement the logic of the Logout Use Case - -* * * - -- `LogoutOutputData.java` - - - [ ] TODO: save the parameters in the instance variables. - -* * * +User +- String username +- String password -- `LogoutPresenter.java` (tip: refer to `SignupPresenter.java` for similar code) +Feedback +- Translator wrongTranslation +- String inputFeedback - - [ ] TODO: assign to the three instance variables. - - [ ] TODO: have prepareSuccessView update the LoggedInState - - [ ] TODO: have prepareSuccessView update the LoginState - -* * * - -1. Make a branch named the first part of your UofT email address, everything before the `@`. -For example, if your email address is `paul.gries@mail.utoronto.ca`, then the branch name would -be `paul.gries`. - -Make sure you switch to the new branch. - -In the terminal, this would look like below, but replaced with your own information: -``` -git branch paul.gries -git switch paul.gries -``` - -2. Complete your assigned TODOs and make a pull request on GitHub. In your pull request, - briefly describe what your TODOs were and how you implemented them. If you aren't sure - about part of it, include this in your pull request so everyone knows what to look - for when reviewing — or you can of course discuss with your team before making your - pull request since you are physically working in the same space. - - **Important: don't push any changes to the `.idea` folder, as that - may cause issues for your other teammates, as some files contain - configurations specific to your individual IntelliJ projects.** - -3. Review each other's pull requests to ensure each TODO is correctly implemented and that - there are no Checkstyle issues in the files that were modified. - -4. Once all TODOs are completed, your team should debug as needed to ensure the - correctness of the code. Setting a breakpoint where the log-out use case - interactor starts its work will likely be a great place to start when debugging. - -And that's it; you now have a working Logout Use Case! Instructions for -how to submit your work on MarkUs will be posted later. - -Your team should spend the rest of the lab working on your project blueprint. - -* * * +**Proposed API to Use:** +https://www.deepl.com/en/docs-api -# Project Blueprint +**Scheduled Meeting Times + Mode of Communication:** -See Quercus for details about the project blueprint! By the end of the week, -the goal is for your team to have a fully drafted blueprint so that your team -will be ready to get started on your project after Reading Week. +Meeting time outside of lab: Meet on Friday afternoons +Mode of Communication: Discord group chat diff --git a/homework-5.iml b/homework-5.iml new file mode 100644 index 000000000..9e3449c9d --- /dev/null +++ b/homework-5.iml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index e5c1e881f..55bd59c12 100644 --- a/pom.xml +++ b/pom.xml @@ -33,9 +33,25 @@ 5.8.1 test + + com.deepl.api + deepl-java + 1.6.0 + - + + + + org.apache.maven.plugins + maven-compiler-plugin + + 15 + 15 + + + + @@ -44,4 +60,4 @@ UTF-8 - \ No newline at end of file + diff --git a/src/main/java/Example.java b/src/main/java/Example.java new file mode 100644 index 000000000..ddb91cd64 --- /dev/null +++ b/src/main/java/Example.java @@ -0,0 +1,24 @@ +import com.deepl.api.*; + +public class Example { + private Translator translator; + + public Example() throws Exception { + final String authKey = "59431b39-31eb-423d-9fcd-b86eb38b23e0:fx"; // Replace with your key + translator = new Translator(authKey); + final TextResult result = + translator.translateText("Hello, world!", null, "fr"); + System.out.println(result.getText()); // "Bonjour, le monde !" + } + + public static void main(String[] args) { + try { + final String authKey = "59431b39-31eb-423d-9fcd-b86eb38b23e0:fx"; // Replace with your key + final Translator translator2 = new Translator(authKey); + final TextResult result = translator2.translateText("How are you doing", null, "ja"); + System.out.println(result.getText()); + } + catch (InterruptedException e) { + } + catch (DeepLException e) {} +}} diff --git a/src/main/java/app/AppBuilder.java b/src/main/java/app/AppBuilder.java index e9eef5c81..176893385 100644 --- a/src/main/java/app/AppBuilder.java +++ b/src/main/java/app/AppBuilder.java @@ -7,12 +7,20 @@ import javax.swing.WindowConstants; import data_access.InMemoryUserDataAccessObject; +import entity.BookmarkFactory; import entity.CommonUserFactory; +import entity.TranslateFactory; import entity.UserFactory; import interface_adapter.ViewManagerModel; +import interface_adapter.bookmark.BookmarkController; +import interface_adapter.bookmark.BookmarkPresenter; +import interface_adapter.bookmark.BookmarkViewModel; import interface_adapter.change_password.ChangePasswordController; import interface_adapter.change_password.ChangePasswordPresenter; import interface_adapter.change_password.LoggedInViewModel; +import interface_adapter.history.HistoryController; +import interface_adapter.history.HistoryPresenter; +import interface_adapter.history.HistoryViewModel; import interface_adapter.login.LoginController; import interface_adapter.login.LoginPresenter; import interface_adapter.login.LoginViewModel; @@ -21,9 +29,18 @@ import interface_adapter.signup.SignupController; import interface_adapter.signup.SignupPresenter; import interface_adapter.signup.SignupViewModel; +import use_case.bookmark.BookmarkInputBoundary; +import use_case.bookmark.BookmarkInteractor; +import use_case.bookmark.BookmarkOutputBoundary; +import interface_adapter.translate.TranslateController; +import interface_adapter.translate.TranslatePresenter; +import interface_adapter.translate.TranslateViewModel; import use_case.change_password.ChangePasswordInputBoundary; import use_case.change_password.ChangePasswordInteractor; import use_case.change_password.ChangePasswordOutputBoundary; +import use_case.history.HistoryInputBoundary; +import use_case.history.HistoryInteractor; +import use_case.history.HistoryOutputBoundary; import use_case.login.LoginInputBoundary; import use_case.login.LoginInteractor; import use_case.login.LoginOutputBoundary; @@ -33,7 +50,12 @@ import use_case.signup.SignupInputBoundary; import use_case.signup.SignupInteractor; import use_case.signup.SignupOutputBoundary; -import view.LoggedInView; +import use_case.translator.TranslatorInputBoundary; +import use_case.translator.TranslatorInteractor; +import use_case.translator.TranslatorOutputBoundary; +import view.HistoryView; +import view.BookmarkView; +import view.TranslateView; import view.LoginView; import view.SignupView; import view.ViewManager; @@ -54,6 +76,7 @@ public class AppBuilder { private final CardLayout cardLayout = new CardLayout(); // thought question: is the hard dependency below a problem? private final UserFactory userFactory = new CommonUserFactory(); + private final TranslateFactory translateFactory = new TranslateFactory(); private final ViewManagerModel viewManagerModel = new ViewManagerModel(); private final ViewManager viewManager = new ViewManager(cardPanel, cardLayout, viewManagerModel); @@ -64,8 +87,13 @@ public class AppBuilder { private SignupViewModel signupViewModel; private LoginViewModel loginViewModel; private LoggedInViewModel loggedInViewModel; - private LoggedInView loggedInView; + private TranslateViewModel translateViewModel; + private TranslateView translateView; private LoginView loginView; + private HistoryViewModel historyViewModel; + private HistoryView historyView; + private BookmarkViewModel bookmarkViewModel; + private BookmarkView bookmarkView; public AppBuilder() { cardPanel.setLayout(cardLayout); @@ -97,10 +125,34 @@ public AppBuilder addLoginView() { * Adds the LoggedIn View to the application. * @return this builder */ - public AppBuilder addLoggedInView() { + public AppBuilder addTranslateView() { loggedInViewModel = new LoggedInViewModel(); - loggedInView = new LoggedInView(loggedInViewModel); - cardPanel.add(loggedInView, loggedInView.getViewName()); + translateViewModel = new TranslateViewModel(); + historyViewModel = new HistoryViewModel(); + translateView = new TranslateView(loggedInViewModel, translateViewModel, historyViewModel); + cardPanel.add(translateView, translateView.getViewName()); + return this; + } + + /** + * Adds the History View to the application. + * @return this builder + */ + public AppBuilder addHistoryView() { + historyViewModel = new HistoryViewModel(); + historyView = new HistoryView(historyViewModel); + cardPanel.add(historyView, historyView.getViewName()); + return this; + } + + /** + * Adds the Bookmark View to the application. + * @return this builder + */ + public AppBuilder addBookmarkView() { + bookmarkViewModel = new BookmarkViewModel(); + bookmarkView = new BookmarkView(bookmarkViewModel); + cardPanel.add(bookmarkView, bookmarkView.getViewName()); return this; } @@ -140,14 +192,14 @@ public AppBuilder addLoginUseCase() { */ public AppBuilder addChangePasswordUseCase() { final ChangePasswordOutputBoundary changePasswordOutputBoundary = - new ChangePasswordPresenter(loggedInViewModel); + new ChangePasswordPresenter(loggedInViewModel, viewManagerModel, bookmarkViewModel); final ChangePasswordInputBoundary changePasswordInteractor = new ChangePasswordInteractor(userDataAccessObject, changePasswordOutputBoundary, userFactory); final ChangePasswordController changePasswordController = new ChangePasswordController(changePasswordInteractor); - loggedInView.setChangePasswordController(changePasswordController); + translateView.setChangePasswordController(changePasswordController); return this; } @@ -163,7 +215,51 @@ public AppBuilder addLogoutUseCase() { new LogoutInteractor(userDataAccessObject, logoutOutputBoundary); final LogoutController logoutController = new LogoutController(logoutInteractor); - loggedInView.setLogoutController(logoutController); + translateView.setLogoutController(logoutController); + return this; + } + + public AppBuilder addHistoryUseCase() { + final HistoryOutputBoundary historyOutputBoundary = + new HistoryPresenter(historyViewModel, loggedInViewModel, + viewManagerModel); + + final HistoryInputBoundary historyInteractor = + new HistoryInteractor(userDataAccessObject, historyOutputBoundary); + + final HistoryController historyController = + new HistoryController(historyInteractor); + historyView.setHistoryController(historyController); + translateView.setHistoryController(historyController); + return this; + } + + public AppBuilder addTranslateUseCase() { + final TranslatorOutputBoundary translateOutputBoundary = + new TranslatePresenter(viewManagerModel, translateViewModel); + + final TranslatorInputBoundary translatorInteractor = + new TranslatorInteractor(userDataAccessObject, translateOutputBoundary, translateFactory); + + final TranslateController translateController = + new TranslateController(translatorInteractor); + translateView.setTranslateController(translateController); + return this; + } + + /** + * Adds the Bookmark Use Case to the application. + * @return this builder + */ + public AppBuilder addBookmarkUseCase() { + final BookmarkOutputBoundary bookmarkOutputBoundary = new BookmarkPresenter(bookmarkViewModel); + final BookmarkFactory bookmarkFactory = new BookmarkFactory(); + + final BookmarkInputBoundary bookmarkInteractor = new BookmarkInteractor( + userDataAccessObject, bookmarkOutputBoundary, bookmarkFactory); + + final BookmarkController bookmarkController = new BookmarkController(bookmarkInteractor); + bookmarkView.setBookmarkController(bookmarkController); return this; } diff --git a/src/main/java/app/Main.java b/src/main/java/app/Main.java index bef63ad7a..c2e56ea26 100644 --- a/src/main/java/app/Main.java +++ b/src/main/java/app/Main.java @@ -12,16 +12,23 @@ public class Main { */ public static void main(String[] args) { final AppBuilder appBuilder = new AppBuilder(); - // TODO: add the Logout Use Case to the app using the appBuilder final JFrame application = appBuilder .addLoginView() .addSignupView() - .addLoggedInView() + .addTranslateView() + .addHistoryView() + .addBookmarkView() .addSignupUseCase() .addLoginUseCase() + .addLogoutUseCase() .addChangePasswordUseCase() + .addTranslateUseCase() + .addHistoryUseCase() + .addBookmarkUseCase() .build(); - + application.setLocation(550, 200); + application.setSize(600, 200); + application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); application.pack(); application.setVisible(true); } diff --git a/src/main/java/data_access/InMemoryUserDataAccessObject.java b/src/main/java/data_access/InMemoryUserDataAccessObject.java index 71f00862c..b2d0208b4 100644 --- a/src/main/java/data_access/InMemoryUserDataAccessObject.java +++ b/src/main/java/data_access/InMemoryUserDataAccessObject.java @@ -1,13 +1,20 @@ package data_access; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import entity.Bookmark; +import entity.Translate; import entity.User; +import use_case.bookmark.BookmarkUserDataAccessInterface; import use_case.change_password.ChangePasswordUserDataAccessInterface; +import use_case.history.HistoryUserDataAccessInterface; import use_case.login.LoginUserDataAccessInterface; import use_case.logout.LogoutUserDataAccessInterface; import use_case.signup.SignupUserDataAccessInterface; +import use_case.translator.TranslatorUserDataAccessInterface; /** * In-memory implementation of the DAO for storing user data. This implementation does @@ -16,9 +23,15 @@ public class InMemoryUserDataAccessObject implements SignupUserDataAccessInterface, LoginUserDataAccessInterface, ChangePasswordUserDataAccessInterface, - LogoutUserDataAccessInterface { + LogoutUserDataAccessInterface, + TranslatorUserDataAccessInterface, + HistoryUserDataAccessInterface, + BookmarkUserDataAccessInterface { private final Map users = new HashMap<>(); + private final Map> userBookmarks = new HashMap<>(); + private final Map translates = new HashMap<>(); + private final Map> userTranslates = new HashMap<>(); private String currentUsername; @@ -52,4 +65,82 @@ public void setCurrentUsername(String name) { public String getCurrentUsername() { return this.currentUsername; } + + @Override + public void saveTranslation(Translate translation) { + translates.put(translation.getInputText(), translation); + List list = userTranslates.get(get(currentUsername)); + if (list == null) { + list = new ArrayList<>(); + userTranslates.put(get(currentUsername), list); + } + list.add(translation); + } + + @Override + public Translate getTranslation(String text) { + return translates.get(text); + } + + @Override + public void deleteTranslation(String text) { + translates.remove(text); + } + + @Override + public List getAllTranslationsByUser(User user) { + return userTranslates.getOrDefault(user, new ArrayList<>()); + } + + @Override + public Translate getMostRecentTranslation(User user) { + return userTranslates.get(user).get(0); + } + + @Override + public boolean existsByText(String text) { + return users.containsKey(text); + } + + @Override + public void updateTranslation(User user, Translate updatedTranslation) { + translates.put(updatedTranslation.getInputText(), updatedTranslation); + } + + @Override + public void clearHistory(User user) { + translates.clear(); + userTranslates.put(user, new ArrayList<>()); + } + + @Override + public void deleteTranslationHistory(User user, Translate translate) { + final String inputText = translate.getInputText(); + if (existsByText(inputText)) { + translates.remove(inputText); + userTranslates.get(user).remove(translate); + } + else { + System.out.println("Selected history doesn't exist."); + } + } + + @Override + public void addBookmark(Bookmark bookmark) { + userBookmarks.computeIfAbsent(bookmark.getUsername(), mark -> new ArrayList<>()).add(bookmark); + } + + @Override + public void removeBookmark(Bookmark bookmark) { + final List bookmarks = userBookmarks.get(bookmark.getUsername()); + if (bookmarks != null) { + bookmarks.removeIf(mark -> mark.getTranslationId().equals(bookmark.getTranslationId())); + } + } + + @Override + public List getBookmarksByUser(String username) { + return List.of(); + } + } diff --git a/src/main/java/entity/Bookmark.java b/src/main/java/entity/Bookmark.java new file mode 100644 index 000000000..753a4b1ef --- /dev/null +++ b/src/main/java/entity/Bookmark.java @@ -0,0 +1,38 @@ +package entity; + +/** + * Represents a Bookmark for a translation. + */ +public class Bookmark { + private final String username; + private final String translationId; + + /** + * Constructs a Bookmark object. + * + * @param username The username of the user who owns the bookmark. + * @param translationId The ID of the translation being bookmarked. + */ + public Bookmark(String username, String translationId) { + this.username = username; + this.translationId = translationId; + } + + /** + * Gets the username of the user who owns the bookmark. + * + * @return The username. + */ + public String getUsername() { + return username; + } + + /** + * Gets the ID of the translation being bookmarked. + * + * @return The translation ID. + */ + public String getTranslationId() { + return translationId; + } +} diff --git a/src/main/java/entity/BookmarkFactory.java b/src/main/java/entity/BookmarkFactory.java new file mode 100644 index 000000000..21bf99af4 --- /dev/null +++ b/src/main/java/entity/BookmarkFactory.java @@ -0,0 +1,18 @@ +package entity; + +/** + * Factory for creating Bookmark objects. + */ +public class BookmarkFactory { + + /** + * Creates a new Bookmark object. + * + * @param username The username of the user who owns the bookmark. + * @param translationId The ID of the translation to be bookmarked. + * @return A new Bookmark object. + */ + public Bookmark create(String username, String translationId) { + return new Bookmark(username, translationId); + } +} diff --git a/src/main/java/entity/Translate.java b/src/main/java/entity/Translate.java new file mode 100644 index 000000000..af0609567 --- /dev/null +++ b/src/main/java/entity/Translate.java @@ -0,0 +1,66 @@ +package entity; + +import com.deepl.api.*; + +/** + * Translator. + */ +public class Translate { + + private final String inputLanguage; + private final String outputLanguage; + private final String inputText; + private final String outputText; + + public Translate(String inputLanguage, String outputLanguage, String inputText) { + this.inputLanguage = inputLanguage; + this.outputLanguage = outputLanguage; + this.inputText = inputText; + this.outputText = translateText(inputLanguage, outputLanguage, inputText); + } + + public String getInputLanguage() { + return inputLanguage; + } + + public String getOutputLanguage() { + return outputLanguage; + } + + public String getInputText() { + return inputText; + } + + /** + * Translate the given text. + * @param inputLang input language + * @param outputLang output language + * @param input input text + * @return The result of the translation. + */ + private String translateText(String inputLang, String outputLang, String input) { + String output = null; + try { + final String authKey = "563c8dbf-539b-48c2-bc82-fae6a6622677:fx"; + final Translator translator = new Translator(authKey); + final TextResult result = translator.translateText(input, inputLang, outputLang); + output = result.getText(); + } + catch (DeepLException exception) { + System.out.println(exception.getMessage()); + } + catch (InterruptedException exception) { + System.out.println(exception.getMessage()); + } + return output; + } + + public String getOutputText() { + return outputText; + } + + public static void main(String[] args) { + Translate translate = new Translate("ZH", "JA", "你好"); + System.out.println(translate.getOutputText()); + } +} \ No newline at end of file diff --git a/src/main/java/entity/TranslateFactory.java b/src/main/java/entity/TranslateFactory.java new file mode 100644 index 000000000..96e534110 --- /dev/null +++ b/src/main/java/entity/TranslateFactory.java @@ -0,0 +1,8 @@ +package entity; + +public class TranslateFactory { + + public Translate create(String inputLanguage, String outputLanguage, String inputText) { + return new Translate(inputLanguage, outputLanguage, inputText); + } +} diff --git a/src/main/java/interface_adapter/ViewModel.java b/src/main/java/interface_adapter/ViewModel.java index bc2dea65b..36e923623 100644 --- a/src/main/java/interface_adapter/ViewModel.java +++ b/src/main/java/interface_adapter/ViewModel.java @@ -46,7 +46,7 @@ public void firePropertyChanged() { * allows the user to specify a different propertyName. This can be useful * when a class is listening for multiple kinds of property changes. *

- * For example, the LoggedInView listens for two kinds of property changes; + * For example, the TranslateView listens for two kinds of property changes; * it can use the property name to distinguish which property has changed. * @param propertyName the label for the property that was changed */ diff --git a/src/main/java/interface_adapter/bookmark/BookmarkController.java b/src/main/java/interface_adapter/bookmark/BookmarkController.java new file mode 100644 index 000000000..f0200f89e --- /dev/null +++ b/src/main/java/interface_adapter/bookmark/BookmarkController.java @@ -0,0 +1,43 @@ +package interface_adapter.bookmark; + +import use_case.bookmark.BookmarkInputBoundary; +import use_case.bookmark.BookmarkInputData; + +/** + * Controller for the Bookmark Use Case. + * Receives input from the UI and passes it to the use case interactor. + */ +public class BookmarkController { + private final BookmarkInputBoundary bookmarkInputBoundary; + + /** + * Constructs a BookmarkController with the given input boundary. + * + * @param bookmarkInputBoundary The use case interactor to handle bookmark operations. + */ + public BookmarkController(BookmarkInputBoundary bookmarkInputBoundary) { + this.bookmarkInputBoundary = bookmarkInputBoundary; + } + + /** + * Adds a bookmark for the given translation. + * + * @param username The username of the user adding the bookmark. + * @param translationId The ID of the translation to be bookmarked. + */ + public void addBookmark(String username, String translationId) { + final BookmarkInputData inputData = new BookmarkInputData(username, translationId); + bookmarkInputBoundary.addBookmark(inputData); + } + + /** + * Removes a bookmark for the given translation. + * + * @param username The username of the user removing the bookmark. + * @param translationId The ID of the translation to be removed from bookmarks. + */ + public void removeBookmark(String username, String translationId) { + final BookmarkInputData inputData = new BookmarkInputData(username, translationId); + bookmarkInputBoundary.removeBookmark(inputData); + } +} diff --git a/src/main/java/interface_adapter/bookmark/BookmarkPresenter.java b/src/main/java/interface_adapter/bookmark/BookmarkPresenter.java new file mode 100644 index 000000000..27ddc7c65 --- /dev/null +++ b/src/main/java/interface_adapter/bookmark/BookmarkPresenter.java @@ -0,0 +1,31 @@ +package interface_adapter.bookmark; + +import use_case.bookmark.BookmarkOutputBoundary; +import use_case.bookmark.BookmarkOutputData; + +/** + * The Presenter for the Bookmark Use Case. + * Converts output data to a format suitable for the ViewModel. + */ +public class BookmarkPresenter implements BookmarkOutputBoundary { + + private final BookmarkViewModel bookmarkViewModel; + + /** + * Constructs a BookmarkPresenter with the given ViewModel. + * + * @param bookmarkViewModel The ViewModel to update based on the output data. + */ + public BookmarkPresenter(BookmarkViewModel bookmarkViewModel) { + this.bookmarkViewModel = bookmarkViewModel; + } + + @Override + public void prepareSuccessView(BookmarkOutputData outputData) { + } + + @Override + public void prepareFailView(String error) { + // note: this use case currently can't fail + } +} diff --git a/src/main/java/interface_adapter/bookmark/BookmarkState.java b/src/main/java/interface_adapter/bookmark/BookmarkState.java new file mode 100644 index 000000000..8785e1d01 --- /dev/null +++ b/src/main/java/interface_adapter/bookmark/BookmarkState.java @@ -0,0 +1,58 @@ +package interface_adapter.bookmark; + +/** + * Represents the state of the Bookmark feature. + * Stores the username, translation ID, and any status messages. + */ +public class BookmarkState { + private String username; + private String translationId; + private String statusMessage; + + /** + * Constructs a BookmarkState with the given username, translation ID, and status message. + * + * @param username The username associated with the current state. + * @param translationId The ID of the translation. + * @param statusMessage The status message for the bookmark operation. + */ + public BookmarkState(String username, String translationId, String statusMessage) { + this.username = username; + this.translationId = translationId; + this.statusMessage = statusMessage; + } + + public BookmarkState(BookmarkState copy) { + this.username = copy.username; + this.translationId = copy.translationId; + this.statusMessage = copy.statusMessage; + } + + // Default constructor. + public BookmarkState() { + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getTranslationId() { + return translationId; + } + + public void setTranslationId(String translationId) { + this.translationId = translationId; + } + + public String getStatusMessage() { + return statusMessage; + } + + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; + } +} diff --git a/src/main/java/interface_adapter/bookmark/BookmarkViewModel.java b/src/main/java/interface_adapter/bookmark/BookmarkViewModel.java new file mode 100644 index 000000000..3819160db --- /dev/null +++ b/src/main/java/interface_adapter/bookmark/BookmarkViewModel.java @@ -0,0 +1,20 @@ +package interface_adapter.bookmark; + +import interface_adapter.ViewModel; + +/** + * The ViewModel for the Bookmark Use Case. + * Notifies the view of changes to the bookmark state. + */ +public class BookmarkViewModel extends ViewModel { + + public static final String TITLE_LABEL = "Bookmark Manager"; + public static final String ADD_BOOKMARK_BUTTON_LABEL = "Add Bookmark"; + public static final String REMOVE_BOOKMARK_BUTTON_LABEL = "Remove Bookmark"; + public static final String BACK_BUTTON_LABEL = "Back"; + + public BookmarkViewModel() { + super("bookmark"); + setState(new BookmarkState()); + } +} diff --git a/src/main/java/interface_adapter/change_password/ChangePasswordController.java b/src/main/java/interface_adapter/change_password/ChangePasswordController.java index a7abd075f..6a37fb14e 100644 --- a/src/main/java/interface_adapter/change_password/ChangePasswordController.java +++ b/src/main/java/interface_adapter/change_password/ChangePasswordController.java @@ -23,4 +23,11 @@ public void execute(String password, String username) { userChangePasswordUseCaseInteractor.execute(changePasswordInputData); } + + /** + * Executes the "switch to BookmarkView" Use Case. + */ + public void switchToBookmarkView() { + userChangePasswordUseCaseInteractor.switchToBookmarkView(); + } } diff --git a/src/main/java/interface_adapter/change_password/ChangePasswordPresenter.java b/src/main/java/interface_adapter/change_password/ChangePasswordPresenter.java index 3efca4e46..cd10eb0cf 100644 --- a/src/main/java/interface_adapter/change_password/ChangePasswordPresenter.java +++ b/src/main/java/interface_adapter/change_password/ChangePasswordPresenter.java @@ -1,5 +1,7 @@ package interface_adapter.change_password; +import interface_adapter.ViewManagerModel; +import interface_adapter.bookmark.BookmarkViewModel; import use_case.change_password.ChangePasswordOutputBoundary; import use_case.change_password.ChangePasswordOutputData; @@ -9,9 +11,15 @@ public class ChangePasswordPresenter implements ChangePasswordOutputBoundary { private final LoggedInViewModel loggedInViewModel; + private final ViewManagerModel viewManagerModel; + private final BookmarkViewModel bookmarkViewModel; - public ChangePasswordPresenter(LoggedInViewModel loggedInViewModel) { + public ChangePasswordPresenter(LoggedInViewModel loggedInViewModel, + ViewManagerModel viewManagerModel, + BookmarkViewModel bookmarkViewModel) { this.loggedInViewModel = loggedInViewModel; + this.viewManagerModel = viewManagerModel; + this.bookmarkViewModel = bookmarkViewModel; } @Override @@ -28,4 +36,10 @@ public void prepareSuccessView(ChangePasswordOutputData outputData) { public void prepareFailView(String error) { // note: this use case currently can't fail } + + @Override + public void switchToBookmarkView() { + viewManagerModel.setState(bookmarkViewModel.getViewName()); + viewManagerModel.firePropertyChanged(); + } } diff --git a/src/main/java/interface_adapter/change_password/ChangePasswordState.java b/src/main/java/interface_adapter/change_password/ChangePasswordState.java new file mode 100644 index 000000000..9160f330d --- /dev/null +++ b/src/main/java/interface_adapter/change_password/ChangePasswordState.java @@ -0,0 +1,70 @@ +package interface_adapter.change_password; + +/** + * Represents the state of the Change Password feature. + * Stores the username, old password, new password, and any status messages. + */ +public class ChangePasswordState { + private String username; + private String oldPassword; + private String newPassword; + private String statusMessage; + + /** + * Constructs a ChangePasswordState with the given username, old password, new password, and status message. + * + * @param username The username associated with the current state. + * @param oldPassword The old password of the user. + * @param newPassword The new password to be set for the user. + * @param statusMessage The status message for the change password operation. + */ + public ChangePasswordState(String username, String oldPassword, String newPassword, String statusMessage) { + this.username = username; + this.oldPassword = oldPassword; + this.newPassword = newPassword; + this.statusMessage = statusMessage; + } + + public ChangePasswordState(ChangePasswordState copy) { + this.username = copy.username; + this.oldPassword = copy.oldPassword; + this.newPassword = copy.newPassword; + this.statusMessage = copy.statusMessage; + } + + // Default constructor. + public ChangePasswordState() { + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getOldPassword() { + return oldPassword; + } + + public void setOldPassword(String oldPassword) { + this.oldPassword = oldPassword; + } + + public String getNewPassword() { + return newPassword; + } + + public void setNewPassword(String newPassword) { + this.newPassword = newPassword; + } + + public String getStatusMessage() { + return statusMessage; + } + + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; + } +} diff --git a/src/main/java/interface_adapter/change_password/ChangePasswordViewModel.java b/src/main/java/interface_adapter/change_password/ChangePasswordViewModel.java new file mode 100644 index 000000000..d2a6e7f13 --- /dev/null +++ b/src/main/java/interface_adapter/change_password/ChangePasswordViewModel.java @@ -0,0 +1,22 @@ +package interface_adapter.change_password; + +import interface_adapter.ViewModel; + +/** + * The ViewModel for the Change Password Use Case. + * Notifies the view of changes to the change password state. + */ +public class ChangePasswordViewModel extends ViewModel { + + public static final String TITLE_LABEL = "Change Password"; + public static final String USERNAME_LABEL = "Username:"; + public static final String OLD_PASSWORD_LABEL = "Old Password:"; + public static final String NEW_PASSWORD_LABEL = "New Password:"; + public static final String CHANGE_PASSWORD_BUTTON_LABEL = "Change Password"; + public static final String BACK_BUTTON_LABEL = "Back"; + + public ChangePasswordViewModel() { + super("change_password"); + setState(new ChangePasswordState()); + } +} diff --git a/src/main/java/interface_adapter/history/HistoryController.java b/src/main/java/interface_adapter/history/HistoryController.java new file mode 100644 index 000000000..3eeab3da6 --- /dev/null +++ b/src/main/java/interface_adapter/history/HistoryController.java @@ -0,0 +1,39 @@ +package interface_adapter.history; + +import entity.User; +import use_case.history.HistoryInputBoundary; +import use_case.history.HistoryInputData; + +/** + * The controller for the History Use Case. + */ +public class HistoryController { + + private final HistoryInputBoundary historyUseCaseInteractor; + + public HistoryController(HistoryInputBoundary historyUseCaseInteractor) { + this.historyUseCaseInteractor = historyUseCaseInteractor; + } + + /** + * Executes the History Use Case. + * @param user the user logged in. + */ + public void execute(User user) { + final HistoryInputData historyInputData = new HistoryInputData( + user); + + historyUseCaseInteractor.execute(historyInputData); + } + + /** + * Executes the "switch to LoginView" Use Case. + */ + public void switchBackToTranslateView() { + historyUseCaseInteractor.switchBackToTranslateView(); + } + + public void switchToHistoryView() { + historyUseCaseInteractor.switchToHistoryView(); + } +} diff --git a/src/main/java/interface_adapter/history/HistoryPresenter.java b/src/main/java/interface_adapter/history/HistoryPresenter.java new file mode 100644 index 000000000..30f1b6a92 --- /dev/null +++ b/src/main/java/interface_adapter/history/HistoryPresenter.java @@ -0,0 +1,61 @@ +package interface_adapter.history; + +import interface_adapter.ViewManagerModel; +import interface_adapter.change_password.LoggedInViewModel; +import interface_adapter.translate.TranslateState; +import interface_adapter.translate.TranslateViewModel; +import use_case.history.HistoryOutputBoundary; +import use_case.history.HistoryOutputData; + +/** + * The presenter for the History Use Case. + */ +public class HistoryPresenter implements HistoryOutputBoundary { + private final HistoryViewModel historyViewModel; + private final LoggedInViewModel loggedInViewModel; + private final ViewManagerModel viewManagerModel; + + public HistoryPresenter(HistoryViewModel historyViewModel, LoggedInViewModel loggedInViewModel, ViewManagerModel viewManagerModel) { + this.historyViewModel = historyViewModel; + this.loggedInViewModel = loggedInViewModel; + this.viewManagerModel = viewManagerModel; + } + + /** + * Prepare success view. + * @param outputData the output data + */ + @Override + public void prepareSuccessView(HistoryOutputData outputData) { + final HistoryState historyState = historyViewModel.getState(); + historyState.setHistory(outputData.getHistory()); + this.historyViewModel.setState(historyState); + this.historyViewModel.firePropertyChanged("history"); + + this.viewManagerModel.setState(historyViewModel.getViewName()); + this.viewManagerModel.firePropertyChanged(); + } + + /** + * Prepare failed view. + * @param errorMessage the explanation of the failure + */ + @Override + public void prepareFailView(String errorMessage) { + final HistoryState historyState = historyViewModel.getState(); + historyState.setHistoryError(errorMessage); + historyViewModel.firePropertyChanged("history"); + } + + @Override + public void switchBackToTranslateView() { + viewManagerModel.setState(loggedInViewModel.getViewName()); + viewManagerModel.firePropertyChanged(); + } + + @Override + public void switchToHistoryView() { + viewManagerModel.setState(historyViewModel.getViewName()); + viewManagerModel.firePropertyChanged(); + } +} diff --git a/src/main/java/interface_adapter/history/HistoryState.java b/src/main/java/interface_adapter/history/HistoryState.java new file mode 100644 index 000000000..838fc69b0 --- /dev/null +++ b/src/main/java/interface_adapter/history/HistoryState.java @@ -0,0 +1,27 @@ +package interface_adapter.history; + +import java.util.Map; + +/** + * The State for the History View. + */ +public class HistoryState { + private Map history; + private String historyError; + + public Map getHistory() { + return history; + } + + public void setHistory(Map history) { + this.history = history; + } + + public String getHistoryError() { + return historyError; + } + + public void setHistoryError(String historyError) { + this.historyError = historyError; + } +} diff --git a/src/main/java/interface_adapter/history/HistoryViewModel.java b/src/main/java/interface_adapter/history/HistoryViewModel.java new file mode 100644 index 000000000..c6c44be8c --- /dev/null +++ b/src/main/java/interface_adapter/history/HistoryViewModel.java @@ -0,0 +1,15 @@ +package interface_adapter.history; + +import interface_adapter.ViewModel; + +/** + * The ViewModel for History View. + */ +public class HistoryViewModel extends ViewModel { + public static final String BACK_BUTTON_LABLE = "Back"; + + public HistoryViewModel() { + super("history"); + setState(new HistoryState()); + } +} diff --git a/src/main/java/interface_adapter/login/LoginPresenter.java b/src/main/java/interface_adapter/login/LoginPresenter.java index 66560d51a..116a2d92f 100644 --- a/src/main/java/interface_adapter/login/LoginPresenter.java +++ b/src/main/java/interface_adapter/login/LoginPresenter.java @@ -30,7 +30,7 @@ public void prepareSuccessView(LoginOutputData response) { final LoggedInState loggedInState = loggedInViewModel.getState(); loggedInState.setUsername(response.getUsername()); this.loggedInViewModel.setState(loggedInState); - this.loggedInViewModel.firePropertyChanged(); + this.loggedInViewModel.firePropertyChanged("login"); this.viewManagerModel.setState(loggedInViewModel.getViewName()); this.viewManagerModel.firePropertyChanged(); diff --git a/src/main/java/interface_adapter/login/LoginState.java b/src/main/java/interface_adapter/login/LoginState.java index e42632034..cd8b3aa8d 100644 --- a/src/main/java/interface_adapter/login/LoginState.java +++ b/src/main/java/interface_adapter/login/LoginState.java @@ -1,13 +1,20 @@ package interface_adapter.login; +import entity.User; + /** * The state for the Login View Model. */ public class LoginState { + private User user; private String username = ""; private String loginError; private String password = ""; + public User getUser() { + return user; + } + public String getUsername() { return username; } @@ -20,6 +27,10 @@ public String getPassword() { return password; } + public void setUser(User user) { + this.user = user; + } + public void setUsername(String username) { this.username = username; } diff --git a/src/main/java/interface_adapter/logout/LogoutController.java b/src/main/java/interface_adapter/logout/LogoutController.java index e184a3bba..7ce432838 100644 --- a/src/main/java/interface_adapter/logout/LogoutController.java +++ b/src/main/java/interface_adapter/logout/LogoutController.java @@ -1,6 +1,7 @@ package interface_adapter.logout; import use_case.logout.LogoutInputBoundary; +import use_case.logout.LogoutInputData; /** * The controller for the Logout Use Case. @@ -11,6 +12,7 @@ public class LogoutController { public LogoutController(LogoutInputBoundary logoutUseCaseInteractor) { // TODO: Save the interactor in the instance variable. + this.logoutUseCaseInteractor = logoutUseCaseInteractor; } /** @@ -21,5 +23,11 @@ public void execute(String username) { // TODO: run the use case interactor for the logout use case // 1. instantiate the `LogoutInputData`, which should contain the username. // 2. tell the Interactor to execute. + + final LogoutInputData logoutInputData = new LogoutInputData( + username); + + logoutUseCaseInteractor.execute(logoutInputData); + } } diff --git a/src/main/java/interface_adapter/logout/LogoutPresenter.java b/src/main/java/interface_adapter/logout/LogoutPresenter.java index 78ef306a1..ecb6d8b81 100644 --- a/src/main/java/interface_adapter/logout/LogoutPresenter.java +++ b/src/main/java/interface_adapter/logout/LogoutPresenter.java @@ -1,7 +1,9 @@ package interface_adapter.logout; import interface_adapter.ViewManagerModel; +import interface_adapter.change_password.LoggedInState; import interface_adapter.change_password.LoggedInViewModel; +import interface_adapter.login.LoginState; import interface_adapter.login.LoginViewModel; import use_case.logout.LogoutOutputBoundary; import use_case.logout.LogoutOutputData; @@ -19,6 +21,9 @@ public LogoutPresenter(ViewManagerModel viewManagerModel, LoggedInViewModel loggedInViewModel, LoginViewModel loginViewModel) { // TODO: assign to the three instance variables. + this.viewManagerModel = viewManagerModel; + this.loggedInViewModel = loggedInViewModel; + this.loginViewModel = loginViewModel; } @Override @@ -28,7 +33,16 @@ public void prepareSuccessView(LogoutOutputData response) { // We also need to set the username in the LoggedInState to // the empty string. + final LoggedInState loggedInState = loggedInViewModel.getState(); + loggedInState.setUsername(""); + this.loggedInViewModel.setState(loggedInState); + this.loggedInViewModel.firePropertyChanged(); + final LoginState loginState = loginViewModel.getState(); + loginState.setUsername(""); + loginState.setPassword(""); + this.loginViewModel.setState(loginState); + this.loginViewModel.firePropertyChanged(); // TODO: have prepareSuccessView update the LoggedInState // 1. get the LoggedInState out of the appropriate View Model, // 2. set the username in the state to the empty string diff --git a/src/main/java/interface_adapter/translate/TranslateController.java b/src/main/java/interface_adapter/translate/TranslateController.java new file mode 100644 index 000000000..4bc45edc9 --- /dev/null +++ b/src/main/java/interface_adapter/translate/TranslateController.java @@ -0,0 +1,29 @@ +package interface_adapter.translate; + +import use_case.translator.TranslatorInputBoundary; +import use_case.translator.TranslatorInputData; + +/** + * Controller for the Translate Use Case. + */ +public class TranslateController { + private final TranslatorInputBoundary userTranslateUseCaseController; + + public TranslateController(TranslatorInputBoundary userTranslateUseCaseController) { + this.userTranslateUseCaseController = userTranslateUseCaseController; + } + + /** + * Executes the Translate Use Case. + * @param inputLanguage the input language + * @param outputLanguage the output language + * @param inputText the input text + */ + public void execute(String inputLanguage, String outputLanguage, String inputText) { + final TranslatorInputData translatorInputData = new TranslatorInputData(inputLanguage, + outputLanguage, inputText); + + userTranslateUseCaseController.execute(translatorInputData); + } + +} diff --git a/src/main/java/interface_adapter/translate/TranslatePresenter.java b/src/main/java/interface_adapter/translate/TranslatePresenter.java new file mode 100644 index 000000000..5fe39debf --- /dev/null +++ b/src/main/java/interface_adapter/translate/TranslatePresenter.java @@ -0,0 +1,46 @@ +package interface_adapter.translate; + +import interface_adapter.ViewManagerModel; +import use_case.translator.TranslatorOutputBoundary; +import use_case.translator.TranslatorOutputData; + +/** + * The presenter for the Translate Use Case. + */ +public class TranslatePresenter implements TranslatorOutputBoundary { + + private final TranslateViewModel translateViewModel; + private final ViewManagerModel viewManagerModel; + + public TranslatePresenter(ViewManagerModel viewManagerModel, + TranslateViewModel translateViewModel) { + this.viewManagerModel = viewManagerModel; + this.translateViewModel = translateViewModel; + } + + /** + * Prepare success view. + * @param outputData the output data + */ + @Override + public void prepareSuccessView(TranslatorOutputData outputData) { + final TranslateState translateState = translateViewModel.getState(); + translateState.setOutputText(outputData.getOutputText()); + this.translateViewModel.setState(translateState); + this.translateViewModel.firePropertyChanged(); + + this.viewManagerModel.setState(translateViewModel.getViewName()); + this.viewManagerModel.firePropertyChanged(); + } + + /** + * Prepare failed view. + * @param errorMessage the explanation of the failure + */ + @Override + public void prepareFailView(String errorMessage) { + final TranslateState translateState = translateViewModel.getState(); + translateState.setTranslationError(errorMessage); + translateViewModel.firePropertyChanged(); + } +} diff --git a/src/main/java/interface_adapter/translate/TranslateState.java b/src/main/java/interface_adapter/translate/TranslateState.java new file mode 100644 index 000000000..c5352b445 --- /dev/null +++ b/src/main/java/interface_adapter/translate/TranslateState.java @@ -0,0 +1,76 @@ +package interface_adapter.translate; + +/** + * The State information for managing translation requests. + */ +public class TranslateState { + + private String inputLanguage = ""; + private String outputLanguage = ""; + private String inputText = ""; + private String outputText = ""; + private String translatedText = ""; + private String translationError; + + // Copy constructor + public TranslateState(TranslateState copy) { + this.inputLanguage = copy.inputLanguage; + this.outputLanguage = copy.outputLanguage; + this.inputText = copy.inputText; + this.outputText = copy.outputText; + this.translatedText = copy.translatedText; + this.translationError = copy.translationError; + } + + // Default constructor + public TranslateState() { + } + + public String getInputLanguage() { + return inputLanguage; + } + + public void setInputLanguage(String inputLanguage) { + this.inputLanguage = inputLanguage; + } + + public String getOutputLanguage() { + return outputLanguage; + } + + public void setOutputLanguage(String outputLanguage) { + this.outputLanguage = outputLanguage; + } + + public String getInputText() { + return inputText; + } + + public void setInputText(String inputText) { + this.inputText = inputText; + } + + public String getOutputText() { + return outputText; + } + + public void setOutputText(String outputText) { + this.outputText = outputText; + } + + public String getTranslatedText() { + return translatedText; + } + + public void setTranslatedText(String translatedText) { + this.translatedText = translatedText; + } + + public String getTranslationError() { + return translationError; + } + + public void setTranslationError(String translationError) { + this.translationError = translationError; + } +} diff --git a/src/main/java/interface_adapter/translate/TranslateViewModel.java b/src/main/java/interface_adapter/translate/TranslateViewModel.java new file mode 100644 index 000000000..7f4dc6d86 --- /dev/null +++ b/src/main/java/interface_adapter/translate/TranslateViewModel.java @@ -0,0 +1,35 @@ +package interface_adapter.translate; + +import interface_adapter.ViewModel; + +/** + * The ViewModel for Translator. + */ + +public class TranslateViewModel extends ViewModel { + + public static final String TITLE_LABEL = "Translator"; + public static final String LOGOUT_LABEL = "Log out"; + + public static final String INPUT_LANGUAGE_LABEL = "Choose your inout language"; + public static final String OUTPUT_LANGUAGE_LABEL = "Choose your output language"; + + public static final String INPUT_TEXT_LABEL = "Input your text here"; + public static final String OUTPUT_TEXT_LABEL = "Your translation will be here"; + + public static final String TRANSLATE_F_LABEL = "Translate"; + public static final String OTHER_TRANSLATION_F_LABEL = "Others"; + + public static final String HISTORY_LABEL = "History"; + + public static final String BOOKMARK_F_LABEL = "Bookmark current translation"; + public static final String BOOKMARKS_LABEL = "Bookmarks"; + + public static final String FEEDBACK_F_LABEL = "Submit feedback"; + + public TranslateViewModel() { + super("translate"); + setState(new TranslateState()); + } + +} diff --git a/src/main/java/use_case/bookmark/BookmarkInputBoundary.java b/src/main/java/use_case/bookmark/BookmarkInputBoundary.java new file mode 100644 index 000000000..aba4e7030 --- /dev/null +++ b/src/main/java/use_case/bookmark/BookmarkInputBoundary.java @@ -0,0 +1,21 @@ +package use_case.bookmark; + +/** + * The Bookmark Use Case Input Boundary. + * Defines the interface to execute bookmark actions. + */ +public interface BookmarkInputBoundary { + /** + * Adds a bookmark for a specific translation. + * + * @param inputData The input data containing information about the user and the translation to be bookmarked. + */ + void addBookmark(BookmarkInputData inputData); + + /** + * Removes a bookmark for a specific translation. + * + * @param inputData The input data containing information about the user and the translation to be removed. + */ + void removeBookmark(BookmarkInputData inputData); +} diff --git a/src/main/java/use_case/bookmark/BookmarkInputData.java b/src/main/java/use_case/bookmark/BookmarkInputData.java new file mode 100644 index 000000000..4f9691363 --- /dev/null +++ b/src/main/java/use_case/bookmark/BookmarkInputData.java @@ -0,0 +1,39 @@ +package use_case.bookmark; + +/** + * The input data for the Bookmark Use Case. + * Contains the information required to perform a bookmark action. + */ +public class BookmarkInputData { + private final String username; + private final String translationId; + + /** + * Constructs a new BookmarkInputData object. + * + * @param username The username of the user performing the action. + * @param translationId The ID of the translation to be bookmarked or removed. + */ + public BookmarkInputData(String username, String translationId) { + this.username = username; + this.translationId = translationId; + } + + /** + * Gets the username of the user performing the action. + * + * @return The username of the user. + */ + public String getUsername() { + return username; + } + + /** + * Gets the ID of the translation to be bookmarked or removed. + * + * @return The translation ID. + */ + public String getTranslationId() { + return translationId; + } +} diff --git a/src/main/java/use_case/bookmark/BookmarkInteractor.java b/src/main/java/use_case/bookmark/BookmarkInteractor.java new file mode 100644 index 000000000..bae6af956 --- /dev/null +++ b/src/main/java/use_case/bookmark/BookmarkInteractor.java @@ -0,0 +1,55 @@ +package use_case.bookmark; + +import entity.Bookmark; +import entity.BookmarkFactory; + +/** + * The Bookmark Interactor. + * Implements the use case logic for adding and removing bookmarks. + */ +public class BookmarkInteractor implements BookmarkInputBoundary { + private final BookmarkUserDataAccessInterface bookmarkDataAccess; + private final BookmarkOutputBoundary bookmarkPresenter; + private final BookmarkFactory bookmarkFactory; + + /** + * Constructs a new BookmarkInteractor. + * + * @param bookmarkDataAccess The data access interface for bookmark operations. + * @param bookmarkPresenter The output boundary for presenting bookmark results. + * @param bookmarkFactory The factory for creating Bookmark entities. + */ + public BookmarkInteractor(BookmarkUserDataAccessInterface bookmarkDataAccess, + BookmarkOutputBoundary bookmarkPresenter, + BookmarkFactory bookmarkFactory) { + this.bookmarkDataAccess = bookmarkDataAccess; + this.bookmarkPresenter = bookmarkPresenter; + this.bookmarkFactory = bookmarkFactory; + } + + /** + * Adds a bookmark for a specific translation. + * + * @param inputData The input data containing information about the user and the translation to be bookmarked. + */ + @Override + public void addBookmark(BookmarkInputData inputData) { + final Bookmark bookmark = bookmarkFactory.create(inputData.getUsername(), inputData.getTranslationId()); + bookmarkDataAccess.addBookmark(bookmark); + bookmarkPresenter.prepareSuccessView(new BookmarkOutputData(inputData.getUsername(), + inputData.getTranslationId(), "Bookmark added successfully")); + } + + /** + * Removes a bookmark for a specific translation. + * + * @param inputData The input data containing information about the user and the translation to be removed. + */ + @Override + public void removeBookmark(BookmarkInputData inputData) { + final Bookmark bookmark = bookmarkFactory.create(inputData.getUsername(), inputData.getTranslationId()); + bookmarkDataAccess.removeBookmark(bookmark); + bookmarkPresenter.prepareSuccessView(new BookmarkOutputData(inputData.getUsername(), + inputData.getTranslationId(), "Bookmark removed successfully")); + } +} diff --git a/src/main/java/use_case/bookmark/BookmarkOutputBoundary.java b/src/main/java/use_case/bookmark/BookmarkOutputBoundary.java new file mode 100644 index 000000000..aaed6434e --- /dev/null +++ b/src/main/java/use_case/bookmark/BookmarkOutputBoundary.java @@ -0,0 +1,21 @@ +package use_case.bookmark; + +/** + * The output boundary for the Bookmark Use Case. + * Defines the methods to present the results of bookmark actions. + */ +public interface BookmarkOutputBoundary { + /** + * Prepares the success view for a bookmark action. + * + * @param outputData The output data containing the result of the bookmark action. + */ + void prepareSuccessView(BookmarkOutputData outputData); + + /** + * Prepares the failure view for a bookmark action. + * + * @param errorMessage The error message describing why the bookmark action failed. + */ + void prepareFailView(String errorMessage); +} \ No newline at end of file diff --git a/src/main/java/use_case/bookmark/BookmarkOutputData.java b/src/main/java/use_case/bookmark/BookmarkOutputData.java new file mode 100644 index 000000000..247cd658b --- /dev/null +++ b/src/main/java/use_case/bookmark/BookmarkOutputData.java @@ -0,0 +1,28 @@ +package use_case.bookmark; + +/** + * Output data for the Bookmark Use Case. + */ +public class BookmarkOutputData { + private final String username; + private final String translationId; + private final String message; + + public BookmarkOutputData(String username, String translationId, String message) { + this.username = username; + this.translationId = translationId; + this.message = message; + } + + public String getUsername() { + return username; + } + + public String getTranslationId() { + return translationId; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/use_case/bookmark/BookmarkUserDataAccessInterface.java b/src/main/java/use_case/bookmark/BookmarkUserDataAccessInterface.java new file mode 100644 index 000000000..cc30290d0 --- /dev/null +++ b/src/main/java/use_case/bookmark/BookmarkUserDataAccessInterface.java @@ -0,0 +1,35 @@ +package use_case.bookmark; + +import java.util.List; + +import entity.Bookmark; + +/** + * The interface for the Bookmark Data Access Object. + * This interface provides methods to interact with the Bookmark data, + * such as adding, removing, and retrieving bookmarks. + */ +public interface BookmarkUserDataAccessInterface { + + /** + * Adds a bookmark to the system for a specific user. + * + * @param bookmark The bookmark to be added. + */ + void addBookmark(Bookmark bookmark); + + /** + * Removes a bookmark from the system for a specific user. + * + * @param bookmark The bookmark to be removed. + */ + void removeBookmark(Bookmark bookmark); + + /** + * Retrieves the list of bookmarks for a specific user. + * + * @param username The username of the user whose bookmarks are to be retrieved. + * @return A list of bookmarks associated with the specified user. + */ + List getBookmarksByUser(String username); +} diff --git a/src/main/java/use_case/change_password/ChangePasswordInputBoundary.java b/src/main/java/use_case/change_password/ChangePasswordInputBoundary.java index 06ae9448e..7e66cebf1 100644 --- a/src/main/java/use_case/change_password/ChangePasswordInputBoundary.java +++ b/src/main/java/use_case/change_password/ChangePasswordInputBoundary.java @@ -11,4 +11,9 @@ public interface ChangePasswordInputBoundary { */ void execute(ChangePasswordInputData changePasswordInputData); + /** + * Executes the switch to bookmark view use case. + */ + void switchToBookmarkView(); + } diff --git a/src/main/java/use_case/change_password/ChangePasswordInteractor.java b/src/main/java/use_case/change_password/ChangePasswordInteractor.java index df91196c1..ecb28d918 100644 --- a/src/main/java/use_case/change_password/ChangePasswordInteractor.java +++ b/src/main/java/use_case/change_password/ChangePasswordInteractor.java @@ -29,4 +29,8 @@ public void execute(ChangePasswordInputData changePasswordInputData) { false); userPresenter.prepareSuccessView(changePasswordOutputData); } + + @Override + public void switchToBookmarkView() { + userPresenter.switchToBookmarkView(); } } diff --git a/src/main/java/use_case/change_password/ChangePasswordOutputBoundary.java b/src/main/java/use_case/change_password/ChangePasswordOutputBoundary.java index fce28367b..ee02575e3 100644 --- a/src/main/java/use_case/change_password/ChangePasswordOutputBoundary.java +++ b/src/main/java/use_case/change_password/ChangePasswordOutputBoundary.java @@ -15,4 +15,9 @@ public interface ChangePasswordOutputBoundary { * @param errorMessage the explanation of the failure */ void prepareFailView(String errorMessage); + + /** + * Switches to the Bookmark View. + */ + void switchToBookmarkView(); } diff --git a/src/main/java/use_case/history/HistoryInputBoundary.java b/src/main/java/use_case/history/HistoryInputBoundary.java new file mode 100644 index 000000000..46a41e4fd --- /dev/null +++ b/src/main/java/use_case/history/HistoryInputBoundary.java @@ -0,0 +1,23 @@ +package use_case.history; + +/** + * Input Boundary for actions which are related to History. + */ +public interface HistoryInputBoundary { + + /** + * Executes the history case. + * @param historyInputData the input data + */ + void execute(HistoryInputData historyInputData); + + /** + * Executes to go back to translate view. + */ + void switchBackToTranslateView(); + + /** + * Executes to go to history view. + */ + void switchToHistoryView(); +} diff --git a/src/main/java/use_case/history/HistoryInputData.java b/src/main/java/use_case/history/HistoryInputData.java new file mode 100644 index 000000000..defade68c --- /dev/null +++ b/src/main/java/use_case/history/HistoryInputData.java @@ -0,0 +1,37 @@ +package use_case.history; + +import data_access.InMemoryUserDataAccessObject; +import entity.Translate; +import entity.User; +import use_case.translator.TranslatorInputData; +import use_case.translator.TranslatorUserDataAccessInterface; + +import java.util.List; + +/** + * The input data for the history UseCase. + */ +public class HistoryInputData { + private final User user; + + public HistoryInputData(User user) { + this.user = user; + } + + public User getUser() { + return user; + } + + public String getUsername() { + return user.getName(); + } + +// /** +// * Get all translations by user. +// * @return a list of translations. +// */ +// public List getAllTranslationsByUser() { +// final TranslatorUserDataAccessInterface inMemoryUserDataAccessObject = new InMemoryUserDataAccessObject(); +// return inMemoryUserDataAccessObject.getAllTranslationsByUser(user); +// } +} diff --git a/src/main/java/use_case/history/HistoryInteractor.java b/src/main/java/use_case/history/HistoryInteractor.java new file mode 100644 index 000000000..4eb468605 --- /dev/null +++ b/src/main/java/use_case/history/HistoryInteractor.java @@ -0,0 +1,63 @@ +package use_case.history; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import entity.Translate; +import entity.User; + +/** + * The History Interactor. + */ +public class HistoryInteractor implements HistoryInputBoundary { + + private final HistoryUserDataAccessInterface historyDataAccessObject; + private final HistoryOutputBoundary historyPresenter; + + public HistoryInteractor(HistoryUserDataAccessInterface historyDataAccessObject, + HistoryOutputBoundary historyPresenter) { + this.historyDataAccessObject = historyDataAccessObject; + this.historyPresenter = historyPresenter; + } + + /** + * @param historyInputData the input data + */ + @Override + public void execute(HistoryInputData historyInputData) { + final User user = historyInputData.getUser(); + final List allTranslation = historyDataAccessObject.getAllTranslationsByUser(user); + if (allTranslation == null || allTranslation.isEmpty()) { + historyPresenter.prepareFailView("There is no searching history currently."); + } + + else { + try { + final Map history = new HashMap<>(); + for (Translate translate : allTranslation) { + history.put(translate.getInputText(), translate.getOutputText()); + } + final HistoryOutputData outputData = new HistoryOutputData(user, history, false); + historyPresenter.prepareSuccessView(outputData); + } + catch (IllegalArgumentException illegalArgumentException) { + historyPresenter.prepareFailView("An error occurred. " + + illegalArgumentException.getMessage()); + } + } + } + + /** + * Switch back to Translate View. + */ + @Override + public void switchBackToTranslateView() { + historyPresenter.switchBackToTranslateView(); + } + + @Override + public void switchToHistoryView() { + historyPresenter.switchToHistoryView(); + } +} diff --git a/src/main/java/use_case/history/HistoryOutputBoundary.java b/src/main/java/use_case/history/HistoryOutputBoundary.java new file mode 100644 index 000000000..6d6b629a3 --- /dev/null +++ b/src/main/java/use_case/history/HistoryOutputBoundary.java @@ -0,0 +1,29 @@ +package use_case.history; + +/** + * The output boundary for the History Use Case. + */ +public interface HistoryOutputBoundary { + + /** + * Prepares the success view for the History Use Case. + * @param outputData the output data + */ + void prepareSuccessView(HistoryOutputData outputData); + + /** + * Prepares the failure view for the History Use Case. + * @param errorMessage the explanation of the failure + */ + void prepareFailView(String errorMessage); + + /** + * Executes to go back to translate view. + */ + void switchBackToTranslateView(); + + /** + * Executes to go to history view. + */ + void switchToHistoryView(); +} diff --git a/src/main/java/use_case/history/HistoryOutputData.java b/src/main/java/use_case/history/HistoryOutputData.java new file mode 100644 index 000000000..ee9aeb31c --- /dev/null +++ b/src/main/java/use_case/history/HistoryOutputData.java @@ -0,0 +1,38 @@ +package use_case.history; + +import entity.User; + +import java.util.HashMap; +import java.util.Map; + +/** + * Output Data for the History Use Case. + */ +public class HistoryOutputData { + private final User user; + private final Map history; + private final boolean useCaseFailed; + + public HistoryOutputData(User user, Map history, boolean useCaseFailed) { + this.user = user; + this.history = history; + this.useCaseFailed = useCaseFailed; + } + + public User getUser() { + return user; + } + + public Map getHistory() { + return history; + } + +// public Map setHistory(Map history) { +// this.history = history; +// } + + public boolean isUseCaseFailed() { + return useCaseFailed; + } + +} diff --git a/src/main/java/use_case/history/HistoryUserDataAccessInterface.java b/src/main/java/use_case/history/HistoryUserDataAccessInterface.java new file mode 100644 index 000000000..77e061e45 --- /dev/null +++ b/src/main/java/use_case/history/HistoryUserDataAccessInterface.java @@ -0,0 +1,46 @@ +package use_case.history; + +import entity.Translate; +import entity.User; + +import java.util.List; +import java.util.Map; + +/** + * DAO for the History Use Case. + */ +public interface HistoryUserDataAccessInterface { + + /** + * Get all translation history. + * @param user a user. + * @return a list of translates result. + */ + List getAllTranslationsByUser(User user); + + /** + * Get the most recent translation history. + * @param user a user. + * @return a list of recent translates result. + */ + Translate getMostRecentTranslation(User user); + + /** + * Delete the selected translation history. + * @param user a user + * @param translate Translate + */ + void deleteTranslationHistory(User user, Translate translate); + + /** + * Delete all translation history. + * @param user a user + */ + void clearHistory(User user); + +// /** +// * Get a specific translation history. +// * @return a map from input text to translation output. +// */ +// Map getTranslationHistory(); +} diff --git a/src/main/java/use_case/logout/LogoutInputData.java b/src/main/java/use_case/logout/LogoutInputData.java index 56a33b375..5d576e19e 100644 --- a/src/main/java/use_case/logout/LogoutInputData.java +++ b/src/main/java/use_case/logout/LogoutInputData.java @@ -4,9 +4,14 @@ * The Input Data for the Logout Use Case. */ public class LogoutInputData { + private String username; public LogoutInputData(String username) { // TODO: save the current username in an instance variable and add a getter. + this.username = username; } + public String getUsername() { + return this.username; + } } diff --git a/src/main/java/use_case/logout/LogoutInteractor.java b/src/main/java/use_case/logout/LogoutInteractor.java index 1ca93b44e..6a8bde97a 100644 --- a/src/main/java/use_case/logout/LogoutInteractor.java +++ b/src/main/java/use_case/logout/LogoutInteractor.java @@ -11,6 +11,8 @@ public LogoutInteractor(LogoutUserDataAccessInterface userDataAccessInterface, LogoutOutputBoundary logoutOutputBoundary) { // TODO: save the DAO and Presenter in the instance variables. // Which parameter is the DAO and which is the presenter? + this.userDataAccessObject = userDataAccessInterface; + this.logoutPresenter = logoutOutputBoundary; } @Override @@ -20,6 +22,10 @@ public void execute(LogoutInputData logoutInputData) { // * set the username to null in the DAO // * instantiate the `LogoutOutputData`, which needs to contain the username. // * tell the presenter to prepare a success view. + final String username = logoutInputData.getUsername(); + userDataAccessObject.setCurrentUsername(null); + final LogoutOutputData logoutOutputData = new LogoutOutputData(username, false); + logoutPresenter.prepareSuccessView(logoutOutputData); } } diff --git a/src/main/java/use_case/logout/LogoutOutputData.java b/src/main/java/use_case/logout/LogoutOutputData.java index 974279155..05f06f058 100644 --- a/src/main/java/use_case/logout/LogoutOutputData.java +++ b/src/main/java/use_case/logout/LogoutOutputData.java @@ -10,6 +10,8 @@ public class LogoutOutputData { public LogoutOutputData(String username, boolean useCaseFailed) { // TODO: save the parameters in the instance variables. + this.username = username; + this.useCaseFailed = useCaseFailed; } public String getUsername() { diff --git a/src/main/java/use_case/translator/TranslatorInputBoundary.java b/src/main/java/use_case/translator/TranslatorInputBoundary.java new file mode 100644 index 000000000..61e3dcef1 --- /dev/null +++ b/src/main/java/use_case/translator/TranslatorInputBoundary.java @@ -0,0 +1,13 @@ +package use_case.translator; + +/** + * Input Boundary for actions which are related to translate. + */ +public interface TranslatorInputBoundary { + + /** + * Executes the Translator use case. + * @param translatorInputData the input data. + */ + void execute(TranslatorInputData translatorInputData); +} diff --git a/src/main/java/use_case/translator/TranslatorInputData.java b/src/main/java/use_case/translator/TranslatorInputData.java new file mode 100644 index 000000000..c09e7cfd4 --- /dev/null +++ b/src/main/java/use_case/translator/TranslatorInputData.java @@ -0,0 +1,28 @@ +package use_case.translator; + +/** + * The input data for the Translator Use case. + */ +public class TranslatorInputData { + private final String inputLanguage; + private final String outputLanguage; + private final String inputText; + + public TranslatorInputData(String inputLanguage, String outputLanguage, String inputText) { + this.inputLanguage = inputLanguage; + this.outputLanguage = outputLanguage; + this.inputText = inputText; + } + + public String getInputLanguage() { + return inputLanguage; + } + + public String getOutputLanguage() { + return outputLanguage; + } + + public String getInputText() { + return inputText; + } +} diff --git a/src/main/java/use_case/translator/TranslatorInteractor.java b/src/main/java/use_case/translator/TranslatorInteractor.java new file mode 100644 index 000000000..03d2947f0 --- /dev/null +++ b/src/main/java/use_case/translator/TranslatorInteractor.java @@ -0,0 +1,58 @@ +package use_case.translator; + +import entity.Translate; +import entity.TranslateFactory; + +/** + * The Translator Interactor. + */ + +public class TranslatorInteractor implements TranslatorInputBoundary { + private final TranslatorUserDataAccessInterface translatorDataAccessObject; + private final TranslatorOutputBoundary translatorPresenter; + private final TranslateFactory translateFactory; + + public TranslatorInteractor(TranslatorUserDataAccessInterface translatorDataAccessObject, + TranslatorOutputBoundary translatorPresenter, + TranslateFactory translateFactory) { + this.translatorDataAccessObject = translatorDataAccessObject; + this.translatorPresenter = translatorPresenter; + this.translateFactory = translateFactory; + } + + /** + * Executes the translation process with the given input data. + * + * @param inputData the input data containing text and language details + */ + + public void execute(TranslatorInputData inputData) { + final String inputText = inputData.getInputText(); + final String inputLanguage = inputData.getInputLanguage(); + final String outputLanguage = inputData.getOutputLanguage(); + + if (inputText == null || inputText.isBlank()) { + translatorPresenter.prepareFailView("Input text cannot be empty."); + } + + else if (inputLanguage.equals(outputLanguage)) { + translatorPresenter.prepareFailView("Input and output languages must be different."); + } + + else { + try { + final Translate translateObject = translateFactory.create(inputLanguage, outputLanguage, inputText); + final String translatedText = translateObject.getOutputText(); + translatorDataAccessObject.saveTranslation(translateObject); + + + final TranslatorOutputData outputData = new TranslatorOutputData(translatedText, false); + translatorPresenter.prepareSuccessView(outputData); + } + catch (IllegalArgumentException illegalArgumentException) { + translatorPresenter.prepareFailView("An error occurred during translation: " + + illegalArgumentException.getMessage()); + } + } + } +} diff --git a/src/main/java/use_case/translator/TranslatorOutputBoundary.java b/src/main/java/use_case/translator/TranslatorOutputBoundary.java new file mode 100644 index 000000000..855bed32a --- /dev/null +++ b/src/main/java/use_case/translator/TranslatorOutputBoundary.java @@ -0,0 +1,19 @@ +package use_case.translator; + +/** + * The output boundary for the Translator Use Case. + */ +public interface TranslatorOutputBoundary { + + /** + * Prepares the success view for the Translator Use Case. + * @param outputData the output data + */ + void prepareSuccessView(TranslatorOutputData outputData); + + /** + * Prepares the failure view for the Translator Use Case. + * @param errorMessage the explanation of the failure + */ + void prepareFailView(String errorMessage); +} diff --git a/src/main/java/use_case/translator/TranslatorOutputData.java b/src/main/java/use_case/translator/TranslatorOutputData.java new file mode 100644 index 000000000..1c576b60f --- /dev/null +++ b/src/main/java/use_case/translator/TranslatorOutputData.java @@ -0,0 +1,24 @@ +package use_case.translator; + +/** + * Output Data for the Translator Use Case. + */ +public class TranslatorOutputData { + + private final String outputText; + private final boolean useCaseFailed; + + public TranslatorOutputData(String outputText, boolean useCaseFailed) { + this.outputText = outputText; + this.useCaseFailed = useCaseFailed; + } + + public String getOutputText() { + return outputText; + } + + public boolean isUseCaseFailed() { + return useCaseFailed; + } + +} diff --git a/src/main/java/use_case/translator/TranslatorUserDataAccessInterface.java b/src/main/java/use_case/translator/TranslatorUserDataAccessInterface.java new file mode 100644 index 000000000..ca5f317df --- /dev/null +++ b/src/main/java/use_case/translator/TranslatorUserDataAccessInterface.java @@ -0,0 +1,59 @@ +package use_case.translator; + +import java.util.List; + +import entity.Translate; +import entity.User; + +/** + * DAO for handling translation operations. + */ +public interface TranslatorUserDataAccessInterface { + + /** + * Saves a translation request. + * @param translation the translation request to save + */ + void saveTranslation(Translate translation); + + /** + * Retrieves a translation by its ID. + * @param text the unique identifier of the translation + * @return the translation request associated with the given ID + */ + Translate getTranslation(String text); + + /** + * Deletes a translation by its ID. + * @param text the unique identifier of the translation to delete + */ + void deleteTranslation(String text); + + /** + * Retrieves all translation requests made by a specific user. + * @param user the user + * @return a list of translations made by the user + */ + List getAllTranslationsByUser(User user); + + /** + * Retrieves the most recent translation request for a specific user. + * @param user the user + * @return the most recent translation request made by the user + */ + Translate getMostRecentTranslation(User user); + + /** + * Checks if a translation exists by its text. + * @param text the unique input text of the translation + * @return true if the translation exists; false otherwise + */ + boolean existsByText(String text); + + /** + * Updates an existing translation request. + * @param user the user using the translator + * @param updatedTranslation the updated translation details + */ + void updateTranslation(User user, Translate updatedTranslation); +} diff --git a/src/main/java/view/BookmarkView.java b/src/main/java/view/BookmarkView.java new file mode 100644 index 000000000..9a7f08fcb --- /dev/null +++ b/src/main/java/view/BookmarkView.java @@ -0,0 +1,81 @@ +package view; + +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import interface_adapter.bookmark.BookmarkController; +import interface_adapter.bookmark.BookmarkState; +import interface_adapter.bookmark.BookmarkViewModel; + +/** + * The View for the Bookmark Use Case. + */ +public class BookmarkView extends JPanel implements PropertyChangeListener { + + private final String viewName = "bookmark"; + private final BookmarkViewModel bookmarkViewModel; + private BookmarkController bookmarkController; + + private final JButton addBookmarkButton; + private final JButton removeBookmarkButton; + private final JButton backButton; + + public BookmarkView(BookmarkViewModel bookmarkViewModel) { + this.bookmarkViewModel = bookmarkViewModel; + this.bookmarkViewModel.addPropertyChangeListener(this); + + final JLabel title = new JLabel(BookmarkViewModel.TITLE_LABEL); + title.setAlignmentX(Component.CENTER_ALIGNMENT); + + final JPanel buttons = new JPanel(); + addBookmarkButton = new JButton(BookmarkViewModel.ADD_BOOKMARK_BUTTON_LABEL); + buttons.add(addBookmarkButton); + removeBookmarkButton = new JButton(BookmarkViewModel.REMOVE_BOOKMARK_BUTTON_LABEL); + buttons.add(removeBookmarkButton); + backButton = new JButton(BookmarkViewModel.BACK_BUTTON_LABEL); + buttons.add(backButton); + + addBookmarkButton.addActionListener(evt -> { + final BookmarkState currentState = bookmarkViewModel.getState(); + if (currentState != null && currentState.getTranslationId() != null) { + bookmarkController.addBookmark(currentState.getUsername(), currentState.getTranslationId()); + } + }); + + removeBookmarkButton.addActionListener(evt -> { + final BookmarkState currentState = bookmarkViewModel.getState(); + if (currentState != null && currentState.getTranslationId() != null) { + bookmarkController.removeBookmark(currentState.getUsername(), currentState.getTranslationId()); + } + }); + + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + this.add(title); + this.add(buttons); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + final BookmarkState state = (BookmarkState) evt.getNewValue(); + if (state != null) { + if (state.getStatusMessage() != null && !state.getStatusMessage().isEmpty()) { + JOptionPane.showMessageDialog(this, state.getStatusMessage()); + } + } + } + + public String getViewName() { + return viewName; + } + + public void setBookmarkController(BookmarkController controller) { + this.bookmarkController = controller; + } +} diff --git a/src/main/java/view/ChangePasswordView.java b/src/main/java/view/ChangePasswordView.java new file mode 100644 index 000000000..78bf35ca5 --- /dev/null +++ b/src/main/java/view/ChangePasswordView.java @@ -0,0 +1,100 @@ +package view; + +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JTextField; + +import interface_adapter.change_password.ChangePasswordController; +import interface_adapter.change_password.ChangePasswordState; +import interface_adapter.change_password.ChangePasswordViewModel; + +/** + * The View for the Change Password Use Case. + */ +public class ChangePasswordView extends JPanel implements PropertyChangeListener { + + private static final int FIELD_WIDTH = 15; + private final String viewName = "change_password"; + private final ChangePasswordViewModel changePasswordViewModel; + private ChangePasswordController changePasswordController; + private final JTextField usernameField; + private final JPasswordField oldPasswordField; + private final JPasswordField newPasswordField; + private final JButton changePasswordButton; + private final JButton backButton; + + public ChangePasswordView(ChangePasswordViewModel changePasswordViewModel) { + this.changePasswordViewModel = changePasswordViewModel; + this.changePasswordViewModel.addPropertyChangeListener(this); + + final JLabel title = new JLabel(ChangePasswordViewModel.TITLE_LABEL); + title.setAlignmentX(Component.CENTER_ALIGNMENT); + + final JLabel usernameLabel = new JLabel(ChangePasswordViewModel.USERNAME_LABEL); + usernameField = new JTextField(FIELD_WIDTH); + + final JLabel oldPasswordLabel = new JLabel(ChangePasswordViewModel.OLD_PASSWORD_LABEL); + oldPasswordField = new JPasswordField(FIELD_WIDTH); + + final JLabel newPasswordLabel = new JLabel(ChangePasswordViewModel.NEW_PASSWORD_LABEL); + newPasswordField = new JPasswordField(FIELD_WIDTH); + + final JPanel inputPanel = new JPanel(); + inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS)); + inputPanel.add(usernameLabel); + inputPanel.add(usernameField); + inputPanel.add(oldPasswordLabel); + inputPanel.add(oldPasswordField); + inputPanel.add(newPasswordLabel); + inputPanel.add(newPasswordField); + + final JPanel buttons = new JPanel(); + changePasswordButton = new JButton(ChangePasswordViewModel.CHANGE_PASSWORD_BUTTON_LABEL); + buttons.add(changePasswordButton); + backButton = new JButton(ChangePasswordViewModel.BACK_BUTTON_LABEL); + buttons.add(backButton); + + changePasswordButton.addActionListener(evt -> { + final String username = usernameField.getText(); + final String oldPassword = new String(oldPasswordField.getPassword()); + final String newPassword = new String(newPasswordField.getPassword()); + + if (!username.isEmpty() && !oldPassword.isEmpty() && !newPassword.isEmpty()) { + changePasswordController.execute(newPassword, username); + } + }); + + backButton.addActionListener(evt -> changePasswordController.switchToBookmarkView()); + + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + this.add(title); + this.add(inputPanel); + this.add(buttons); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + final ChangePasswordState state = (ChangePasswordState) evt.getNewValue(); + if (state != null) { + if (state.getStatusMessage() != null && !state.getStatusMessage().isEmpty()) { + JOptionPane.showMessageDialog(this, state.getStatusMessage()); + } + } + } + + public String getViewName() { + return viewName; + } + + public void setChangePasswordController(ChangePasswordController controller) { + this.changePasswordController = controller; + } +} diff --git a/src/main/java/view/HistoryView.java b/src/main/java/view/HistoryView.java new file mode 100644 index 000000000..30238d619 --- /dev/null +++ b/src/main/java/view/HistoryView.java @@ -0,0 +1,103 @@ +package view; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import interface_adapter.change_password.LoggedInState; +import interface_adapter.history.HistoryController; +import interface_adapter.history.HistoryState; +import interface_adapter.history.HistoryViewModel; + +import javax.swing.*; +import java.awt.*; +import java.util.Map; + +/** + * The view of translation history. + */ +public class HistoryView extends JPanel implements PropertyChangeListener { + private final String viewname = "history"; + private HistoryViewModel historyViewModel; + private HistoryController historyController; + + private final JButton back; + private final JButton clear; + + public HistoryView(HistoryViewModel historyViewModel) { + this.historyViewModel = historyViewModel; + historyViewModel.addPropertyChangeListener(this); + + final JPanel first = new JPanel(new FlowLayout(FlowLayout.LEFT)); + this.back = new JButton("Back"); + this.clear = new JButton("Clear History"); + first.add(back); + first.add(clear); + + back.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent evt) { + historyController.switchBackToTranslateView(); + } + } + ); + + final JScrollPane scroll = new JScrollPane(); + final HistoryState historyState = historyViewModel.getState(); + final Map historyMap = historyState.getHistory(); + final JPanel insidePanel = new JPanel(); + insidePanel.setLayout(new BoxLayout(insidePanel, BoxLayout.Y_AXIS)); + insidePanel.add(first); + if (historyMap != null) { + for (String key: historyMap.keySet()) { + final JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + final JLabel labelKey = new JLabel(key); + final JLabel labelValue = new JLabel(historyMap.get(key)); + panel.add(labelKey); + panel.add(labelValue); + insidePanel.add(panel, 1); + } + } + + clear.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent evt) { + insidePanel.removeAll(); + insidePanel.add(first); + } + } + ); + + scroll.add(insidePanel); + this.add(scroll); + scroll.setViewportView(insidePanel); + } + + /** + * React to a button click that results in evt. + * @param evt the ActionEvent to react to + */ + public void actionPerformed(ActionEvent evt) { + System.out.println("Click " + evt.getActionCommand()); + } + + /** + * @param evt A PropertyChangeEvent object describing the event source + * and the property that has changed. + */ + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("history")) { + this.back.setVisible(true); + } + } + + public String getViewName() { + return viewname; + } + + public void setHistoryController(HistoryController historyController) { + this.historyController = historyController; + } +} diff --git a/src/main/java/view/LoggedInView.java b/src/main/java/view/LoggedInView.java deleted file mode 100644 index 76d40c0f1..000000000 --- a/src/main/java/view/LoggedInView.java +++ /dev/null @@ -1,143 +0,0 @@ -package view; - -import java.awt.Component; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -import interface_adapter.change_password.ChangePasswordController; -import interface_adapter.change_password.LoggedInState; -import interface_adapter.change_password.LoggedInViewModel; -import interface_adapter.logout.LogoutController; - -/** - * The View for when the user is logged into the program. - */ -public class LoggedInView extends JPanel implements PropertyChangeListener { - - private final String viewName = "logged in"; - private final LoggedInViewModel loggedInViewModel; - private final JLabel passwordErrorField = new JLabel(); - private ChangePasswordController changePasswordController; - private LogoutController logoutController; - - private final JLabel username; - - private final JButton logOut; - - private final JTextField passwordInputField = new JTextField(15); - private final JButton changePassword; - - public LoggedInView(LoggedInViewModel loggedInViewModel) { - this.loggedInViewModel = loggedInViewModel; - this.loggedInViewModel.addPropertyChangeListener(this); - - final JLabel title = new JLabel("Logged In Screen"); - title.setAlignmentX(Component.CENTER_ALIGNMENT); - - final LabelTextPanel passwordInfo = new LabelTextPanel( - new JLabel("Password"), passwordInputField); - - final JLabel usernameInfo = new JLabel("Currently logged in: "); - username = new JLabel(); - - final JPanel buttons = new JPanel(); - logOut = new JButton("Log Out"); - buttons.add(logOut); - - changePassword = new JButton("Change Password"); - buttons.add(changePassword); - - this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - - passwordInputField.getDocument().addDocumentListener(new DocumentListener() { - - private void documentListenerHelper() { - final LoggedInState currentState = loggedInViewModel.getState(); - currentState.setPassword(passwordInputField.getText()); - loggedInViewModel.setState(currentState); - } - - @Override - public void insertUpdate(DocumentEvent e) { - documentListenerHelper(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - documentListenerHelper(); - } - - @Override - public void changedUpdate(DocumentEvent e) { - documentListenerHelper(); - } - }); - - changePassword.addActionListener( - // This creates an anonymous subclass of ActionListener and instantiates it. - evt -> { - if (evt.getSource().equals(changePassword)) { - final LoggedInState currentState = loggedInViewModel.getState(); - - this.changePasswordController.execute( - currentState.getUsername(), - currentState.getPassword() - ); - } - } - ); - - logOut.addActionListener( - // This creates an anonymous subclass of ActionListener and instantiates it. - evt -> { - if (evt.getSource().equals(logOut)) { - // TODO: execute the logout use case through the Controller - // 1. get the state out of the loggedInViewModel. It contains the username. - // 2. Execute the logout Controller. - } - } - ); - - this.add(title); - this.add(usernameInfo); - this.add(username); - - this.add(passwordInfo); - this.add(passwordErrorField); - this.add(buttons); - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals("state")) { - final LoggedInState state = (LoggedInState) evt.getNewValue(); - username.setText(state.getUsername()); - } - else if (evt.getPropertyName().equals("password")) { - final LoggedInState state = (LoggedInState) evt.getNewValue(); - JOptionPane.showMessageDialog(null, "password updated for " + state.getUsername()); - } - - } - - public String getViewName() { - return viewName; - } - - public void setChangePasswordController(ChangePasswordController changePasswordController) { - this.changePasswordController = changePasswordController; - } - - public void setLogoutController(LogoutController logoutController) { - // TODO: save the logout controller in the instance variable. - } -} diff --git a/src/main/java/view/TranslateView.java b/src/main/java/view/TranslateView.java new file mode 100644 index 000000000..b33234d68 --- /dev/null +++ b/src/main/java/view/TranslateView.java @@ -0,0 +1,290 @@ +package view; + +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.*; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +import data_access.InMemoryUserDataAccessObject; +import entity.Translate; +import entity.User; +import interface_adapter.change_password.ChangePasswordController; +import interface_adapter.change_password.LoggedInState; +import interface_adapter.change_password.LoggedInViewModel; +import interface_adapter.history.HistoryController; +import interface_adapter.history.HistoryState; +import interface_adapter.history.HistoryViewModel; +import interface_adapter.logout.LogoutController; +import interface_adapter.translate.TranslateController; +import interface_adapter.translate.TranslateState; +import interface_adapter.translate.TranslateViewModel; +import org.json.JSONArray; +import org.json.JSONString; +import use_case.history.HistoryUserDataAccessInterface; +import use_case.login.LoginUserDataAccessInterface; + +/** + * The View for when the user is logged into the program. + */ +public class TranslateView extends JPanel implements PropertyChangeListener { + + private final String viewName = "logged in"; + private final LoggedInViewModel loggedInViewModel; + private final TranslateViewModel translateViewModel; + private final HistoryViewModel historyViewModel; + private final JLabel passwordErrorField = new JLabel(); + private ChangePasswordController changePasswordController; + private LogoutController logoutController; + private TranslateController translateController; + private HistoryController historyController; + + private final JLabel username; + + private final JButton logOut; + private final JButton translate; + private final JButton history; + + private final JTextField languageInputField = new JTextField(15); + private final JTextField languageOutputField = new JTextField(15); + + public TranslateView(LoggedInViewModel loggedInViewModel, TranslateViewModel translateViewModel, + HistoryViewModel historyViewModel) { + this.loggedInViewModel = loggedInViewModel; + this.translateViewModel = translateViewModel; + this.historyViewModel = historyViewModel; + this.loggedInViewModel.addPropertyChangeListener(this); + this.translateViewModel.addPropertyChangeListener(this); + this.historyViewModel.addPropertyChangeListener(this); + + final JLabel title = new JLabel("Translator Name"); + title.setAlignmentX(Component.CENTER_ALIGNMENT); +// final LabelTextPanel languageInput = new LabelTextPanel( +// new JLabel(""), languageInputField); +// +// final LabelTextPanel languageOutput = new LabelTextPanel( +// new JLabel(""), languageOutputField); + + final JLabel usernameInfo = new JLabel("Currently logged in: "); + username = new JLabel(); + +// final JLabel languageInfo = new JLabel("Language"); +// final JLabel translatedLanguageInfo = new JLabel(" Language"); + + // final JLabel sourceLanguageLabel = new JLabel("Source Language: "); + // final JLabel translatedLanguageLabel = new JLabel("Translated Language: "); + + // final JPanel buttons = new JPanel(); + logOut = new JButton("Log Out"); + this.add(logOut); + + translate = new JButton("Translate"); + this.add(translate); + + history = new JButton("History"); + this.add(history); + + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + final String[] languages = {"Danish", "German", "English", "Spanish", "French", "Italian", "Japanese", "Korean", + "Norwegian Bokmål", "Dutch", "Polish", "Portuguese", "Romanian", "Russian", "Swedish", "Chinese"}; + final String[] codes = {"DA", "DE", "EN", "ES", "FR", "IT", "JA", "KO", "NB", "NL", "PL", "PT", "RO", "RU", + "SV", "ZH"}; + final String[] codes2 = {"DA", "DE", "EN-US", "ES", "FR", "IT", "JA", "KO", "NB", "NL", "PL", "PT", "RO", "RU", + "SV", "ZH"}; + + Map languagesToCodes = new HashMap<>(); + Map languagesToCodes2 = new HashMap<>(); + for (int i = 0; i < languages.length; i++) { + languagesToCodes.put(languages[i], codes[i]); + languagesToCodes2.put(languages[i], codes2[i]); + } + // final List languageslist = new ArrayList<>(Arrays.asList(languages)); + final JComboBox sourceLanguageBox = new JComboBox(); + final JComboBox resultLanguageBox = new JComboBox(); + for (String language: languages) { + sourceLanguageBox.addItem(language); + resultLanguageBox.addItem(language); + } + + sourceLanguageBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final TranslateState currentState = translateViewModel.getState(); + currentState.setInputLanguage((String) languagesToCodes.get(sourceLanguageBox.getSelectedItem())); + +// final LoginUserDataAccessInterface userDataAccessObject = new InMemoryUserDataAccessObject(); +// final User user = userDataAccessObject.get(currentState.getUsername()); +// this.translateController.execute(user); + } + }); + + resultLanguageBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final TranslateState currentState = translateViewModel.getState(); + currentState.setOutputLanguage((String) languagesToCodes2.get(resultLanguageBox.getSelectedItem())); +// translateController.execute("English (American)", currentState.getOutputLanguage(), +// currentState.getInputText()); + } + }); + + final JPanel firstRow = new JPanel(new FlowLayout(FlowLayout.LEFT)); + firstRow.add(sourceLanguageBox); + firstRow.add(translate); + firstRow.add(resultLanguageBox); + + final JPanel seconedRow = new JPanel(new FlowLayout(FlowLayout.LEFT)); + seconedRow.add(languageInputField); + seconedRow.add(languageOutputField); + + final JPanel thiredRow = new JPanel(new FlowLayout(FlowLayout.LEFT)); + thiredRow.add(history); + + languageInputField.getDocument().addDocumentListener(new DocumentListener() { + private void documentListenerHelper() { + final TranslateState currentState = translateViewModel.getState(); + currentState.setInputText(languageInputField.getText()); + translateViewModel.setState(currentState); + } + + @Override + public void insertUpdate(DocumentEvent e) { + documentListenerHelper(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + documentListenerHelper(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + documentListenerHelper(); + } + }); + + + + +// languageOutputField.getDocument().addDocumentListener(new DocumentListener() { +// +// private void documentListenerHelper() { +// final LoggedInState currentState = loggedInViewModel.getState(); +// currentState.setPassword(languageOutputField.getText()); +// loggedInViewModel.setState(currentState); +// } +// +// @Override +// public void insertUpdate(DocumentEvent e) { +// documentListenerHelper(); +// } +// +// @Override +// public void removeUpdate(DocumentEvent e) { +// documentListenerHelper(); +// } +// +// @Override +// public void changedUpdate(DocumentEvent e) { +// documentListenerHelper(); +// } +// }); + + translate.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent evt) { + if (evt.getSource().equals(translate)) { + final TranslateState currentState = translateViewModel.getState(); + + translateController.execute( + currentState.getInputLanguage(), + currentState.getOutputLanguage(), currentState.getInputText() + ); + } + } + } + ); + + logOut.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent evt) { + if (evt.getSource().equals(logOut)) { + // 1. get the state out of the loggedInViewModel. It contains the username. + // 2. Execute the logout Controller. + final LoggedInState currentState = loggedInViewModel.getState(); + + logoutController.execute( + currentState.getUsername() + ); + } + } + } + ); + + history.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent evt) { + if (evt.getSource().equals(history)) { + final LoggedInState currentState = loggedInViewModel.getState(); + final LoginUserDataAccessInterface userDataAccessObject = new InMemoryUserDataAccessObject(); + final User user = userDataAccessObject.get(currentState.getUsername()); + historyController.execute(user); + historyController.switchToHistoryView(); + } + } + } + ); + + this.add(title); + this.add(usernameInfo); + this.add(username); + + this.add(firstRow); + + this.add(seconedRow); + + this.add(thiredRow); + + this.add(logOut); + } + + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("login")) { + final LoggedInState state = (LoggedInState) evt.getNewValue(); + username.setText(state.getUsername()); + } + else if (evt.getPropertyName().equals("password")) { + final LoggedInState state = (LoggedInState) evt.getNewValue(); + JOptionPane.showMessageDialog(null, "password updated for " + state.getUsername()); + } + if (evt.getPropertyName().equals("state")) { + final TranslateState state = (TranslateState) evt.getNewValue(); + languageOutputField.setText(state.getOutputText()); + } + } + + public String getViewName() { + return viewName; + } + + public void setChangePasswordController(ChangePasswordController changePasswordController) { + this.changePasswordController = changePasswordController; + } + + public void setLogoutController(LogoutController logoutController) { + this.logoutController = logoutController; + } + + public void setTranslateController(TranslateController translateController) { + this.translateController = translateController; + } + + public void setHistoryController(HistoryController historyController) { + this.historyController = historyController; + } +}