diff --git a/src/main/java/Model/Exchange.java b/src/main/java/Model/Exchange.java index a15512f..40646b7 100644 --- a/src/main/java/Model/Exchange.java +++ b/src/main/java/Model/Exchange.java @@ -17,12 +17,22 @@ public class Exchange { private final List observers = new ArrayList<>(); public Exchange(String name, List stocks) { + if (name == null || name.isBlank()) { + throw new IllegalArgumentException("Exchange name cannot be null or blank"); + } + if (stocks == null) { + throw new IllegalArgumentException("Stock list cannot be null"); + } + this.name = name; this.week = 1; this.stockMap = new HashMap<>(); this.random = new Random(); for (Stock stock : stocks) { + if (stock == null) { + throw new IllegalArgumentException("Stock list must not contain null entries"); + } stockMap.put(stock.getSymbol(), stock); } } @@ -30,7 +40,10 @@ public Exchange(String name, List stocks) { // ---- Observer ---- public void addObserver(ExchangeObserver observer) { - if (observer != null && !observers.contains(observer)) { + if (observer == null) { + throw new IllegalArgumentException("Observer cannot be null"); + } + if (!observers.contains(observer)) { observers.add(observer); } } @@ -54,14 +67,23 @@ public int getWeek() { } public boolean hasStock(String symbol) { + if (symbol == null || symbol.isBlank()) { + throw new IllegalArgumentException("Symbol cannot be null or blank"); + } return stockMap.containsKey(symbol); } public Stock getStock(String symbol) { + if (symbol == null || symbol.isBlank()) { + throw new IllegalArgumentException("Symbol cannot be null or blank"); + } return stockMap.get(symbol); } public List findStocks(String searchTerm) { + if (searchTerm == null) { + throw new IllegalArgumentException("Search term cannot be null"); + } List result = new ArrayList<>(); String lowerSearch = searchTerm.toLowerCase(); @@ -76,20 +98,27 @@ public List findStocks(String searchTerm) { } public Transaction buy(String symbol, BigDecimal quantity, Player player) { + if (symbol == null || symbol.isBlank()) { + throw new IllegalArgumentException("Symbol cannot be null or blank"); + } + if (quantity == null) { + throw new IllegalArgumentException("Quantity cannot be null"); + } + if (quantity.compareTo(BigDecimal.ZERO) <= 0) { + throw new IllegalArgumentException("Quantity must be greater than zero"); + } + if (player == null) { + throw new IllegalArgumentException("Player cannot be null"); + } + Stock stock = getStock(symbol); - - // unngå nullpointerexception if (stock == null) { - return null; + throw new IllegalArgumentException("No stock found with symbol: " + symbol); } // lager en ny "andel" basert på nåværende salgspris Share shareToBuy = new Share(stock, quantity, stock.getSalesPrice()); - - // oppretter kjøpstransaksjonen for den uka via fabrikken - Transaction purchase = TransactionFactory.createPurchase(shareToBuy, this.week); - - // committer til player + Purchase purchase = new Purchase(shareToBuy, this.week); purchase.commit(player); notifyObservers(); @@ -98,15 +127,14 @@ public Transaction buy(String symbol, BigDecimal quantity, Player player) { } public Transaction sell(Share share, Player player) { - // unngå nullpointerexception if (share == null) { - return null; + throw new IllegalArgumentException("Share cannot be null"); + } + if (player == null) { + throw new IllegalArgumentException("Player cannot be null"); } - // oppretter salgstransaksjonen for den uka via fabrikken - Transaction sale = TransactionFactory.createSale(share, this.week); - - // commiter til player + Sale sale = new Sale(share, this.week); sale.commit(player); notifyObservers(); @@ -138,14 +166,14 @@ public void advance() { public List getGainers(int limit) { // viser "vinnerne" return stockMap.values().stream() - .sorted((stock1, stock2) -> stock2.getLatestPriceChange().compareTo(stock1.getLatestPriceChange())) + .sorted((s1, s2) -> s2.getLatestPriceChange().compareTo(s1.getLatestPriceChange())) .limit(limit) .toList(); } public List getLosers(int limit) { // viser "taperne" return stockMap.values().stream() - .sorted((stock1, stock2) -> stock1.getLatestPriceChange().compareTo(stock2.getLatestPriceChange())) + .sorted((s1, s2) -> s1.getLatestPriceChange().compareTo(s2.getLatestPriceChange())) .limit(limit) .toList(); } diff --git a/src/main/java/Model/Player.java b/src/main/java/Model/Player.java index e7a1e31..cf3d8a3 100644 --- a/src/main/java/Model/Player.java +++ b/src/main/java/Model/Player.java @@ -9,6 +9,16 @@ public class Player { private TransactionArchive transactionArchive; public Player(String name, BigDecimal startingMoney) { + if (name == null || name.isBlank()) { + throw new IllegalArgumentException("Player name cannot be null or blank"); + } + if (startingMoney == null) { + throw new IllegalArgumentException("Starting money cannot be null"); + } + if (startingMoney.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("Starting money cannot be negative"); + } + this.name = name; this.startingMoney = startingMoney; this.money = startingMoney; @@ -25,10 +35,22 @@ public BigDecimal getMoney() { } public void addMoney(BigDecimal amount) { + if (amount == null) { + throw new IllegalArgumentException("Amount cannot be null"); + } + if (amount.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("Amount to add cannot be negative"); + } this.money = this.money.add(amount); } public void withdrawMoney(BigDecimal amount) { + if (amount == null) { + throw new IllegalArgumentException("Amount cannot be null"); + } + if (amount.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("Amount to withdraw cannot be negative"); + } this.money = this.money.subtract(amount); } diff --git a/src/main/java/Model/Portfolio.java b/src/main/java/Model/Portfolio.java index 05dd1de..949bea3 100644 --- a/src/main/java/Model/Portfolio.java +++ b/src/main/java/Model/Portfolio.java @@ -12,10 +12,16 @@ public Portfolio() { } public boolean addShare(Share share) { + if (share == null) { + throw new IllegalArgumentException("Share cannot be null"); + } return shares.add(share); } public boolean removeShare(Share share) { + if (share == null) { + throw new IllegalArgumentException("Share cannot be null"); + } return shares.remove(share); } @@ -24,6 +30,9 @@ public List getShares() { } public List getShares(String symbol) { + if (symbol == null || symbol.isBlank()) { + throw new IllegalArgumentException("Symbol cannot be null or blank"); + } List result = new ArrayList<>(); for (Share share : shares) { if (share.getStock().getSymbol().equals(symbol)) { @@ -34,6 +43,9 @@ public List getShares(String symbol) { } public boolean contains(Share share) { + if (share == null) { + throw new IllegalArgumentException("Share cannot be null"); + } return shares.contains(share); } diff --git a/src/main/java/Model/Purchase.java b/src/main/java/Model/Purchase.java index d0b14fe..33c41e5 100644 --- a/src/main/java/Model/Purchase.java +++ b/src/main/java/Model/Purchase.java @@ -8,10 +8,19 @@ public Purchase(Share share, int week) { @Override public void commit(Player player) { + if (player == null) { + throw new IllegalArgumentException("Player cannot be null"); + } + if (isCommitted()) { + throw new IllegalStateException("Purchase has already been committed"); + } + BigDecimal price = this.getCalculator().calculateTotal(); - if (isCommitted() || (player.getMoney().compareTo(price) < 0)) { - return; + if (player.getMoney().compareTo(price) < 0) { + throw new IllegalStateException( + "Insufficient funds: required " + price + ", available " + player.getMoney() + ); } player.withdrawMoney(price); diff --git a/src/main/java/Model/Sale.java b/src/main/java/Model/Sale.java index 42fee68..7653df4 100644 --- a/src/main/java/Model/Sale.java +++ b/src/main/java/Model/Sale.java @@ -6,12 +6,21 @@ public Sale(Share share, int week) { super(share, week, new SaleCalculator(share)); } + @Override public void commit(Player player) { - BigDecimal price = getCalculator().calculateTotal(); - - if (isCommitted() || !player.getPortfolio().contains(this.getShare())) { - return; + if (player == null) { + throw new IllegalArgumentException("Player cannot be null"); + } + if (isCommitted()) { + throw new IllegalStateException("Sale has already been committed"); } + if (!player.getPortfolio().contains(this.getShare())) { + throw new IllegalStateException( + "Share not found in player's portfolio: " + this.getShare().getStock().getSymbol() + ); + } + + BigDecimal price = getCalculator().calculateTotal(); player.addMoney(price); player.getPortfolio().removeShare(this.getShare()); diff --git a/src/main/java/Model/Share.java b/src/main/java/Model/Share.java index dee79dd..92d6101 100644 --- a/src/main/java/Model/Share.java +++ b/src/main/java/Model/Share.java @@ -8,6 +8,22 @@ public class Share { private final BigDecimal purchasePrice; public Share(Stock stock, BigDecimal quantity, BigDecimal purchasePrice) { + if (stock == null) { + throw new IllegalArgumentException("Stock cannot be null"); + } + if (quantity == null) { + throw new IllegalArgumentException("Quantity cannot be null"); + } + if (quantity.compareTo(BigDecimal.ZERO) <= 0) { + throw new IllegalArgumentException("Quantity must be greater than zero"); + } + if (purchasePrice == null) { + throw new IllegalArgumentException("Purchase price cannot be null"); + } + if (purchasePrice.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("Purchase price cannot be negative"); + } + this.stock = stock; this.quantity = quantity; this.purchasePrice = purchasePrice; diff --git a/src/main/java/Model/Stock.java b/src/main/java/Model/Stock.java index 6916dc3..52c1fd2 100644 --- a/src/main/java/Model/Stock.java +++ b/src/main/java/Model/Stock.java @@ -10,6 +10,19 @@ public class Stock { private final List prices; public Stock(String symbol, String company, BigDecimal salesPrice) { + if (symbol == null || symbol.isBlank()) { + throw new IllegalArgumentException("Symbol cannot be null or blank"); + } + if (company == null || company.isBlank()) { + throw new IllegalArgumentException("Company name cannot be null or blank"); + } + if (salesPrice == null) { + throw new IllegalArgumentException("Initial sales price cannot be null"); + } + if (salesPrice.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("Initial sales price cannot be negative"); + } + this.symbol = symbol; this.company = company; this.prices = new ArrayList<>(); @@ -29,6 +42,12 @@ public BigDecimal getSalesPrice() { } public void addNewSalesPrice(BigDecimal price) { + if (price == null) { + throw new IllegalArgumentException("Price cannot be null"); + } + if (price.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("Price cannot be negative"); + } prices.add(price); } diff --git a/src/main/java/Model/Transaction.java b/src/main/java/Model/Transaction.java index 1ef6aa8..de68854 100644 --- a/src/main/java/Model/Transaction.java +++ b/src/main/java/Model/Transaction.java @@ -6,6 +6,16 @@ public abstract class Transaction { protected boolean committed; protected Transaction(Share share, int week, TransactionCalculator calculator) { + if (share == null) { + throw new IllegalArgumentException("Share cannot be null"); + } + if (week < 1) { + throw new IllegalArgumentException("Week must be at least 1"); + } + if (calculator == null) { + throw new IllegalArgumentException("Calculator cannot be null"); + } + this.share = share; this.week = week; this.calculator = calculator;