diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/controller/PlayerStatusController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/controller/PlayerStatusController.java index aa45ab6..b69af32 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/controller/PlayerStatusController.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/controller/PlayerStatusController.java @@ -3,8 +3,6 @@ import edu.ntnu.idi.idatt2003.g40.mappe.model.Player; import edu.ntnu.idi.idatt2003.g40.mappe.model.PlayerStatus; -import java.math.BigDecimal; - /** * Controls and calculates the players' status. * @@ -20,38 +18,22 @@ private PlayerStatusController() { * *

Calculates what status the player should get * based on players' net worth compared to starting - * money, and current week.

+ * money.

* * @param player the player to give a status to. * * @return a PlayerStatus * */ public static PlayerStatus getStatus(final Player player) { - Integer startingMoneyInt = player.getStartingMoney().intValue(); - - BigDecimal difference = - player.getNetWorth().subtract(player.getStartingMoney()); - - return switch ((Integer) difference.intValue()) { - case Integer val when val >= percentAmount(startingMoneyInt, 900) -> PlayerStatus.OMNIPOTENT; - case Integer val when val >= percentAmount(startingMoneyInt, 400) -> PlayerStatus.SEER; - case Integer val when val >= percentAmount(startingMoneyInt, 200) -> PlayerStatus.PRO; - case Integer val when val >= percentAmount(startingMoneyInt, 100) -> PlayerStatus.TRYHARD; - case Integer val when val >= percentAmount(startingMoneyInt, 50) -> PlayerStatus.GOOD; - case Integer val when val >= percentAmount(startingMoneyInt, 20) -> PlayerStatus.NOVICE; - default -> PlayerStatus.NOOB; - }; - } + float differenceInPercent = ((player.getNetWorth().floatValue() + / player.getStartingMoney().floatValue()) - 1) * 100; - /** - * Helper method for increasing a value by x percent. - * - * @param value the value to calculate from - * @param x the percent amount - * - * @return the increased value. - * */ - private static Integer percentAmount(final Integer value, final Integer x) { - return (value * x) / 100; + for (int i = PlayerStatus.values().length; i > 0; i--) { + PlayerStatus curStatus = PlayerStatus.values()[i - 1]; + if (differenceInPercent >= curStatus.getPercentIncreaseNeeded()) { + return curStatus; + } + } + return PlayerStatus.NOOB; } } diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/controller/package-info.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/controller/package-info.java new file mode 100644 index 0000000..421838f --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * Contains classes that control certain aspects of the application, + * such as the + * {@link edu.ntnu.idi.idatt2003.g40.mappe.controller.PlayerStatusController}. + * */ +package edu.ntnu.idi.idatt2003.g40.mappe.controller; diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java index 6d5b004..8eec48d 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java @@ -1,14 +1,15 @@ package edu.ntnu.idi.idatt2003.g40.mappe.engine; +import edu.ntnu.idi.idatt2003.g40.mappe.model.Player; import edu.ntnu.idi.idatt2003.g40.mappe.model.Purchase; import edu.ntnu.idi.idatt2003.g40.mappe.model.Sale; import edu.ntnu.idi.idatt2003.g40.mappe.model.Share; -import edu.ntnu.idi.idatt2003.g40.mappe.model.Player; import edu.ntnu.idi.idatt2003.g40.mappe.model.Stock; import edu.ntnu.idi.idatt2003.g40.mappe.model.Transaction; import edu.ntnu.idi.idatt2003.g40.mappe.service.PurchaseCalculator; import edu.ntnu.idi.idatt2003.g40.mappe.service.SaleCalculator; import edu.ntnu.idi.idatt2003.g40.mappe.service.TransactionCalculator; +import edu.ntnu.idi.idatt2003.g40.mappe.utils.Validator; import java.math.BigDecimal; import java.util.ArrayList; @@ -56,13 +57,17 @@ public final class Exchange { * * @param name name of exchange. * @param stocks list of {@link Stock} objects. + * + * @throws IllegalArgumentException if name or stocks are empty/null. * */ - public Exchange(final String name, final List stocks) { + public Exchange(final String name, final List stocks) throws IllegalArgumentException { + if (!Validator.NOT_EMPTY.isValid(name) || stocks == null || stocks.isEmpty()) { + throw new IllegalArgumentException("Invalid exchange parameters!"); + } this.name = name; this.week = 1; this.stockMap = new HashMap<>(); this.random = new Random(); - for (Stock stock : stocks) { stockMap.put(stock.getSymbol(), stock); } @@ -103,8 +108,14 @@ public boolean hasStock(final String symbol) { * @param symbol the symbol of the stock to get. * * @return {@link Stock} element gotten. + * + * @throws IllegalArgumentException if symbol is invalid. * */ - public Stock getStock(final String symbol) { + public Stock getStock(final String symbol) throws IllegalArgumentException { + if (!Validator.VALID_STOCK_NAME.isValid(symbol)) { + throw new IllegalArgumentException( + Validator.VALID_STOCK_NAME.getErrorMessage()); + } return stockMap.get(symbol); } @@ -136,10 +147,15 @@ public List findStocks(final String searchTerm) { * @param player the player buying stock. * * @return Transaction representing the transaction. + * + * @throws IllegalArgumentException if symbol or player is invalid. * */ public Transaction buy(final String symbol, final BigDecimal quantity, - final Player player) { + final Player player) throws IllegalArgumentException { + if (!Validator.VALID_STOCK_NAME.isValid(symbol) || player == null) { + throw new IllegalArgumentException("Invalid purchase!"); + } Stock stock = stockMap.get(symbol); Share share = new Share(stock, quantity, stock.getSalesPrice()); TransactionCalculator calculator = new PurchaseCalculator(share); @@ -154,8 +170,14 @@ public Transaction buy(final String symbol, * @param player the player buying stock. * * @return Transaction representing the transaction. + * + * @throws IllegalArgumentException if share or player is null. * */ - public Transaction sell(final Share share, final Player player) { + public Transaction sell(final Share share, final Player player) + throws IllegalArgumentException { + if (share == null || player == null) { + throw new IllegalArgumentException("Invalid sell!"); + } TransactionCalculator calculator = new SaleCalculator(share); player.addMoney(calculator.calculateTotal()); return new Sale(share, week, calculator); diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/package-info.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/package-info.java new file mode 100644 index 0000000..70a3863 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/package-info.java @@ -0,0 +1,5 @@ +/** + * Contains classes giving a high level control of the application, + * such as {@link edu.ntnu.idi.idatt2003.g40.mappe.engine.Exchange}. + * */ +package edu.ntnu.idi.idatt2003.g40.mappe.engine; diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Player.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Player.java index 8b997ce..971313e 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Player.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Player.java @@ -1,8 +1,8 @@ package edu.ntnu.idi.idatt2003.g40.mappe.model; -import edu.ntnu.idi.idatt2003.g40.mappe.engine.Exchange; +import edu.ntnu.idi.idatt2003.g40.mappe.controller.PlayerStatusController; import edu.ntnu.idi.idatt2003.g40.mappe.engine.TransactionArchive; - +import edu.ntnu.idi.idatt2003.g40.mappe.utils.Validator; import java.math.BigDecimal; /** @@ -11,7 +11,8 @@ *

Each player:

*
    *
  • Has a portfolio
  • - *
  • Can buy and sell shares on an {@link Exchange}
  • + *
  • Can buy and sell shares on an + * {@link edu.ntnu.idi.idatt2003.g40.mappe.engine.Exchange}.
  • *
  • Has a set amount of money to use on said exchange.
  • *
  • Has a {@link TransactionArchive}
  • *
@@ -49,8 +50,13 @@ public final class Player { * * @param name the name of the player * @param startingMoney the starting amount of money + * + * @throws IllegalArgumentException if name is null. */ - public Player(final String name, final BigDecimal startingMoney) { + public Player(final String name, final BigDecimal startingMoney) throws IllegalArgumentException { + if (!Validator.NOT_EMPTY.isValid(name)) { + throw new IllegalArgumentException("Invalid name!"); + } this.name = name; this.startingMoney = startingMoney; this.money = this.startingMoney; @@ -132,4 +138,15 @@ public BigDecimal getNetWorth() { netWorth = netWorth.add(portfolio.getNetWorth()).add(money); return netWorth; } + + /** + * Getter method for players' current status. + * + *

Leaves calculations for the {@link PlayerStatusController}

+ * + * @return PlayerStatus. + * */ + public PlayerStatus getStatus() { + return PlayerStatusController.getStatus(this); + } } diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/PlayerStatus.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/PlayerStatus.java index edd8705..d34c54e 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/PlayerStatus.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/PlayerStatus.java @@ -9,32 +9,56 @@ public enum PlayerStatus { /** Status representing a beginner. */ - NOOB, + NOOB(0), /** * Status representing a player who has increased * their net worth by at least 20 percent. */ - NOVICE, + NOVICE(20), /** * Status representing a player who has increased * their net worth by at least 50 percent. */ - GOOD, + GOOD(50), /** Status representing a player who has at least doubled their net worth. */ - TRYHARD, + TRYHARD(100), /** Status representing a player who has at least tripled their net worth. */ - PRO, + PRO(200), /** * Status representing a player who has at least quintupled their * net worth. */ - SEER, + SEER(400), /** * Status representing a player who has at least dectupled their * net worth. */ - OMNIPOTENT; + OMNIPOTENT(900); + + /** + * Value representing percent increase + * from starting money needed to get the respective status. + * */ + private final int percentIncreaseNeeded; + + /** + * Constructor. + * + * @param percentIncreaseNeeded the increase needed to get the status. + * */ + PlayerStatus(final int percentIncreaseNeeded) { + this.percentIncreaseNeeded = percentIncreaseNeeded; + } + + /** + * Getter method for percentincrease needed. + * + * @return percentIncreaseNeeded. + * */ + public int getPercentIncreaseNeeded() { + return percentIncreaseNeeded; + } } diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Portfolio.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Portfolio.java index 305a7e1..756dc96 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Portfolio.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Portfolio.java @@ -1,6 +1,7 @@ package edu.ntnu.idi.idatt2003.g40.mappe.model; import edu.ntnu.idi.idatt2003.g40.mappe.service.SaleCalculator; +import edu.ntnu.idi.idatt2003.g40.mappe.utils.Validator; import java.math.BigDecimal; import java.util.ArrayList; @@ -31,10 +32,15 @@ public Portfolio() { * Adds a share to the portfolio. * * @param share the share to add + * * @return {@code true} if the share was added, {@code false} otherwise + * + * @throws IllegalArgumentException if share is null. */ - public boolean addShare(final Share share) { - Objects.requireNonNull(share, "share cannot be null"); + public boolean addShare(final Share share) throws IllegalArgumentException { + if (share == null) { + throw new IllegalArgumentException("Invalid share!"); + } return shares.add(share); } @@ -42,11 +48,17 @@ public boolean addShare(final Share share) { * Removes a share from the portfolio. * * @param share the share to remove + * * @return {@code true} if the share was removed, * {@code false} if it was not present. + * + * @throws IllegalArgumentException if share is null. + * */ - public boolean removeShare(final Share share) { - Objects.requireNonNull(share, "share cannot be null"); + public boolean removeShare(final Share share) throws IllegalArgumentException { + if (share == null) { + throw new IllegalArgumentException("Invalid share!"); + } return shares.remove(share); } @@ -65,9 +77,14 @@ public List getShares() { * * @param symbol the stock symbol to match * @return a list of shares matching the symbol + * + * @throws IllegalArgumentException if symbol is invalid. */ - public List getShares(final String symbol) { - Objects.requireNonNull(symbol, "symbol cannot be null"); + public List getShares(final String symbol) throws IllegalArgumentException { + if (!Validator.VALID_STOCK_NAME.isValid(symbol)) { + throw new IllegalArgumentException( + Validator.VALID_STOCK_NAME.getErrorMessage()); + } return shares.stream() .filter(s -> symbol.equalsIgnoreCase(s.getStock().getSymbol())) .toList(); @@ -77,11 +94,16 @@ public List getShares(final String symbol) { * Checks whether the given share exists in the portfolio. * * @param share the share to check + * * @return {@code true} if the portfolio * contains the share, otherwise {@code false} + * + * @throws IllegalArgumentException if share is null. */ - public boolean contains(final Share share) { - Objects.requireNonNull(share, "share cannot be null"); + public boolean contains(final Share share) throws IllegalArgumentException { + if (share == null) { + throw new IllegalArgumentException("Invalid share!"); + } return shares.contains(share); } diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Share.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Share.java index 88e51eb..3328a74 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Share.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Share.java @@ -31,10 +31,15 @@ public final class Share { * @param stock the stock that was purchased * @param quantity the quantity purchased * @param purchasePrice the price per unit at purchase time + * + * @throws IllegalArgumentException if stock is null. */ public Share(final Stock stock, final BigDecimal quantity, - final BigDecimal purchasePrice) { + final BigDecimal purchasePrice) throws IllegalArgumentException { + if (stock == null) { + throw new IllegalArgumentException("Invalid stock!"); + } this.stock = stock; this.quantity = quantity; this.purchasePrice = purchasePrice; diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Stock.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Stock.java index a781ee4..11a444e 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Stock.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Stock.java @@ -1,5 +1,6 @@ package edu.ntnu.idi.idatt2003.g40.mappe.model; +import edu.ntnu.idi.idatt2003.g40.mappe.utils.Validator; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Comparator; @@ -34,15 +35,15 @@ public final class Stock { */ public Stock(final String symbol, final String company, - final BigDecimal salesPrice) { - - if (symbol.length() != 4) { + final BigDecimal salesPrice) throws IllegalArgumentException { + if (!Validator.VALID_STOCK_NAME.isValid(symbol)) { throw new IllegalArgumentException( - "Stock's symbol must be 4 characters!"); + Validator.VALID_STOCK_NAME.getErrorMessage()); + } else { + this.symbol = symbol; + this.company = company; + prices.add(salesPrice); } - this.symbol = symbol; - this.company = company; - prices.add(salesPrice); } /** @@ -50,7 +51,7 @@ public Stock(final String symbol, * * @return the stock symbol */ - public String getSymbol() { + public String getSymbol() { return symbol; } @@ -76,9 +77,16 @@ public BigDecimal getSalesPrice() { * Adds a new sales price to the price history. * * @param price the new sales price + * + * @throws IllegalArgumentException if price is 0 or null. */ - public void addNewSalesPrice(final BigDecimal price) { - prices.add(price); + public void addNewSalesPrice(final BigDecimal price) + throws IllegalArgumentException { + if (price != null && price.intValue() != 0) { + prices.add(price); + } else { + throw new IllegalArgumentException("Invalid price to add to stock: " + getSymbol()); + } } /** diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Transaction.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Transaction.java index f0b210d..fe7e6c5 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Transaction.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Transaction.java @@ -34,13 +34,20 @@ public abstract class Transaction { * @param share the share to perform the transaction on * @param week the current week to perform the transaction under * @param calculator the {@link TransactionCalculator} to use. + * + * @throws IllegalArgumentException if any parameter is null. */ protected Transaction(final Share share, final int week, - final TransactionCalculator calculator) { - this.share = share; - this.week = week; - this.calculator = calculator; + final TransactionCalculator calculator) + throws IllegalArgumentException{ + if (share == null || calculator == null) { + throw new IllegalArgumentException("Invalid stock or calculator!"); + } else { + this.share = share; + this.week = week; + this.calculator = calculator; + } } /** diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/package-info.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/package-info.java new file mode 100644 index 0000000..94c2b46 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/package-info.java @@ -0,0 +1,5 @@ +/** + * Contains classes representing data in the application, + * such as shares, stocks and transactions. + * */ +package edu.ntnu.idi.idatt2003.g40.mappe.model; diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/FileConverter.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/FileConverter.java index 9a479ec..397328d 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/FileConverter.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/FileConverter.java @@ -1,7 +1,6 @@ package edu.ntnu.idi.idatt2003.g40.mappe.service; import edu.ntnu.idi.idatt2003.g40.mappe.model.Stock; - import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -35,32 +34,37 @@ public class FileConverter { * * @return {@link List} * - * @throws IllegalArgumentException if stock object(s) cannot be converted. + * @throws IllegalArgumentException if stock object(s) cannot be converted, + * or if list is null/empty. * * */ - public List getStocksFromStrings(final List validStocks) { - - List stocksFromFile = new ArrayList<>(); - List stockSymbols = new ArrayList<>(); + public List getStocksFromStrings(final List validStocks) + throws IllegalArgumentException { + if (validStocks == null || validStocks.isEmpty()) { + throw new IllegalArgumentException("Empty or null stock list!"); + } else { + List stocksFromFile = new ArrayList<>(); + List stockSymbols = new ArrayList<>(); - validStocks.forEach(s -> { - String[] lineElements = s.split(","); - String stockSymbol = lineElements[0].trim(); - String stockName = lineElements[1].trim(); - BigDecimal stockPrice = new BigDecimal(lineElements[2].trim()); + validStocks.forEach(s -> { + String[] lineElements = s.split(","); + String stockSymbol = lineElements[0].trim(); + String stockName = lineElements[1].trim(); + BigDecimal stockPrice = new BigDecimal(lineElements[2].trim()); - try { - Stock stockObject = new Stock(stockSymbol, stockName, stockPrice); - if (!stockSymbols.contains(stockSymbol)) { - stockSymbols.add(stockSymbol); - stocksFromFile.add(stockObject); + try { + Stock stockObject = new Stock(stockSymbol, stockName, stockPrice); + if (!stockSymbols.contains(stockSymbol)) { + stockSymbols.add(stockSymbol); + stocksFromFile.add(stockObject); + } + } catch (IllegalArgumentException e) { + System.err.println("(" + s + ") is not a valid stock! Skipping..."); } - } catch (IllegalArgumentException e) { - System.err.println("(" + s + ") is not a valid stock! Skipping..."); - } - }); - return stocksFromFile; + }); + return stocksFromFile; + } } /** @@ -71,13 +75,19 @@ public List getStocksFromStrings(final List validStocks) { * @param stocks a list of {@link Stock} objects. * * @return a list of string representation of the stock objects. + * + * @throws IllegalArgumentException if stocks is empty or null. * */ public List stocksToStrings(final List stocks) { - ArrayList stringList = new ArrayList<>(); - stocks.forEach(s -> - stringList.add(s.getSymbol().trim() + "," + s.getCompany().trim() - + "," + s.getSalesPrice().toString()) - ); - return stringList; + if (stocks == null || stocks.isEmpty()) { + throw new IllegalArgumentException("Empty or null stock list!"); + } else { + ArrayList stringList = new ArrayList<>(); + stocks.forEach(s -> + stringList.add(s.getSymbol().trim() + "," + s.getCompany().trim() + + "," + s.getSalesPrice().toString()) + ); + return stringList; + } } } diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/FileParser.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/FileParser.java index 155d36d..9d0bf27 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/FileParser.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/FileParser.java @@ -164,21 +164,25 @@ public List readFile() throws IOException { * @throws IOException if writing process throws error. * */ public void writeStocksToFile(final List stringList) - throws IOException { - Path path = Paths.get(pathName); - - try (BufferedWriter writer = Files.newBufferedWriter(path, - StandardOpenOption.CREATE, - StandardOpenOption.APPEND)) { + throws IllegalArgumentException, IOException { + if (stringList == null || stringList.isEmpty()) { + throw new IllegalArgumentException("Empty or null list of stocks!"); + } else { + Path path = Paths.get(pathName); - writer.newLine(); + try (BufferedWriter writer = Files.newBufferedWriter(path, + StandardOpenOption.CREATE, + StandardOpenOption.APPEND)) { - for (String line : stringList) { - writer.write(line); writer.newLine(); + + for (String line : stringList) { + writer.write(line); + writer.newLine(); + } + } catch (IOException e) { + throw new IOException("Error during buffered write", e); } - } catch (IOException e) { - throw new IOException("Error during buffered write", e); } } } diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/PurchaseCalculator.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/PurchaseCalculator.java index 49ce7c1..e253dd3 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/PurchaseCalculator.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/PurchaseCalculator.java @@ -1,7 +1,6 @@ package edu.ntnu.idi.idatt2003.g40.mappe.service; import edu.ntnu.idi.idatt2003.g40.mappe.model.Share; - import java.math.BigDecimal; /** @@ -32,10 +31,19 @@ public final class PurchaseCalculator implements TransactionCalculator { * Creates a new {@code PurchaseCalculator} based on a share. * * @param share the share to base calculations on + * + * @throws IllegalArgumentException if share is null. */ - public PurchaseCalculator(final Share share) { - this.purchasePrice = share.getPurchasePrice(); - this.quantity = share.getQuantity(); + public PurchaseCalculator(final Share share) throws IllegalArgumentException { + if (share == null) { + throw new IllegalArgumentException( + "Invalid share for PurchaseCalculator!" + ); + } else { + this.purchasePrice = share.getPurchasePrice(); + this.quantity = share.getQuantity(); + } + } /** diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaleCalculator.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaleCalculator.java index 0cba5dc..1c2a0bb 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaleCalculator.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaleCalculator.java @@ -1,7 +1,6 @@ package edu.ntnu.idi.idatt2003.g40.mappe.service; import edu.ntnu.idi.idatt2003.g40.mappe.model.Share; - import java.math.BigDecimal; /** @@ -43,11 +42,17 @@ public final class SaleCalculator implements TransactionCalculator { * Creates a new {@code SaleCalculator} based on a share. * * @param share the share to base calculations on + * + * @throws IllegalArgumentException if share is null. */ - public SaleCalculator(final Share share) { - this.purchasePrice = share.getPurchasePrice(); - this.salesPrice = share.getStock().getSalesPrice(); - this.quantity = share.getQuantity(); + public SaleCalculator(final Share share) throws IllegalArgumentException { + if (share == null) { + throw new IllegalArgumentException("Invalid share for SaleCalculator!"); + } else { + this.purchasePrice = share.getPurchasePrice(); + this.salesPrice = share.getStock().getSalesPrice(); + this.quantity = share.getQuantity(); + } } /** diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/event/package-info.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/event/package-info.java new file mode 100644 index 0000000..4ad31e6 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/event/package-info.java @@ -0,0 +1,5 @@ +/** + * Contains classes providing a flexible event system that follows + * the publisher/subscriber model. + * */ +package edu.ntnu.idi.idatt2003.g40.mappe.service.event; diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/package-info.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/package-info.java new file mode 100644 index 0000000..633c60a --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/package-info.java @@ -0,0 +1,5 @@ +/** + * Contains classes providing modular functionality to the application, + * such as the {@link edu.ntnu.idi.idatt2003.g40.mappe.service.FileConverter}. + * */ +package edu.ntnu.idi.idatt2003.g40.mappe.service; diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/utils/Validator.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/utils/Validator.java new file mode 100644 index 0000000..6d12cbc --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/utils/Validator.java @@ -0,0 +1,115 @@ +package edu.ntnu.idi.idatt2003.g40.mappe.utils; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.util.function.Predicate; + +/** + * Enum containing rules for different types of validation. + * + *

Validates by using {@link Predicate}

+ * + *

Every constant has the following attributes:

+ *
    + *
  • A rule for a specific validation, defined by a {@link Predicate}.
  • + *
  • + * An error message to be used if input is invalid according to the rule. + *
  • + *
+ * + *

Responsibilities:

+ *
    + *
  • + * Checking whether given string is + * valid based on the given validation rule. + *
  • + *
+ * + * @author Tohja + * @version 1.0.0 + * + * @see Enum + * @see Predicate + */ +public enum Validator { + + /** + * Rule that checks if string is not empty. + * */ + NOT_EMPTY(s -> s != null && !s.trim().isEmpty(), + "Empty string!"), + + /** + * Rule that checks if string is not empty, + * and if it can be parsed into an {@link Integer}. + */ + VALID_INT(NOT_EMPTY.validationRule.and(s -> { + try { + Integer.parseInt(s); + return true; + } catch (NumberFormatException _) { + return false; + } + }), "Invalid Integer!"), + + /** + * Rule that checks if a string is considered a valid stock name. + * */ + VALID_STOCK_NAME(NOT_EMPTY.validationRule.and(s -> + s.length() == 4), "Invalid stock name!"), + + /** + * Rule that checks if a string represents a positive integer. + * */ + VALID_POSITIVE_INT(VALID_INT.validationRule.and(s -> + Integer.parseInt(s) >= 0), "Number is not positive!"), + /** + * Rule that checks if string is not empty, + * and if it can be parsed into a {@link LocalDate} object. + */ + VALID_DATE(NOT_EMPTY.validationRule.and(s -> { + try { + LocalDate.parse(s); + return true; + } catch (DateTimeParseException e) { + return false; + } + }), "Invalid Date!"); + + /** The predicate field set when creating constants. */ + private final Predicate validationRule; + + /** The error message field set when creating constants. */ + private final String errorMessage; + + /** + * Constructor. + * + * @param validationRule the {@link Predicate} object to set as rule. + * @param errorMessage the message to use on invalid input. + */ + Validator(final Predicate validationRule, final String errorMessage) { + this.validationRule = validationRule; + this.errorMessage = errorMessage; + } + + /** + * Method used to validate a given string by the given constant. + * + * @param input the input string to validate. + * + * @return {@link Boolean} value, true if input is valid, false otherwise. + */ + public boolean isValid(final String input) { + return validationRule.test(input); + } + + /** + * Method used to get the error message of the given constant. + * + * @return the error message. + */ + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/utils/package-info.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/utils/package-info.java new file mode 100644 index 0000000..11c8c6c --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/utils/package-info.java @@ -0,0 +1,4 @@ +/** + * Package containing utility enums and classes. + * */ +package edu.ntnu.idi.idatt2003.g40.mappe.utils; diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewData.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewData.java index 06dbdfc..33fca3c 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewData.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewData.java @@ -1,5 +1,7 @@ package edu.ntnu.idi.idatt2003.g40.mappe.view; +import edu.ntnu.idi.idatt2003.g40.mappe.utils.Validator; + /** * Object containing data about {@link ViewElement} objects. * @@ -22,9 +24,14 @@ public class ViewData { * * @param sceneName the name of the scene. * + * @throws IllegalArgumentException if sceneName is empty or null. */ - public ViewData(final String sceneName) { - this.sceneName = sceneName; + public ViewData(final String sceneName) throws IllegalArgumentException { + if (Validator.NOT_EMPTY.isValid(sceneName)) { + this.sceneName = sceneName; + } else { + throw new IllegalArgumentException(Validator.NOT_EMPTY.getErrorMessage()); + } } /** diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewElement.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewElement.java index fec4af4..554ccfc 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewElement.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewElement.java @@ -1,12 +1,13 @@ package edu.ntnu.idi.idatt2003.g40.mappe.view; - +import edu.ntnu.idi.idatt2003.g40.mappe.utils.Validator; +import java.util.ArrayList; import javafx.scene.control.Button; import javafx.scene.layout.Pane; -import java.util.ArrayList; /** - * Base class for view elements, such as the main menu, or list items. + * Base class for view elements, such as the main menu, + * or navigation bars used across several views. * *

Extends {@link Pane}

* @@ -20,6 +21,7 @@ public abstract class ViewElement { * */ private final ArrayList