/*******************************************************************************
 * Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved.
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 ******************************************************************************/  
package org.eclipse.persistence.testing.tests.inheritance;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier; 
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.DeleteAllQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.UpdateAllQuery;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.queries.ReadAllQuery;

import org.eclipse.persistence.testing.framework.JoinedAttributeTestHelper;
import org.eclipse.persistence.testing.framework.TestCase;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.framework.TestSuite;

import org.eclipse.persistence.testing.models.inheritance.*;

public class STI_JoinedAttributeTest extends TestCase {
        
    // If the flag is set to true then setup method ensures
    // that the objects in db are exactly those created by
    // STI_EmployeePopulator, and nothing else.
    static protected boolean eachTestShouldEnsurePopulation = false;
    
    // the following static variables are used only in case eachTestShouldEnsurePopulation==true
    static protected Class[] classes = {STI_Employee.class, STI_Project.class};
    static protected Vector[] objectVectors = {null, null};
    static protected STI_EmployeePopulator populator = new STI_EmployeePopulator();

    // The name should start with "test" prefix,
    // it coinsides with the method name the test should use.
    // For instance "testProjectJoinTeamMembers" causes the test's test
    // method to invoke testProjectJoinTeamMembers method.
    public STI_JoinedAttributeTest(String name) {
        super();
        setName(name);
    }
    
    // Junit-style trick: this method creates a TestSuite which contains
    // a TestCase for each method with the name starting with "test".
    public static TestSuite getTestSuite() {
        TestSuite suite = new TestSuite();
        suite.setName("STI_JoinedAttributeTest");
        suite.setDescription("This suite tests join attribute on a Single Table Inheritance version of Employee/Project.");
        Method[] methods= STI_JoinedAttributeTest.class.getDeclaredMethods();
        for (int i= 0; i < methods.length; i++) {
            if(isPublicTestMethod(methods[i])) {
                suite.addTest(new STI_JoinedAttributeTest(methods[i].getName()));
            }
        }
        return suite;
    }
    
	// stolen from junit.framework.TestSuite
    private static boolean isPublicTestMethod(Method m) {
		return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
	 }
	 
	// stolen from junit.framework.TestSuite
	private static boolean isTestMethod(Method m) {
		String name= m.getName();
		Class[] parameters= m.getParameterTypes();
		Class returnType= m.getReturnType();
		return parameters.length == 0 && name.startsWith("test") && returnType.equals(Void.TYPE);
	 }
     
    // This method is designed to make sure that the tests always work in the same environment:
    // db has all the objects produced by populate method - and no other objects of the relevant classes.
    // In order to enforce that the first test populates the db and caches the objects in static collections,
    // the following test reads all the objects from the db, compares them with the cached ones - if they are the
    // same (the case if the tests run directly one after another) then no population occurs.
    // Switched on/off with eachTestShouldEnsurePopulation flag.
    protected void setup() throws Throwable {
        clearCache();
        if(eachTestShouldEnsurePopulation) {
            if(!compare()) {
                clear();
                populate();
            }
            clearCache();
        }
    }
    
    // executes the method with the same name as the test
    protected void test() throws Exception {
        Method method = this.getClass().getDeclaredMethod(getName(), new Class[]{});
        method.invoke(this, new Object[] {});
    }
    
    public void reset() {
        clearCache();
    }
        
    protected void clear() {
        UnitOfWork uow = getSession().acquireUnitOfWork();

        UpdateAllQuery updateEmployees = new UpdateAllQuery(STI_Employee.class);
        updateEmployees.addUpdate("manager", null);
        uow.executeQuery(updateEmployees);
    
        UpdateAllQuery updateProjects = new UpdateAllQuery(STI_Project.class);
        updateProjects.addUpdate("teamLeader", null);
        uow.executeQuery(updateProjects);
    
        uow.executeQuery(new DeleteAllQuery(STI_Employee.class));
        uow.executeQuery(new DeleteAllQuery(STI_Project.class));

        uow.commit();
        clearCache();
    }
    
    protected void populate() {
        populator.buildExamples();
        populator.persistExample(getSession());
        clearCache();
        for(int i=0; i < classes.length; i++) {
            objectVectors[i] = getSession().readAllObjects(classes[i]);
        }
    }
    
