package org.multibit.mbm.core.model;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import org.multibit.mbm.utils.ObjectUtils;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;
/**
* <p>DTO to provide the following to the application</p>
* <ul>
* <li>Provision of persistent state</li>
* </ul>
* <p>A Delivery provides the mechanism for temporary storage of {@link Item}s. A {@link Supplier} maintains a single Delivery
* (created on demand) </p>
*/
@Entity
@Table(name = "deliveries")
public class Delivery implements Serializable {
private static final long serialVersionUID = 38947590321234L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id = null;
/**
* Many Deliveries come from a single Supplier
*/
@ManyToOne()
private Supplier supplier = null;
/**
* A Delivery has many DeliveryItems that need to be eager to have meaning
* There is no inherent order for this collection
*/
@OneToMany(targetEntity = DeliveryItem.class,
cascade = {CascadeType.ALL},
mappedBy = "primaryKey.delivery",
fetch = FetchType.EAGER,
orphanRemoval = true
)
private Set<DeliveryItem> deliveryItems = Sets.newLinkedHashSet();
/*
* Default constructor required for Hibernate
*/
public Delivery() {
}
/*
* Mandatory field constructor required for builders
*/
public Delivery(Supplier supplier) {
Preconditions.checkNotNull(supplier, "supplier cannot be null");
this.supplier = supplier;
supplier.getDeliveries().add(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<DeliveryItem> deliveryItemOptional = getDeliveryItemByItem(item);
if (quantity > 0) {
if (deliveryItemOptional.isPresent()) {
// Update
deliveryItemOptional.get().setQuantity(quantity);
} else {
// Insert
DeliveryItem newDeliveryItem = new DeliveryItem(this, item);
newDeliveryItem.setQuantity(quantity);
deliveryItems.add(newDeliveryItem);
}
} else {
if (deliveryItemOptional.isPresent()) {
// Remove
deliveryItems.remove(deliveryItemOptional.get());
}
}
}
/**
* @param item The Item to search for
*
* @return The DeliveryItem that contains the Item, or absent
*/
@Transient
public Optional<DeliveryItem> getDeliveryItemByItem(Item item) {
Preconditions.checkNotNull(item, "item cannot be null");
for (DeliveryItem deliveryItem : deliveryItems) {
if (deliveryItem.getItem().equals(item)) {
return Optional.of(deliveryItem);
}
}
return Optional.absent();
}
/**
* @return The number of separate items
*/
@Transient
public int getItemTotal() {
return deliveryItems.size();
}
/**
*
* @return The total quantity of all items
*/
@Transient
public int getQuantityTotal() {
int itemCount = 0;
for (DeliveryItem deliveryItem : deliveryItems) {
itemCount += deliveryItem.getQuantity();
}
return itemCount;
}
/**
* @return The internal unique ID
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* @return The Supplier that owns this Delivery
*/
public Supplier getSupplier() {
return supplier;
}
public void setSupplier(Supplier supplier) {
this.supplier = supplier;
}
/**
* @return The DeliveryItems (contains the quantity, batch reference etc)
*/
public Set<DeliveryItem> getDeliveryItems() {
return deliveryItems;
}
public void setDeliveryItems(Set<DeliveryItem> deliveryItems) {
this.deliveryItems = deliveryItems;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Delivery other = (Delivery) obj;
return ObjectUtils.isEqual(
id, other.id
);
}
@Override
public int hashCode() {
return ObjectUtils.getHashCode(id);
}
@Override
public String toString() {
return String.format("Delivery[id=%s]]", id);
}
}