/**
 * This software program, Simple Data Access Layer (SDAL), is copyrighted by Object
 * Computing inc of St. Louis MO USA. It is provided under the open-source model
 * and is free of license fees. You are free to modify this code for your own use
 * but you may not claim copyright.
 *
 * Since SDAL is open source and free of licensing fees, you are free to use,
 * modify, and distribute the source code, as long as you include this copyright
 * statement.
 *
 * In particular, you can use SDAL to build proprietary software and are under no
 * obligation to redistribute any of your source code that is built using SDAL.
 * Note, however, that you may not do anything to the SDAL code, such as
 * copyrighting it yourself or claiming authorship of the SDAL code, that will
 * prevent SDAL from being distributed freely using an open source development
 * model.
 *
 * Warranty
 * LICENSED PRODUCT, SDAL, IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE,
 * NONINFRINGEMENT, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 *
 * Support
 * LICENSED PRODUCT, SDAL, IS PROVIDED WITH NO SUPPORT AND WITHOUT ANY OBLIGATION ON THE
 * PART OF OCI OR ANY OF ITS SUBSIDIARIES OR AFFILIATES TO ASSIST IN ITS USE,
 * CORRECTION, MODIFICATION OR ENHANCEMENT.
 *
 * Support may be available from OCI to users who have agreed to a support
 * contract.
 *
 * Liability
 * OCI OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH
 * RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY
 * LICENSED PRODUCT OR ANY PART THEREOF.
 *
 * IN NO EVENT WILL OCI OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR ANY
 * LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL DAMAGES,
 * EVEN IF OCI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * Copyright OCI. St. Louis MO USA, 2004
 *
 */
package com.ociweb.domain;

import com.ociweb.bean.Product;
import com.ociweb.bean.Customer;
import com.ociweb.bean.Order;
import com.ociweb.bean.Orderitem;
import com.ociweb.service.GlobalSessionFactory;
import com.ociweb.service.ThreadSessionHolder;
import com.ociweb.service.GlobalServiceLocator;
import com.ociweb.service.CriteriaQuery;
import com.ociweb.service.GlobalQueryFactory;
import com.ociweb.service.Expression;
import com.ociweb.service.LookupException;

import junit.framework.TestCase;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;

public class FunctionalBusinessTest extends TestCase {
    private static final String PIANO_STRINGS = "Piano Strings";
    private static final String CUSTOMER_NAME = "Keith Jarrett";
    private static final String LOZENGES = "Lozenges";

    protected void setUp() throws Exception {
        net.sf.hibernate.Session hibSession = GlobalSessionFactory.get().newSession();
        ThreadSessionHolder.set(hibSession);
    }

    protected void tearDown() throws Exception {
        ThreadSessionHolder.set(null);
    }

    public void testProduct() throws Exception {
        addProduct(PIANO_STRINGS);
        removeAllProducts();
    }

    public void testCustomer() throws Exception {
        addCustomer();
        removeAllCustomers();
    }

    public void testOrderAndOrderitems() throws Exception {
        addOrderAndOrderItems();
        removeAllOrders();
        removeAllCustomers();
        removeAllProducts();
    }

    private void addProduct(String productName) throws Exception {
        Product product = new Product();
        product.setName(productName);
        product.setCost(10.0);
        ProductMgr mgr = (ProductMgr) GlobalServiceLocator.get().getDomainObjectManager(ProductMgr.class);
        mgr.add(product);
        Product addedProduct = findProductByName(productName);
        assertNotNull(addedProduct);
        assertEquals(productName, addedProduct.getName());
    }

    private Product findProductByName(String name) throws Exception {
        ProductMgr mgr = (ProductMgr)GlobalServiceLocator.get().getDomainObjectManager(ProductMgr.class);
        //Find by named query being used here
        Collection products = mgr.findProductByName(name);
        return (Product)products.iterator().next();
    }

    private void removeAllProducts() throws Exception {
        ProductMgr mgr = (ProductMgr) GlobalServiceLocator.get().getDomainObjectManager(ProductMgr.class);
        Collection products = mgr.findAll();
        if (products.size() > 0) {
            for (Iterator iter = products.iterator(); iter.hasNext();) {
                Product product = (Product) iter.next();
                mgr.remove(product);
            }
            products = mgr.findAll();
            assertEquals(0, products.size());
        }
    }

    private void addCustomer() throws Exception {
        Customer customer = new Customer();
        customer.setName(CUSTOMER_NAME);
        CustomerMgr mgr = (CustomerMgr) GlobalServiceLocator.get().getDomainObjectManager(CustomerMgr.class);
        mgr.add(customer);
        Customer addedCustomer = findCustomerByName(CUSTOMER_NAME);
        assertNotNull(addedCustomer);
        assertEquals(CUSTOMER_NAME, addedCustomer.getName());
    }

    private Customer findCustomerByName(String name) throws LookupException {
        //Example of a CriterialQuery
        CriteriaQuery query = GlobalQueryFactory.get().newCriteriaQuery(Customer.class);
        query.add(Expression.eq("name", name));
        return (Customer) query.execute().iterator().next();
    }

    private void removeAllCustomers() throws Exception {
        CustomerMgr mgr = (CustomerMgr) GlobalServiceLocator.get().getDomainObjectManager(CustomerMgr.class);
        Collection customers = mgr.findAll();
        if (customers.size() > 0) {
            for (Iterator iter = customers.iterator(); iter.hasNext();) {
                Customer customer = (Customer) iter.next();
                mgr.remove(customer);
            }
            customers = mgr.findAll();
            assertEquals(0, customers.size());
        }
    }

    private void addOrderAndOrderItems() throws Exception {
        addCustomer();
        addProduct(PIANO_STRINGS);
        addProduct(LOZENGES);

        Customer customer = findCustomerByName(CUSTOMER_NAME);

        Order order = new Order();
        order.setCustomer(customer);

        Orderitem item1 = new Orderitem();
        item1.setOrder(order);
        item1.setProduct(findProductByName(PIANO_STRINGS));
        item1.setQuantity(88);

        Orderitem item2 = new Orderitem();
        item2.setOrder(order);
        item2.setProduct(findProductByName(LOZENGES));
        item2.setQuantity(12);

        Set orderItems = new HashSet();
        orderItems.add(item1);
        orderItems.add(item2);

        order.setOrderitems(orderItems);

        OrderMgr orderMgr = (OrderMgr) GlobalServiceLocator.get().getDomainObjectManager(OrderMgr.class);
        orderMgr.add(order);

        Collection orders = orderMgr.findAll();
        assertEquals(1, orders.size());
        Order addedOrder = (Order) orders.iterator().next();
        assertEquals(2, addedOrder.getOrderitems().size());
    }

    private void removeAllOrders() throws Exception {
        OrderMgr mgr = (OrderMgr)GlobalServiceLocator.get().getDomainObjectManager(OrderMgr.class);
        Collection orders = mgr.findAll();
        if (orders.size() > 0) {
            for (Iterator iter = orders.iterator(); iter.hasNext();) {
                Order order = (Order)iter.next();
                mgr.remove(order);
            }
            orders = mgr.findAll();
            assertEquals(0, orders.size());
        }
    }
}
