package org.multibit.mbm.core.model; import com.google.common.collect.Lists; import org.joda.money.BigMoney; import java.util.Collection; import java.util.List; /** *  <p>Builder to provide the following to {@link Item}:</p> *  <ul> *  <li>Provide a fluent interface to facilitate building the entity</li> *  </ul> * * @since 0.0.1 *   */ public class PurchaseOrderBuilder { private Long id; private Supplier supplier; private List<AddPurchaseOrderItem> addPurchaseOrderItems = Lists.newArrayList(); private boolean isBuilt = false; /** * @return A new instance of the builder */ public static PurchaseOrderBuilder newInstance() { return new PurchaseOrderBuilder(); } /** * Handles the building process. No further configuration is possible after this. * * @return The item instance */ public PurchaseOrder build() { validateState(); // PurchaseOrder is a DTO so requires a default constructor PurchaseOrder purchaseOrder = new PurchaseOrder(); purchaseOrder.setId(id); purchaseOrder.setSupplier(supplier); // Add any items for (AddPurchaseOrderItem addPurchaseOrderItem : addPurchaseOrderItems) { addPurchaseOrderItem.applyTo(purchaseOrder); } isBuilt = true; return purchaseOrder; } private void validateState() { if (isBuilt) { throw new IllegalStateException("Build process is complete - no further changes can be made"); } if (supplier == null) { throw new IllegalStateException("PurchaseOrder requires a Supplier"); } } /** * Creates a PurchaseOrderItem entry based on the parameters * * @param id The ID * * @return The builder */ public PurchaseOrderBuilder withId(Long id) { validateState(); this.id = id; return this; } /** * Creates a PurchaseOrderItem entry based on the parameters * * @param item The persistent Item (this should already exist in the database) * @param quantity The quantity * @param unitPrice The price per unit * @param unitTax The tax per unit * * @return The builder */ public PurchaseOrderBuilder withPurchaseOrderItem( Item item, int quantity, BigMoney unitPrice, BigMoney unitTax) { validateState(); addPurchaseOrderItems.add( new AddPurchaseOrderItem( item, quantity, unitPrice, unitTax)); return this; } /** * Creates a PurchaseOrderItem entry based on the parameters * * @param purchaseOrderItem A PurchaseOrderItem * * @return The builder */ public PurchaseOrderBuilder withPurchaseOrderItem(PurchaseOrderItem purchaseOrderItem) { validateState(); addPurchaseOrderItems.add( new AddPurchaseOrderItem( purchaseOrderItem.getItem(), purchaseOrderItem.getQuantity(), purchaseOrderItem.getUnitPrice(), purchaseOrderItem.getUnitTax())); return this; } /** * Creates multiple PurchaseOrderItem entries based on the parameters * * @param purchaseOrderItems A collection of PurchaseOrderItems (Item will be re-used) * * @return The builder */ public PurchaseOrderBuilder withPurchaseOrderItems(Collection<PurchaseOrderItem> purchaseOrderItems) { validateState(); for (PurchaseOrderItem purchaseOrderItem : purchaseOrderItems) { withPurchaseOrderItem(purchaseOrderItem); } return this; } public PurchaseOrderBuilder withSupplier(Supplier supplier) { this.supplier = supplier; return this; } /** * Storage of parameters until ready for application */ private class AddPurchaseOrderItem { private final Item item; private final int quantity; private final BigMoney unitPrice; private final BigMoney unitTax; AddPurchaseOrderItem( Item item, int quantity, BigMoney unitPrice, BigMoney unitTax) { this.item = item; this.quantity = quantity; this.unitPrice = unitPrice; this.unitTax = unitTax; } /** * Applies the parameters to the given PurchaseOrder * * @param purchaseOrder The PurchaseOrder */ void applyTo(PurchaseOrder purchaseOrder) { // Bind the Item to the PurchaseOrder using the primary key PurchaseOrderItem.PurchaseOrderItemPk purchaseOrderItemPk = new PurchaseOrderItem.PurchaseOrderItemPk(); purchaseOrderItemPk.setPurchaseOrder(purchaseOrder); purchaseOrderItemPk.setItem(item); PurchaseOrderItem purchaseOrderItem = new PurchaseOrderItem(); purchaseOrderItem.setPrimaryKey(purchaseOrderItemPk); purchaseOrderItem.setQuantity(quantity); purchaseOrderItem.setUnitPrice(unitPrice); purchaseOrderItem.setUnitTax(unitTax); purchaseOrder.getPurchaseOrderItems().add(purchaseOrderItem); } } }