Skip to content
Open
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
39 changes: 39 additions & 0 deletions src/main/java/com/example/Category.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.example;
import java.util.*;

public class Category {
private static final Map<String, Category> CACHE = new HashMap<>();
private final String name;

private Category(String name) {
this.name = name;
}
public static Category of(String name) {
if (name == null) {
throw new IllegalArgumentException("Category name can't be null");
}
if (name.isBlank()) {
throw new IllegalArgumentException("Category name can't be blank");
}
String normalized = name.trim().substring(0, 1).toUpperCase() + name.trim().substring(1).toLowerCase();
return CACHE.computeIfAbsent(normalized, Category::new);
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Category)) return false;
Category category = (Category) o;
return name.equals(category.name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/example/ElectronicsProduct.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.example;
import java.math.BigDecimal;
import java.util.UUID;


public class ElectronicsProduct extends Product implements Shippable {
private final int warrantyMonths;
private final BigDecimal weight;

public ElectronicsProduct(UUID uuid, String name, Category category,
BigDecimal price, int warrantyMonths, BigDecimal weight) {
super(uuid, name, category, price);
if (warrantyMonths < 0) {
throw new IllegalArgumentException("Warranty months cannot be negative.");
}
this.warrantyMonths = warrantyMonths;
this.weight = weight;
}
public int warrantyMonths() {
return warrantyMonths;
}

@Override
public BigDecimal weight() {
return weight;
}
@Override
public BigDecimal calculateShippingCost() {
double w = weight.doubleValue();
BigDecimal cost = BigDecimal.valueOf(79);
if (w > 5.0) cost = cost.add(BigDecimal.valueOf(49));
return cost;
}
@Override
public String productDetails() {
return "Electronics: " + name() + ", Warranty: " + warrantyMonths + " months";
}
}
36 changes: 36 additions & 0 deletions src/main/java/com/example/FoodProduct.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.example;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;

public class FoodProduct extends Product implements Perishable, Shippable{
private final LocalDate expirationDate;
private final BigDecimal weight;

public FoodProduct(UUID uuid, String name, Category category,
BigDecimal price, LocalDate expirationDate, BigDecimal weight) {
super(uuid, name, category, price);
if (price.compareTo(BigDecimal.ZERO) < 0)
throw new IllegalArgumentException("Price cannot be negative.");
if (weight.compareTo(BigDecimal.ZERO) < 0)
throw new IllegalArgumentException("Weight cannot be negative.");
this.expirationDate = expirationDate;
this.weight = weight;
}
@Override
public LocalDate expirationDate() {
return expirationDate;
}
@Override
public BigDecimal weight() {
return weight;
}
@Override
public BigDecimal calculateShippingCost() {
return weight.multiply (BigDecimal.valueOf(50));
}
@Override
public String productDetails() {
return "Food: " + name() + ", Expires: " + expirationDate;
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/example/Perishable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example;
import java.time.LocalDate;


public interface Perishable {
LocalDate expirationDate();

default boolean isExpired() {
return expirationDate().isBefore(LocalDate.now());
}
}
47 changes: 47 additions & 0 deletions src/main/java/com/example/Product.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.example;
import java.math.BigDecimal;
import java.util.UUID;

public abstract class Product {
private final UUID uuid;
private final String name;
private final Category category;
private BigDecimal price;

public Product(UUID uuid, String name, Category category, BigDecimal price) {
if (uuid == null) throw new IllegalArgumentException("UUID cannot be null");
if (name == null || name.isBlank()) throw new IllegalArgumentException("Name cannot be blank");
if (category == null) throw new IllegalArgumentException("Category cannot be null");
if (price == null) throw new IllegalArgumentException("Price cannot be null");
if (price.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Price cannot be negative.");

this.uuid = uuid;
this.name = name;
this.category = category;
this.price = price;
}
public UUID uuid() {
return uuid;
}

public String name() {
return name;
}

public Category category() {
return category;
}

public BigDecimal price() {
return price;
}

public void setPrice(BigDecimal price) {
if (price == null || price.compareTo(BigDecimal.ZERO) < 0)
throw new IllegalArgumentException("Price can't be negative");
this.price = price;
}

public abstract String productDetails();

}
8 changes: 8 additions & 0 deletions src/main/java/com/example/Shippable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example;
import java.math.BigDecimal;


public interface Shippable {
BigDecimal calculateShippingCost();
BigDecimal weight();
}
84 changes: 84 additions & 0 deletions src/main/java/com/example/Warehouse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.example;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

public class Warehouse {
private static Warehouse instance;
private final String name;
private final List<Product> products = new ArrayList<>();

private Warehouse(String name) {
this.name = name;
}

public static Warehouse getInstance(String name) {
if (instance == null) {
instance = new Warehouse(name);
}
return instance;
}
public static Warehouse getInstance() {
return getInstance("Default");
}

public void clearProducts() {
products.clear();
}

public boolean isEmpty() {
return products.isEmpty();
}

public void addProduct(Product product) {
if (product == null) {
throw new IllegalArgumentException("Product cannot be null.");
}
boolean duplicate = products.stream()
.anyMatch(p->p.uuid().equals(product.uuid()));
if (duplicate) {
throw new IllegalArgumentException("Product with that id already exists, use updateProduct for updates.");
}
products.add(product);
}

public void remove(UUID id) {
products.removeIf(p -> p.uuid().equals(id));
}

public Optional<Product> getProductById(UUID id) {
return products.stream().filter(p -> p.uuid().equals(id)).findFirst();
}

public Map<Category, List<Product>> getProductsGroupedByCategories() {
return products.stream().collect(Collectors.groupingBy(Product::category));
}

public List<Product> getProducts() {
return Collections.unmodifiableList(products);
}

public List<Perishable> expiredProducts() {
LocalDate today = LocalDate.now();
return products.stream()
.filter(p -> p instanceof Perishable per && per.expirationDate().isBefore(today))
.map(p -> (Perishable) p)
.toList();
}

public List<Shippable> shippableProducts() {
return products.stream()
.filter(p -> p instanceof Shippable)
.map(p -> (Shippable) p)
.toList();
}

public void updateProductPrice(UUID id, BigDecimal newPrice) {
Product product = getProductById(id).orElseThrow(() -> new NoSuchElementException("Product not found with id: " + id));
product.setPrice(newPrice);
}

}

Loading
Loading