/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2005 Bull S.A.
 * Contact: jonas-team@objectweb.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas.jtests.clients.entity;

import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import javax.ejb.FinderException;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.objectweb.jonas.jtests.beans.relation.cascade.AddressBean;
import org.objectweb.jonas.jtests.beans.relation.cascade.AddressDO;
import org.objectweb.jonas.jtests.beans.relation.cascade.AddressHR;
import org.objectweb.jonas.jtests.beans.relation.cascade.AddressR;
import org.objectweb.jonas.jtests.beans.relation.cascade.CreditCardHR;
import org.objectweb.jonas.jtests.beans.relation.cascade.CustomerHR;
import org.objectweb.jonas.jtests.beans.relation.cascade.CustomerR;
import org.objectweb.jonas.jtests.beans.relation.cascade.Name;
import org.objectweb.jonas.jtests.beans.relation.cascade.PhoneHR;
import org.objectweb.jonas.jtests.beans.relation.cascade.CarHR;
import org.objectweb.jonas.jtests.util.JTestCase;

/**
 * This is a test suite on cascade-delete facility
 * @author Philippe Durieux
 */
public class F_Cascade extends JTestCase {

    private static CustomerHR customerhome = null;
    private static CreditCardHR creditcardhome = null;
    private static AddressHR addresshome = null;
    private static PhoneHR phonehome = null;
    private static CarHR carhome = null;

    public F_Cascade(String name) {
        super(name);
    }

    protected boolean isInit = false;

    protected void setUp() {
        super.setUp();
        if (!isInit) {
            useBeans("cascade", false);
            try {
                customerhome = (CustomerHR) PortableRemoteObject.narrow(ictx.lookup("cascadeCustomerHomeRemote"),
                                                                        CustomerHR.class);
                creditcardhome = (CreditCardHR) PortableRemoteObject.narrow(ictx.lookup("cascadeCreditCardHomeRemote"),
                                                                            CreditCardHR.class);
                addresshome = (AddressHR) PortableRemoteObject.narrow(ictx.lookup("cascadeAddressHomeRemote"),
                                                                      AddressHR.class);
                phonehome = (PhoneHR) PortableRemoteObject.narrow(ictx.lookup("cascadePhoneHomeRemote"),
                                                                  PhoneHR.class);
                carhome = (CarHR) PortableRemoteObject.narrow(ictx.lookup("cascadeCarHomeRemote"),
                                                                  CarHR.class);
            } catch (NamingException e) {
                fail("Cannot get bean home: " + e.getMessage());
            }
            isInit = true;
        }
    }

    /**
     * test cascade delete in case of a relation one-to-one
     * We use the bean customer and its credit card.
     */
    public void testCascadeDeleteCC() throws Exception {
        // create new customer
        CustomerR customer = customerhome.create(new Integer(15));
        String lastname = "Dupont";
        Name name = new Name(lastname, "Jean");
        customer.setName(name);
        // set its credit card
        customer.setCreditCard(new Date(), "154563", lastname);
        // check we can retrieve it
        creditcardhome.findByName(lastname);
        // remove customer
        customer.remove();
        // check its credit card has been removed
        try {
            creditcardhome.findByName(lastname);
            fail("credit card has not been removed by cascade delete");
        } catch (FinderException e) {
        }
    }

    /**
     * test cascade delete in case of a relation one-to-one
     * We use the bean customer and its address.
     */
    public void testCascadeDeleteAd() throws Exception {
        // create new customer
        CustomerR customer = customerhome.create(new Integer(16));
        String lastname = "Durand";
        Name name = new Name(lastname, "Jacques");
        customer.setName(name);
        // set its address
        String zip = "38170";
        customer.setAddress("rue Quirole", "Seyssinet", "France", zip);
        // check we can retrieve it
        Collection coll = addresshome.findByZip(zip);
        assertEquals("wrong number of Addresses", 1, coll.size());
        // remove customer
        customer.remove();
        // check its address has been removed
        try {
            coll = addresshome.findByZip(zip);
            assertEquals("Address have not been removed", 0, coll.size());
        } catch (FinderException e) {
        }
    }

    /**
     * test cascade delete in case of a relation one-to-many
     * We use the bean customer and its phones.
     */
    public void testCascadeDeletePhs() throws Exception {
        // create new customer
        CustomerR customer = customerhome.create(new Integer(17));
        String lastname = "Bertrand";
        Name name = new Name(lastname, "Jules");
        customer.setName(name);
        // add phones
        customer.addPhoneNumber("1111", (byte) 1);
        customer.addPhoneNumber("2222", (byte) 2);
        customer.addPhoneNumber("3333", (byte) 3);
        // check we can retrieve them
        Collection coll = phonehome.findByName(lastname);
        assertEquals("wrong number of phones", 3, coll.size());
        // remove customer
        customer.remove();
        // check its phones have been removed
        coll = phonehome.findByName(lastname);
        assertEquals("phones have not been removed", 0, coll.size());
    }

