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
69 changes: 69 additions & 0 deletions src/main/java/com/example/Category.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.example;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

public class Category {

private static final Map<String, Category> CACHE = new ConcurrentHashMap<>();
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");
}

name = name.trim();
if (name.isEmpty()) {
throw new IllegalArgumentException("Category name can't be blank");
}

String formattedName = capitalize(name);

return CACHE.computeIfAbsent(formattedName, Category::new);
}

private static String capitalize(String name) {
return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
}

public String getName() {
return name;
}

public List<Product> findProductsByCategory(Category category) {
if (category == null) {
throw new IllegalArgumentException("Category cannot be null");
}

return Warehouse.getProducts().stream()
.filter(p -> p.getCategory().equals(category))
.toList();
}



@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Category category)) return false;
return name.equals(category.name);
}

@Override
public int hashCode() {
return name.hashCode();
}

@Override
public String toString() {
return "Category{name='" + name + "'}";
}
}
53 changes: 53 additions & 0 deletions src/main/java/com/example/ElectronicsProduct.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.example;

import jdk.jfr.Category;

import java.math.BigDecimal;
import java.util.UUID;

public class ElectronicsProduct extends Product implements Shippable {

private final int warrantyMonths;
private final BigDecimal weight; // in kilograms

public ElectronicsProduct(UUID uuid, String name, Category category, BigDecimal price, int warrantyMonths, BigDecimal weight) {
super(uuid, name, category, price);

if (price.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("Price cannot be negative.");
}
if (warrantyMonths < 0) {
throw new IllegalArgumentException("Warranty months cannot be negative.");
}
if (weight.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("Weight cannot be negative.");
}

this.warrantyMonths = warrantyMonths;
this.weight = weight;
}

public int getWarrantyMonths() {
return warrantyMonths;
}

@Override
public BigDecimal weight() {
return weight;
}

@Override
public BigDecimal calculateShippingCost() {
// Shipping rule: base 79 + (if heavy > 5kg, add 49)
BigDecimal cost = BigDecimal.valueOf(79);
if (weight.compareTo(BigDecimal.valueOf(5)) > 0) {
cost = cost.add(BigDecimal.valueOf(49));
}
return cost;
}

@Override
public String productDetails() {
return "Electronics: " + name() + ", Warranty: " + warrantyMonths + " months";
}
}
61 changes: 61 additions & 0 deletions src/main/java/com/example/FoodProduct.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.example;

import jdk.jfr.Category;

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; // in kilograms

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;
}

public LocalDate getExpirationDate() {
return expirationDate;
}

@Override
public BigDecimal weight() {
return weight;
}

@Override
public BigDecimal calculateShippingCost() {
// Shipping rule: cost = weight * 50
return weight.multiply(BigDecimal.valueOf(50));
}

@Override
public String productDetails() {
return "Food: " + name() + ", Expires: " + expirationDate;
}

@Override
public LocalDate getExpiryDate() {
return null;
}

public boolean isExpired() {
return LocalDate.now().isAfter(expirationDate);
}

@Override
public LocalDate expirationDate() {
return null;
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/example/Perishable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example;

import java.time.LocalDate;

public interface Perishable {
LocalDate getExpiryDate();

default boolean isExpired() {
return getExpiryDate().isBefore(LocalDate.now());
}

LocalDate expirationDate();
}
87 changes: 87 additions & 0 deletions src/main/java/com/example/Product.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.example;

import jdk.jfr.Category;

import java.math.BigDecimal;
import java.util.Objects;
import java.util.UUID;

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

protected Product(UUID uuid, String name, Category category, BigDecimal price) {
this.uuid = Objects.requireNonNull(uuid, "UUID cannot be null.");
this.name = validateName(name);
this.category = Objects.requireNonNull(category, "Category cannot be null.");
this.price = validatePrice(price);
}


public UUID uuid() {
return uuid;
}

public String name() {
return name;
}

public Category getCategory() {
return category;
}

public BigDecimal price() {
return price;
}


public void setPrice(BigDecimal newPrice) {
this.price = validatePrice(newPrice);
}


public abstract String productDetails();


private String validateName(String name) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("Product name cannot be blank.");
}
return name.trim();
}

private BigDecimal validatePrice(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.");
}
return price;
}


@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Product)) return false;
Product that = (Product) o;
return uuid.equals(that.uuid);
}

@Override
public int hashCode() {
return uuid.hashCode();
}

@Override
public String toString() {
return name + " (" + category.getClass() + ")";
}

public Category category() {
return null;
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/example/Shippable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example;

import java.math.BigDecimal;

public interface Shippable {

BigDecimal weight();


BigDecimal calculateShippingCost();

BigDecimal price();
}
41 changes: 41 additions & 0 deletions src/main/java/com/example/ShippingGroup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.example;

import com.example.Shippable;

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

class ShippingGroup {
private final List<Shippable> products;
private final BigDecimal totalWeight;
private final BigDecimal totalShippingCost;

public ShippingGroup(List<Shippable> products) {
this.products = new ArrayList<>(products);


this.totalWeight = products.stream()
.map(Shippable::weight)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);


this.totalShippingCost = products.stream()
.map(Shippable::calculateShippingCost)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}

public List<Shippable> getProducts() {
return new ArrayList<>(products);
}

public BigDecimal getTotalWeight() {
return totalWeight;
}

public BigDecimal getTotalShippingCost() {
return totalShippingCost;
}
}
Loading