/*
 * Created by IntelliJ IDEA.
 * User: Matt
 * Date: Jun 10, 2002
 * Time: 9:22:44 PM
 * To change template for new class use
 * Code Style | Class Templates options (Tools | IDE Options).
 */
package org.apache.ojb.odmg;

import junit.framework.TestCase;
import org.apache.ojb.broker.Fish;
import org.apache.ojb.broker.Salad;
import org.apache.ojb.broker.TestHelper;
import org.odmg.Database;
import org.odmg.Implementation;
import org.odmg.OQLQuery;
import org.odmg.Transaction;

import java.util.List;


public class ManyToManyTest extends TestCase
{
    public static void main(String[] args)
    {
        String[] arr = {ManyToManyTest.class.getName()};
        junit.textui.TestRunner.main(arr);
    }

    Database db;
    Implementation odmg;

    /**
     * Insert the method's description here.
     * Creation date: (24.12.2000 00:33:40)
     */
    public ManyToManyTest(String name)
    {
        super(name);
    }

    /**
     * Insert the method's description here.
     * Creation date: (06.12.2000 21:58:53)
     */
    public void setUp() throws Exception
    {
        odmg = OJB.getInstance();
        db = odmg.newDatabase();
        db.open(TestHelper.DEF_DATABASE_NAME, Database.OPEN_READ_WRITE);
    }

    /**
     * Insert the method's description here.
     * Creation date: (06.12.2000 21:59:14)
     */
    public void tearDown() throws Exception
    {
        if (odmg.currentTransaction() != null && odmg.currentTransaction().isOpen())
        {
            odmg.currentTransaction().abort();
        }
        db.close();
        odmg = null;
    }


    /**
     * this tests if polymorph collections (i.e. collections of objects
     * implementing a common interface) are treated correctly
     */
    public void testPolymorphMToN() throws Exception
    {
        ODMGGourmet james = new ODMGGourmet("james");
        ODMGGourmet doris = new ODMGGourmet("doris");

        Fish tuna = new Fish("tuna", 242, "salt");
        Fish trout = new Fish("trout", 52, "fresh water");

        Salad radiccio = new Salad("Radiccio", 7, "red");
        Salad lolloverde = new Salad("Lollo verde", 7, "green");

        james.addFavoriteFood(tuna);
        james.addFavoriteFood(radiccio);

        doris.addFavoriteFood(tuna);
        doris.addFavoriteFood(trout);
        doris.addFavoriteFood(lolloverde);

        Transaction tx = odmg.newTransaction();
        tx.begin();
        db.makePersistent(james);
        db.makePersistent(doris);
        tx.commit();

        int dorisId = doris.getGourmetId();
        int jamesId = james.getGourmetId();

        tx = odmg.newTransaction();
        tx.begin();
        OQLQuery query = odmg.newOQLQuery();
        query.create("select gourmets from " + ODMGGourmet.class.getName() +
                " where gourmetId=$1");
        query.bind(new Integer(dorisId));
        List gourmets = (List) query.execute();
        tx.commit();
        assertEquals(1, gourmets.size());
        ODMGGourmet loadedDoris = (ODMGGourmet) gourmets.get(0);
        //System.err.println(loadedDoris);
        assertEquals(3, loadedDoris.getFavoriteFood().size());

        tx.begin();
        query = odmg.newOQLQuery();
        query.create("select gourmets from " + ODMGGourmet.class.getName() +
                " where gourmetId=$1");
        query.bind(new Integer(jamesId));
        gourmets = (List) query.execute();
        tx.commit();
        assertEquals(1, gourmets.size());
        ODMGGourmet loadedJames = (ODMGGourmet) gourmets.get(0);
        //System.err.println(loadedJames);
        assertEquals(2, loadedJames.getFavoriteFood().size());
    }

