Skip to content

Add exceptions #21

Merged
merged 8 commits into from
May 24, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 45 additions & 17 deletions src/main/java/Model/Exchange.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,33 @@ public class Exchange {
private final List<ExchangeObserver> observers = new ArrayList<>();

public Exchange(String name, List<Stock> 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);
}
}

// ---- 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);
}
}
Expand All @@ -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<Stock> findStocks(String searchTerm) {
if (searchTerm == null) {
throw new IllegalArgumentException("Search term cannot be null");
}
List<Stock> result = new ArrayList<>();
String lowerSearch = searchTerm.toLowerCase();

Expand All @@ -76,20 +98,27 @@ public List<Stock> 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();
Expand All @@ -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();
Expand Down Expand Up @@ -138,14 +166,14 @@ public void advance() {

public List<Stock> 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<Stock> 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();
}
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/Model/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down
12 changes: 12 additions & 0 deletions src/main/java/Model/Portfolio.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -24,6 +30,9 @@ public List<Share> getShares() {
}

public List<Share> getShares(String symbol) {
if (symbol == null || symbol.isBlank()) {
throw new IllegalArgumentException("Symbol cannot be null or blank");
}
List<Share> result = new ArrayList<>();
for (Share share : shares) {
if (share.getStock().getSymbol().equals(symbol)) {
Expand All @@ -34,6 +43,9 @@ public List<Share> getShares(String symbol) {
}

public boolean contains(Share share) {
if (share == null) {
throw new IllegalArgumentException("Share cannot be null");
}
return shares.contains(share);
}

Expand Down
13 changes: 11 additions & 2 deletions src/main/java/Model/Purchase.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/Model/Sale.java
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/Model/Share.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/Model/Stock.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ public class Stock {
private final List<BigDecimal> 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<>();
Expand All @@ -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);
}

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/Model/Transaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down