Skip to content

Commit

Permalink
Merge pull request #21 from solvena/20-add-exceptions
Browse files Browse the repository at this point in the history
Add exceptions
  • Loading branch information
solvena authored May 24, 2026
2 parents 9225c8c + b332c59 commit 5c9dfe7
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 23 deletions.
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

0 comments on commit 5c9dfe7

Please sign in to comment.