    /**
     * Store the objects and return the result of the query
     * "select gourmets from " + ODMGGourmet.class.getName() + " where gourmetId=$1"
     */
    private int store(Implementation odmg, Database db, ODMGGourmet gourmet) throws Exception
    {
        Transaction tx = odmg.newTransaction();
        tx.begin();
        db.makePersistent(gourmet);
        tx.commit();

        tx.begin();
        OQLQuery query = odmg.newOQLQuery();
        query = odmg.newOQLQuery();
        query.create("select gourmets from " + ODMGGourmet.class.getName() +
                " where gourmetId=$1");
        query.bind(new Integer(gourmet.getGourmetId()));
        List gourmets = (List) query.execute();
        tx.commit();
        return gourmets.size();
    }

    public void testMtoNSeparate_I() throws Exception
    {
        ODMGGourmet paula = new ODMGGourmet("a_testMtoNSeparate_I");
        ODMGGourmet candy = new ODMGGourmet("b_testMtoNSeparate_I");

        long timestamp = System.currentTimeMillis();
        Fish tuna = new Fish("tuna_" + timestamp, 242, "salt");
        Fish trout = new Fish("trout_" + timestamp, 52, "fresh water");

        paula.addFavoriteFood(trout);
        candy.addFavoriteFood(tuna);

        /*
        we expect one created 'gourment' per store
        */
        assertEquals(1, store(odmg, db, paula));
        assertEquals(1, store(odmg, db, candy));

        OQLQuery query = odmg.newOQLQuery();
        query.create("select fishs from " + Fish.class.getName() +
                " where (name=$1 or name=$2)");
        query.bind(tuna.getName());
        query.bind(trout.getName());
        List fishs = (List) query.execute();
        /*
        we expect 2 created 'fish'
        */
        assertEquals(2, fishs.size());
    }

    public void testMtoNSeparate_II() throws Exception
    {
        ODMGGourmet james = new ODMGGourmet("a_testMtoNSeparate_II");
        ODMGGourmet doris = new ODMGGourmet("b_testMtoNSeparate_II");

        long timestamp = System.currentTimeMillis();
        Fish tuna = new Fish("tuna_" + timestamp, 242, "salt");
        Fish trout = new Fish("trout_" + timestamp, 52, "fresh water");

        james.addFavoriteFood(tuna);

        doris.addFavoriteFood(tuna);
        doris.addFavoriteFood(trout);

        /*
        we expect one created 'gourment' per store
        */
        assertEquals(1, store(odmg, db, james));
        assertEquals(1, store(odmg, db, doris));

        OQLQuery query = odmg.newOQLQuery();
        query.create("select fishs from " + Fish.class.getName() +
                " where (name=$1 or name=$2)");
        query.bind(tuna.getName());
        query.bind(trout.getName());
        List fishs = (List) query.execute();
        /*
        we expect 2 created 'fish'
        */
        assertEquals(2, fishs.size());
    }

    public void testMtoNTogether() throws Exception
    {
        long timestamp = System.currentTimeMillis();
        Fish tuna = new Fish("tuna_" + timestamp, 242, "salt");
        Fish trout = new Fish("trout_" + timestamp, 52, "fresh water");

        ODMGGourmet paula = new ODMGGourmet("a_testMtoNTogether");
        ODMGGourmet candy = new ODMGGourmet("b_testMtoNTogether");
        ODMGGourmet james = new ODMGGourmet("c_testMtoNTogether");
        ODMGGourmet doris = new ODMGGourmet("d_testMtoNTogether");

        paula.addFavoriteFood(trout);
        candy.addFavoriteFood(tuna);
        james.addFavoriteFood(tuna);
        doris.addFavoriteFood(tuna);
        doris.addFavoriteFood(trout);

        /*
        we expect one created 'gourment' per store
        */
        assertEquals(1, store(odmg, db, paula));
        assertEquals(1, store(odmg, db, candy));
        assertEquals(1, store(odmg, db, james));
        assertEquals(1, store(odmg, db, doris));

        OQLQuery query = odmg.newOQLQuery();
        query.create("select fishs from " + Fish.class.getName() +
                " where (name=$1 or name=$2)");
        query.bind(tuna.getName());
        query.bind(trout.getName());
        List fishs = (List) query.execute();
        /*
        we expect 2 created 'fish'
        */
        assertEquals(2, fishs.size());
    }

}

