package org.multibit.mbm.core.model;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.multibit.mbm.utils.ObjectUtils;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
/**
* <p>DTO to provide the following to the application</p>
* <ul>
* <li>Provision of persistent state</li>
* </ul>
* <p>A Cart provides the mechanism for temporary storage of {@link Item}s. A {@link Customer} maintains a single Cart
* (created on demand) </p>
*/
@Entity
@Table(name = "carts")
public class Cart implements Serializable {
private static final long serialVersionUID = 38947590321234L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id = null;
/**
* A Cart has a single Customer
*/
@OneToOne(mappedBy = "cart")
private Customer customer = null;
/**
* A Cart has many CartItems that need to be eager to have meaning
* They also have an order
*/
@OneToMany(targetEntity = CartItem.class,
cascade = {CascadeType.ALL},
mappedBy = "primaryKey.cart",
fetch = FetchType.EAGER,
orphanRemoval = true
)
@OrderBy(value = "index")
private List<CartItem> cartItems = Lists.newArrayList();
/*
* Default constructor required for Hibernate
*/
public Cart() {
}
/*
* Mandatory field constructor required for builders
*/
public Cart(Customer customer) {
Preconditions.checkNotNull(customer, "customer cannot be null");
this.customer = customer;
customer.setCart(this);
}
/**
* Handles the process of updating the Item quantities
*
* @param item The Item (usually source from ItemDao)
* @param quantity The quantity (>0 is add/update, otherwise remove)
*/
@Transient
public void setItemQuantity(Item item, int quantity) {
Preconditions.checkNotNull(item, "item cannot be null");
Optional<CartItem> cartItemOptional = getCartItemByItem(item);
if (quantity > 0) {
if (cartItemOptional.isPresent()) {
// Update
cartItemOptional.get().setQuantity(quantity);
} else {
// Insert
CartItem newCartItem = new CartItem(this, item);
newCartItem.setIndex(cartItems.size());
newCartItem.setQuantity(quantity);
cartItems.add(newCartItem);
}
} else {
if (cartItemOptional.isPresent()) {
// Remove
cartItems.remove(cartItemOptional.get());
// Re-align the other cart item index values
int i=0;
for (CartItem cartItem : cartItems) {
cartItem.setIndex(i++);
}
}
}
}
/**
* @param item The Item to search for
*
* @return The CartItem that contains the Item, or absent
*/
@Transient
public Optional<CartItem> getCartItemByItem(Item item) {
Preconditions.checkNotNull(item, "item cannot be null");
for (CartItem cartItem : cartItems) {
if (cartItem.getItem().equals(item)) {
return Optional.of(cartItem);
}
}
return Optional.absent();
}
/**
* @return The number of separate items
*/
@Transient
public int getItemTotal() {
return cartItems.size();
}
/**
*
* @return The total quantity of all items
*/
@Transient
public int getQuantityTotal() {
int itemCount = 0;
for (CartItem cartItem : cartItems) {
itemCount += cartItem.getQuantity();
}
return itemCount;
}
/**
* @return The internal unique ID
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* @return The Customer that owns this Cart
*/
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
/**
* @return The CartItems (contains the ordering index, quantity, date etc)
*/
public List<CartItem> getCartItems() {
return cartItems;
}
public void setCartItems(List<CartItem> cartItems) {
this.cartItems = cartItems;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Cart other = (Cart) obj;
return ObjectUtils.isEqual(
id, other.id
);
}
@Override
public int hashCode() {
return ObjectUtils.getHashCode(id);
}
@Override
public String toString() {
return String.format("Cart[id=%s]]", id);
}
}