package edu.wustl.cab2b.server.util;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

import org.apache.log4j.Logger;

import edu.common.dynamicextensions.domaininterface.AttributeInterface;
import edu.wustl.cab2b.common.exception.RuntimeException;
import edu.wustl.cab2b.common.queryengine.result.IRecord;
import edu.wustl.cab2b.common.util.Utility;
import edu.wustl.cab2b.server.cache.EntityCache;
import edu.wustl.cab2b.server.category.CategoryCache;
import edu.wustl.cab2b.server.datalist.DataListOperationsController;
import edu.wustl.cab2b.server.path.PathFinder;
import edu.wustl.common.bizlogic.DefaultBizLogic;
import edu.wustl.common.exception.BizLogicException;
import edu.wustl.common.querysuite.metadata.path.CuratedPath;
import edu.wustl.common.security.exceptions.UserNotAuthorizedException;
import edu.wustl.common.util.global.Constants;

/**
 * Operations class for utility bean
 * @author chandrakant_talele
 */
public class UtilityOperations extends DefaultBizLogic {
    private static final Logger logger = edu.wustl.common.util.logger.Logger.getLogger(UtilityOperations.class);

    /**
     * Hibernate DAO Type to use.
     */
    private static int daoType = Constants.HIBERNATE_DAO;

    /**
     * @param cab2bObject
     */
    public void insert(Object cab2bObject) {
        try {
            insert(cab2bObject, daoType);
            logger.debug(cab2bObject.getClass().getName() + " inserted Successfully ");
        } catch (BizLogicException e) {
            throw (new RuntimeException(e.getMessage(), e));
        } catch (UserNotAuthorizedException e) {
            throw (new RuntimeException(e.getMessage(), e));
        }
    }

    /**
     * @param cab2bObject
     */
    public void update(Object cab2bObject) {
        try {
            update(cab2bObject, daoType);
            logger.debug(cab2bObject.getClass().getName() + " inserted Successfully ");
        } catch (BizLogicException e) {
            logger.debug(Utility.getStackTrace(e));
            throw (new RuntimeException(e.getMessage(), e));
        } catch (UserNotAuthorizedException e) {
            logger.debug(Utility.getStackTrace(e));
            throw (new RuntimeException(e.getMessage(), e));
        }
    }

    /**
     * This method returns the list of tree set containing the unique record values for a given entity identifier.
     * Tree set stores the values in sorted order. 
     * @param entityId entityId
     * @return List of TreeSet
     */
    public List<TreeSet<Comparable<?>>> getUniqueRecordValues(Long entityId) {
        //getting record list
        List<IRecord> entityRecordList = new DataListOperationsController().getEntityRecords(entityId);
        if (entityRecordList == null || entityRecordList.size() == 0) {
            return null;
        }

        //initializing column value set
        ArrayList<TreeSet<Comparable<?>>> entityRecordValues = new ArrayList<TreeSet<Comparable<?>>>();
        for (int i = 0; i < entityRecordList.get(0).getAttributes().size(); i++) {
            entityRecordValues.add(i, new TreeSet<Comparable<?>>());
        }

        for (IRecord entityRecord : entityRecordList) {
            process(entityRecord, entityRecordValues);
        }
        return entityRecordValues;
    }

    private void process(IRecord record, List<TreeSet<Comparable<?>>> entityRecordValues) {
        int index = 0;
        List<AttributeInterface> attributeList = Utility.getAttributeList(record.getAttributes());
        for (AttributeInterface attribute : attributeList) {
            TreeSet<Comparable<?>> columnValues = entityRecordValues.get(index);
            Comparable<?> attributeValue = (Comparable<?>) record.getValueForAttribute(attribute);
            if (attributeValue != null) {
                columnValues.add(attributeValue);
            }
            index++;
        }
    }

    /**
     * Method to refresh Path and Entity cache. 
     * 
     * @param refreshEntityCache If true refreshes entity cache along with path. If false, only rereshes path cache.
     */
    public void refreshPathAndEntityCache(boolean refreshEntityCache) {
        logger.info("Successful access on remote bean!!!!");
        Connection connection = ConnectionUtil.getConnection();
        PathFinder.refreshCache(connection, refreshEntityCache);
    }

    /**
     * Method to refresh category cache.
     */
    public void refreshCategoryAndEntityCache() {
        EntityCache.getInstance().refreshCache();
        Connection connection = ConnectionUtil.getConnection();
        CategoryCache.getInstance().refreshCategoryCache(connection);
    }

    /**
     * Adds the curated path to cache
     * @param curatedPath path to be added to cache.
     */
    public void addCuratedPathToCache(CuratedPath curatedPath) {
        Connection connection = ConnectionUtil.getConnection();
        PathFinder.getInstance(connection).addCuratedPath(curatedPath);
    }
}

@@ -2918,32 +2918,78 @@
 ll;%0D%0A        %7D%0D%0A
+        IRecord rec = entityRecordList.get(0);
 %0D%0A        //init
@@ -3023,21 +3023,16 @@
         
-Array
 List%3CTre
@@ -3077,146 +3077,200 @@
 s = 
-new ArrayList%3CTreeSet%3CComparable%3C?%3E%3E%3E();%0D%0A        for (int i = 0; i %3C entityRecordList.get(0).getAttributes().size(); i++) %7B%0D%0A
+initEntityRecordValues(rec.getAttributes().size());%0D%0A        for (IRecord entityRecord : entityRecordList) %7B%0D%0A            process(entityRecord, entityRecordValues);%0D%0A  
      
+ %7D%0D%0A
        
+ return 
 enti
@@ -3287,170 +3287,279 @@
 lues
-.add(i, new TreeSet%3CComparable%3C?%3E%3E());%0D%0A        %7D%0D%0A%0D%0A        for (IRecord entityRecord : entityRecordList) %7B%0D%0A            process(entityRecord, entityRecordValues
+;%0D%0A    %7D%0D%0A    private List%3CTreeSet%3CComparable%3C?%3E%3E%3E initEntityRecordValues(int size) %7B%0D%0A        List%3CTreeSet%3CComparable%3C?%3E%3E%3E list = new ArrayList%3CTreeSet%3CComparable%3C?%3E%3E%3E(size);%0D%0A        for (int i = 0; i %3C size; i++) %7B%0D%0A            list.add(i, new TreeSet%3CComparable%3C?%3E%3E()
 );%0D%0A
@@ -3584,34 +3584,20 @@
  return 
-entityRecordValues
+list
 ;%0D%0A    %7D

Split getUniqueRecordValues() into two methods to address PMD error