package edu.wustl.cab2b.client.ui.viewresults;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import edu.common.dynamicextensions.domaininterface.AttributeInterface;
import edu.common.dynamicextensions.domaininterface.EntityInterface;
import edu.wustl.cab2b.client.ui.query.ClientQueryBuilder;
import edu.wustl.cab2b.client.ui.util.CommonUtils;
import edu.wustl.cab2b.common.datalist.DataRow;
import edu.wustl.cab2b.common.datalist.IDataRow;
import edu.wustl.cab2b.common.ejb.queryengine.QueryEngineBusinessInterface;
import edu.wustl.cab2b.common.exception.RuntimeException;
import edu.wustl.cab2b.common.queryengine.ICab2bQuery;
import edu.wustl.cab2b.common.queryengine.result.IQueryResult;
import edu.wustl.cab2b.common.queryengine.result.IRecord;
import edu.wustl.cab2b.common.util.Utility;
import edu.wustl.common.querysuite.exceptions.CyclicException;
import edu.wustl.common.querysuite.metadata.associations.IAssociation;
import edu.wustl.common.querysuite.metadata.associations.IInterModelAssociation;
import edu.wustl.common.querysuite.metadata.associations.IIntraModelAssociation;
import edu.wustl.common.util.logger.Logger;

public class QueryExecutionCallable implements Callable<QueryResultObject> {

    private IDataRow m_sourceEntity;

    private IDataRow m_destinationEntity;

    private QueryEngineBusinessInterface m_queryEngineBus;

    private List<IDataRow> m_childNodes;

    public QueryExecutionCallable(
            IDataRow sourceEntity,
            IDataRow destinationEntity,
            QueryEngineBusinessInterface queryEngineBus,
            List<IDataRow> childNodes) {
        m_sourceEntity = sourceEntity;
        m_destinationEntity = destinationEntity;
        m_queryEngineBus = queryEngineBus;
        m_childNodes = childNodes;
    }

    /**
     * 
     */
    public QueryResultObject call() throws Exception {
        // TODO Auto-generated method stub
        List<IDataRow> results = executeRelatedQuery();
        if (null != results) {
            QueryResultObject queryResult = new QueryResultObject(results, m_childNodes);
            return queryResult;
        }
        return null;
    }

    /**
     * Executes the query to get destination enitities associated with source entity
     * @param sourceEntity : The source entity in the query
     * @param destinationEntity : The destination entity in the query 
     * @return 
     */
    private List<IDataRow> executeRelatedQuery() {
        //	Fire query for every child element
        final ClientQueryBuilder queryObject = new ClientQueryBuilder();
        // construct expression object for source entity
        AttributeInterface idAttribute = Utility.getIdAttribute(m_sourceEntity.getEntity());
        List<AttributeInterface> attributes = Collections.singletonList(idAttribute);
        List<String> operators = Collections.singletonList("Equals");
        List<List<String>> values = new ArrayList<List<String>>();
        values.add(Collections.singletonList(m_sourceEntity.getId()));
        
        int sourceExpressionID = queryObject.addRule(attributes, operators, values, idAttribute.getEntity());

        /* Get the source expression id. Needed to add the path.*/
        final EntityInterface targetEntity = m_destinationEntity.getEntity();
        int targetExpressionID = queryObject.createDummyExpression(targetEntity);

        final IAssociation association = m_destinationEntity.getAssociation();
        if (association instanceof IIntraModelAssociation) {
            /*Get the association from the fourth element.*/
            IIntraModelAssociation intraModelAssociation = (IIntraModelAssociation) association;
            try {
                queryObject.addAssociation(targetExpressionID, sourceExpressionID, intraModelAssociation);
            } catch (CyclicException exCyclic) {
                exCyclic.printStackTrace();
            }
            queryObject.setOutputForQueryForSpecifiedURL(targetEntity, m_sourceEntity.getURL());
        } else if (association instanceof IInterModelAssociation) {

            IInterModelAssociation interaModelAssociation = (IInterModelAssociation) association;
            try {
                queryObject.addAssociation(targetExpressionID, sourceExpressionID,
                                           interaModelAssociation.reverse());
                queryObject.setOutputForQuery(targetEntity);
            } catch (CyclicException exCyclic) {
                exCyclic.printStackTrace();
            } catch (RemoteException e) {
                //TODO Handle it properly
                Logger.out.error("Error in setting output URL :" + e.getMessage());
                return null;
            }
           
        }
        IQueryResult<IRecord> relatedQueryResults = null;
        try {
            relatedQueryResults = CommonUtils.executeQuery((ICab2bQuery) queryObject.getQuery(), m_queryEngineBus);
        } catch (RuntimeException e) {
            Logger.out.error("Error in exeuting query :" + e.getMessage());
            return null;
        } catch (RemoteException e) {
            Logger.out.error("Error in exeuting query :" + e.getMessage());
            return null;
        }

        Map<String, List<IRecord>> allRecords = relatedQueryResults.getRecords();
        List<IDataRow> dataRows = new ArrayList<IDataRow>();
        for (String url : allRecords.keySet()) {
            List<IRecord> results = allRecords.get(url);
            for (IRecord record : results) {
                DataRow dataRow = new DataRow(record,relatedQueryResults.getOutputEntity());
                dataRow.setParent(m_sourceEntity);
                dataRow.setAssociation(m_destinationEntity.getAssociation());
                dataRows.add(dataRow);
            }
        }
        return dataRows;
    }

}

@@ -221,24 +221,59 @@
 allable;%0D%0A%0D%0A
+import org.apache.log4j.Logger;%0D%0A%0D%0A
 import edu.c
@@ -970,24 +970,82 @@
 l.Utility;%0D%0A
+import edu.wustl.cab2b.server.queryengine.QueryExecutor;%0D%0A
 import edu.w
@@ -1335,53 +1335,8 @@
 on;%0D
-%0Aimport edu.wustl.common.util.logger.Logger;%0D
 %0A%0D%0Ap
@@ -1411,16 +1411,126 @@
 ject%3E %7B%0D
+%0A    private static final Logger logger = edu.wustl.common.util.logger.Logger.getLogger(QueryExecutor.class);%0D
 %0A%0D%0A    p
@@ -3366,24 +3366,16 @@
 d()));%0D%0A
-        
 %0D%0A      
@@ -4957,35 +4957,31 @@
             
-L
+l
 ogger.
-out.
 error(%22Error
@@ -5071,27 +5071,16 @@
      %7D%0D%0A
-           
 %0D%0A      
@@ -5323,35 +5323,31 @@
             
-L
+l
 ogger.
-out.
 error(%22Error
@@ -5469,19 +5469,15 @@
     
-L
+l
 ogger.
-out.
 erro
@@ -5917,16 +5917,17 @@
 (record,
+ 
 relatedQ

Corrected the Logger