Skip to content

Commit

Permalink
Switch to records
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarosanchez committed May 17, 2024
1 parent 7114a5b commit 9414514
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ HttpResponse<Cart> postCart(@PathVariable String cartId,
LOG.info("Received {} with cart {}", cartId, newCart);
Optional<Cart> cartHolder = cartRepository.findById(cartId);
if (cartHolder.isEmpty()) {
newCart.setId(cartId);
newCart = newCart.withId(cartId);
cartRepository.save(newCart);
LOG.info("Cart created: {}", newCart);
return HttpResponse.created(newCart);
Expand All @@ -136,9 +136,8 @@ Cart updateCartItem(@PathVariable String cartId, @Body Item qItem) {
);

for (Item item : cart.getItems()) {
if (item.getItemId().equals(qItem.getItemId())) {
item.setQuantity(qItem.getQuantity());

if (item.itemId().equals(qItem.itemId())) {
cart.updateItem(item.withQuantity(qItem.quantity()));
cartRepository.update(cart);
LOG.info("Cart item updated: {}", cart);
return cart;
Expand Down
84 changes: 30 additions & 54 deletions src/carts/lib/src/main/java/mushop/carts/entities/Cart.java
Original file line number Diff line number Diff line change
@@ -1,82 +1,58 @@
package mushop.carts.entities;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import jakarta.validation.constraints.NotNull;
import java.util.function.Function;
import java.util.stream.Collectors;

import io.micronaut.core.annotation.Creator;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;

@MappedEntity
public class Cart {
public record Cart(@Id String id, String customerId, Map<String, Item> items) {

@Id
private String id;

private String customerId;

private List<Item> items = new ArrayList<>();

public Cart() {
id = UUID.randomUUID().toString();
}

public Cart(String id) {
this.id = id;
}

public String getId() {
return id;
}

public String getCustomerId() {
return customerId;
}

public List<Item> getItems() {
return items;
public static Cart of(String customerId, List<Item> items) {
return new Cart(UUID.randomUUID().toString(), customerId, items);
}

public void setId(String id) {
this.id = id;
public Cart(@Id String id, String customerId, List<Item> itemList) {
this(id, customerId, itemList.stream().collect(Collectors.toMap(Item::itemId, Function.identity())));
}

public void setCustomerId(String customerId) {
this.customerId = customerId;
public boolean removeItem(String itemId) {
Item removed = items.remove(itemId);
return removed != null;
}

public void setItems(List<Item> items) {
this.items = items;
public void updateItem(Item item) {
items.put(item.itemId(), item);
}

public boolean removeItem(String itemId) {
return items.removeIf(item -> itemId.equalsIgnoreCase(item.getItemId()));
public Cart merge(Cart cart) {
return new Cart(id, cart.customerId(), mergeItems(cart.items));
}

public void merge(Cart cart) {
customerId = cart.getCustomerId();
for (Item item : cart.items) {
mergeItem(item);
private Map<String, Item> mergeItems(Map<String, Item> newItems) {
Map<String, Item> result = new HashMap<>(items);
for (Item newItem : newItems.values()) {
result.computeIfPresent(newItem.itemId(), (itemId, existing) -> new Item(existing.id(), itemId, existing.quantity() + newItem.quantity(), existing.unitPrice()));
result.putIfAbsent(newItem.itemId(), newItem);
}
return result;
}

private void mergeItem(Item item) {
for (Item existing : items) {
if (existing.getItemId().equals(item.getItemId())) {
existing.setQuantity(existing.getQuantity() + item.getQuantity());
return;
}
}
items.add(item);
public Cart withId(String cartId) {
return new Cart(cartId, customerId, items);
}

@Override
public String toString() {
return "Cart [customerId=" + customerId +
", id=" + id +
", items=" + items +
"]";
public List<Item> getItems() {
return Optional.ofNullable(items)
.map(Map::values)
.map(ArrayList::new)
.orElseGet(ArrayList::new);
}
}
57 changes: 5 additions & 52 deletions src/carts/lib/src/main/java/mushop/carts/entities/Item.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,63 +5,16 @@

import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;
import jakarta.validation.constraints.NotNull;

@MappedEntity
public class Item {
public record Item(@Id String id, String itemId, int quantity, BigDecimal unitPrice) {

@Id
private String id;
public static Item of(String itemId, int quantity, BigDecimal unitPrice) {
return new Item(UUID.randomUUID().toString(), itemId, quantity, unitPrice);

@NotNull
private String itemId;

private int quantity;
private BigDecimal unitPrice;

public Item() {
id = UUID.randomUUID().toString();
quantity = 1;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getItemId() {
return itemId;
}

public void setItemId(String itemId) {
this.itemId = itemId;
}

public int getQuantity() {
return quantity;
}

public void setQuantity(int quantity) {
this.quantity = quantity;
}

public BigDecimal getUnitPrice() {
return unitPrice;
}

public void setUnitPrice(BigDecimal unitPrice) {
this.unitPrice = unitPrice;
}

@Override
public String toString() {
return "Item [id=" + id +
", itemId=" + itemId +
", quantity=" + quantity +
", unitPrice=" + unitPrice +
"]";
public Item withQuantity(int newQuantity) {
return new Item(id, itemId, newQuantity, unitPrice);
}
}
83 changes: 83 additions & 0 deletions src/carts/lib/src/test/java/mushop/carts/entities/CartTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package mushop.carts.entities;

import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

class CartTest {

@Test
void testRemoveItem() {
String itemId = "itemId";

Item item = Item.of(itemId, 0, new BigDecimal(0));
Cart cart = new Cart(null, null, List.of(item));

assertEquals(1, cart.items().size());
assertTrue(cart.removeItem(itemId));
assertEquals(0, cart.items().size());
assertFalse(cart.removeItem(itemId));
}

@Test
void testMergeCartsSameItems() {
String itemId = "itemId";

Item cart1Item = Item.of(itemId, 1, new BigDecimal(10));
Cart cart1 = new Cart(null, null, List.of(cart1Item));

Item cart2Item = Item.of(itemId, 3, new BigDecimal(20));
Cart cart2 = new Cart(null, null, List.of(cart2Item));

Cart merged = cart1.merge(cart2);
assertEquals(1, merged.items().size());

Item first = merged.getItems().getFirst();
assertEquals(4, first.quantity());
assertEquals(10, first.unitPrice().intValue());
}

@Test
void testMergeCartsMoreItems() {
Item cart1item1 = Item.of("1", 1, new BigDecimal(1));
Item cart2item1 = Item.of("1", 2, new BigDecimal(1));

Item item2 = Item.of("2", 2, new BigDecimal(2));

Cart cart1 = new Cart(null, null, List.of(cart1item1));
Cart cart2 = new Cart(null, null, List.of(cart2item1, item2));

Cart merged = cart1.merge(cart2);
assertEquals(2, merged.items().size());

Item mergedItem1 = merged.getItems().stream().filter(item -> item.itemId().equals("1")).findFirst().get();
assertEquals(3, mergedItem1.quantity());

Item mergedItem2 = merged.getItems().stream().filter(item -> item.itemId().equals("2")).findFirst().get();
assertEquals(2, mergedItem2.quantity());
}

@Test
void testMergeCartsLessItems() {
Item cart1item1 = Item.of("1", 1, new BigDecimal(1));
Item cart2item1 = Item.of("1", 2, new BigDecimal(1));

Item item2 = Item.of("2", 2, new BigDecimal(2));

Cart cart1 = new Cart(null, null, List.of(cart1item1, item2));
Cart cart2 = new Cart(null, null, List.of(cart2item1));

Cart merged = cart1.merge(cart2);
assertEquals(2, merged.items().size());

Item mergedItem1 = merged.getItems().stream().filter(item -> item.itemId().equals("1")).findFirst().get();
assertEquals(3, mergedItem1.quantity());

Item mergedItem2 = merged.getItems().stream().filter(item -> item.itemId().equals("2")).findFirst().get();
assertEquals(2, mergedItem2.quantity());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import mushop.carts.entities.Cart;
import mushop.carts.entities.Item;
import mushop.carts.repositories.CartRepository;
import org.testcontainers.shaded.org.checkerframework.checker.units.qual.C;

abstract class AbstractCartRepositoryMongoTest {

Expand All @@ -42,23 +43,18 @@ void testCartRepositoryResolution(){

@Test
void testCartRepository() {
Cart cart = new Cart("1234");
cart.setCustomerId("abcd");
Item item = new Item();
item.setItemId("item id");
item.setId("ab");
item.setQuantity(3);
item.setUnitPrice(new BigDecimal(101));
Item item = new Item("ab", "item id", 3, new BigDecimal(101));
Cart cart = new Cart("1234", "abcd", List.of(item));
cart.getItems().add(item);
cartRepository.save(cart);

Optional<Cart> acart = cartRepository.findById("1234");
assertTrue(acart.isPresent());
assertEquals(cart.getCustomerId(), acart.get().getCustomerId());
assertEquals(cart.customerId(), acart.get().customerId());

List<Cart> customerCart = cartRepository.getByCustomerId("abcd");
assertNotNull(customerCart);
assertEquals(1, customerCart.size());
assertEquals(cart.getCustomerId(), customerCart.get(0).getCustomerId());
assertEquals(cart.customerId(), customerCart.get(0).customerId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,38 @@ abstract class AbstractTestCartService {

@Inject
@Client("/")
HttpClient httpClient;
HttpClient client;


@Test
public void testMetricsJson() {
JsonNode result = httpClient.toBlocking().retrieve("/metrics", JsonNode.class);
JsonNode result = client.toBlocking().retrieve("/metrics", JsonNode.class);
assertThat(result.get("names").size(), greaterThan(0));
}



@Test
public void testStoreCart() {
Item i = new Item();
i.setUnitPrice(BigDecimal.valueOf(123));
i.setQuantity(47);
i.setItemId("I123");
Item i = Item.of("I123", 47, BigDecimal.valueOf(123));
Cart c = Cart.of("c1", List.of(i));

Cart c = new Cart();
c.setCustomerId("c1");
c.getItems().add(i);

HttpResponse<Cart> created = httpClient.toBlocking().exchange(HttpRequest.POST("/carts/" + c.getId(), c), Cart.class);
HttpResponse<Cart> created = client.toBlocking().exchange(HttpRequest.POST("/carts/" + c.id(), c), Cart.class);
assertEquals(HttpStatus.CREATED, created.getStatus());
assertEquals(c.getId(), created.body().getId());
assertEquals(c.id(), created.body().id());

HttpResponse<List<Item>> items = httpClient.toBlocking().exchange(HttpRequest.GET("/carts/" + c.getId() + "/items"), Argument.listOf(Item.class));
HttpResponse<List<Item>> items = client.toBlocking().exchange(HttpRequest.GET("/carts/" + c.id() + "/items"), Argument.listOf(Item.class));
assertEquals(1, items.body().size());
assertEquals(i.getId(), items.body().get(0).getId());
assertEquals(i.id(), items.body().get(0).id());

HttpResponse<Cart> updateItem = client.toBlocking().exchange(HttpRequest.PUT("/carts/" + c.id() + "/items", i.withQuantity(23)), Cart.class);
assertEquals(HttpStatus.OK, updateItem.getStatus());
assertEquals(23, updateItem.body().getItems().getFirst().quantity());

HttpResponse<Cart> deleteItem = httpClient.toBlocking().exchange(HttpRequest.DELETE("/carts/" + c.getId() + "/items/" + i.getItemId()), Cart.class);
HttpResponse<Cart> deleteItem = client.toBlocking().exchange(HttpRequest.DELETE("/carts/" + c.id() + "/items/" + i.itemId()), Cart.class);
assertEquals(HttpStatus.OK, deleteItem.getStatus());

items = httpClient.toBlocking().exchange(HttpRequest.GET("/carts/" + c.getId() + "/items"), Argument.listOf(Item.class));
items = client.toBlocking().exchange(HttpRequest.GET("/carts/" + c.id() + "/items"), Argument.listOf(Item.class));
assertEquals(0, items.body().size());
}
}

0 comments on commit 9414514

Please sign in to comment.