From d317ca2a1405ec615f92ae49b6efe98762af9db3 Mon Sep 17 00:00:00 2001 From: shahdhoss Date: Sat, 14 Dec 2024 18:35:09 +0200 Subject: [PATCH] addressed the comments regarding changing lists to maps and adding maven assembly plugin --- session-facade/README.md | 41 ++++++--- session-facade/pom.xml | 26 ++++-- .../java/com/iluwatar/sessionfacade/App.java | 27 +++++- .../iluwatar/sessionfacade/CartService.java | 44 +++++----- .../iluwatar/sessionfacade/OrderService.java | 42 ++++++++-- .../sessionfacade/PaymentService.java | 13 ++- .../com/iluwatar/sessionfacade/Product.java | 2 - .../sessionfacade/ProductCatalogService.java | 28 +++++-- .../sessionfacade/ShoppingFacade.java | 84 ++++++++++++------- .../sessionfacade/CartServiceTest.java | 14 ++-- .../sessionfacade/PaymentServiceTest.java | 16 ++++ .../sessionfacade/ShoppingFacadeTest.java | 14 ++-- 12 files changed, 248 insertions(+), 103 deletions(-) diff --git a/session-facade/README.md b/session-facade/README.md index 01adda263c62..20a093334e92 100644 --- a/session-facade/README.md +++ b/session-facade/README.md @@ -58,26 +58,30 @@ public class App { The `ShoppingFacade` acts as an intermediary that facilitates interaction between different services promoting low coupling between these services. ```java public class ShoppingFacade { - List productCatalog; - List cart; - CartService cartService; - OrderService orderService; - PaymentService paymentService; + + private final CartService cartService; + private final OrderService orderService; + private final PaymentService paymentService; public ShoppingFacade() { - productCatalog = new ArrayList<>(); - productCatalog.add(new Product(1, "Wireless Mouse", 25.99, "Ergonomic wireless mouse with USB receiver.")); - productCatalog.add(new Product(2, "Gaming Keyboard", 79.99, "RGB mechanical gaming keyboard with programmable keys.")); - cart = new ArrayList<>(); + Map productCatalog = new HashMap<>(); + productCatalog.put(1, new Product(1, "Wireless Mouse", 25.99, "Ergonomic wireless mouse with USB receiver.")); + productCatalog.put(2, new Product(2, "Gaming Keyboard", 79.99, "RGB mechanical gaming keyboard with programmable keys.")); + Map cart = new HashMap<>(); cartService = new CartService(cart, productCatalog); orderService = new OrderService(cart); paymentService = new PaymentService(); } + public Map getCart() { + return this.cartService.getCart(); + } + public void addToCart(int productId) { this.cartService.addToCart(productId); } - + + public void removeFromCart(int productId) { this.cartService.removeFromCart(productId); } @@ -86,10 +90,21 @@ public class ShoppingFacade { this.orderService.order(); } - public void selectPaymentMethod(String method) { - this.paymentService.selectPaymentMethod(method); + public Boolean isPaymentRequired() { + double total = this.orderService.getTotal(); + if (total == 0.0) { + LOGGER.info("No payment required"); + return false; + } + return true; + } + + public void processPayment(String method) { + Boolean isPaymentRequired = isPaymentRequired(); + if (Boolean.TRUE.equals(isPaymentRequired)) { + paymentService.selectPaymentMethod(method); + } } -} ``` Console output for starting the `App` class's `main` method: diff --git a/session-facade/pom.xml b/session-facade/pom.xml index d7e5ad956d41..2dfe12e0c80c 100644 --- a/session-facade/pom.xml +++ b/session-facade/pom.xml @@ -36,12 +36,6 @@ session-facade - - - 17 - 17 - UTF-8 - org.junit.jupiter @@ -54,5 +48,23 @@ test - + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.sessionfacade.App + + + + + + + + \ No newline at end of file diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/App.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/App.java index 985648d7c418..4f136b9fa360 100644 --- a/session-facade/src/main/java/com/iluwatar/sessionfacade/App.java +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/App.java @@ -26,18 +26,37 @@ package com.iluwatar.sessionfacade; /** - * The type App. + * The main entry point of the application that demonstrates the usage + * of the ShoppingFacade to manage the shopping process using the Session Facade pattern. + * This class serves as a client that interacts with the simplified + * interface provided by the ShoppingFacade, which encapsulates + * complex interactions with the underlying business services. + * The ShoppingFacade acts as a session bean that coordinates the communication + * between multiple services, hiding their complexity and providing a single, unified API. */ public class App { /** - * The entry point of application. + * The entry point of the application. + * This method demonstrates how the ShoppingFacade, acting as a Session Facade, is used to: + * - Add items to the shopping cart + * - Process a payment + * - Place the order + * The session facade manages the communication between the individual services + * and simplifies the interactions for the client. * * @param args the input arguments */ public static void main(String[] args) { ShoppingFacade shoppingFacade = new ShoppingFacade(); + + // Adding items to the shopping cart shoppingFacade.addToCart(1); + shoppingFacade.addToCart(2); + + // Processing the payment with the chosen method + shoppingFacade.processPayment("cash"); + + // Finalizing the order shoppingFacade.order(); - shoppingFacade.selectPaymentMethod("cash"); } -} \ No newline at end of file +} diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/CartService.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/CartService.java index 7a091f879e56..4bf9bde261cf 100644 --- a/session-facade/src/main/java/com/iluwatar/sessionfacade/CartService.java +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/CartService.java @@ -25,18 +25,24 @@ package com.iluwatar.sessionfacade; -import java.util.List; -import lombok.extern.slf4j.Slf4j; +import java.util.Map; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; /** * The type Cart service. + * Represents the cart entity, has add to cart and remove from cart methods */ @Slf4j public class CartService { - - private final List cart; - private final List productCatalog; + /** + * -- GETTER -- + * Gets cart. + */ + @Getter + private final Map cart; + private final Map productCatalog; /** * Instantiates a new Cart service. @@ -44,7 +50,7 @@ public class CartService { * @param cart the cart * @param productCatalog the product catalog */ - public CartService(List cart, List productCatalog) { + public CartService(Map cart, Map productCatalog) { this.cart = cart; this.productCatalog = productCatalog; } @@ -55,14 +61,13 @@ public CartService(List cart, List productCatalog) { * @param productId the product id */ public void addToCart(int productId) { - for (Product product : productCatalog) { - if (productId == product.id()) { - this.cart.add(product); - LOGGER.info("{} successfully added to the cart", product); - return; - } + Product product = productCatalog.get(productId); + if (product != null) { + cart.put(productId, product); + LOGGER.info("{} successfully added to the cart", product); + } else { + LOGGER.info("No product is found in catalog with id {}", productId); } - LOGGER.info("No product is found with id {}", productId); } /** @@ -71,13 +76,12 @@ public void addToCart(int productId) { * @param productId the product id */ public void removeFromCart(int productId) { - for (Product product : productCatalog) { - if (productId == product.id()) { - this.cart.remove(product); - LOGGER.info("{} successfully removed from the cart", product); - return; - } + Product product = cart.remove(productId); // Remove product from cart + if (product != null) { + LOGGER.info("{} successfully removed from the cart", product); + } else { + LOGGER.info("No product is found in cart with id {}", productId); } - LOGGER.info("No product is found with the id {}", productId); } + } diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/OrderService.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/OrderService.java index 5a317ab61679..9ffa94b7148a 100644 --- a/session-facade/src/main/java/com/iluwatar/sessionfacade/OrderService.java +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/OrderService.java @@ -25,23 +25,27 @@ package com.iluwatar.sessionfacade; -import java.util.List; +import java.util.Map; import lombok.extern.slf4j.Slf4j; - /** - * The type Order service. + * The OrderService class is responsible for finalizing a customer's order. + * It includes a method to calculate the total cost of the order, which follows + * the information expert principle from GRASP by assigning the responsibility + * of total calculation to this service. + * Additionally, it provides a method to complete the order, which empties the + * client's shopping cart once the order is finalized. */ @Slf4j public class OrderService { - private final List cart; + private final Map cart; /** * Instantiates a new Order service. * * @param cart the cart */ - public OrderService(List cart) { + public OrderService(Map cart) { this.cart = cart; } @@ -49,7 +53,31 @@ public OrderService(List cart) { * Order. */ public void order() { - LOGGER.info("Client has chosen to order {}", cart); - cart.clear(); + Double total = getTotal(); + if (!this.cart.isEmpty()) { + LOGGER.info("Client has chosen to order {} with total {}", cart, + String.format("%.2f", total)); + this.completeOrder(); + } else { + LOGGER.info("Client's shopping cart is empty"); + } + } + + /** + * Gets total. + * + * @return the total + */ + public double getTotal() { + final double[] total = {0.0}; + this.cart.forEach((key, product) -> total[0] += product.price()); + return total[0]; + } + + /** + * Complete order. + */ + public void completeOrder() { + this.cart.clear(); } } diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/PaymentService.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/PaymentService.java index 4d0120e4aa06..ce9ce8fed17c 100644 --- a/session-facade/src/main/java/com/iluwatar/sessionfacade/PaymentService.java +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/PaymentService.java @@ -29,10 +29,19 @@ import org.slf4j.LoggerFactory; /** - * The type Payment service. + * The PaymentService class is responsible for handling the selection and processing + * of different payment methods. It provides functionality to select a payment method + * (cash or credit card) and process the corresponding payment option. The class uses + * logging to inform the client of the selected payment method. + * It includes methods to: + * - Select the payment method based on the client's choice. + * - Process cash payments through the `cashPayment()` method. + * - Process credit card payments through the `creditCardPayment()` method. */ - public class PaymentService { + /** + * The constant LOGGER. + */ public static Logger LOGGER = LoggerFactory.getLogger(PaymentService.class); /** diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/Product.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/Product.java index 06e21cd344cb..9727a94db11e 100644 --- a/session-facade/src/main/java/com/iluwatar/sessionfacade/Product.java +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/Product.java @@ -29,12 +29,10 @@ * The type Product. */ public record Product(int id, String name, double price, String description) { - @Override public String toString() { return "ID: " + id + "\nName: " + name + "\nPrice: $" + price + "\nDescription: " + description; } - } diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/ProductCatalogService.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/ProductCatalogService.java index 3780a686b52e..cd6a997f9b01 100644 --- a/session-facade/src/main/java/com/iluwatar/sessionfacade/ProductCatalogService.java +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/ProductCatalogService.java @@ -25,20 +25,36 @@ package com.iluwatar.sessionfacade; -import java.util.List; +import java.util.Map; /** - * The type Product catalog service. + * The type ProductCatalogService. + * This class manages a catalog of products. It holds a map of products, + * where each product is identified by a unique ID. The class + * provides functionality to access and manage the products in the catalog. */ public class ProductCatalogService { - private List products; + + private final Map products; /** - * Instantiates a new Product catalog service. + * Instantiates a new ProductCatalogService. * - * @param products the products + * @param products the map of products to be used by this service */ - public ProductCatalogService(List products) { + public ProductCatalogService(Map products) { this.products = products; } + + // Additional methods to interact with products can be added here, for example: + + /** + * Retrieves a product by its ID. + * + * @param id the product ID + * @return the product corresponding to the ID + */ + public Product getProductById(int id) { + return products.get(id); + } } diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/ShoppingFacade.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/ShoppingFacade.java index cdc00d98f40c..14560518129f 100644 --- a/session-facade/src/main/java/com/iluwatar/sessionfacade/ShoppingFacade.java +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/ShoppingFacade.java @@ -25,47 +25,54 @@ package com.iluwatar.sessionfacade; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; + /** - * The type Shopping facade. + * The ShoppingFacade class provides a simplified interface for clients to interact with the shopping system. + * It acts as a facade to handle operations related to a shopping cart, order processing, and payment. + * Responsibilities: + * - Add products to the shopping cart. + * - Remove products from the shopping cart. + * - Retrieve the current shopping cart. + * - Finalize an order by calling the order service. + * - Check if a payment is required based on the order total. + * - Process payment using different payment methods (e.g., cash, credit card). + * The ShoppingFacade class delegates operations to the following services: + * - CartService: Manages the cart and product catalog. + * - OrderService: Handles the order finalization process and calculation of the total. + * - PaymentService: Handles the payment processing based on the selected payment method. */ +@Slf4j public class ShoppingFacade { - /** - * The Product catalog. - */ - List productCatalog = new ArrayList<>(); - /** - * The Cart. - */ - List cart = new ArrayList<>(); - /** - * The Cart service. - */ - CartService cartService = new CartService(cart, productCatalog); - /** - * The Order service. - */ - OrderService orderService = new OrderService(cart); - /** - * The Payment service. - */ - PaymentService paymentService = new PaymentService(); + private final CartService cartService; + private final OrderService orderService; + private final PaymentService paymentService; /** * Instantiates a new Shopping facade. */ public ShoppingFacade() { - productCatalog = new ArrayList<>(); - productCatalog.add(new Product(1, "Wireless Mouse", 25.99, "Ergonomic wireless mouse with USB receiver.")); - productCatalog.add(new Product(2, "Gaming Keyboard", 79.99, "RGB mechanical gaming keyboard with programmable keys.")); - cart = new ArrayList<>(); + Map productCatalog = new HashMap<>(); + productCatalog.put(1, new Product(1, "Wireless Mouse", 25.99, "Ergonomic wireless mouse with USB receiver.")); + productCatalog.put(2, new Product(2, "Gaming Keyboard", 79.99, "RGB mechanical gaming keyboard with programmable keys.")); + Map cart = new HashMap<>(); cartService = new CartService(cart, productCatalog); orderService = new OrderService(cart); paymentService = new PaymentService(); } + /** + * Gets cart. + * + * @return the cart + */ + public Map getCart() { + return this.cartService.getCart(); + } + /** * Add to cart. * @@ -92,11 +99,28 @@ public void order() { } /** - * Select payment method. + * Is payment required boolean. + * + * @return the boolean + */ + public Boolean isPaymentRequired() { + double total = this.orderService.getTotal(); + if (total == 0.0) { + LOGGER.info("No payment required"); + return false; + } + return true; + } + + /** + * Process payment. * * @param method the method */ - public void selectPaymentMethod(String method) { - this.paymentService.selectPaymentMethod(method); + public void processPayment(String method) { + Boolean isPaymentRequired = isPaymentRequired(); + if (Boolean.TRUE.equals(isPaymentRequired)) { + paymentService.selectPaymentMethod(method); + } } } diff --git a/session-facade/src/test/java/com/iluwatar/sessionfacade/CartServiceTest.java b/session-facade/src/test/java/com/iluwatar/sessionfacade/CartServiceTest.java index 6f0c48e51f6e..958bd20f9e25 100644 --- a/session-facade/src/test/java/com/iluwatar/sessionfacade/CartServiceTest.java +++ b/session-facade/src/test/java/com/iluwatar/sessionfacade/CartServiceTest.java @@ -30,7 +30,9 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.junit.jupiter.api.Assertions.*; @@ -41,7 +43,7 @@ class CartServiceTest { private CartService cartService; - private List cart; + private Map cart; /** * Sets up. @@ -49,10 +51,10 @@ class CartServiceTest { @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); - cart = new ArrayList<>(); - List productCatalog = new ArrayList<>(); - productCatalog.add(new Product(1, "Product A", 2.0, "any description")); - productCatalog.add(new Product(2, "Product B", 300.0, "a watch")); + cart = new HashMap<>(); + Map productCatalog = new HashMap<>(); + productCatalog.put(1,new Product(1, "Product A", 2.0, "any description")); + productCatalog.put(2,new Product(2, "Product B", 300.0, "a watch")); cartService = new CartService(cart, productCatalog); } @@ -63,7 +65,7 @@ void setUp() { void testAddToCart() { cartService.addToCart(1); assertEquals(1, cart.size()); - assertEquals("Product A", cart.get(0).name()); + assertEquals("Product A", cart.get(1).name()); } /** diff --git a/session-facade/src/test/java/com/iluwatar/sessionfacade/PaymentServiceTest.java b/session-facade/src/test/java/com/iluwatar/sessionfacade/PaymentServiceTest.java index fac4b39fbfb8..583b8a6f9e91 100644 --- a/session-facade/src/test/java/com/iluwatar/sessionfacade/PaymentServiceTest.java +++ b/session-facade/src/test/java/com/iluwatar/sessionfacade/PaymentServiceTest.java @@ -30,10 +30,17 @@ import static org.mockito.Mockito.*; +/** + * The type Payment service test. + */ class PaymentServiceTest { private PaymentService paymentService; + private OrderService orderService; private Logger mockLogger; + /** + * Sets up. + */ @BeforeEach void setUp() { paymentService = new PaymentService(); @@ -41,6 +48,9 @@ void setUp() { paymentService.LOGGER = mockLogger; } + /** + * Test select cash payment method. + */ @Test void testSelectCashPaymentMethod() { String method = "cash"; @@ -48,6 +58,9 @@ void testSelectCashPaymentMethod() { verify(mockLogger).info("Client have chosen cash payment option"); } + /** + * Test select credit card payment method. + */ @Test void testSelectCreditCardPaymentMethod() { String method = "credit"; @@ -55,6 +68,9 @@ void testSelectCreditCardPaymentMethod() { verify(mockLogger).info("Client have chosen credit card payment option"); } + /** + * Test select unspecified payment method. + */ @Test void testSelectUnspecifiedPaymentMethod() { String method = "cheque"; diff --git a/session-facade/src/test/java/com/iluwatar/sessionfacade/ShoppingFacadeTest.java b/session-facade/src/test/java/com/iluwatar/sessionfacade/ShoppingFacadeTest.java index f5fffd49db79..01e4cb588e9c 100644 --- a/session-facade/src/test/java/com/iluwatar/sessionfacade/ShoppingFacadeTest.java +++ b/session-facade/src/test/java/com/iluwatar/sessionfacade/ShoppingFacadeTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.List; +import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -47,10 +48,10 @@ void setUp() { void testAddToCart() { shoppingFacade.addToCart(1); shoppingFacade.addToCart(2); - List cart = shoppingFacade.cart; + Map cart = shoppingFacade.getCart(); assertEquals(2, cart.size(), "Cart should contain two items."); - assertEquals("Wireless Mouse", cart.get(0).name(), "First item in the cart should be 'Wireless Mouse'."); - assertEquals("Gaming Keyboard", cart.get(1).name(), "Second item in the cart should be 'Gaming Keyboard'."); + assertEquals("Wireless Mouse", cart.get(1).name(), "First item in the cart should be 'Wireless Mouse'."); + assertEquals("Gaming Keyboard", cart.get(2).name(), "Second item in the cart should be 'Gaming Keyboard'."); } @Test @@ -58,16 +59,17 @@ void testRemoveFromCart() { shoppingFacade.addToCart(1); shoppingFacade.addToCart(2); shoppingFacade.removeFromCart(1); - List cart = shoppingFacade.cart; + Map cart = shoppingFacade.getCart(); assertEquals(1, cart.size(), "Cart should contain one item after removal."); - assertEquals("Gaming Keyboard", cart.get(0).name(), "Remaining item should be 'Gaming Keyboard'."); + assertEquals("Gaming Keyboard", cart.get(2).name(), "Remaining item should be 'Gaming Keyboard'."); } @Test void testOrder() { shoppingFacade.addToCart(1); shoppingFacade.addToCart(2); + shoppingFacade.processPayment("cash"); shoppingFacade.order(); - assertTrue(shoppingFacade.cart.isEmpty(), "Cart should be empty after placing the order."); + assertTrue(shoppingFacade.getCart().isEmpty(), "Cart should be empty after placing the order."); } }