/*******************************************************************************
 * 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.framework;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.indirection.ValueHolder;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.expressions.QueryKeyExpression;
import org.eclipse.persistence.internal.helper.Helper;
import java.util.*;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.InMemoryQueryIndirectionPolicy;
import org.eclipse.persistence.mappings.DatabaseMapping;
 
public class JoinedAttributeTestHelper {
            
    /**
     * Pass to this method controlQuery and query with joined attributes to be tested.
     * The method executes both controlQuery and query with joined attributes and compares results.
     * The errorMessage is returned - empty return means the result are equal.
     * Note that comparison:
     *   takes into account all objects returned by queries;
     *   doesn't instantiate indirection;
     *   error is reported in case on query has indirection instantiated and the other doesn't.
     *   joinedAttributes expressions set on the second query used to read the relevant values into
     *   the result of controlQuery.
     * 
     * A simple way to create control query the will be in sync with queryWithJoins to be tested:
     *   instantiate queryWithJoins - the one to be tested,
     *   set it's referenceClass, selectionCriteria,..., everything but joinedAttributes;
     *   clone queryWithJoins - this clone is controlQuery;
     *   now add joined attributes to queryWithJoins;
     *   pass controlQuery and queryWithJoins to this method.
     */
    public static String executeQueriesAndCompareResults(ObjectLevelReadQuery controlQuery, ObjectLevelReadQuery queryWithJoins, AbstractSession session) {
        session.logMessage("JoinedAttributeTestHelper: executing queryWithJoins:");
        session.getIdentityMapAccessor().initializeAllIdentityMaps();
        Object result = session.executeQuery(queryWithJoins);
        session.logMessage("JoinedAttributeTestHelper: getting control result:");
        Object controlResult = getControlResultsFromControlQuery(controlQuery, queryWithJoins, session);
        String errorMsg = "";
        if (controlResult instanceof Collection) {
            errorMsg = compareCollections((Collection)controlResult, (Collection)result, controlQuery.getDescriptor(), session);
        } else {
            errorMsg = compareObjects(controlResult, result, session);
        }
        return errorMsg;
    }
    
    /**
     * Pass to this method controlQuery and query with joined attributes to be tested.
     * The method executes controlQuery and returns the results after triggering the relations
     * that need to be joined (using the queryWithJoins).
     * 
     * @see executeQueriesAndCompareResults
     */
    public static Object getControlResultsFromControlQuery (ObjectLevelReadQuery controlQuery, ObjectLevelReadQuery queryWithJoins, AbstractSession session){
        int valueHolderPolicy = InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION;
        session.getIdentityMapAccessor().initializeAllIdentityMaps();
        // Need to execute the control query twice, once to determine objects excluded from outjoins,
        // and once to instantiate indirection on only those objects not excluded (otherwise may instantiate indirection differently than join query).
        Object controlResult = session.executeQuery(controlQuery);
        boolean isCollection = false;
        Collection collectionResult = null;
        if (controlResult instanceof Collection) {
            collectionResult = (Collection)controlResult;
            isCollection = true;
        } else {
            collectionResult = new Vector(1);
            collectionResult.add(controlResult);
        }
        Set excluded = new HashSet();
        // Iterate over the result and add removed results to the excluded set.
        for (Iterator iterator = collectionResult.iterator(); iterator.hasNext(); ) {
            Object object = iterator.next();
            boolean remove = false;
            for (Iterator joinsIterator = queryWithJoins.getJoinedAttributeManager().getJoinedAttributeExpressions().iterator(); joinsIterator.hasNext(); ) {
                Expression joinExpression = (Expression)joinsIterator.next();
                joinExpression.getBuilder().setSession(session);
                joinExpression.getBuilder().setQueryClass(queryWithJoins.getReferenceClass());
                // Instantiate value holders that should be instantiated.
                Object value = joinExpression.valueFromObject(object, session, null, valueHolderPolicy, false);
                if (joinExpression.isQueryKeyExpression()) {
                    QueryKeyExpression queryKeyExpression = ((QueryKeyExpression)joinExpression);
                    // Iin case of NOT an outer join, remove objects with null / empty values.
                    if (!queryKeyExpression.shouldUseOuterJoin()) {
                        if (value == null) {
                            remove = true;
                            break;
                        } else if (value instanceof Collection) {
                            Collection collection = (Collection)value;
                            if (collection.isEmpty()) {
                            remove = true;
                                break;
                            } else if (!queryKeyExpression.shouldQueryToManyRelationship()) {
                                Iterator collectionIterator = collection.iterator();
                                while (collectionIterator.hasNext()) {
                                    if (collectionIterator.next() == null) {
                                        remove = true;
                                        break;
                                    }
                                }
                                if (remove == true) {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            if (remove) {
                excluded.add(new CacheKey(session.getId(object)));
            }
        }
        session.getIdentityMapAccessor().initializeAllIdentityMaps();
        
        // Now execute and only instantiate indirection in non-excluded objects.
        controlResult = session.executeQuery(controlQuery);
        isCollection = false;
        collectionResult = null;
        if (controlResult instanceof Collection) {
            collectionResult = (Collection)controlResult;
            isCollection = true;
        } else {
            collectionResult = new Vector(1);
            collectionResult.add(controlResult);
        }
        // Iterate over the result and instantiate all joined indirection.
        for (Iterator iterator = collectionResult.iterator(); iterator.hasNext(); ) {
            Object object = iterator.next();
            if (excluded.contains(new CacheKey(session.getId(object)))) {
                iterator.remove();
            } else {
                for (Iterator joinsIterator = queryWithJoins.getJoinedAttributeManager().getJoinedAttributeExpressions().iterator(); joinsIterator.hasNext(); ) {
                    Expression joinExpression = (Expression)joinsIterator.next();
                    // Instantiate value holders that should be instantiated.
                    joinExpression.valueFromObject(object, session, null, valueHolderPolicy, false);                
                }
            }
        }
        session.getIdentityMapAccessor().initializeAllIdentityMaps();

        if (isCollection){
            return collectionResult;
        } else {
            return controlResult;
        }
    }

    // The errorMessage is returned - empty return means the collections are equal.
    // Note that comparison:
    //   takes into account all objects in collections: pks are extracted, objects with the same pks are compared.
    public static String compareCollections(Collection col1, Collection col2, ClassDescriptor desc, AbstractSession session) {
        Map processed = new IdentityHashMap();
        return compareCollections(col1, col2, desc, session, processed);
    }
    
    // The errorMessage is returned - empty return means the objects are equal.
    // Note that comparison:
    //   takes into account all objects referenced by the objects compared;
    //   doesn't instantiate indirection;
    //   error is reported in case on query has indirection instantiated and the other doesn't.
    public static String compareObjects(Object obj1, Object obj2, AbstractSession session) {
        Map processed = new IdentityHashMap();
        return compareObjects(obj1, obj2, session, processed);
    }

    protected static String compareCollections(Collection col1, Collection col2, ClassDescriptor desc, AbstractSession session, Map processed) {
        if(col1==null && col2==null) {
            return "";
        }
        String errorMsg = "";
        if(col1 != null) {
            if(processed.containsKey(col1)) {
                return "";
            }
            processed.put(col1, col1);
            if(col2==null) {
                errorMsg = ": " + col1.toString() + "!= null ;  ";
                return errorMsg;
            }
        }
        if(col2 != null) {
            if(processed.containsKey(col2)) {
                return "";
            }
            processed.put(col2, col2);
            if(col1 == null) {
                errorMsg = ": null !=" + col2.toString() + ";  ";
                return errorMsg;
            }
        }
        if(col1.size() != col2.size()) {
            errorMsg = ": size1==" + Integer.toString(col1.size()) + "!= size2==" + Integer.toString(col2.size()) + ";  ";
            return errorMsg;
        }

        if(desc != null) {
            // objects keyed by pks
            HashMap map1 = new HashMap(col1.size());
            HashMap map2 = new HashMap(col2.size());
            
            ObjectBuilder builder = desc.getObjectBuilder();
            Iterator it1 = col1.iterator();
            Iterator it2 = col2.iterator();
            while(it1.hasNext()) {
                Object obj1 = it1.next();
                Object obj2 = it2.next();
                Object pk1 = builder.extractPrimaryKeyFromObject(obj1, session);
                Object pk2 = builder.extractPrimaryKeyFromObject(obj2, session);
                map1.put(pk1, obj1);
                map2.put(pk2, obj2);
            }
    
            Iterator itEntries1 = map1.entrySet().iterator();
            while(itEntries1.hasNext()) {
                Map.Entry entry = (Map.Entry)itEntries1.next();
                Object pk = entry.getKey();
                Object obj1 = entry.getValue();
                Object obj2 = map2.get(pk);
                String objErrorMsg = compareObjects(obj1, obj2, session, processed);
                if(objErrorMsg.length() > 0) {
                    errorMsg += "PK = " + pk.toString() + ": " + Helper.getShortClassName(obj1.getClass()) + objErrorMsg + "  ";
                }
                
            }
        } else {
            // there's no target descriptor - compare collections directly
            if(!col1.equals(col2)) {
                errorMsg += "Collections " + col1.toString() + " and " + col2.toString() + " are not equal; ";
            }
        }

        return errorMsg;
    }
    
    protected static String compareMaps(Map map1, Map map2, AbstractSession session, Map processed) {
        if(map1==null && map2==null) {
            return "";
        }
        String errorMsg = "";
        if(map1 != null) {
            if(processed.containsKey(map1)) {
                return "";
            }
            processed.put(map1, map1);
            if(map2==null) {
                errorMsg = ": " + map1.toString() + "!= null ;  ";
                return errorMsg;
            }
        }
        if(map2 != null) {
            if(processed.containsKey(map2)) {
                return "";
            }
            processed.put(map2, map2);
            if(map1 == null) {
                errorMsg = ": null !=" + map2.toString() + ";  ";
                return errorMsg;
            }
        }
        if(map1.size() != map2.size()) {
            errorMsg = ": size1==" + Integer.toString(map1.size()) + "!= size2==" + Integer.toString(map2.size()) + ";  ";
            return errorMsg;
        }

        Iterator itEntries1 = map1.entrySet().iterator();
        while(itEntries1.hasNext()) {
            Map.Entry entry = (Map.Entry)itEntries1.next();
            Object key = entry.getKey();
            Object obj1 = entry.getValue();
            Object obj2 = map2.get(key);
            String objErrorMsg = compareObjects(obj1, obj2, session, processed);
            if(objErrorMsg.length() > 0) {
                errorMsg += "Key = " + key.toString() + ": " + Helper.getShortClassName(obj1.getClass()) + objErrorMsg + "  ";
            }
            
        }

        return errorMsg;
    }
    
    protected static String compareObjects(Object obj1, Object obj2, AbstractSession session, Map processed) {
        if(obj1==null && obj2==null) {
            return "";
        }
        String errorMsg = "";
        if(obj1 != null) {
            if(processed.containsKey(obj1)) {
                return "";
            }
            processed.put(obj1, obj1);
            if(obj2==null) {
                errorMsg = ": " + obj1.toString() + "!= null;  ";
                return errorMsg;
            }
        }
        if(obj2 != null) {
            if(processed.containsKey(obj2)) {
                return "";
            }
            processed.put(obj2, obj2);
            if(obj1 == null) {
                errorMsg = ": null !=" + obj2.toString() + ";  ";
                return errorMsg;
            }
        }

        if(obj1.getClass() != obj2.getClass()) {
            errorMsg = ": " + obj1.getClass().getName() + "!=" + obj2.getClass().getName() + "; ";
            return errorMsg;
        }
        
        ClassDescriptor desc = session.getDescriptor(obj1);
        if(desc == null ) {
            if (!obj1.equals(obj2)) {
                errorMsg = ": " + obj1.toString() + "!=" +obj2.toString() + ";  ";
            }
            return errorMsg;
        }
        
        Vector mappings = desc.getMappings();
        for (int index = 0; index < mappings.size(); index++) {
            DatabaseMapping mapping = (DatabaseMapping)mappings.get(index);
            String mappingErrorMsg = compareAttributes(obj1, obj2, mapping, session, processed);
            errorMsg += mappingErrorMsg;
        }

        return errorMsg;
    }

    protected static String compareAttributes(Object obj1, Object obj2, DatabaseMapping mapping, AbstractSession session, Map processed) {
        String errorMsg = "";
        if(mapping.isForeignReferenceMapping()) {
            ForeignReferenceMapping frm = (ForeignReferenceMapping)mapping;
            Object value1 = frm.getAttributeValueFromObject(obj1);
            Object value2 = frm.getAttributeValueFromObject(obj2);
            boolean isInstantiated1 = frm.getIndirectionPolicy().objectIsInstantiated(value1);
            boolean isInstantiated2 = frm.getIndirectionPolicy().objectIsInstantiated(value2);
            if(!isInstantiated1 && !isInstantiated2) {
                return "";
            } else if(isInstantiated1 && !isInstantiated2) {
                if(frm.isOneToOneMapping() && value1 instanceof ValueHolder && ((ValueHolder)(value1)).getValue() == null) {
                    // In OneToOne case if the foreign key of the read object is null then ValueHolder (which is always instantiated) with value null is created 
                } else {
                    errorMsg = ":  indirection instantiated != indirection NOT instantiated; ";
                }
            } else if(!isInstantiated1 && isInstantiated2) {
                if(frm.isOneToOneMapping() && value2 instanceof ValueHolder && ((ValueHolder)(value2)).getValue() == null) {
                    // In OneToOne case if the foreign key of the read object is null then ValueHolder (which is always instantiated) with value null is created 
                } else {
                    errorMsg = ": indirection NOT instantiated != indirection instantiated; ";
                }
            } else {
                value1 = frm.getRealAttributeValueFromObject(obj1, session);
                value2 = frm.getRealAttributeValueFromObject(obj2, session);
                if(frm.isCollectionMapping()) {
                    Class containerClass = ((CollectionMapping)frm).getContainerPolicy().getContainerClass();
                    if(Collection.class.isAssignableFrom(containerClass)) {
                        errorMsg += compareCollections((Collection)value1, (Collection)value2, frm.getReferenceDescriptor(), session, processed);
                    } else if(Map.class.isAssignableFrom(containerClass)) {
                        errorMsg += compareMaps((Map)value1, (Map)value2, session, processed);
                    } else {
                        errorMsg += mapping.toString() + " container class implements neither Collection nor Map - can't processl; "; 
                    }
                } else {
                    errorMsg += compareObjects(value1, value2, session, processed);
                }
            }
        } else if (!mapping.compareObjects(obj1, obj2, session)) {
            Object value1 = mapping.getAttributeValueFromObject(obj1);
            if(value1 == null) {
                value1 = new String("null");
            }
            Object value2 = mapping.getAttributeValueFromObject(obj2);
            if(value2 == null) {
                value2 = new String("null");
            }
            errorMsg = ": " + value1.toString() + "!=" + value2.toString() + "; ";
        }
        if(errorMsg.length() > 0) {
            errorMsg = "." + mapping.getAttributeName() + errorMsg;
        }
        return errorMsg;
    }
}
