
package org.objectweb.jonas.stests.manyops;

import java.rmi.RemoteException;

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

import org.objectweb.jonas.stests.util.JTestCase;


public abstract class A_manyops extends JTestCase {

    // Product's number initially created in the database table
    private static final int NB_PRODUCTS = 2500;
    // Create operation number done for one "many-create" operation
    private static final int NB_CREATE = 20;

    //
    protected static InitDBHome idbHome = null;
    protected static InitDB idb = null;
    protected static ProductHome pHome = null;
    protected static boolean initialized = false;

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

    protected void setUp() throws Exception {
	super.setUp();
	if (idbHome == null) {
	    useBeans("manyops");
	    idbHome = (InitDBHome) PortableRemoteObject.narrow(ictx.lookup("manyopsInitDBHome"), InitDBHome.class);
	}
	if (idb == null) {
	    idb = idbHome.create();
	}
	if (pHome == null) {
	    pHome = getProductHome();
	}
	if (!initialized) {
	    // The first time, create the database tables needed, and insert NB_PRODUCTS lines
	    idb.createTable();
	    for (int i=1; i<=NB_PRODUCTS; i++) {
		pHome.create("p"+i, i, 0);
	    }
	    initialized = true;
	}
    }

    /**
     * return a Product Home
     */
    abstract ProductHome getProductHome() throws NamingException;
    
    protected void tearDown() throws Exception {
	super.tearDown();
    }

    /**
     * Allows to do 'opNb' times of the 'opType' operation on a Product bean.
     * The 'opType' may be:
     * - 'create',
     * - 'createmany' (ie one operation is N create operation)
     * - 'delete'
     * - 'get'
     * - 'set'
     * - 'findByPk'
     * - 'findByNumber'
     */
    public void manyops(int opNb, String opType) throws Exception {
	if (opNb > NB_PRODUCTS) {
	    throw new Exception("Operation number must be less than the initial product number");
	}
	// Do 'opNb' times the 'opType' operation
	for (int i=1; i<=opNb; i++) {
	    Product bean;
	    int p;
	    if ("create".equals(opType)) {
		int ipk = NB_PRODUCTS+i;
		String spk = "p"+ipk;
		bean = pHome.create(spk, ipk, 1);
	    } else if ("createmany".equals(opType)) {
		for (int ii=1; ii<=NB_CREATE; ii++) {
		    int iipk = NB_PRODUCTS+ii;
		    bean = pHome.create("p"+iipk, iipk, 1);
		}
		for (int ii=1; ii<=NB_CREATE; ii++) {
		    int iipk = NB_PRODUCTS+ii;
		    pHome.remove("p"+iipk);
		}
	    } else if ("delete".equals(opType)) {
		String spk = "p"+i;
		pHome.remove(spk);
	    } else {
		// Choose randomly the bean on which the operation is done
		int ipk = random(NB_PRODUCTS)+1;
		String spk = "p"+ipk;
		if ("get".equals(opType)) {
		    bean = pHome.findByPrimaryKey(spk);
		    p = bean.getPrice();
		} else if ("set".equals(opType)) {
		    bean = pHome.findByPrimaryKey(spk);
		    bean.setPrice(2);
		} else if ("findByPk".equals(opType)) {
		    bean = pHome.findByPrimaryKey(spk);
		} else if ("findByNumber".equals(opType)) {
		    bean = pHome.findByNumber(ipk);
		} else {
		    throw new Exception("Invalid operation name ("+opType+")");
		}
	    }
	}
	// Undo
	for (int i=1; i<=opNb; i++) {
	    if ("create".equals(opType)) {
		int ipk = NB_PRODUCTS+i;
		String spk = "p"+ipk;
		pHome.remove(spk);
	    } else if ("createmany".equals(opType)) {
		// Nothing to undo
	    } else if ("get".equals(opType)) {
		// Nothing to undo
	    } else if ("set".equals(opType)) {
		// Nothing to undo
	    } else if ("findByPk".equals(opType)) {
		// Nothing to undo
	    } else if ("delete".equals(opType)) {
		String spk = "p"+i;
		pHome.create(spk, i, 0);
	    }
	}
    }

    /**
     * random returns an integer between 0 and max-1
     */
    private int random(int max) throws RemoteException {
	double d = Math.random();
	int ret = (int) (max * d);
	return ret;
    }

    public void test_100_create() throws Exception {
	manyops(100, "create");
    }
    public void test_100_get() throws Exception {
	manyops(100, "get");
    }
    public void test_100_set() throws Exception {
	manyops(100, "set");
    }
    public void test_100_findByPk() throws Exception {
	manyops(100, "findByPk");
    }
    public void test_100_findByNumber() throws Exception {
	manyops(100, "findByNumber");
    }
    public void test_100_delete() throws Exception {
	manyops(100, "delete");
    }
    public void test_100_createmany() throws Exception {
	manyops(100, "createmany");
    }

    public void test_250_create() throws Exception {
	manyops(250, "create");
    }
    public void test_250_get() throws Exception {
	manyops(250, "get");
    }
    public void test_250_set() throws Exception {
	manyops(250, "set");
    }
    public void test_250_findByPk() throws Exception {
	manyops(250, "findByPk");
    }
    public void test_250_findByNumber() throws Exception {
	manyops(250, "findByNumber");
    }
    public void test_250_delete() throws Exception {
	manyops(100, "delete");
    }
    public void test_250_createmany() throws Exception {
	manyops(250, "createmany");
    }

    public void test_500_create() throws Exception {
	manyops(500, "create");
    }
    public void test_500_get() throws Exception {
	manyops(500, "get");
    }
    public void test_500_set() throws Exception {
	manyops(500, "set");
    }
    public void test_500_findByPk() throws Exception {
	manyops(500, "findByPk");
    }
    public void test_500_findByNumber() throws Exception {
	manyops(500, "findByNumber");
    }
    public void test_500_delete() throws Exception {
	manyops(100, "delete");
    }
    public void test_500_createmany() throws Exception {
	manyops(500, "createmany");
    }

}
