/*
 * 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.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

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

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

import org.objectweb.jonas.jtests.beans.relation.s3pkcomp.AHomeRemote;
import org.objectweb.jonas.jtests.beans.relation.s3pkcomp.ARemote;
import org.objectweb.jonas.jtests.beans.relation.s3pkcomp.BHomeRemote;
import org.objectweb.jonas.jtests.beans.relation.s3pkcomp.Pk;


/**
 * For testing one-to-many unidirectional relationships
 * this test uses beans s3pkcomp/*
 * @author Helene Joanin
 */
public class F_Relation_s3pkcompEC2 extends A_Cmp2Util {

    private static String BEAN_HOME_A = "relation_s3pkcomp_AHome";
    protected static AHomeRemote ahome = null;
    private static String BEAN_HOME_B = "relation_s3pkcomp_BHome";
    protected static BHomeRemote bhome = null;

    static Hashtable tbRelationA2B = new Hashtable();

    static {
        tbRelationA2B.put(new Integer(0), new int[]{});
        tbRelationA2B.put(new Integer(1), new int[]{1001, 1002, 1003});
        tbRelationA2B.put(new Integer(2), new int[]{2001, 2002, 2003});
        tbRelationA2B.put(new Integer(3), new int[]{3001});
        // Translate the int[] to a Collection of Pk
        for (Enumeration ea = tbRelationA2B.keys(); ea.hasMoreElements();) {
            Integer aid = (Integer) (ea.nextElement());
            int[] tb = (int[]) tbRelationA2B.get(aid);
            ArrayList col = new ArrayList(tb.length);
            for (int i = 0; i < tb.length; i++) {
                col.add(new Pk(tb[i]));
            }
            tbRelationA2B.put(aid, col);
        }
    }

    public F_Relation_s3pkcompEC2(String name) {
        super(name);
	debug("F_Relation_s3pkcompEC2("+name+")");
    }

    protected boolean isInit = false;

    protected void setUp() {
        super.setUp();
	boolean ok = false;
	int nbtry = 0;
	while (!ok && nbtry < 3) {
	    if (!isInit) {
		// load bean if not loaded yet
		useBeans("s3pkcomp", false);
		try {
		    ahome = (AHomeRemote) PortableRemoteObject.narrow(ictx.lookup(BEAN_HOME_A),
								      AHomeRemote.class);
		    bhome = (BHomeRemote) PortableRemoteObject.narrow(ictx.lookup(BEAN_HOME_B),
								      BHomeRemote.class);
		} catch (NamingException e) {
		    fail("Cannot get bean home: " + e.getMessage());
		}
		// check if tables have been initialized
		try {
		    ahome.findByPrimaryKey(new Pk(0));
		} catch (Exception e) {
		    try {
			utx.begin();
			bhome.create(0);
			bhome.create(1001);
			bhome.create(1002);
			bhome.create(1003);
			bhome.create(2001);
			bhome.create(2002);
			bhome.create(2003);
			bhome.create(3001);
			ARemote a0 = ahome.create(0);
			ARemote a1 = ahome.create(1);
			ARemote a2 = ahome.create(2);
			ARemote a3 = ahome.create(3);
			a1.assignB((Collection)tbRelationA2B.get(new Integer(1)));
			a2.assignB((Collection)tbRelationA2B.get(new Integer(2)));
			a3.assignB((Collection)tbRelationA2B.get(new Integer(3)));
		    } catch (Exception i) {
			fail("InitialState creation problem:: "+i);
		    } finally {
			try {
			    utx.commit();
			} catch (Exception ii) {
			}
		    }
		}
		isInit = true;
	    }
	    // Check that all is OK. Sometimes, a test has failed and has corrupted
	    // the bean state in the database. We must unload and reload the bean then.
	    nbtry++;
	    try {
		if (initStateOK()) {
		    ok = true;
		}
	    } catch (Exception e) {
	    }
	    if (!ok) {
		isInit = false;
		unloadBeans("s3pkcomp");
	    }
	}
    }

    /*
     * Check that we are in the same state as after the tables creation for thoses beans A and B
     * (ie if it is the initial state)
     */
    boolean initStateOK() throws Exception {
        boolean isOk = true;
        msgerror = new StringBuffer();
        for (Enumeration ea = tbRelationA2B.keys(); ea.hasMoreElements();) {
            Integer aid = (Integer) (ea.nextElement());
            ARemote a = ahome.findByPrimaryKey(new Pk(aid));
            Collection colActual = a.retrieveB();
            ArrayList colExpected = (ArrayList) (tbRelationA2B.get(aid));
	    debug("Relation for " + aid + " : expected:" + colExpected + ", found:" + colActual );
            if (!isCollectionEqual(colExpected, colActual)) {
                isOk = false;
                msgerror = msgerror.append("Wrong relation for " + aid
                    + " (expected:" + colExpected
                    + ", found:" + colActual + ")");
            }
        }
	return isOk;
    }


    /**
     * Not really a test, just to verify the checkIsInitialState() method.
     */
    public void testEmpty() throws Exception {
	checkIsInitialState();
    }

    /**
     * Test the calling of the ahome.findAll() method
     */
    public void _testFindAllA(int tx) throws Exception {
	if (tx == TX_CONT) {
	    // The transaction attribute of the findAll method is TX_SUPPORT,
	    // so the transaction cannot be initiate by the container
	    fail("Transaction cannot be initiate by the container for this test");
	}
        if ((tx == TX_CALL) || (tx == TX_RB)) {
            utx.begin();
        }
	Collection cA = ahome.findAll();
        if (tx == TX_CALL) {
            utx.commit();
        } else if (tx == TX_RB) {
            utx.rollback();
        }
	// Check
	int nbA = 0;
	for (Iterator iA = cA.iterator(); iA.hasNext(); iA.next()) {
	    nbA++;
	}
	assertEquals("Wrong number for beans A for findAll: ", tbRelationA2B.size(), nbA);
    }
    
    public void testFindAllATxNo() throws Exception {
	_testFindAllA(TX_NO);
    }

    public void testFindAllATxCall() throws Exception {
	_testFindAllA(TX_CALL);
    }

    public void testFindAllATxRb() throws Exception {
	_testFindAllA(TX_RB);
    }


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

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

}
