/*
 * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the
 * License at http://www.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.metadata;

import com.redhat.persistence.common.Path;
import com.redhat.persistence.metadata.JoinThrough;
import com.arsdigita.persistence.metadata.ObjectType;
import com.arsdigita.persistence.metadata.Property;
import com.arsdigita.persistence.metadata.Association;
import com.arsdigita.persistence.metadata.MetadataRoot;
import com.arsdigita.persistence.DataOperation;
import com.arsdigita.persistence.DataAssociation;
import com.arsdigita.persistence.DataAssociationCursor;
import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.OID;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.PersistenceException;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.math.BigDecimal;
import org.apache.log4j.Logger;

/**
 * @author Patrick McNeill
 * @version $Revision: #13 $ $Date: 2004/04/07 $
 */

public class DynamicAssociationTest extends PersistenceTestCase {
    private static Logger s_log =
        Logger.getLogger(DynamicAssociationTest.class.getName());

    private MetadataRoot m_root = MetadataRoot.getMetadataRoot();
    private List m_tables = new ArrayList();
    private List m_assocs = new ArrayList();

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

    protected void persistenceTearDown() {
        load("com/arsdigita/metadata/pdl/DataOperation.pdl");


        DataCollection dc = getSession().retrieve
            ("com.arsdigita.persistence.DynamicAssociation");
        dc.addEqualsFilter("modelName", "teststuff.foo");
        while (dc.next()) {
            System.out.println("Deleting....");
            dc.getDataObject().delete();
        }
        // this is here so that the "delete" operation above takes
        getSession().getTransactionContext().commitTxn();
        getSession().getTransactionContext().beginTxn();

        Iterator iter = m_tables.iterator();
        java.sql.Statement statement = null;
        try {
            statement = SessionManager.getSession()
                .getConnection()
                .createStatement();
            while (iter.hasNext()) {
                String table = (String)iter.next();
                try {
                    statement.executeUpdate("drop table " + table);
                } catch (Exception e) {
                    s_log.warn("Error executing statement " +
                               "'drop table " + table + "': " + e);
                }
            }

            Iterator assocs = m_assocs.iterator();
            while (assocs.hasNext()) {
                DynamicAssociation assoc = (DynamicAssociation) assocs.next();
//                assoc.delete();
            }
        } catch (Exception e) {
            s_log.error("Error creating statement: " + e.getMessage(), e);
        } finally {
            try {
                statement.close();
            } catch (Exception e) {
                //ignore
            }
        }

        getSession().getTransactionContext().abortTxn();
        getSession().getTransactionContext().beginTxn();


        super.persistenceTearDown();
    }


    public void testCreation() throws Exception {

        /*
        DynamicAssociation dass = new DynamicAssociation(
                                                         "teststuff.foo",
                                                         "com.arsdigita.kernel.ACSObject",
                                                         "owned",
                                                         Property.COLLECTION,
                                                         "com.arsdigita.kernel.User",
                                                         "owner",
                                                         Property.NULLABLE);

        Association assoc = dass.save();
        m_assocs.add(assoc);
        ObjectType object =
            m_root.getObjectType("com.arsdigita.kernel.ACSObject");
        ObjectType user =
            m_root.getObjectType("com.arsdigita.kernel.User");

        assertTrue("Property not found in User",
                   user.getProperty("owned") != null);
        assertTrue("Property not found in ACSObject",
                   object.getProperty("owner") != null);

        DynamicAssociation dass2 = new DynamicAssociation(
                                                          "teststuff.foo",
                                                          "com.arsdigita.kernel.ACSObject",
                                                          "owned",
                                                          "com.arsdigita.kernel.User",
                                                          "owner");

        Association assoc2 = dass2.save();
        m_assocs.add(dass2);
        assertTrue("Saved associations are different", assoc.equals(assoc2));

        try {
            dass2 = new DynamicAssociation(
                                           "teststuff.foo",
                                           "com.arsdigita.kernel.ACSObject",
                                           "container",
                                           "com.arsdigita.kernel.User",
                                           "owner");

            fail("No error thrown on bad association");
        } catch (Exception e) {
        }

        // assume there's at least one user in the system
        DataCollection collection =
            getSession().retrieve("com.arsdigita.kernel.User");
        m_tables.add
            (((JoinThrough) DynamicObjectTypeTest.getObjectMap
              (assoc.getRoleOne().getContainer()).getMapping
              (Path.get(assoc.getRoleOne().getName())))
             .getFrom().getTable().getName());

        if (collection.next()) {
            DataObject userObj = collection.getDataObject();
            OID userID = userObj.getOID();

            DataObject testObj1 =
                getSession().create("com.arsdigita.kernel.ACSObject");
            testObj1.set("id", new BigDecimal(-101));
            testObj1.set("objectType", "com.arsdigita.kernel.ACSObject");
            testObj1.set("displayName", "Test Object 1");
            testObj1.save();
            OID testID1 = testObj1.getOID();

            DataObject testObj2 =
                getSession().create("com.arsdigita.kernel.ACSObject");
            testObj2.set("id", new BigDecimal(-102));
            testObj2.set("objectType", "com.arsdigita.kernel.ACSObject");
            testObj2.set("displayName", "Test Object 2");
            testObj2.save();
            OID testID2 = testObj2.getOID();

            DataAssociation owned = (DataAssociation)userObj.get("owned");
            owned.add(testObj1);
            owned.add(testObj2);
            userObj.save();

            userObj = getSession().retrieve(userID);
            testObj1 = getSession().retrieve(testID1);
            testObj2 = getSession().retrieve(testID2);

            owned = (DataAssociation)userObj.get("owned");
            DataAssociationCursor cursor = owned.cursor();

            assertTrue("Incorrect number of objects associated",
                       cursor.size() == 2);

            boolean found1 = false;
            boolean found2 = false;

            while (cursor.next()) {
                DataObject next = cursor.getDataObject();

                if (next.equals(testObj1)) {
                    found1 = true;
                } else if (next.equals(testObj2)) {
                    found2 = true;
                } else {
                    fail("Incorrect dataobject retrieved");
                }

                cursor.remove();
            }
            userObj.save();

            assertTrue("Association was missing an object", found1 && found2);

            testObj1.delete();
            testObj2.delete();
        }

        collection.close();
        */
    }
}
