Resolve "Fill out previous methods, classes and packages with Javadocs"

This commit is contained in:
2021-10-22 13:44:08 +00:00
parent b92b9f481b
commit 11e92de3e6
26 changed files with 306 additions and 75 deletions
@@ -8,6 +8,9 @@ import it1901.groups2021.gr2141.core.models.CardContent;
import it1901.groups2021.gr2141.core.models.CardDeck;
import it1901.groups2021.gr2141.core.state.Observable;
/**
* A class handling card navigation from a CardDeck
*/
public class FlashcardProvider extends Observable<FlashcardProvider> {
private static final Preferences prefs = Preferences.userRoot().node(FlashcardProvider.class.getName());
@@ -20,24 +23,37 @@ public class FlashcardProvider extends Observable<FlashcardProvider> {
private boolean cardOrderIsRandomMode;
private boolean firstLastWrapAroundMode;
/**
* Default constructor.
*
* @param deck the initial carddeck to register to the provider.
*/
public FlashcardProvider(CardDeck deck) {
this.setCardDeck(deck);
this.cardIndex = 0;
this.cardShowsFront = true;
this.showOrderIsFlippedMode = prefs.getBoolean("showOrderIsFlippedMode", false);
this.cardOrderIsRandomMode = prefs.getBoolean("cardOrderIsRandomMode",false);
this.cardOrderIsRandomMode = prefs.getBoolean("cardOrderIsRandomMode", false);
this.firstLastWrapAroundMode = prefs.getBoolean("firstLastWrapAroundMode", true);
}
private void updateSubscribers() {
super.updateSubscribers(this);
}
/**
* @return The active deck
*/
public CardDeck getCardDeck() {
return this.deck;
return this.deck;
}
/**
* Replace the active deck with a new one.
*
* @param deck The new deck.
*/
public void setCardDeck(CardDeck deck) {
if (deck == null) {
throw new IllegalArgumentException("deck can not be null.");
@@ -54,25 +70,27 @@ public class FlashcardProvider extends Observable<FlashcardProvider> {
updateSubscribers();
}
/**
* @return the number of the currently chosen card.
*/
public int getCardIndex() {
return this.cardIndex;
return this.cardIndex;
}
/**
* Updates the UI to show a new card.
*
* @param card
* @return the showing side of the currently chosen card.
*/
public CardContent getCard() {
var card = this.deck.getFlashcards().get(cardIndex);
return cardShowsFront ^ showOrderIsFlippedMode ? card.getFront() : card.getBack();
}
/**
* When at last card in deck, turn to first card in deck when pressing next card
* Turn to a specified card. This will also turn the card so that it shows the
* front. If randomMode is activated, this will choose a random card, no matter
* what cardIndex is given.
*
* @param cardIndex
* @param cardIndex The number of the card to turn to.
*/
public void turnToCard(int cardIndex) throws IllegalArgumentException {
if (!(firstLastWrapAroundMode || cardOrderIsRandomMode)
@@ -92,29 +110,34 @@ public class FlashcardProvider extends Observable<FlashcardProvider> {
cardShowsFront = true;
updateSubscribers();
}
// used for later iterations
// public void turnToFirstCard() {
// turnToCard(0);
// turnToCard(0);
// }
// public void turnToLastCard() {
// turnToCard(this.deck.getNumberOfCards() - 1);
// turnToCard(this.deck.getNumberOfCards() - 1);
// }
public void turnToNextCard() throws IllegalArgumentException {
/**
* Turn to the next card in the stack.
*
* @see #turnToCard(int) for more details.
*/
public void turnToNextCard() {
turnToCard(this.cardIndex + 1);
}
public void turnToPreviousCard() throws IllegalArgumentException {
/**
* Turn to the previous card in the stack.
*
* @see #turnToCard(int) for more details.
*/
public void turnToPreviousCard() {
turnToCard(this.cardIndex - 1);
}
/**
* Generate a random cardIndex
*
* @return cardIndex
*/
private int generateRandomCardIndex() {
if (deck.getNumberOfCards() <= 1) {
return 0;
@@ -127,41 +150,75 @@ public class FlashcardProvider extends Observable<FlashcardProvider> {
}
/**
* Flip the current card to show the other side.
*/
public void flipCard() {
this.cardShowsFront = !this.cardShowsFront;
updateSubscribers();
}
/**
* @return Whether the backside is show first by default.
*/
public boolean isShowOrderIsFlippedMode() {
return this.showOrderIsFlippedMode;
}
/**
* @return Whether turning the card results in a random card.
*/
public boolean isCardOrderIsRandomMode() {
return this.cardOrderIsRandomMode;
}
/**
* This is turned on by default.
*
* @return Whether the provider shows the first card when executing
* {@link #turnToNextCard turnToNextCard} at the last card in the deck,
* and the same for the other way around.
*/
public boolean isFirstLastWrapAroundMode() {
return this.firstLastWrapAroundMode;
}
/**
* Turn on/off ShowOrderIsFlippedMode. This will also save the state to disk.
*
* @see #isShowOrderIsFlippedMode()
*/
public void toggleShowOrderIsFlippedMode() {
this.showOrderIsFlippedMode = !this.showOrderIsFlippedMode;
prefs.putBoolean("showOrderIsFlippedMode", this.showOrderIsFlippedMode);
updateSubscribers();
}
/**
* Turn on/off CardOrderIsRandomMode. This will also save the state to disk.
*
* @see #isCardOrderIsRandomMode
*/
public void toggleCardOrderIsRandomMode() {
this.cardOrderIsRandomMode = !this.cardOrderIsRandomMode;
prefs.putBoolean("cardOrderIsRandomMode", this.cardOrderIsRandomMode);
updateSubscribers();
}
/**
* Turn on/off FirstLastWrapAroundMode. This will also save the state to disk.
*
* @see #isFirstLastWrapAroundMode()
*/
public void toggleFirstLastWrapAroundMode() {
this.firstLastWrapAroundMode = !this.firstLastWrapAroundMode;
prefs.putBoolean("firstLastWrapAroundMode", this.firstLastWrapAroundMode);
updateSubscribers();
}
/**
* Set all modes to their default values.
*/
public void resetModes() {
this.showOrderIsFlippedMode = false;
this.cardOrderIsRandomMode = false;
@@ -169,6 +226,9 @@ public class FlashcardProvider extends Observable<FlashcardProvider> {
updateSubscribers();
}
/**
* Clear the stored values from disk.
*/
public static void clearPreferences() {
List.of(
"showOrderIsFlippedMode",
@@ -0,0 +1,4 @@
/**
* Classes which provides core logic, like handling interaction between models.
*/
package it1901.groups2021.gr2141.core.domainlogic;
@@ -14,7 +14,6 @@ public class CardContent {
/**
* Create a new instance with lines of text.
* @param lines The lines of text.
* @throws IllegalArgumentException if the lines are null, or the list is empty.
*/
public CardContent(List<String> lines) {
if (lines == null || lines.size() == 0)
@@ -25,8 +24,7 @@ public class CardContent {
/**
* Create a new instance with lines of text.
* @param lines The lines of text.
* @throws IllegalArgumentException if the lines are null, or the list is empty.
* @param text The lines of text.
*/
public CardContent(String text) {
if (text == null || text.length() == 0)
@@ -50,6 +48,9 @@ public class CardContent {
return lines;
}
/**
* @return All lines as a string.
*/
public String getText() {
return String.join("\n", lines);
}
@@ -23,7 +23,6 @@ public class CardDeck extends Observable<CardDeck> {
* Create an instance from a list of {@link Flashcard Flashcard}s
*
* @param flashcards A list of {@link Flashcard Flashcard} instances
* @throws IllegalArgumentException if flashcards is null.
*/
public CardDeck(List<Flashcard> flashcards) {
if (flashcards == null)
@@ -82,7 +81,6 @@ public class CardDeck extends Observable<CardDeck> {
* Add a new flashcard to the deck. Has the bieffect of updating all listeners.
*
* @param card The new flashcard to add.
* @throws IllegalArgumentException if card is null.
*/
public void add(Flashcard card) {
if (card == null)
@@ -98,8 +96,6 @@ public class CardDeck extends Observable<CardDeck> {
*
* @param index The index of where to add the card.
* @param card The new flashcard to add.
* @throws IllegalArgumentException if card is null or if the index is out of
* range.
*/
public void add(int index, Flashcard card) {
if (card == null)
@@ -117,8 +113,6 @@ public class CardDeck extends Observable<CardDeck> {
*
* @param index The index of the card to update.
* @param card The updated flashcard.
* @throws IllegalArgumentException if card is null or if the index is out of
* range.
*/
public void update(int index, Flashcard card) {
if (card == null)
@@ -137,7 +131,6 @@ public class CardDeck extends Observable<CardDeck> {
* listeners.
*
* @param index The index of the card to remove
* @throws IllegalArgumentException if the index is out of range
*/
public void remove(int index) {
if (index < 0 || index > flashcards.size())
@@ -1,7 +1,6 @@
package it1901.groups2021.gr2141.core.models;
import java.util.List;
import java.util.Arrays;
/**
* Data model representing a flashcard.
@@ -17,7 +16,6 @@ public class Flashcard {
*
* @param front The front side of the card
* @param back The back side of the card
* @throws IllegalArgumentException if either side is null.
*/
public Flashcard(CardContent front, CardContent back) {
if (front == null || back == null)
@@ -16,10 +16,18 @@ import com.fasterxml.jackson.databind.JsonNode;
* Deserializer for {@link it1901.groups2021.gr2141.core.models.CardContent CardContent}
*/
public class CardContentDeserializer extends StdDeserializer<CardContent> {
/**
* Constructor sets card content deserializer to null
*/
public CardContentDeserializer() {
this(null);
}
/**
* Initialize super object
* @param t
*/
public CardContentDeserializer(Class<CardContent> t) {
super(t);
}
@@ -31,6 +39,9 @@ public class CardContentDeserializer extends StdDeserializer<CardContent> {
return deserialize(node);
}
/**
* Deserialization logic
*/
CardContent deserialize(JsonNode node) {
List<String> lines = new ArrayList<>();
@@ -11,10 +11,17 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
* Serializer for {@link it1901.groups2021.gr2141.core.models.CardContent CardContent}
*/
public class CardContentSerializer extends StdSerializer<CardContent> {
/**
* Constructor sets card content serializer to null
*/
public CardContentSerializer() {
this(null);
}
/**
* Initialize super object
* @param t
*/
public CardContentSerializer(Class<CardContent> t) {
super(t);
}
@@ -20,10 +20,17 @@ public class CardDeckDeserializer extends StdDeserializer<CardDeck> {
private FlashcardDeserializer flashcardDeserializer = new FlashcardDeserializer();
/**
* Constructor sets card deck deserializer to null
*/
public CardDeckDeserializer() {
this(null);
}
/**
* Initialize super object
* @param t
*/
public CardDeckDeserializer(Class<CardDeck> t) {
super(t);
}
@@ -34,6 +41,9 @@ public class CardDeckDeserializer extends StdDeserializer<CardDeck> {
return deserialize(node);
}
/**
* Deserialization logic
*/
CardDeck deserialize(JsonNode node) {
List<Flashcard> cards = new ArrayList<>();
@@ -12,10 +12,18 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
* Serializer for {@link it1901.groups2021.gr2141.core.models.CardDeck CardDeck}
*/
public class CardDeckSerializer extends StdSerializer<CardDeck> {
/**
* Constructor sets card deck serializer to null
*/
public CardDeckSerializer() {
this(null);
}
/**
* Initialize super object
* @param t
*/
public CardDeckSerializer(Class<CardDeck> t) {
super(t);
}
@@ -18,10 +18,17 @@ public class FlashcardDeserializer extends StdDeserializer<Flashcard> {
private CardContentDeserializer cardContentDeserializer = new CardContentDeserializer();
/**
* Constructor sets flashcard deserializer to null
*/
public FlashcardDeserializer() {
this(null);
}
/**
* Initialize super object
* @param t
*/
public FlashcardDeserializer(Class<Flashcard> t) {
super(t);
}
@@ -33,6 +40,9 @@ public class FlashcardDeserializer extends StdDeserializer<Flashcard> {
return deserialize(node);
}
/**
* Deserialization logic
*/
Flashcard deserialize(JsonNode node) {
CardContent front = cardContentDeserializer.deserialize(node.get("front"));
CardContent back = cardContentDeserializer.deserialize(node.get("back"));
@@ -12,10 +12,18 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
* Serializer for {@link it1901.groups2021.gr2141.core.models.Flashcard Flashcard}
*/
public class FlashcardSerializer extends StdSerializer<Flashcard> {
/**
* Constructor sets flashcard serializer to null
*/
public FlashcardSerializer() {
this(null);
}
/**
* Initialize super object
* @param t
*/
public FlashcardSerializer(Class<Flashcard> t) {
super(t);
}
@@ -13,6 +13,10 @@ public class ModelSerializingModule extends SimpleModule {
private static final String NAME = "FlashcardModule";
/**
* Model that initializes serializing and deserializing
*
*/
public ModelSerializingModule() {
super(NAME, Version.unknownVersion());
addSerializer(CardContent.class, new CardContentSerializer());
@@ -4,17 +4,35 @@ import java.util.Collection;
import java.util.function.Consumer;
import java.util.ArrayList;
/**
* A class that lets its subclasses execute a set of subscriber functions every
* time something changes.
*/
public abstract class Observable<T> {
private Collection<Consumer<T>> subscribers = new ArrayList<>();
public void subscribe(Consumer<T> function) throws IllegalArgumentException {
/**
* Add a function to execute whenever {@link #updateSubscribers
* updateSubscribers} is run
*
* @param function An executable
*/
public void subscribe(Consumer<T> function) {
this.subscribers.add(function);
}
/**
* Execute all subscriber functions
*
* @param newValue the new state of the object.
*/
public void updateSubscribers(T newValue) {
this.subscribers.forEach((s) -> s.accept(newValue));
}
/**
* Remove all subscriber functions
*/
public void clearSubscribers() {
this.subscribers.clear();
}
@@ -0,0 +1,4 @@
/**
* Classes which are used to help organize state.
*/
package it1901.groups2021.gr2141.core.state;
@@ -14,12 +14,18 @@ import it1901.groups2021.gr2141.core.models.CardDeck;
import it1901.groups2021.gr2141.core.models.serializers.ModelSerializingModule;
/**
* A class which handles saving/loading {@link it1901.groups2021.gr2141.core.models.CardDeck CardDeck}s.
* A class which handles saving/loading
* {@link it1901.groups2021.gr2141.core.models.CardDeck CardDeck}s.
*/
public final class CardDeckStorage {
private static final ObjectMapper mapper = new ObjectMapper().registerModule(new ModelSerializingModule());
private static Path dataDirectory = getUserDataDirectory();
/**
* Override the default data directory with a new one.
*
* @param dataDirectory The path to the new data directory.
*/
public static void setUserDataDirectory(Path dataDirectory) {
if (dataDirectory == null)
throw new IllegalArgumentException("dataDirectory can not be null");
@@ -27,28 +33,41 @@ public final class CardDeckStorage {
CardDeckStorage.dataDirectory = dataDirectory;
};
// private CardDeckStorage() {}
private CardDeckStorage() {}
/**
* @return Name of operating system
*/
protected static String getOSName() {
return (System.getProperty("os.name")).toLowerCase();
}
/**
* @return Data directory for all Windows systems.
*/
protected static Path getWindowsDataRootPath() {
return Paths.get(System.getenv("AppData"));
}
/**
* @return Data directory for all UNIX-like systems. This is the default
* location according to the XDG-specification
*
* @see <a href=
* "https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html">specifications.freedesktop.org</a>
*/
protected static Path getUnixDataRootPath() {
return Paths.get(System.getProperty("user.home"), ".local/share");
}
/**
* Sets a directory where the json file is saved.
*
* @return the directory
* @see #getDataFiles()
* @see #writeDeck(CardDeck)
* @see #readDeck(int)
*/
* Sets a directory where the user data is saved.
*
* @return the directory
* @see #getDataFiles()
* @see #writeDeck(CardDeck)
* @see #readDeck(int)
*/
public static Path getUserDataDirectory() {
String OS = getOSName();
Path dataDir;
@@ -77,29 +96,32 @@ public final class CardDeckStorage {
return Arrays.asList(dataDirectory.toFile().listFiles());
}
/**
* Check the ids (names) of all files in dataDirectory, and return the next
* available id
*
* @return id
*/
private static int getNextDeckID() {
var i = 0;
while (dataDirectory.resolve("deck-" + i + ".json").toFile().exists()) i++;
while (dataDirectory.resolve("deck-" + i + ".json").toFile().exists())
i++;
return i;
}
/** Write a card deck to the next available id
/**
* Write a card deck to the next available id
*
* @param deck
* @throws IOException if deck is not found
*/
public static void writeDeck(CardDeck deck) throws IOException {
writeDeck(deck, getNextDeckID());
}
/**
* Write a card deck to a specific id. Create the file if it doesn't exist.
* Check that id is not a negative number
* Write a card deck with a specified. This will overwrite the deck already
* saved, if it exists.
*
* @param deck The deck to be saved
* @param id The id to write the deck to.
* @see #writeDeckToFile(File, CardDeck)
* @throws IOException if deck is not found
* @throws IllegalArgumentException when id is less than 0
*/
public static void writeDeck(CardDeck deck, int id) throws IOException {
if (id < 0)
@@ -113,11 +135,25 @@ public final class CardDeckStorage {
writeDeckToFile(file, deck);
}
/**
* Reads a CardDeck from disk with specified id.
*
* @param id The id of the CardDeck to read.
* @return The specified CardDeck.
* @throws IOException if deck id is not found
*/
public static CardDeck readDeck(int id) throws IOException {
File file = dataDirectory.resolve("deck-" + Integer.toString(id) + ".json").toFile();
return readDeckFromFile(file);
}
/**
* Reads all saved CardDecks.
*
* @see #readDeck(int)
* @return A list of all the CardDecks on disk.
* @throws IOException if deck is not found
*/
public static List<CardDeck> readAllDecks() throws IOException {
List<CardDeck> result = new ArrayList<>();
for (File f : getDataFiles()) {
@@ -1,4 +1,4 @@
/**
* Classes which logic for saving and loading data.
* Classes with logic for saving and loading data.
*/
package it1901.groups2021.gr2141.core.storage;
@@ -9,9 +9,10 @@ import javafx.fxml.Initializable;
import it1901.groups2021.gr2141.ui.controllers.Controller;
/**
* Root controller of the application UI.
* Root UI controller
*/
public class AppController extends Controller implements Initializable {
private static void setupStorageListener() {
getFlashcardProvider().subscribe((newModel) -> {
try {
@@ -8,12 +8,18 @@ import it1901.groups2021.gr2141.core.models.CardDeck;
import it1901.groups2021.gr2141.core.models.Flashcard;
import it1901.groups2021.gr2141.core.storage.CardDeckStorage;
/**
* A singleton containing the state of the whole application.
*/
public final class AppState {
private static FlashcardProvider flashCardProvider;
private AppState() {}
/**
* Initialize the FlashcardProvider with default values.
*/
public static void initializeProvider() {
CardDeck deck;
@@ -26,15 +32,23 @@ public final class AppState {
flashCardProvider = new FlashcardProvider(deck);
}
/**
* @return The FlashcardProvider.
*/
public static FlashcardProvider getFlashcardProvider() {
return flashCardProvider;
}
public static void setFlashcardProvider(FlashcardProvider flashCardProvider) {
if (flashCardProvider == null) {
/**
* Swap the old FlashcardProvider for a new one.
*
* @param flashcardProvider The new provider.
*/
public static void setFlashcardProvider(FlashcardProvider flashcardProvider) {
if (flashcardProvider == null) {
throw new IllegalArgumentException(" can not be null");
}
AppState.flashCardProvider = flashCardProvider;
AppState.flashCardProvider = flashcardProvider;
}
}
@@ -13,7 +13,11 @@ import javafx.scene.image.Image;
* Root of the application.
*/
public class Flashy extends Application {
/**
* Starting the application
* @param args
*/
public static void main(String[] args) {
launch(args);
}
@@ -17,23 +17,25 @@ public class CardAreaController extends Controller implements Initializable {
@FXML
private Label showCard;
/**
* Initializes the card deck.
*
* @param url
* @param resourceBundle
*/
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
showCurrentCardContent();
getFlashcardProvider().subscribe((newFlashCardModel) -> showCurrentCardContent());
}
/**
* Updates the card shown in the UI
*/
public void showCurrentCardContent() {
var content = getFlashcardProvider().getCard();
showCard.setText(content.getText());
}
/**
* Flips the card. This is connected to an FXML element.
*
* @param event
*/
@FXML
public void handleFlipCardMouse(MouseEvent event) {
getFlashcardProvider().flipCard();
@@ -3,13 +3,26 @@ package it1901.groups2021.gr2141.ui.controllers;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
/**
* Card Navigation controller of the application UI.
*/
public class CardNavigationController extends Controller {
/**
* Flips the card by pressing the button.
*
* @param event
*/
@FXML
public void handleFlipCardButton(ActionEvent event) {
getFlashcardProvider().flipCard();
}
/**
* Turns to the next card in the deck.
*
* @param event
*/
@FXML
public void handleTurnToNextCard(ActionEvent event) {
try {
@@ -17,6 +30,11 @@ public class CardNavigationController extends Controller {
} catch (IllegalArgumentException e) {}
}
/**
* Turns to the previous card in the deck.
*
* @param event
*/
@FXML
public void handleTurnToPreviousCard(ActionEvent event) {
try {
@@ -3,7 +3,14 @@ package it1901.groups2021.gr2141.ui.controllers;
import it1901.groups2021.gr2141.core.domainlogic.FlashcardProvider;
import it1901.groups2021.gr2141.ui.AppState;
/**
* Common elements for all JavaFX Controllers
*/
public abstract class Controller {
/**
* @return the FlashCardProvider for the application state
*/
protected static FlashcardProvider getFlashcardProvider() {
return AppState.getFlashcardProvider();
}
@@ -17,7 +17,7 @@ public class MenuController extends Controller {
private TextField writeBack;
/**
* Creates a card and saves the card
* Creates a new card and adds it to the active deck.
*
* @param event
*/
@@ -23,12 +23,6 @@ public class NavbarController extends Controller implements Initializable {
@FXML
private ToggleButton btnToggleShowOtherSide;
/**
* Initializes the card deck.
*
* @param url
* @param resourceBundle
*/
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
setToggleButtonValues();
@@ -40,16 +34,28 @@ public class NavbarController extends Controller implements Initializable {
btnToggleFirstLastWrapAroundMode.setSelected(getFlashcardProvider().isFirstLastWrapAroundMode());
}
/**
* @see it1901.groups2021.gr2141.core.domainlogic.FlashcardProvider#isShowOrderIsFlippedMode
* @param event
*/
@FXML
public void handleToggleShowOtherSide(ActionEvent event) {
getFlashcardProvider().toggleShowOrderIsFlippedMode();
}
/**
* @see it1901.groups2021.gr2141.core.domainlogic.FlashcardProvider#isCardOrderIsRandomMode for more details.
* @param event
*/
@FXML
public void handleToggleCardOrderIsRandom(ActionEvent event) {
getFlashcardProvider().toggleCardOrderIsRandomMode();
}
/**
* @see it1901.groups2021.gr2141.core.domainlogic.FlashcardProvider#isFirstLastWrapAroundMode for more details.
* @param event
*/
@FXML
public void handleToggleFirstLastWrapAroundMode(ActionEvent event) {
getFlashcardProvider().toggleFirstLastWrapAroundMode();
@@ -0,0 +1,4 @@
/**
* Controllers for the JavaFX user interface components.
*/
package it1901.groups2021.gr2141.ui.controllers;
@@ -4,11 +4,14 @@ import it1901.groups2021.gr2141.ui.Flashy;
/**
* A starting point of the application.
*
* Should be used as the starting point when the application is packaged into a JAR file.
*/
public class FlashyLauncher {
/**
* Should be used as the starting point when the application is packaged into a JAR file.
*
* @param args
*/
public static void main(String[] args) {
Flashy.main(args);
}