/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 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.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 multiple threads accessing relationship beans
 * @author Philippe Durieux
 */
public class G_MultiRelation 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 G_MultiRelation(String name) {
        super(name);
    }

    protected boolean isInit = false;
    protected boolean threadfail = 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;
        }
    }

    private CustomerR createFullCustomer(int pk, String lname, String cc) throws Exception {
        // create new customer
        CustomerR customer = customerhome.create(new Integer(pk));
        Name name = new Name(lname, "Jean");
        customer.setName(name);
        // set its credit card
        customer.setCreditCard(new Date(), cc, lname);
        // set its address
        String zip = "38170";
        customer.setAddress("rue des fleurs", "Seyssinet", "France", zip);
        // add phones
        customer.addPhoneNumber("1111", (byte) 1);
        customer.addPhoneNumber("2222", (byte) 2);
        customer.addPhoneNumber("3333", (byte) 3);
        return customer;
    }
    
    private void removeFullCustomer(int pk) throws Exception {
        CustomerR customer = customerhome.findByPrimaryKey(new Integer(pk));
        customer.remove();
    }
    
    private void runThreads(int threads, int pkmin, int pkmax) throws Exception {
        // Create and start all threads
        Ithread[] t_thr = new Ithread[threads];
        for (int i = 0; i < threads; i++) {
            t_thr[i] = new Ithread(pkmin, pkmax);
            t_thr[i].start();
        }

        // Wait end of all threads
        for (int p = 0; p < threads; p++) {
            t_thr[p].join();
        }

        // Check if all threads run ok
        if (threadfail) {
            throw new Error("thread error");
        }
    }
    
    public void testBasicCreateRemove() throws Exception {
        int pk = 7;
        createFullCustomer(pk, "Galtier", "65423");
        removeFullCustomer(pk);
    }

    public void testCreateRemoveTwice() throws Exception {
        int pk = 8;
        createFullCustomer(pk, "Galtier", "65423");
        removeFullCustomer(pk);
        createFullCustomer(pk, "Galtier", "65423");
        removeFullCustomer(pk);
    }
    
    public void testManyThreads() throws Exception {
        stopTxAt(200);
        int pkmin = 100;
        int pkmax = 300;
        for (int pk = pkmin; pk < pkmax; pk++) {
            CustomerR customer = createFullCustomer(pk, "Nom" + pk, "65423" + pk);
            // add cars
            String carnb = "car-pk" + pk;
            customer.addCar("1111" + pk, (byte) 1);
            customer.addCar(carnb, (byte) 2);
            customer.addCar("1131" + pk, (byte) 3);
            // crash
            customer.accident(carnb, carnb + "-inv");
        }
        runThreads(80, pkmin, pkmax);
        for (int pk = pkmin; pk < pkmax; pk++) {
            removeFullCustomer(pk);
        }
    }
    
    protected boolean initStateOK() throws Exception {
        return true;
    }

    
    public static Test suite() {
        return new TestSuite(G_MultiRelation.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 G_MultiRelation(testtorun));
        }
    }
    
    class Ithread extends Thread {
        int pkmin;
        int pkmax;
        
        public Ithread(int pkmin, int pkmax) {
            this.pkmin = pkmin;
            this.pkmax = pkmax;
        }

        public void run() {
            try {
                for (int pk = pkmin; pk < pkmax; pk++) {
                    CustomerR customer = customerhome.findByPrimaryKey(new Integer(pk));
                    yield();
                    AddressDO addr = customer.getAddress();
                }
            } catch (Exception e) {
                threadfail = true;
            }
        }
    }
}