    public void testProjectJoinTeamMembers() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);
        
        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        
        query.addJoinedAttribute(query.getExpressionBuilder().anyOf("teamMembers"));

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }
    
    public void testProjectJoinTeamLeaderWhereTeamLeaderNotNull() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);
        Expression teamLeader = query.getExpressionBuilder().get("teamLeader");
        query.setSelectionCriteria(teamLeader.notNull());
        
        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        
        query.addJoinedAttribute(teamLeader);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }
    
    public void testProjectOuterJoinTeamMembers() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);
        
        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        
        Expression teamMembers = query.getExpressionBuilder().anyOfAllowingNone("teamMembers");
        query.addJoinedAttribute(teamMembers);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }
    
    public void testProblemReporterProjectJoinTeamMembers() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);
        query.setSelectionCriteria(query.getExpressionBuilder().get("name").equal("Problem Reporter"));
        
        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        
        Expression teamMembers = query.getExpressionBuilder().anyOf("teamMembers");
        query.addJoinedAttribute(teamMembers);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }
    
    public void testEmployeeJoinProjects() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Employee.class);
        
        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        query.addJoinedAttribute(query.getExpressionBuilder().anyOf("projects"));

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }
    
    public void testEmployeeJoinProjectsJoinTeamLeaderWhereManagerIsNull() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Employee.class);
        query.setSelectionCriteria(query.getExpressionBuilder().get("manager").isNull());
        
        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        Expression projects = query.getExpressionBuilder().anyOf("projects");
        query.addJoinedAttribute(projects);
        Expression teamLeader = projects.get("teamLeader");
        query.addJoinedAttribute(teamLeader);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }
    
    public void testProjectOuterJoinTeamLeaderTeamMembersWhereProjectName() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Project.class);
        query.setSelectionCriteria(query.getExpressionBuilder().get("name").equal("Problem Reporting System").
            or(query.getExpressionBuilder().get("name").equal("Bleep Blob")));
        
        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        
        Expression teamLeader = query.getExpressionBuilder().getAllowingNull("teamLeader");
        query.addJoinedAttribute(teamLeader);
        Expression teamMembers = query.getExpressionBuilder().anyOfAllowingNone("teamMembers");
        query.addJoinedAttribute(teamMembers);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }
    
    public void testEmployeeOuterJoinProjectsTeamLeader() {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(STI_Employee.class);
        
        ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
        
        Expression projects = query.getExpressionBuilder().anyOfAllowingNone("projects");
        query.addJoinedAttribute(projects);
        Expression teamLeader = projects.getAllowingNull("teamLeader");
        query.addJoinedAttribute(teamLeader);
        Expression teamMembers = projects.anyOfAllowingNone("teamMembers");
        query.addJoinedAttribute(teamMembers);

        String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
        if(errorMsg.length() > 0) {
            failTest(errorMsg);
        }
    }
    
    protected String executeQueriesAndCompareResults(ObjectLevelReadQuery controlQuery, ObjectLevelReadQuery queryWithJoins) {
        return JoinedAttributeTestHelper.executeQueriesAndCompareResults(controlQuery, queryWithJoins, (AbstractSession)getSession());
    }

    protected void failTest(String errorMsg) {
        throw new TestErrorException(errorMsg);        
    }
    
    protected boolean compare() {
        for(int i=0; i < classes.length; i++) {
            if(!compare(i)) {
                return false;
            }
        }
        return true;
    }

    protected boolean compare(int i) {
        if(objectVectors[i] == null) {
            return false;
        }
        Vector currentVector = getSession().readAllObjects(classes[i]);
        
        if(currentVector.size() != objectVectors[i].size()) {
            return false;
        }
        ClassDescriptor descriptor = getSession().getDescriptor(classes[i]);
        for(int j=0; j < currentVector.size(); j++) {
            Object obj1 = objectVectors[i].elementAt(j);
            Object obj2 = currentVector.elementAt(j);
            if(!descriptor.getObjectBuilder().compareObjects(obj1, obj2, (org.eclipse.persistence.internal.sessions.AbstractSession)getSession())) {
                return false;
            }
        }
        return true;
    }

    protected void clearCache() {
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
    }
}