    /**
     * test Cascade delete with Address + PhoneMumbers
     */
    public void testCDAdPh() throws Exception {
        // create new customer
        CustomerR customer = customerhome.create(new Integer(17));
        String lastname = "Bertrand";
        Name name = new Name(lastname, "Jules");
        customer.setName(name);
        // add phones
        customer.addPhoneNumber("1111", (byte) 1);
        customer.addPhoneNumber("2222", (byte) 2);
        customer.addPhoneNumber("3333", (byte) 3);
        // check we can retrieve them
        Collection coll = phonehome.findByName(lastname);
        assertEquals("wrong number of phones", 3, coll.size());
        // set its address
        String zip = "38170";
        customer.setAddress("rue Quirole", "Seyssinet", "France", zip);
        // check we can retrieve it
        coll = addresshome.findByZip(zip);
        assertEquals("wrong number of Addresses", 1, coll.size());
        // remove customer
        customer.remove();
        // check its phones have been removed
        coll = phonehome.findByName(lastname);
        assertEquals("phones have not been removed", 0, coll.size());
    }

    /**
     * test Cascade delete with Address + PhoneMumbers
     * This test works only if cascade-delete is set on customer from address.
     */
    public void _testCDAdPhRemByAd() throws Exception {
        // create new customer
        CustomerR customer = customerhome.create(new Integer(17));
        String lastname = "Bertrand";
        Name name = new Name(lastname, "Jules");
        customer.setName(name);
        // add phones
        customer.addPhoneNumber("1111", (byte) 1);
        customer.addPhoneNumber("2222", (byte) 2);
        customer.addPhoneNumber("3333", (byte) 3);
        // check we can retrieve them
        Collection coll = phonehome.findByName(lastname);
        assertEquals("wrong number of phones", 3, coll.size());
        // set its address
        String zip = "38170";
        customer.setAddress("rue Quirole", "Seyssinet", "France", zip);
        // check we can retrieve it
        coll = addresshome.findByZip(zip);
        assertEquals("wrong number of Addresses", 1, coll.size());
        AddressR ad = (AddressR) coll.iterator().next();
        // remove customer by its adress
        ad.remove();
        // check its phones have been removed
        coll = phonehome.findByName(lastname);
        assertEquals("phones have not been removed", 0, coll.size());
    }

    /**
     * test cascade delete in case of a relation one-to-many
     * We use the bean customer and its cars.
     */
    public void testCascadeDeleteCars() throws Exception {
        // create new customer
        CustomerR customer = customerhome.create(new Integer(17));
        String lastname = "Bertrand";
        Name name = new Name(lastname, "Jules");
        customer.setName(name);
        // add cars
        customer.addCar("1111", (byte) 1);
        customer.addCar("2222", (byte) 2);
        customer.addCar("3333", (byte) 3);
        // check we can retrieve them
        Collection coll = carhome.findByName(lastname);
        assertEquals("wrong number of cars", 3, coll.size());
        // remove customer
        customer.remove();
        // check its cars have been removed
        coll = carhome.findByName(lastname);
        assertEquals("cars have not been removed", 0, coll.size());
    }

    public void testCrash1() throws Exception {
        // create new customer
        CustomerR customer = customerhome.create(new Integer(17));
        Name name = new Name("Bertrand", "Jules");
        customer.setName(name);
        // add cars
        customer.addCar("1111", (byte) 1);
        // crash
        customer.accident("1111", "111101");
        // remove customer
        customer.remove();
    }

    /**
     * test create in postCreate
     */
    public void testCreateInPostCreate() throws Exception {
        String zip = "30010";
        AddressDO addr = new AddressDO("St1", "C1", "E1", zip);
        CustomerR customer = customerhome.createWithAddress(new Integer(18), addr);
        // Check address has been created
        Collection coll = addresshome.findByZip(zip);
        assertEquals("Address not created", 1, coll.size());
        Iterator i = coll.iterator();
        AddressR a = (AddressR) PortableRemoteObject.narrow(i.next(), AddressR.class);
        Integer cid = a.getCustomerId();
        assertEquals("Coherence not done", customer.getId().intValue(), cid.intValue());
        // cleaning
        customer.remove();
    }

    protected boolean initStateOK() throws Exception {
        return true;
    }


    public static Test suite() {
        return new TestSuite(F_Cascade.class);
    }

    public static void main (String args[]) {
        String testtorun = null;
        // Get args
        for (int argn = 0; argn < args.length; argn++) {
            String sarg = args[argn];
            if (sarg.equals("-n")) {
                testtorun = args[++argn];
            }
        }
        if (testtorun == null) {
            junit.textui.TestRunner.run(suite());
        } else {
            junit.textui.TestRunner.run(new F_Cascade(testtorun));
        }
    }
}
