Skip to content

Commit 75f7c9a

Browse files
Lagt till kommentarer samt ändrat till mer funtionell kod på vissa ställen
1 parent d47572d commit 75f7c9a

File tree

7 files changed

+360
-149
lines changed

7 files changed

+360
-149
lines changed

src/main/java/com/example/warehouse/Category.java

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,51 @@
44
import java.util.Map;
55
import java.util.Objects;
66

7+
/**
8+
* Represents a product category. This class implements the Flyweight design pattern,
9+
* ensuring that only one instance exists for each unique category name
10+
* after normalization (e.g., "food", "Food", and "FOOD" all map to "Food").
11+
*/
712
public class Category {
13+
814
private final String name;
15+
//Map to store and retrieve Category instances.
916
private static final Map<String, Category> categories = new HashMap<>();
1017

18+
/**
19+
* Private constructor for the Flyweight pattern. Instances can only be created
20+
* internally via the Code.of factory method.
21+
*
22+
* @param name The name of the category.
23+
*/
1124
private Category(String name) {
1225
this.name = name;
1326
}
14-
// factory method
1527

28+
/**
29+
* Factory method to retrieve a Category instance based on the input name.
30+
* The input name is validated and then normalized (first letter capitalized, rest lowercased)
31+
* before checking the cache.
32+
*
33+
* @param name The desired category name (case-insensitive for lookup).
34+
* @return A unique, cached instance of the Category.
35+
* @throws IllegalArgumentException if the provided name is null or blank.
36+
*/
1637
public static Category of(String name) {
1738

1839
if (name == null) throw new IllegalArgumentException("Category name can't be null");
1940
if (name.isBlank()) throw new IllegalArgumentException("Category name can't be blank");
20-
//if (name.isEmpty()) throw new IllegalArgumentException("Category name can't be blank");
2141

22-
//Tar banan och gör om den till Banan - normaliserar namnet för att kunna matcha namnet i (flyweight/cache) syfte
2342
String normalized = name.trim().substring(0, 1).toUpperCase() + name.trim().substring(1).toLowerCase();
2443

25-
if (categories.containsKey(normalized)) {
26-
return categories.get(normalized); //Återanvänd det som finns
27-
} else {
28-
Category category = new Category(normalized);//skapa ny om ej funnen
29-
categories.put(normalized, category);
30-
return category;
31-
}
44+
return categories.computeIfAbsent(normalized, Category::new);
3245
}
3346

34-
47+
/**
48+
* Retrieves the name of the category.
49+
*
50+
* @return The normalized name of the category (e.g., "Food").
51+
*/
3552

3653
public String getName() {
3754
return name;

src/main/java/com/example/warehouse/ElectronicsProduct.java

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,71 @@
44
import java.math.RoundingMode;
55
import java.util.UUID;
66

7-
import static java.lang.String.format;
8-
9-
public class ElectronicsProduct extends Product implements Shippable{
10-
// Implements Shippable.
11-
// Fields: int warrantyMonths, BigDecimal weight (kg).
12-
// Validation: negative warranty -> IllegalArgumentException("Warranty months cannot be negative.").
13-
// productDetails() should look like: "Electronics: Laptop, Warranty: 24 months".
14-
// Shipping rule: base 79, add 49 if weight > 5.0 kg.
7+
/**
8+
* Represents an electronic item in the warehouse.
9+
* An ElectronicsProduct implements Shippable (it has a weight and calculated shipping cost)
10+
* and includes a specific warranty period.
11+
*/
12+
public class ElectronicsProduct extends Product implements Shippable {
13+
1514
private final int warrantyMonths;
1615
private final BigDecimal weight;
16+
17+
/**
18+
* Constructs a new ElectronicsProduct.
19+
* * @param id The unique identifier for the product.
20+
*
21+
* @param name The name of the electronic product.
22+
* @param category The product's category.
23+
* @param price The initial price of the product.
24+
* @param warrantyMonths The length of the product warranty in months.
25+
* @param weight The weight of the product.
26+
* @throws IllegalArgumentException if the warranty months or weight is negative.
27+
*/
1728
public ElectronicsProduct(UUID id, String name, Category category, BigDecimal price, int warrantyMonths, BigDecimal weight) {
18-
super(name, category, price);
19-
//validering om pris negativt warrantyMonths
20-
if(warrantyMonths < 0) throw new IllegalArgumentException("Warranty months cannot be negative.");
21-
if(weight.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Weight cannot be negative.");
29+
super(id, name, category, price);
30+
if (warrantyMonths < 0) throw new IllegalArgumentException("Warranty months cannot be negative.");
31+
if (weight.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Weight cannot be negative.");
2232
this.warrantyMonths = warrantyMonths;
2333
this.weight = weight;
2434
}
2535

36+
/**
37+
* Provides a summary of the electronics product.
38+
* * @return A String containing the product name and its warranty period.
39+
*/
2640
@Override
2741
public String productDetails() {
2842
return String.format("Electronics: %s, Warranty: %s months", name(), warrantyMonths);
2943
}
3044

45+
// --- Implementation of Shippable Interface ---
46+
47+
/**
48+
* Calculates the shipping cost for electronics, applying a surcharge for heavy items.
49+
* Base cost is 79. An extra of 49 is added if the weight is over 5 units(kg).
50+
* * @return The calculated shipping cost, rounded up to two decimals.
51+
*/
3152
@Override
3253
public BigDecimal calculateShippingCost() {
33-
//Baspris 79, om vikten är över 5kg baspris + 49
34-
//if (weight > 5.0)
35-
//konvertera tillbaka weight som en BigDecimal
36-
//HALF_UP
37-
//this.weight.add(BigDecimal.valueOf(weight()));
54+
3855
BigDecimal baseShippingCost = BigDecimal.valueOf(79);
3956
BigDecimal extraShippingCost = BigDecimal.valueOf(49);
4057

4158
if (this.weight.compareTo(BigDecimal.valueOf(5)) > 0) {
4259
baseShippingCost = baseShippingCost.add(extraShippingCost);
4360
}
44-
return baseShippingCost.setScale(2, RoundingMode.HALF_UP);
45-
46-
61+
return baseShippingCost.setScale(2, RoundingMode.HALF_UP);
4762
}
4863

64+
/**
65+
* Retrieves the weight of the product as a double.
66+
*
67+
* @return The product's weight.
68+
*/
4969
@Override
5070
public Double weight() {
71+
// Converts the BigDecimal weight to a double for the interface contract.
5172
return this.weight.doubleValue();
52-
//i calculateShipping - konvertera tillbaka till BigDecimal
5373
}
5474
}

src/main/java/com/example/warehouse/FoodProduct.java

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,78 @@
33
import java.math.BigDecimal;
44
import java.math.RoundingMode;
55
import java.time.LocalDate;
6-
import java.util.Objects;
76
import java.util.UUID;
87

9-
//todo Rad 293 i basictest
10-
public class FoodProduct extends Product implements Perishable, Shippable{
8+
/**
9+
* Represents a food product in the warehouse.
10+
* A FoodProduct implements both Perishable (has an expiration date) and
11+
* Shippable (has a weight and a defined shipping cost calculation).
12+
*/
13+
public class FoodProduct extends Product implements Perishable, Shippable {
1114

1215
private final LocalDate expirationDate;
1316
private final BigDecimal weight;
1417

15-
public FoodProduct(UUID id, String name,Category category,BigDecimal price, LocalDate expirationDate, BigDecimal weight) {
16-
super(name, category, price);
17-
//Validering för vikt med negativt värde
18-
if(weight.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Weight cannot be negative.");
18+
/**
19+
* Constructs a new FoodProduct.
20+
*
21+
* @param id The unique identifier for the product
22+
* @param name The name of the food product.
23+
* @param category The product's category.
24+
* @param price The initial price of the product.
25+
* @param expirationDate The date on which the product expires.
26+
* @param weight The weight of the product.
27+
* @throws IllegalArgumentException if the provided weight is negative.
28+
*/
29+
public FoodProduct(UUID id, String name, Category category, BigDecimal price, LocalDate expirationDate, BigDecimal weight) {
30+
31+
// Calls the abstract Product constructor.
32+
super(id, name, category, price);
33+
if (weight.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Weight cannot be negative.");
1934
this.expirationDate = expirationDate;
2035
this.weight = weight;
2136
}
37+
38+
/**
39+
* Provides a summary of the food product, forced from the superclass.
40+
* * @return A formatted String containing the product name and its expiration date.
41+
*/
2242
@Override
2343
public String productDetails() {
2444
return String.format("Food: %s, Expires: %s", name(), expirationDate);
2545
}
2646

27-
@Override
47+
// ----- Implementation of the interface Shippable ----
48+
49+
/**
50+
* Calculates the shipping cost based on the product's weight.
51+
* Uses weight * 50, rounded to two decimals.
52+
* * @return The calculated shipping cost.
53+
*/
54+
@Override
2855
public BigDecimal calculateShippingCost() {
29-
//Validations: negative price -> IllegalArgumentException("Price cannot be negative."); negative weight -> IllegalArgumentException("Weight cannot be negative.").
30-
//Shipping rule: cost = weight * 50.
3156

32-
return weight.multiply(new BigDecimal(50)).setScale(2, RoundingMode.HALF_UP);
57+
return weight.multiply(new BigDecimal(50)).setScale(2, RoundingMode.HALF_UP);
3358
}
59+
60+
/**
61+
* Retrieves the weight of the product as a double.
62+
* * @return The product's weight.
63+
*/
3464
@Override
3565
public Double weight() {
3666

3767
return this.weight.doubleValue();
3868
}
69+
// ----Implementation of the Interface Perishable ----
70+
71+
/**
72+
* Retrieves the specific expiration date for this food product.
73+
* * @return The product's expiration date.
74+
*/
3975
@Override
4076
public LocalDate expirationDate() {
41-
//returnera this för att referera till denna specifika instans i FoodProdukt
42-
return this.expirationDate;
77+
78+
return this.expirationDate;
4379
}
4480
}

src/main/java/com/example/warehouse/Perishable.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,23 @@
33
import java.math.BigDecimal;
44
import java.time.LocalDate;
55

6+
/**
7+
* Defines a contract for products that have an expiration date, such as food or certain chemicals.
8+
* Items implementing this interface can be checked for expiration.
9+
*/
610
public interface Perishable {
7-
//Ska representera produkter med utgånget datum
8-
//Alla klasser som implementeras av interfacet måste använda dess metoder
9-
//expose expirationDate() and a default isExpired() based on LocalDate.now().
10-
//En metod för att få utgångsdatum på produkt
11+
1112
LocalDate expirationDate();
13+
14+
/**
15+
* Checks if the item has expired based on the current date.
16+
*
17+
* @return true if the expiration date has passed and false if not.
18+
*/
1219
default boolean isExpired() {
13-
//returnerar true om produkten gått ut
20+
1421
LocalDate idag = LocalDate.now();
22+
// Checks if the recorded expiration date is before today's date.
1523
return expirationDate().isBefore(idag);
1624
}
1725

src/main/java/com/example/warehouse/Product.java

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,89 @@
33
import java.math.BigDecimal;
44
import java.util.UUID;
55

6+
/**
7+
* An abstract base class for all products managed by the warehouse.
8+
* It provides core properties (ID, name, category, price) and enforces
9+
* rules, such as non-negative pricing.
10+
*/
611
public abstract class Product {
7-
//"Final" så att de ej kan ändras, endast BigDecimal ska kunna ändras för prisändring.
12+
813
private final UUID id;
914
private final String name;
1015
private final Category category;
11-
private BigDecimal price;
16+
private BigDecimal price; // Price is not final (can be changed later)
17+
18+
/**
19+
* protected Constructor - Constructs a new Product instance. A unique UUID is generated automatically.
20+
* * @param name The product's name.
21+
*
22+
* @param category The product's category.
23+
* @param price The initial price of the product.
24+
* @throws IllegalArgumentException if the provided price is negative.
25+
*/
26+
protected Product(UUID id, String name, Category category, BigDecimal price) {
1227

13-
protected Product(String name, Category category, BigDecimal price) {
14-
//jämför mot En BigDecimal med värdet 0
15-
if(price.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Price cannot be negative.");
16-
this.id = UUID.randomUUID(); // Ger ett random id-nummer (128bit)
28+
if (price.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Price cannot be negative.");
29+
this.id = id; // Gives a random id-number (128bit)
1730
this.name = name;
1831
this.category = category;
1932
this.price = price;
2033
}
2134

35+
/**
36+
* Retrieves the unique identifier (UUID) for this product.
37+
*
38+
* @return The UUID of the product.
39+
*/
2240
public UUID uuid() {
23-
return id;
24-
}
25-
public String name() {
26-
return name;
27-
}
28-
public Category category() {
29-
return category;
30-
}
31-
public BigDecimal price() {
32-
return price;
33-
}
34-
public void price(BigDecimal newPrice) {
35-
if(price.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Price cannot be negative.");
36-
//Uppdatera DETTA objektets fält 'price', sätt det till lika med det som skickas in som parameter:'newPrice'.
41+
return id;
42+
}
43+
44+
/**
45+
* Retrieves the name of the product.
46+
*
47+
* @return The product's name.
48+
*/
49+
public String name() {
50+
return name;
51+
}
52+
53+
/**
54+
* Retrieves the category of the product.
55+
*
56+
* @return The product's Category.
57+
*/
58+
public Category category() {
59+
return category;
60+
}
61+
62+
/**
63+
* Retrieves the current price of the product.
64+
*
65+
* @return The price as a BigDecimal.
66+
*/
67+
public BigDecimal price() {
68+
return price;
69+
}
70+
71+
/**
72+
* Updates the product's price.
73+
*
74+
* @param newPrice The new price to set.
75+
* @throws IllegalArgumentException if the provided new price is negative.
76+
*/
77+
public void price(BigDecimal newPrice) {
78+
if (newPrice.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Price cannot be negative.");
79+
3780
this.price = newPrice;
38-
}
81+
}
82+
83+
/**
84+
* Defines the abstract method for returning specific details about the product.
85+
* Subclasses must implement this to provide their own unique description.
86+
*
87+
* @return A String description of the product.
88+
*/
89+
public abstract String productDetails();
3990

40-
public abstract String productDetails();
4191
}

0 commit comments

Comments
 (0)