com.att.pirates.controller.ProjectController.java Source code

Java tutorial

Introduction

Here is the source code for com.att.pirates.controller.ProjectController.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.att.pirates.controller;

import com.att.pirates.model.ATTEmployee;
import com.att.pirates.model.AppProjectArtifactOwnersHistory;
import com.att.pirates.model.Company;
import com.att.pirates.model.ImpactTypes;
import com.att.pirates.model.InsightProject;
import com.att.pirates.model.InsightRelease;
import com.att.pirates.model.JQueryDataTableParamModel;
import com.att.pirates.model.Module;
import com.att.pirates.model.PercentageModel;
import com.att.pirates.model.ProjectAppOwnerModel;
import com.att.pirates.model.ProjectApplicationModule;
import com.att.pirates.model.ProjectApplications;
import com.att.pirates.model.ProjectDetailsPersonnel;
import com.att.pirates.model.ProjectDetailsPersonnelModelView;
import com.att.pirates.model.ProjectDetailsStatusViewModel;
import com.att.pirates.model.ProjectNoteViewModel;
import com.att.pirates.model.ProjectStatusViewModel;
import com.att.pirates.model.Threshold;
import com.att.pirates.util.DBUtility;
import com.att.pirates.util.DataService;
import com.att.pirates.util.DataTablesParamUtility;
import com.att.pirates.util.PiratesConstants;
import com.google.gson.Gson;
import com.google.gson.JsonIOException;
import com.google.gson.JsonObject;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.Valid;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.util.HtmlUtils;

/**
 *
 * @author mercychan
 */
@Controller
public class ProjectController {
    private static final Logger logger = Logger.getLogger(ProjectController.class);
    private static final String msgHeader = "[Merce]: ";
    private static List<ATTEmployee> employees = null;
    private static List<ATTEmployee> employees_prismid = null;
    private static List<ATTEmployee> employees_application = null;
    private static List<AppProjectArtifactOwnersHistory> artifactHistory = null;

    @RequestMapping(value = "/projects/{prismId}/applicationlist", method = RequestMethod.GET)
    public @ResponseBody String getApplicationListForPrismId(@PathVariable("prismId") String prismId) {
        List<ProjectApplications> apps = DataService.getProjectApplications(prismId);
        JsonObject jsonResponse = new JsonObject();

        for (ProjectApplications ap : apps) {
            jsonResponse.addProperty(ap.getApplicationName(), ap.getApplicationName());
        }

        logger.error(msgHeader + jsonResponse.toString());
        return jsonResponse.toString();
    }

    /* action to handle adding new projects */
    @RequestMapping(value = "/projects/add", method = RequestMethod.POST)
    public String setAdministration(HttpServletRequest request, Model model) {
        String sessionUser = (String) request.getSession().getAttribute("loginUser");
        if (sessionUser == null || sessionUser.isEmpty() || "Not Logged In".equalsIgnoreCase(sessionUser)) {
            request.getSession().setAttribute("loginUser", "Not Logged In");
            logger.error("[Merce]: user not logged in.. redirecting to logout page");
            return "redirect:/logout";
        }

        String release = request.getParameter("drpdwnRelease");
        String pid = request.getParameter("pid");
        String domain = request.getParameter("domain");
        String projectName = request.getParameter("projectName");
        String projectDescription = request.getParameter("projectDescription");
        String applicationName = request.getParameter("drpdwnAppId");

        String status = request.getParameter("drpdwnStatusId");
        String lpm = request.getParameter("drpdwnleadPMId");

        logger.error(msgHeader + "drpdwnStatusId: " + status);
        logger.error(msgHeader + "drpdwnleadPMId: " + lpm);

        logger.error(msgHeader + "projectName: " + projectName);
        logger.error(msgHeader + "projectDescription: " + HtmlUtils.htmlEscape(projectDescription));
        logger.error(msgHeader + "applicationName: " + applicationName);

        if (status.isEmpty()) {
            return "redirect:/Administration";
        }

        if (lpm.isEmpty()) {
            return "redirect:/Administration";
        }

        if (pid == null || pid.isEmpty()) {
            // return without going to data layer
            return "redirect:/Administration";
        }

        if (domain == null || domain.isEmpty()) {
            // return without going to data layer
            return "redirect:/Administration";
        }

        if (projectName == null || projectName.isEmpty()) {
            // return without going to data layer
            return "redirect:/Administration";
        }

        if (projectDescription == null || projectDescription.isEmpty()) {
            // return without going to data layer
            return "redirect:/Administration";
        }

        if (applicationName == null || applicationName.isEmpty() || applicationName.equalsIgnoreCase("0")) {
            // return without going to data layer
            return "redirect:/Administration";
        }

        List<String> allPids = DataService.getAllPrismIds();
        if (allPids.contains(pid)) {
            request.getSession().setAttribute("pidExists", pid);
            // return without going to data layer
            return "redirect:/Administration";
        }

        // do not support these characters
        // !"#$%&*+/:;=?@[]^`{|}~\
        pid = pid.replace("\"", "").replace("#", "").replace("%", "").replace("&", "").replace(":", "")
                .replace(";", "").replace("=", "").replace("?", "").replace("\'", "").replace("[", "")
                .replace("]", "").replace("{", "").replace("}", "").replace("~", "").replace("\\", "")
                .replace("/", "");

        DataService.addNewProjectToPIRATES(sessionUser, pid, Integer.valueOf(domain), Integer.valueOf(release),
                projectName, projectDescription, applicationName, Integer.valueOf(status), lpm);
        return "redirect:/projects/index/" + pid;
    }

    /* action to handle adding application to project */
    @RequestMapping(value = "/projects/application/add/{prismId}", method = RequestMethod.POST)
    public String addApplicationToProject(HttpServletRequest request, @PathVariable("prismId") String prismId) {
        String appName = request.getParameter("drpdwnAppId");
        if (appName == null || appName.isEmpty() || appName == "0") {
            // return without going to data layer
            return "redirect:/projects/index/{prismId}";
        } else {
            // 1. add to ProjectApplicationModules
            // 2. add to ProjectApplicationModulesEx
            // 3. add BR, SR, DES, DEV, AID, IST etc to AppProjectArtifactOwners
            String sessionUser = (String) request.getSession().getAttribute("loginUser");
            if (sessionUser == null || sessionUser.isEmpty() || "Not Logged In".equalsIgnoreCase(sessionUser)) {
                request.getSession().setAttribute("loginUser", "Not Logged In");
                logger.error("[Merce]: user not logged in.. redirecting to logout page");
                return "redirect:/logout";
            }
            DataService.processAddApplicationToProject(prismId, appName, sessionUser);
            return "redirect:/projects/index/{prismId}";
        }
    }

    public static List<String> getAvailableApplicationForUUID(String uuid, String prismId) {
        return DataService.getAvailableApplicationForUUID(uuid, prismId);
    }

    public static List<String> getAvailableApplicationsForUUID(String uuid) {
        return DataService.getAvailableApplicationsForUUID(uuid);
    }

    /* main project details entry point */
    @RequestMapping(value = "/projects/index/{prismId}", method = RequestMethod.GET)
    public String projectIndex(@PathVariable("prismId") String prismId, Model model, HttpServletRequest request) {
        // logger.error(msgHeader + "prismId passed in is: " + prismId);
        model.addAttribute("prismId", prismId);
        InsightProject p = getProjectInfo(prismId).get(0);
        String projectname = p.getProjectName();
        String releaseName = p.getReleaseName();
        model.addAttribute("projectname", projectname);
        model.addAttribute("ReleaseList", DataService.getReleases());
        model.addAttribute("StatusList", DataService.getStatusList());
        model.addAttribute("ReleaseName", releaseName);
        model.addAttribute("ATTEmployees", getATTEmployees(prismId));
        model.addAttribute("ATTLeadPMs", getAllPMs());

        String expandNote = (String) request.getSession().getAttribute("expandNote");
        if (expandNote != null) {
            model.addAttribute("expandNote", expandNote);
            // reset expandNote session value
            request.getSession().setAttribute("expandNote", "false");
        }

        String sessionUser = (String) request.getSession().getAttribute("loginUser");
        if (sessionUser == null || sessionUser.isEmpty() || "Not Logged In".equalsIgnoreCase(sessionUser)) {
            request.getSession().setAttribute("loginUser", "Not Logged In");
            logger.error("[Merce]: user not logged in.. redirecting to logout page");
            return "redirect:/logout";
        }

        List<InsightRelease> rc = GlobalDataController.GetProjectHierarchiesPOJO(sessionUser);

        // TODO:  go to db and get project name by prismid
        List<InsightProject> projects = getProjectInfo(prismId);
        InsightProject prj = null;

        if (projects != null && projects.size() > 0) {
            prj = projects.get(0);
        } else {
            prj = new InsightProject();
        }
        model.addAttribute("projectInfo", prj);

        InsightProject next = DataService.getNextProjectFromList(rc, prj);
        InsightProject previous = DataService.getPreviousProjectFromList(rc, prj);
        model.addAttribute("NextprojectInfo", next);
        model.addAttribute("PreviousprojectInfo", previous);

        return "projectIndex";
    }

    /// <summary>
    /// Method that returns all companies used in this example
    /// </summary>
    /// <returns>List of companies</returns>
    /// <summary>
    /// Singleton collection of companies
    /// </summary>
    public static List<InsightProject> getProjectInfo(String prismId) {
        List<InsightProject> projects = new ArrayList<InsightProject>();

        // TODO:  port over to hibernate later
        // logger.error(msgHeader + "getProjectInfo called with prismId: "+ prismId);
        ResultSet rs = null;
        Connection conn = null;
        PreparedStatement preparedStatement = null;

        try {
            conn = DBUtility.getDBConnection();
            // SQL query command
            String SQL = " SELECT p.[PRISMId] " + "      ,p.[ProjectName] " + "      ,p.[ProjectDescription] "
                    + "      ,p.[ProjectDueDate] " + "      ,p.[LeadPM] " + "      ,ps.[StatusName] "
                    + "      ,r.ReleaseName " + "      ,p.[ProjectStartDate] " + "      ,p.StatusId "
                    + "      ,p.ReleaseId " + "  FROM Projects p Join  "
                    + "  Releases r on r.ReleaseId = p.ReleaseId "
                    + "  join ProjectStatus ps on ps.StatusId = p.StatusId " + "  Where p.PRISMId = ? ";

            preparedStatement = conn.prepareStatement(SQL);
            preparedStatement.setString(1, prismId);
            rs = preparedStatement.executeQuery();
            int rowCount = 0;

            while (rs.next()) {
                rowCount++;
                String projectName = HtmlUtils.htmlUnescape(rs.getString("ProjectName"));
                String projectDescription = rs.getString("ProjectDescription"); // HtmlUtils.htmlUnescape(rs.getString("ProjectDescription")) ;
                String projectDueDate = rs.getString("ProjectDueDate");
                String leadPM = rs.getString("LeadPM");
                String statusName = rs.getString("StatusName");
                String releaseName = rs.getString("ReleaseName");
                int statusId = rs.getInt("StatusId");
                int releaseId = rs.getInt("ReleaseId");

                String projectStartDate = rs.getString("ProjectStartDate");
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                SimpleDateFormat yFormat = new SimpleDateFormat("MM/dd/yyyy");

                projectDueDate = yFormat.format(format.parse(projectDueDate));
                projectStartDate = yFormat.format(format.parse(projectStartDate));

                logger.error(msgHeader + "projectDueDate: " + projectDueDate);
                logger.error(msgHeader + "projectStartDate: " + projectStartDate);

                // create a project and add it to list
                InsightProject p = new InsightProject();
                p.setProjectName(projectName);
                p.setProjectDescription(projectDescription);
                p.setPrismId(prismId);
                p.setReleaseName(releaseName);
                p.setProjectDueDate(projectDueDate);
                p.setLeadPM(leadPM);
                p.setProjectStatus(statusName);
                p.setProjectStartDate(projectStartDate);
                p.setStatudId(statusId);
                p.setReleaseId(releaseId);

                projects.add(p);
                // logger.error(msgHeader + releaseName + "," + prismId + "," + projectName + ", "+ projectDescription);
            }
            logger.error(msgHeader + "getProjectInfo called, got results: " + rowCount);
        } catch (SQLException e) {
            logger.error(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (preparedStatement != null)
                    preparedStatement.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (conn != null)
                    conn.close();
            } catch (Exception e) {
            }
            ;
        }

        return projects;
    }

    @RequestMapping(value = "/pid/{prismId}/getProjectNotesJson", method = RequestMethod.GET)
    public @ResponseBody String getCompanies(@PathVariable("prismId") String prismId, HttpServletRequest request) {
        // logger.error(msgHeader + " getCompanies prismId: " + prismId);
        JQueryDataTableParamModel param = DataTablesParamUtility.getParam(request);

        String sEcho = param.sEcho;
        int iTotalRecords; // total number of records (unfiltered)
        int iTotalDisplayRecords; //value will be set when code filters companies by keyword
        List<Company> allNotes = GlobalDataController.GetCompanies(prismId);

        iTotalRecords = allNotes.size();
        List<Company> companies = new LinkedList<Company>();
        for (Company c : allNotes) {
            if (c.getName().toLowerCase().contains(param.sSearch.toLowerCase())
                    || c.getAddress().toLowerCase().contains(param.sSearch.toLowerCase())
                    || c.getTown().toLowerCase().contains(param.sSearch.toLowerCase())
                    || c.getDateCreated().toLowerCase().contains(param.sSearch.toLowerCase())) {
                companies.add(c); // add company that matches given search criterion
            }
        }
        iTotalDisplayRecords = companies.size();// number of companies that match search criterion should be returned

        final int sortColumnIndex = param.iSortColumnIndex;
        final int sortDirection = param.sSortDirection.equals("asc") ? -1 : 1;

        Collections.sort(companies, new Comparator<Company>() {
            @Override
            public int compare(Company c1, Company c2) {
                switch (sortColumnIndex) {
                case 0:
                    return 0; // sort by id is not allowed
                case 1:
                    return c1.getName().compareTo(c2.getName()) * sortDirection;
                case 2:
                    return c1.getAddress().compareTo(c2.getAddress()) * sortDirection;
                case 3:
                    return c1.getTown().compareTo(c2.getTown()) * sortDirection;
                case 4:
                    SimpleDateFormat yFormat = new SimpleDateFormat("MM/dd/yyyy");
                    try {
                        Date c1d = yFormat.parse(c1.getDateCreated());
                        Date c2d = yFormat.parse(c2.getDateCreated());

                        return c1d.compareTo(c2d) * sortDirection;
                    } catch (ParseException ex) {
                        logger.error(ex.getMessage());
                    }
                }
                return 0;
            }
        });

        if (companies.size() < param.iDisplayStart + param.iDisplayLength) {
            companies = companies.subList(param.iDisplayStart, companies.size());
        } else {
            companies = companies.subList(param.iDisplayStart, param.iDisplayStart + param.iDisplayLength);
        }

        try {
            JsonObject jsonResponse = new JsonObject();
            jsonResponse.addProperty("sEcho", sEcho);
            jsonResponse.addProperty("iTotalRecords", iTotalRecords);
            jsonResponse.addProperty("iTotalDisplayRecords", iTotalDisplayRecords);
            Gson gson = new Gson();
            jsonResponse.add("aaData", gson.toJsonTree(companies));

            String tmp = jsonResponse.toString();
            // logger.error(msgHeader + ".. json string: " + tmp);
            return jsonResponse.toString();
        } catch (JsonIOException e) {
            logger.error(msgHeader + e.getMessage());
        }
        return null;
    }

    public static List<ATTEmployee> getATTEmployeesForApplication(String PrismId, String applicationName) {
        if (employees_application != null && !employees_application.isEmpty()) {
            employees_application.clear();
        }

        employees_application = null;
        if (employees_application == null) {
            employees_application = new ArrayList<ATTEmployee>();

            // logger.error(msgHeader + "getATTEmployeesForApplication called. ");
            ResultSet rs = null;
            Connection conn = null;
            PreparedStatement preparedStatement = null;

            try {
                conn = DBUtility.getDBConnection();
                // SQL query command
                String SQL = " select e.UUID, e.Fullname " + "  from ATTEmployeeApplicationAssignments ea join "
                        + "  ATT_Employees e on e.UUID = ea.UUID " + "  where exists " + "  ( " + "  select * "
                        + "  from ProjectApplicationModules t "
                        + "  where t.PRISMId = ? and t.applicationname = ? and "
                        + "  t.applicationname = ea.applicationname " + "  ) "
                        + "  order by e.displayorder, e.firstname, e.lastname ";
                preparedStatement = conn.prepareStatement(SQL);
                preparedStatement.setString(1, PrismId);
                preparedStatement.setString(2, applicationName);
                rs = preparedStatement.executeQuery();

                int rowCount = 0;
                while (rs.next()) {
                    rowCount++;
                    String UUID = rs.getString("UUID").toUpperCase();
                    String Fullname = rs.getString("FullName");

                    ATTEmployee e = new ATTEmployee();
                    e.setUUID(UUID);
                    e.setFullName(Fullname);
                    employees_application.add(e);
                }
                // logger.error(msgHeader + "getATTEmployees called, got results: "+rowCount);
            } catch (SQLException e) {
                logger.error(e.getMessage());
            } catch (Exception e) {
                logger.error(e.getMessage());
            } finally {
                try {
                    if (rs != null)
                        rs.close();
                } catch (Exception e) {
                }
                ;
                try {
                    if (preparedStatement != null)
                        preparedStatement.close();
                } catch (Exception e) {
                }
                ;
                try {
                    if (conn != null)
                        conn.close();
                } catch (Exception e) {
                }
                ;
            }
        }

        return employees_application;
    }

    public static List<ATTEmployee> getAllPMs() {
        List<ATTEmployee> rc = new ArrayList<ATTEmployee>();

        ResultSet rs = null;
        Connection conn = null;
        PreparedStatement preparedStatement = null;

        try {
            conn = DBUtility.getDBConnection();
            // SQL query command
            String SQL = "  SELECT [UUID] "
                    + "      ,cast([FirstName] as varchar(125)) + ' ' + cast([LastName] as varchar(125)) as [FullName]  "
                    + "  FROM [ATT_Employees_PM]  ";
            preparedStatement = conn.prepareStatement(SQL);
            rs = preparedStatement.executeQuery();

            while (rs.next()) {
                String UUID = rs.getString("UUID");
                String Fullname = rs.getString("FullName");

                ATTEmployee e = new ATTEmployee();
                e.setUUID(UUID);
                e.setFullName(Fullname);
                rc.add(e);
            } // end while
              // logger.error(msgHeader + "getATTEmployees called, got results: "+rowCount);
        } catch (SQLException e) {
            logger.error(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (preparedStatement != null)
                    preparedStatement.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (conn != null)
                    conn.close();
            } catch (Exception e) {
            }
            ;
        }
        return rc;
    }

    public static List<ATTEmployee> getATTEmployees(String PrismId) {
        employees_prismid = null;
        if (employees_prismid == null) {
            employees_prismid = new ArrayList<ATTEmployee>();

            // TODO:  port over to hibernate later
            // logger.error(msgHeader + "getATTEmployees called. ");
            ResultSet rs = null;
            Connection conn = null;
            PreparedStatement preparedStatement = null;

            try {
                conn = DBUtility.getDBConnection();
                // SQL query command
                String SQL = "   select e.UUID, e.Fullname " + "  from ATTEmployeeApplicationAssignments ea join "
                        + "  ATT_Employees e on e.UUID = ea.UUID " + "  where exists " + "  ( " + "  select * "
                        + "  from ProjectApplicationModules t " + "  where t.PRISMId = ? and  "
                        + "  t.applicationname = ea.applicationname " + "  ) "
                        + "  order by e.displayorder, e.firstname, e.lastname ";
                preparedStatement = conn.prepareStatement(SQL);
                preparedStatement.setString(1, PrismId);
                rs = preparedStatement.executeQuery();

                int rowCount = 0;

                while (rs.next()) {
                    rowCount++;
                    String UUID = rs.getString("UUID");
                    String Fullname = rs.getString("FullName");

                    boolean s = false;
                    for (ATTEmployee a : employees_prismid) {
                        if (a.getUUID().equalsIgnoreCase(UUID)) {
                            s = true;
                            break;
                        }
                    }
                    if (!s) {
                        ATTEmployee e = new ATTEmployee();
                        e.setUUID(UUID);
                        e.setFullName(Fullname);
                        employees_prismid.add(e);
                    }
                } // end while
                  // logger.error(msgHeader + "getATTEmployees called, got results: "+rowCount);
            } catch (SQLException e) {
                logger.error(e.getMessage());
            } catch (Exception e) {
                logger.error(e.getMessage());
            } finally {
                try {
                    if (rs != null)
                        rs.close();
                } catch (Exception e) {
                }
                ;
                try {
                    if (preparedStatement != null)
                        preparedStatement.close();
                } catch (Exception e) {
                }
                ;
                try {
                    if (conn != null)
                        conn.close();
                } catch (Exception e) {
                }
                ;
            }
        }

        return employees_prismid;
    }

    public static List<ATTEmployee> getATTEmployees_All() {
        if (employees == null) {
            employees = new ArrayList<ATTEmployee>();

            // TODO:  port over to hibernate later
            // logger.error(msgHeader + "getATTEmployees called. ");
            ResultSet rs = null;
            Connection conn = null;
            PreparedStatement preparedStatement = null;

            try {
                conn = DBUtility.getDBConnection();
                // SQL query command
                String SQL = " SELECT UUID " + "  ,FullName " + "  FROM ATT_Employees " + "  Order By UUID ";

                preparedStatement = conn.prepareStatement(SQL);
                rs = preparedStatement.executeQuery();
                int rowCount = 0;

                while (rs.next()) {
                    rowCount++;
                    String UUID = rs.getString("UUID");
                    String Fullname = rs.getString("FullName");

                    ATTEmployee e = new ATTEmployee();
                    e.setUUID(UUID);
                    e.setFullName(Fullname);
                    employees.add(e);
                }
                // logger.error(msgHeader + "getATTEmployees called, got results: "+rowCount);
            } catch (SQLException e) {
                logger.error(e.getMessage());
            } catch (Exception e) {
                logger.error(e.getMessage());
            } finally {
                try {
                    if (rs != null)
                        rs.close();
                } catch (Exception e) {
                }
                ;
                try {
                    if (preparedStatement != null)
                        preparedStatement.close();
                } catch (Exception e) {
                }
                ;
                try {
                    if (conn != null)
                        conn.close();
                } catch (Exception e) {
                }
                ;
            }
        }

        return employees;
    }

    public static ATTEmployee getATTEmployeeObjectByUUID(String UUID) {
        ATTEmployee rc = new ATTEmployee();
        rc.setFullName(UUID);
        rc.setUUID(UUID);

        if (employees == null) {
            getATTEmployees_All();
        }

        for (ATTEmployee e : employees) {
            if (e.getUUID().equalsIgnoreCase(UUID)) {
                return e;
            }
        }

        return rc;
    }

    private static List<PercentageModel> getPercentageModels(boolean isAgile) {
        List<PercentageModel> results = new ArrayList<PercentageModel>();

        PercentageModel m1 = new PercentageModel();
        m1.setLabel("0%");
        m1.setValue("0.00");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("5%");
        m1.setValue("0.05");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("10%");
        m1.setValue("0.10");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("15%");
        m1.setValue("0.15");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("20%");
        m1.setValue("0.20");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("25%");
        m1.setValue("0.25");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("30%");
        m1.setValue("0.30");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("35%");
        m1.setValue("0.35");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("40%");
        m1.setValue("0.40");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("45%");
        m1.setValue("0.45");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("50%");
        m1.setValue("0.50");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("55%");
        m1.setValue("0.55");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("60%");
        m1.setValue("0.60");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("65%");
        m1.setValue("0.65");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("70%");
        m1.setValue("0.70");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("75%");
        m1.setValue("0.75");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("80%");
        m1.setValue("0.80");
        results.add(m1);

        m1 = new PercentageModel();
        m1.setLabel("85%");
        m1.setValue("0.85");
        results.add(m1);

        if (isAgile) {
            m1 = new PercentageModel();
            m1.setLabel("90%");
            m1.setValue("0.90");
            results.add(m1);

            m1 = new PercentageModel();
            m1.setLabel("95%");
            m1.setValue("0.95");
            results.add(m1);
        } else {
            m1 = new PercentageModel();
            m1.setLabel("90% - Out for Review");
            m1.setValue("0.90");
            results.add(m1);

            m1 = new PercentageModel();
            m1.setLabel("95% - Out for Approval");
            m1.setValue("0.95");
            results.add(m1);
        }

        m1 = new PercentageModel();
        m1.setLabel("100%");
        m1.setValue("1.00");
        results.add(m1);

        return results;
    }

    @RequestMapping(value = "/addProjectStatus", method = RequestMethod.GET)
    public String addProjectPersonnel(HttpServletRequest request, Model model) {
        model.addAttribute("PercentageModel", getPercentageModels(false));
        model.addAttribute("PercentageModelAgile", getPercentageModels(true));
        // in request, id is applicationid and prismid is project prismid
        // use these two pieces of info to query the the latest percentage complete for
        // 1. this prismid
        // 2. this application (insight: bcts or insight: dss)
        // 3. BR current complete percentage, SR, HLD etc
        // no need to set default percentage to avoid confusion
        ProjectStatusViewModel statusViewModel = new ProjectStatusViewModel();
        // TODO: grab default pecentage for this applicationid and prismid
        String id = request.getParameter("id");
        String prismId = request.getParameter("prismId");
        int applicationId = Integer.parseInt(id);
        String appName = DataService.getApplicationNameByPrismIdApplicationId(applicationId, prismId);
        int impactType = DataService.getImpactTypeIdByPrismIdAndApplicationName(prismId, appName);

        List<ProjectAppOwnerModel> owners = getProjectAppOwners(prismId);

        if (!owners.isEmpty()) {
            // logger.error("[Merce]: owners returned size.. " + owners.size());
            for (ProjectAppOwnerModel p : owners) {
                // logger.error("[Merce]: p.getApplicationName() is.. " + p.getApplicationName() + ", appName to compare is: " + appName);
                if (appName.equalsIgnoreCase(p.getApplicationName())) { // run through one application
                                                                        // Agile
                    if (PiratesConstants.AGILE.equalsIgnoreCase(p.getArtifactName())) {
                        // if this application is Agile
                        if (p.isIsPrimaryOwner()) {
                            // logger.error("Match, assigning BR % to: " + p.getPercentageCompleteStr());
                            statusViewModel.setAgilePercentageComplete(p.getPercentageCompleteStr());
                            statusViewModel.setAgileDateCreated(p.getDateCreated());
                        }
                        break;
                    } // end yes agile
                    else {
                        // if this application is NOT agile
                        // BR
                        if (PiratesConstants.BR.equalsIgnoreCase(p.getArtifactName())) {
                            if (p.isIsPrimaryOwner()) {
                                // logger.error("Match, assigning BR % to: " + p.getPercentageCompleteStr());
                                statusViewModel.setBRPercentageComplete(p.getPercentageCompleteStr());
                                statusViewModel.setBRDateCreated(p.getDateCreated());
                            }
                        }
                        // SR
                        if (PiratesConstants.SR.equalsIgnoreCase(p.getArtifactName())) {
                            if (p.isIsPrimaryOwner()) {
                                // logger.error("Match, assigning SR % to: " + p.getPercentageCompleteStr());
                                statusViewModel.setSRPercentageComplete(p.getPercentageCompleteStr());
                                statusViewModel.setSRDateCreated(p.getDateCreated());
                            }
                        }
                        // HLD
                        if (PiratesConstants.HLD.equalsIgnoreCase(p.getArtifactName())) {
                            if (p.isIsPrimaryOwner()) {
                                // logger.error("Match, assigning HLD % to: " + p.getPercentageCompleteStr());
                                statusViewModel.setHLDPercentageComplete(p.getPercentageCompleteStr());
                                statusViewModel.setHLDDateCreated(p.getDateCreated());
                            }
                        }
                        // AID
                        if (PiratesConstants.AID.equalsIgnoreCase(p.getArtifactName())) {
                            if (p.isIsPrimaryOwner()) {
                                // logger.error("Match, assigning AID % to: " + p.getPercentageCompleteStr());
                                statusViewModel.setAIDPercentageComplete(p.getPercentageCompleteStr());
                                statusViewModel.setAIDDateCreated(p.getDateCreated());
                            }
                        }

                        // DES
                        if (PiratesConstants.DES.equalsIgnoreCase(p.getArtifactName())) {
                            if (p.isIsPrimaryOwner()) {
                                // logger.error("Match, assigning DES % to: " + p.getPercentageCompleteStr());
                                statusViewModel.setDESPercentageComplete(p.getPercentageCompleteStr());
                                statusViewModel.setDESDateCreated(p.getDateCreated());
                            }
                        }
                        // DEV
                        if (PiratesConstants.DEV.equalsIgnoreCase(p.getArtifactName())) {
                            if (p.isIsPrimaryOwner()) {
                                // logger.error("Match, assigning DEV % to: " + p.getPercentageCompleteStr());
                                statusViewModel.setDEVPercentageComplete(p.getPercentageCompleteStr());
                                statusViewModel.setDEVDateCreated(p.getDateCreated());
                            }
                        }
                        // IST
                        if (PiratesConstants.IST.equalsIgnoreCase(p.getArtifactName())) {
                            if (p.isIsPrimaryOwner()) {
                                // logger.error("Match, assigning IST % to: " + p.getPercentageCompleteStr());
                                statusViewModel.setISTPercentageComplete(p.getPercentageCompleteStr());
                                statusViewModel.setISTDateCreated(p.getDateCreated());
                            }
                        }
                        // ISTExec
                        if (PiratesConstants.ISTExec.equalsIgnoreCase(p.getArtifactName()) && impactType != 4) {
                            if (p.isIsPrimaryOwner()) {
                                // logger.error("Match, assigning ISTExec % to: " + p.getPercentageCompleteStr());
                                statusViewModel.setISTExecPercentageComplete(p.getPercentageCompleteStr());
                                statusViewModel.setISTExecDateCreated(p.getDateCreated());
                            }
                        }
                        // CloseOut
                        if (PiratesConstants.CLOSEOUT.equalsIgnoreCase(p.getArtifactName())) {
                            if (p.isIsPrimaryOwner()) {
                                // logger.error("Match, assigning CloseOut % to: " + p.getPercentageCompleteStr());
                                statusViewModel.setCloseOutPercentageComplete(p.getPercentageCompleteStr());
                                statusViewModel.setCODateCreated(p.getDateCreated());
                            }
                        }
                    } // end not agile
                } // end one application
            } // end for loop
        } // end check if results
        model.addAttribute("projectStatusViewModel", statusViewModel);
        model.addAttribute("applicationName", appName);
        model.addAttribute("prismId", prismId);
        model.addAttribute("applicationId", applicationId);

        return "addProjectStatusForm";
    }

    @RequestMapping(value = "/addProjectNotes", method = RequestMethod.GET)
    public String addProjectNotesForm(HttpServletRequest request, Model model) {
        // logger.error(msgHeader + "addProjectNotesForm called..");
        String prismId = request.getParameter("prismId");
        model.addAttribute("prismId", prismId);
        model.addAttribute("projectApplications", DataService.getProjectApplications(prismId));

        // grab loginuser from session
        try {
            String sessionUser = (String) request.getSession().getAttribute("loginUser");

            if (sessionUser == null || sessionUser.isEmpty() || "Not Logged In".equalsIgnoreCase(sessionUser)) {
                request.getSession().setAttribute("loginUser", "Not Logged In");
                logger.error("[Merce]: user not logged in.. redirecting to logout page");
                return "redirect:/logout";
            }
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            ProjectNoteViewModel noteViewModel = new ProjectNoteViewModel();
            noteViewModel.setCreatedBy(sessionUser);
            noteViewModel.setPrismId(prismId);
            noteViewModel.setNoteType(0);
            noteViewModel.setDateCreated(format.format(Calendar.getInstance().getTime()));

            model.addAttribute("projectNoteViewModel", noteViewModel);

        } catch (NullPointerException ex) {
            request.getSession().setAttribute("loginUser", "Not Logged In");
            logger.error("[Merce]: user not logged in.. redirecting to logout page");
            return "redirect:/logout";
        }

        return "addProjectNoteForm";
    }

    // updateprojectpersonnelform
    @RequestMapping(value = "/updateProjectPersonnel", method = RequestMethod.GET)
    public String updateProjectPersonnel(HttpServletRequest request, Model model) {
        String id = request.getParameter("id");
        String prismId = request.getParameter("prismId");
        int applicationId = Integer.parseInt(id);
        String appName = DataService.getApplicationNameByPrismIdApplicationId(applicationId, prismId);
        ProjectDetailsPersonnelModelView mvp = new ProjectDetailsPersonnelModelView();
        List<ProjectDetailsPersonnelModelView> mvPersonnel = getProjectDetailsPersonnelViewModel(prismId);
        if (mvPersonnel == null || mvPersonnel.isEmpty()) {
            mvp = new ProjectDetailsPersonnelModelView();
        } else {
            // locate the correct application to update/modify
            ProjectDetailsPersonnelModelView filledMVS = null;
            for (ProjectDetailsPersonnelModelView v : mvPersonnel) {
                if (v.getApplicationName().equalsIgnoreCase(appName)) {
                    filledMVS = v;
                    break;
                }
            }

            if (filledMVS == null) {
                filledMVS = mvPersonnel.get(0);
            }

            // mvp.setModule(filledMVS.getModule().split(",")[0]);
            String[] ms = filledMVS.getModules();
            if (ms != null && ms.length > 0) {
                // mvp.setModules(ms);
                List<Integer> mIds = new ArrayList<Integer>();
                for (String i : ms) {
                    mIds.add(DataService.getModuleIdByName(i, appName));
                }

                List<String> newList = new ArrayList<String>(mIds.size());
                for (Integer myInt : mIds) {
                    newList.add(String.valueOf(myInt));
                }
                String[] mArray = newList.toArray(new String[newList.size()]);
                mvp.setModuleIds(mArray);
            }

            mvp.setModule(filledMVS.getModule().split(",")[0]);
            mvp.setModuleId(DataService.getModuleIdByName(filledMVS.getModule().split(",")[0], appName));
            mvp.setMethodology(filledMVS.getAgile() ? "Agile" : "Waterfall");
            mvp.setImpact(appName);
            mvp.setImpactTypeId(getImpactByName(filledMVS.getImpact().split(",")[0]));
            mvp.setBrDuedate(filledMVS.getBrDuedate());
            mvp.setSrDuedate(filledMVS.getSrDuedate());
            mvp.setHldDuedate(filledMVS.getHldDuedate());
            mvp.setAidDuedate(filledMVS.getAidDuedate());
            mvp.setDevDuedate(filledMVS.getDevDuedate());
            mvp.setDesDuedate(filledMVS.getDesDuedate());
            mvp.setIstDuedate(filledMVS.getIstDuedate());
            mvp.setIstExecDuedate(filledMVS.getIstExecDuedate());
            mvp.setCloseOutDuedate(filledMVS.getCloseOutDuedate());
            mvp.setAgileDuedate(filledMVS.getAgileDuedate());

            // added per Jason's request
            mvp.setAgileArtifactsu(filledMVS.getAgileArtifactsu());
            mvp.setBRu(filledMVS.getBRu());
            mvp.setSRu(filledMVS.getSRu());
            mvp.setHLDu(filledMVS.getHLDu());
            mvp.setAIDu(filledMVS.getAIDu());
            mvp.setDESu(filledMVS.getDESu());
            mvp.setDEVu(filledMVS.getDEVu());
            mvp.setISTu(filledMVS.getISTu());
            mvp.setIstExecu(filledMVS.getIstExecu());
            mvp.setCloseOutu(filledMVS.getCloseOutu());
            mvp.setImpactDescription(filledMVS.getImpactDescription());
        }

        model.addAttribute("prismId", prismId);
        model.addAttribute("applicationId", applicationId);
        model.addAttribute("applicationName", appName);
        model.addAttribute("ArtifactOwners", getATTEmployeesForApplication(prismId, appName));
        model.addAttribute("emptyProjectPersonnelViewModel", mvp);
        model.addAttribute("Methodology", getProjectMethodologies());
        model.addAttribute("Modules", DataService.getProjectModules(appName));
        model.addAttribute("Impacts", getProjectImpactTypes());
        model.addAttribute("elModules", Arrays.asList(mvp.getModuleIds()));

        return "updateProjectPersonnelForm";
    }

    public static boolean isStringInList(List<String> container, String element) {
        boolean rc = false;
        for (String i : container) {
            if (i.equalsIgnoreCase(element)) {
                rc = true;
                break;
            }
        }
        return rc;
    }

    public static List<Module> getProjectModulesEx(String applicationName) {
        return DataService.getProjectModulesEx(applicationName);
    }

    /*
    this controller action handles the POST request for update ProjectInfo section of the accordian
    the first / top section
    */
    @RequestMapping(value = "/updateProjectInfo/{prismId}", method = RequestMethod.POST)
    public String updateProjectInfo(@PathVariable("prismId") String prismId,
            @Valid @ModelAttribute("projectInfo") InsightProject projectInfo, BindingResult result) {
        if (result.hasErrors()) {
            logger.error("There are " + result.getErrorCount() + " errors..");
            FieldError er = result.getFieldError();
            logger.error("Field: " + er.getField() + " ErrorMsg: " + er.getDefaultMessage());
        } else {
            String es = HtmlUtils.htmlEscape(projectInfo.getProjectDescription());

            String status = projectInfo.getProjectStatus();
            String release = projectInfo.getReleaseName();
            String startdate = projectInfo.getProjectStartDate();
            String dueDate = projectInfo.getProjectDueDate();
            // lookup statusid and releaseid
            int statusId = DataService.getStatusIdByname(status);
            int releaseId = DataService.getReleaseIdByName(release);

            InsightProject prj = new InsightProject();
            prj.setPrismId(prismId);
            prj.setLeadPM(projectInfo.getLeadPM());
            prj.setProjectDescription(es);
            prj.setProjectDueDate(dueDate);
            prj.setProjectName(HtmlUtils.htmlEscape(projectInfo.getProjectName()));
            prj.setProjectStartDate(startdate);
            prj.setStatudId(statusId);
            prj.setProjectStatus(status);
            prj.setReleaseName(release);
            prj.setReleaseId(releaseId);

            boolean rc = DataService.updateProjectInfo(prj);
            if (!rc) {
                logger.error("DataService.updateProjectInfo(prj); failed");
            }
        }
        // prismId will be considered while expanding the placeholders
        // return "redirect:/impact_pirates/projects/index/{prismId}";
        return "redirect:/projects/index/{prismId}";
    }

    @RequestMapping(value = "/addProjectStatus/{prismId}/{applicationId}", method = RequestMethod.POST)
    public String addProjectStatus(@PathVariable("prismId") String prismId,
            @PathVariable("applicationId") String applicationId,
            @Valid @ModelAttribute("projectStatusViewModel") ProjectStatusViewModel projectStatusViewModel,
            HttpServletRequest request, BindingResult result) {
        String sessionUser = (String) request.getSession().getAttribute("loginUser");
        if (sessionUser == null || sessionUser.isEmpty() || "Not Logged In".equalsIgnoreCase(sessionUser)) {
            request.getSession().setAttribute("loginUser", "Not Logged In");
            logger.error("[Merce]: user not logged in.. redirecting to logout page");
            return "redirect:/logout";
        }

        NumberFormat defaultFormat = NumberFormat.getPercentInstance();
        defaultFormat.setMinimumFractionDigits(0);
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
        int appId = Integer.parseInt(applicationId);
        String appName = DataService.getApplicationNameByPrismIdApplicationId(appId, prismId);
        int impactTypeId = DataService.getImpactTypeIdByPrismIdAndApplicationName(prismId, appName);

        if (result.hasErrors()) {
            StringBuilder sb = new StringBuilder();
            for (ObjectError r : result.getAllErrors()) {
                sb.append(r.getDefaultMessage());
            }
            logger.error(msgHeader + " addProjectStatus errors: " + sb.toString());
        }

        // refresh cahce?
        if (artifactHistory != null) {
            artifactHistory = null;
        }
        DataService.initializeProjectAppOwnerByPrismId(prismId);

        // TO
        if (impactTypeId != 3 && impactTypeId != 4) {
            // prefix. Agile
            if (projectStatusViewModel.getAgilePercentageComplete() == null
                    || projectStatusViewModel.getAgilePercentageComplete().isEmpty()) {
                logger.error(msgHeader + " addProjectStatus Agile is not set, so keep record in database as is.");
            } else {
                logger.error(msgHeader + " addProjectStatus Agile is set, updateing ..");

                ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                        prismId, Integer.valueOf(applicationId), PiratesConstants.AGILE);
                if (mod != null && !mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(
                                Double.parseDouble(projectStatusViewModel.getAgilePercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getAgilePercentageComplete())))) {
                    ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                    // now change the percentage completed to user input value
                    mod.setPercentageComplete(projectStatusViewModel.getAgilePercentageComplete());

                    // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                    try {
                        if (projectStatusViewModel.getAgilePercentageComplete().equalsIgnoreCase("1.00")
                                && !sdf.format(sdf.parse(projectStatusViewModel.getAgileDateCreatedT()))
                                        .equals(sdf.format(new Date()))) {
                            logger.error(
                                    "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                            + projectStatusViewModel.getAgileDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getAgileDateCreatedT());
                        } else {
                            logger.error("User chooses to use today as datecreated, using it .. "
                                    + projectStatusViewModel.getAgileDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getAgileDateCreatedT());
                        }
                    } catch (ParseException ex) {
                        logger.error(msgHeader + ex.getMessage());
                    }

                    DataService.processProjectStatusForArtifact(mod, PiratesConstants.AGILE, sessionUser, p);
                } else {
                    if (mod != null && mod.getPercentageComplete()
                            .equalsIgnoreCase(defaultFormat.format(Double
                                    .parseDouble(projectStatusViewModel.getAgilePercentageComplete() == null ? "0"
                                            : projectStatusViewModel.getAgilePercentageComplete())))) {
                        logger.error("Agile has same value as in the DB, ignoring..");
                    } else {
                        logger.error(
                                "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                    }
                }
            }

            // 1. BR
            if (projectStatusViewModel.getBRPercentageComplete() == null
                    || projectStatusViewModel.getBRPercentageComplete().isEmpty()) {
                logger.error(msgHeader + " addProjectStatus BR is not set, so keep record in database as is.");
            } else {
                logger.error(msgHeader + " addProjectStatus BR is set, updateing ..");

                ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                        prismId, Integer.valueOf(applicationId), PiratesConstants.BR);
                if (mod != null && !mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(
                                Double.parseDouble(projectStatusViewModel.getBRPercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getBRPercentageComplete())))) {
                    ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                    // now change the percentage completed to user input value
                    mod.setPercentageComplete(projectStatusViewModel.getBRPercentageComplete());

                    // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                    try {
                        if (projectStatusViewModel.getBRPercentageComplete().equalsIgnoreCase("1.00")
                                && !sdf.format(sdf.parse(projectStatusViewModel.getBRDateCreatedT()))
                                        .equals(sdf.format(new Date()))) {
                            logger.error(
                                    "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                            + projectStatusViewModel.getBRDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getBRDateCreatedT());

                        } else {
                            logger.error("User chooses to use today as datecreated, using it .. "
                                    + projectStatusViewModel.getBRDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getBRDateCreatedT());
                        }
                    } catch (ParseException ex) {
                        logger.error(msgHeader + ex.getMessage());
                    }

                    DataService.processProjectStatusForArtifact(mod, PiratesConstants.BR, sessionUser, p);
                } else {
                    if (mod != null && mod.getPercentageComplete()
                            .equalsIgnoreCase(defaultFormat.format(Double
                                    .parseDouble(projectStatusViewModel.getBRPercentageComplete() == null ? "0"
                                            : projectStatusViewModel.getBRPercentageComplete())))) {
                        logger.error("BR has same value as in the DB, ignoring..");
                    } else {
                        logger.error(
                                "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                    }
                }
            }

            // 2. SR
            if (projectStatusViewModel.getSRPercentageComplete() == null
                    || projectStatusViewModel.getSRPercentageComplete().isEmpty()) {
                logger.error(msgHeader + " addProjectStatus SR is not set, so keep record in database as is.");
            } else {
                logger.error(msgHeader + " addProjectStatus SR is set, updateing ..");
                ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                        prismId, Integer.valueOf(applicationId), PiratesConstants.SR);
                if (mod != null && !mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(
                                Double.parseDouble(projectStatusViewModel.getSRPercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getSRPercentageComplete())))) {
                    ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                    // now change the percentage completed to user input value
                    mod.setPercentageComplete(projectStatusViewModel.getSRPercentageComplete());

                    // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                    try {
                        if (projectStatusViewModel.getSRPercentageComplete().equalsIgnoreCase("1.00")
                                && !sdf.format(sdf.parse(projectStatusViewModel.getSRDateCreatedT()))
                                        .equals(sdf.format(new Date()))) {
                            logger.error(
                                    "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                            + projectStatusViewModel.getSRDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getSRDateCreatedT());

                        } else {
                            logger.error("User chooses to use today as datecreated, using it .. "
                                    + projectStatusViewModel.getSRDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getSRDateCreatedT());
                        }
                    } catch (ParseException ex) {
                        logger.error(msgHeader + ex.getMessage());
                    }

                    DataService.processProjectStatusForArtifact(mod, PiratesConstants.SR, sessionUser, p);
                } else {
                    if (mod != null && mod.getPercentageComplete()
                            .equalsIgnoreCase(defaultFormat.format(Double
                                    .parseDouble(projectStatusViewModel.getSRPercentageComplete() == null ? "0"
                                            : projectStatusViewModel.getSRPercentageComplete())))) {
                        logger.error("SR has same value as in the DB, ignoring..");
                    } else {
                        logger.error(
                                "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                    }

                }
            }

            // 3. HLD
            if (projectStatusViewModel.getHLDPercentageComplete() == null
                    || projectStatusViewModel.getHLDPercentageComplete().isEmpty()) {
                logger.error(msgHeader + " addProjectStatus HLD is not set, so keep record in database as is.");
            } else {
                logger.error(
                        msgHeader + " addProjectStatus HLD is set, updateing .. " + prismId + ", " + applicationId);
                ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                        prismId, Integer.valueOf(applicationId), PiratesConstants.HLD);
                if (mod != null && !mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(
                                Double.parseDouble(projectStatusViewModel.getHLDPercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getHLDPercentageComplete())))) {
                    ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                    // now change the percentage completed to user input value
                    mod.setPercentageComplete(projectStatusViewModel.getHLDPercentageComplete());

                    // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                    try {
                        if (projectStatusViewModel.getHLDPercentageComplete().equalsIgnoreCase("1.00")
                                && !sdf.format(sdf.parse(projectStatusViewModel.getHLDDateCreatedT()))
                                        .equals(sdf.format(new Date()))) {
                            logger.error(
                                    "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                            + projectStatusViewModel.getHLDDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getHLDDateCreatedT());

                        } else {
                            logger.error("User chooses to use today as datecreated, using it .. "
                                    + projectStatusViewModel.getHLDDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getHLDDateCreatedT());
                        }
                    } catch (ParseException ex) {
                        logger.error(msgHeader + ex.getMessage());
                    }

                    DataService.processProjectStatusForArtifact(mod, PiratesConstants.HLD, sessionUser, p);
                } else {
                    if (mod != null && mod.getPercentageComplete()
                            .equalsIgnoreCase(defaultFormat.format(Double
                                    .parseDouble(projectStatusViewModel.getHLDPercentageComplete() == null ? "0"
                                            : projectStatusViewModel.getHLDPercentageComplete())))) {
                        logger.error("HLD has same value as in the DB, ignoring..");
                    } else {
                        logger.error(
                                "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                    }
                }
            }

            // 4. AID
            if (projectStatusViewModel.getAIDPercentageComplete() == null
                    || projectStatusViewModel.getAIDPercentageComplete().isEmpty()) {
                logger.error(msgHeader + " addProjectStatus AID is not set, so keep record in database as is.");
            } else {
                logger.error(msgHeader + " addProjectStatus AID is set, updateing ..");
                ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                        prismId, Integer.valueOf(applicationId), PiratesConstants.AID);
                if (mod != null && !mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(
                                Double.parseDouble(projectStatusViewModel.getAIDPercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getAIDPercentageComplete())))) {
                    ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                    // now change the percentage completed to user input value
                    mod.setPercentageComplete(projectStatusViewModel.getAIDPercentageComplete());

                    // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                    try {
                        if (projectStatusViewModel.getAIDPercentageComplete().equalsIgnoreCase("1.00")
                                && !sdf.format(sdf.parse(projectStatusViewModel.getAIDDateCreatedT()))
                                        .equals(sdf.format(new Date()))) {
                            logger.error(
                                    "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                            + projectStatusViewModel.getAIDDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getAIDDateCreatedT());

                        } else {
                            logger.error("User chooses to use today as datecreated, using it .. "
                                    + projectStatusViewModel.getAIDDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getAIDDateCreatedT());
                        }
                    } catch (ParseException ex) {
                        logger.error(msgHeader + ex.getMessage());
                    }

                    DataService.processProjectStatusForArtifact(mod, PiratesConstants.AID, sessionUser, p);
                } else {
                    if (mod != null && mod.getPercentageComplete()
                            .equalsIgnoreCase(defaultFormat.format(Double
                                    .parseDouble(projectStatusViewModel.getAIDPercentageComplete() == null ? "0"
                                            : projectStatusViewModel.getAIDPercentageComplete())))) {
                        logger.error("AID has same value as in the DB, ignoring..");
                    } else {
                        logger.error(
                                "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                    }
                }
            }

            // 5. DES
            if (projectStatusViewModel.getDESPercentageComplete() == null
                    || projectStatusViewModel.getDESPercentageComplete().isEmpty()) {
                logger.error(msgHeader + " addProjectStatus DES is not set, so keep record in database as is.");
            } else {
                logger.error(msgHeader + " addProjectStatus DES is set, updateing ..");
                ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                        prismId, Integer.valueOf(applicationId), PiratesConstants.DES);
                if (mod != null && !mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(
                                Double.parseDouble(projectStatusViewModel.getDESPercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getDESPercentageComplete())))) {
                    ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                    // now change the percentage completed to user input value
                    mod.setPercentageComplete(projectStatusViewModel.getDESPercentageComplete());

                    // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                    try {
                        if (projectStatusViewModel.getDESPercentageComplete().equalsIgnoreCase("1.00")
                                && !sdf.format(sdf.parse(projectStatusViewModel.getDESDateCreatedT()))
                                        .equals(sdf.format(new Date()))) {
                            logger.error(
                                    "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                            + projectStatusViewModel.getDESDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getDESDateCreatedT());

                        } else {
                            logger.error("User chooses to use today as datecreated, using it .. "
                                    + projectStatusViewModel.getDESDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getDESDateCreatedT());
                        }
                    } catch (ParseException ex) {
                        logger.error(msgHeader + ex.getMessage());
                    }

                    DataService.processProjectStatusForArtifact(mod, PiratesConstants.DES, sessionUser, p);
                } else {
                    if (mod != null && mod.getPercentageComplete()
                            .equalsIgnoreCase(defaultFormat.format(Double
                                    .parseDouble(projectStatusViewModel.getDESPercentageComplete() == null ? "0"
                                            : projectStatusViewModel.getDESPercentageComplete())))) {
                        logger.error("DES has same value as in the DB, ignoring..");
                    } else {
                        logger.error(
                                "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                    }
                }
            }

            // 6. DEV
            if (projectStatusViewModel.getDEVPercentageComplete() == null
                    || projectStatusViewModel.getDEVPercentageComplete().isEmpty()) {
                logger.error(msgHeader + " addProjectStatus DEV is not set, so keep record in database as is.");
            } else {
                logger.error(msgHeader + " addProjectStatus DEV is set, updateing ..");
                ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                        prismId, Integer.valueOf(applicationId), PiratesConstants.DEV);
                if (mod != null && !mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(
                                Double.parseDouble(projectStatusViewModel.getDEVPercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getDEVPercentageComplete())))) {
                    ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                    // now change the percentage completed to user input value
                    mod.setPercentageComplete(projectStatusViewModel.getDEVPercentageComplete());

                    // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                    try {
                        if (projectStatusViewModel.getDEVPercentageComplete().equalsIgnoreCase("1.00")
                                && !sdf.format(sdf.parse(projectStatusViewModel.getDEVDateCreatedT()))
                                        .equals(sdf.format(new Date()))) {
                            logger.error(
                                    "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                            + projectStatusViewModel.getDEVDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getDEVDateCreatedT());

                        } else {
                            logger.error("User chooses to use today as datecreated, using it .. "
                                    + projectStatusViewModel.getDEVDateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getDEVDateCreatedT());
                        }
                    } catch (ParseException ex) {
                        logger.error(msgHeader + ex.getMessage());
                    }

                    DataService.processProjectStatusForArtifact(mod, PiratesConstants.DEV, sessionUser, p);
                } else {
                    if (mod != null && mod.getPercentageComplete()
                            .equalsIgnoreCase(defaultFormat.format(Double
                                    .parseDouble(projectStatusViewModel.getDEVPercentageComplete() == null ? "0"
                                            : projectStatusViewModel.getDEVPercentageComplete())))) {
                        logger.error("DEV has same value as in the DB, ignoring..");
                    } else {
                        logger.error(
                                "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                    }
                }
            }

        } // end not impacttypeid = 3, to and tso 4

        // 7. IST
        if (projectStatusViewModel.getISTPercentageComplete() == null
                || projectStatusViewModel.getISTPercentageComplete().isEmpty()) {
            logger.error(msgHeader + " addProjectStatus IST is not set, so keep record in database as is.");
        } else {
            logger.error(msgHeader + " addProjectStatus IST is set, updateing ..");
            ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                    prismId, Integer.valueOf(applicationId), PiratesConstants.IST);
            if (mod != null && !mod.getPercentageComplete()
                    .equalsIgnoreCase(defaultFormat.format(
                            Double.parseDouble(projectStatusViewModel.getISTPercentageComplete() == null ? "0"
                                    : projectStatusViewModel.getISTPercentageComplete())))) {
                ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                // now change the percentage completed to user input value
                mod.setPercentageComplete(projectStatusViewModel.getISTPercentageComplete());

                // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                try {
                    if (projectStatusViewModel.getISTPercentageComplete().equalsIgnoreCase("1.00")
                            && !sdf.format(sdf.parse(projectStatusViewModel.getISTDateCreatedT()))
                                    .equals(sdf.format(new Date()))) {
                        logger.error(
                                "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                        + projectStatusViewModel.getISTDateCreatedT());
                        mod.setDateCreated(projectStatusViewModel.getISTDateCreatedT());

                    } else {
                        logger.error("User chooses to use today as datecreated, using it .. "
                                + projectStatusViewModel.getISTDateCreatedT());
                        mod.setDateCreated(projectStatusViewModel.getISTDateCreatedT());
                    }
                } catch (ParseException ex) {
                    logger.error(msgHeader + ex.getMessage());
                }

                DataService.processProjectStatusForArtifact(mod, PiratesConstants.IST, sessionUser, p);
            } else {
                if (mod != null && mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(
                                Double.parseDouble(projectStatusViewModel.getISTPercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getISTPercentageComplete())))) {
                    logger.error("IST has same value as in the DB, ignoring..");
                } else {
                    logger.error(
                            "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                }
            }
        }

        // 8. ISTExec
        if (projectStatusViewModel.getISTExecPercentageComplete() == null
                || projectStatusViewModel.getISTExecPercentageComplete().isEmpty()) {
            logger.error(msgHeader + " addProjectStatus ISTExec is not set, so keep record in database as is.");
        } else {
            logger.error(msgHeader + " addProjectStatus ISTExec is set, updateing ..");
            ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                    prismId, Integer.valueOf(applicationId), PiratesConstants.ISTExec);
            if (mod != null && !mod.getPercentageComplete()
                    .equalsIgnoreCase(defaultFormat.format(
                            Double.parseDouble(projectStatusViewModel.getISTExecPercentageComplete() == null ? "0"
                                    : projectStatusViewModel.getISTExecPercentageComplete())))) {
                ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                // now change the percentage completed to user input value
                mod.setPercentageComplete(projectStatusViewModel.getISTExecPercentageComplete());

                // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                try {
                    if (projectStatusViewModel.getISTExecPercentageComplete().equalsIgnoreCase("1.00")
                            && !sdf.format(sdf.parse(projectStatusViewModel.getISTExecDateCreatedT()))
                                    .equals(sdf.format(new Date()))) {
                        logger.error(
                                "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                        + projectStatusViewModel.getISTExecDateCreatedT());
                        mod.setDateCreated(projectStatusViewModel.getISTExecDateCreatedT());

                    } else {
                        logger.error("User chooses to use today as datecreated, using it .. "
                                + projectStatusViewModel.getISTExecDateCreatedT());
                        mod.setDateCreated(projectStatusViewModel.getISTExecDateCreatedT());
                    }
                } catch (ParseException ex) {
                    logger.error(msgHeader + ex.getMessage());
                }

                DataService.processProjectStatusForArtifact(mod, PiratesConstants.ISTExec, sessionUser, p);
            } else {
                if (mod != null && mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(Double
                                .parseDouble(projectStatusViewModel.getISTExecPercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getISTExecPercentageComplete())))) {
                    logger.error("ISTExec has same value as in the DB, ignoring..");
                } else {
                    logger.error(
                            "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                }
            }
        }

        if (impactTypeId != 3 && impactTypeId != 4) {
            // 8. CloseOut
            if (projectStatusViewModel.getCloseOutPercentageComplete() == null
                    || projectStatusViewModel.getCloseOutPercentageComplete().isEmpty()) {
                logger.error(
                        msgHeader + " addProjectStatus Closeout is not set, so keep record in database as is.");
            } else {
                logger.error(msgHeader + " addProjectStatus Closeout is set, updateing ..");
                ProjectAppOwnerModel mod = DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner(
                        prismId, Integer.valueOf(applicationId), PiratesConstants.CLOSEOUT);
                if (mod != null && !mod.getPercentageComplete()
                        .equalsIgnoreCase(defaultFormat.format(Double
                                .parseDouble(projectStatusViewModel.getCloseOutPercentageComplete() == null ? "0"
                                        : projectStatusViewModel.getCloseOutPercentageComplete())))) {
                    ProjectAppOwnerModel p = cloneProjectAppOwnerModel(mod);
                    // now change the percentage completed to user input value
                    mod.setPercentageComplete(projectStatusViewModel.getCloseOutPercentageComplete());

                    // check if percentcomplete user entered is 100%, if so, check if the datecreated has been changed to an earlier date
                    try {
                        if (projectStatusViewModel.getCloseOutPercentageComplete().equalsIgnoreCase("1.00")
                                && !sdf.format(sdf.parse(projectStatusViewModel.getCODateCreatedT()))
                                        .equals(sdf.format(new Date()))) {
                            logger.error(
                                    "100% complete and user changed datecreated to a date that's other than today, using this date instead of today.. "
                                            + projectStatusViewModel.getCODateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getCODateCreatedT());

                        } else {
                            logger.error("User chooses to use today as datecreated, using it .. "
                                    + projectStatusViewModel.getCODateCreatedT());
                            mod.setDateCreated(projectStatusViewModel.getCODateCreatedT());
                        }
                    } catch (ParseException ex) {
                        logger.error(msgHeader + ex.getMessage());
                    }

                    DataService.processProjectStatusForArtifact(mod, PiratesConstants.CLOSEOUT, sessionUser, p);
                } else {
                    if (mod != null && mod.getPercentageComplete()
                            .equalsIgnoreCase(defaultFormat.format(Double.parseDouble(
                                    projectStatusViewModel.getCloseOutPercentageComplete() == null ? "0"
                                            : projectStatusViewModel.getCloseOutPercentageComplete())))) {
                        logger.error("CloseOut has same value as in the DB, ignoring..");
                    } else {
                        logger.error(
                                "addProjectStatus error DataService.getProjectAppOwnerByPrismIdAppNameArtifactNamePrimaryOwner returned null");
                    }
                }
            }
        } // end  && impactTypeId != 4 (TSO) &&  && impactTypeId != 3 (TO)

        // prismId will be considered while expanding the placeholders
        // return "redirect:/impact_pirates/projects/index/{prismId}";
        if (artifactHistory != null) {
            artifactHistory = null;
        }
        DataService.initializeProjectAppOwnerByPrismId(prismId);
        return "redirect:/projects/index/{prismId}";
    }

    private ProjectAppOwnerModel cloneProjectAppOwnerModel(ProjectAppOwnerModel mod) {
        ProjectAppOwnerModel p = new ProjectAppOwnerModel();
        p.setUUID(mod.getUUID());
        p.setCompletionDate(mod.getCompletionDate());
        p.setPercentageComplete(mod.getPercentageComplete());
        p.setArtifactName(mod.getArtifactName());
        p.setApplicationName(mod.getApplicationName());
        p.setPrismId(mod.getPrismId());
        p.setModuleId(mod.getModuleId());
        p.setIsPrimaryOwner(mod.isIsPrimaryOwner());
        p.setMileStoneId(mod.getMileStoneId());
        p.setExecutionPercentage(mod.getExecutionPercentage());
        p.setProjectCloseOutPercentage(mod.getProjectCloseOutPercentage());
        p.setDateCreated(mod.getDateCreated());
        p.setUpdatedByUUID(mod.getUpdatedByUUID());
        p.setSystemNote(mod.getSystemNote());
        p.setApplicationId(mod.getApplicationId());
        p.setDueDate(mod.getDueDate());
        return p;
    }

    private static void processProjectAppOwners(List<ProjectAppOwnerModel> existingOwners,
            List<ProjectAppOwnerModel> userSelectedOwners, String prismId, String applicationId, String[] uuids,
            String artifactName, String moduleId, String UUID, String dueDateForArtifact) {

        existingOwners.clear();
        existingOwners.addAll(DataService.getProjectAppOwnersByPrismIdAppNameAndArtifactName(prismId,
                Integer.parseInt(applicationId), artifactName));
        userSelectedOwners.clear();

        { // build userSelected list from string[]
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String today = format.format(Calendar.getInstance().getTime());

            for (String s : uuids) {
                ProjectAppOwnerModel t = new ProjectAppOwnerModel();
                t.setPrismId(prismId);
                t.setApplicationId(applicationId);
                t.setApplicationName(DataService
                        .getApplicationNameByPrismIdApplicationId(Integer.parseInt(applicationId), prismId));
                t.setUUID(s);
                t.setModuleId(moduleId);
                t.setMileStoneId(DataService.getMileStoneIdByArtifactName(artifactName));
                t.setArtifactName(artifactName);
                t.setDueDate(dueDateForArtifact);
                t.setDateCreated(today);
                t.setUpdatedByUUID(UUID);
                userSelectedOwners.add(t);
            }

            // find to be inserted rows (in userSelectedOwners but not in existingOwners)
            for (ProjectAppOwnerModel owner : userSelectedOwners) {
                boolean found = false;

                for (ProjectAppOwnerModel i : existingOwners) {
                    if (owner.getApplicationId().equalsIgnoreCase(i.getApplicationId())
                            && owner.getArtifactName().equalsIgnoreCase(i.getArtifactName())
                            && owner.getPrismId().equalsIgnoreCase(i.getPrismId())
                            && owner.getUUID().equalsIgnoreCase(i.getUUID())) {
                        // no match, we need to add
                        found = true;
                        break;
                    }
                } // end for each existing owner
                owner.setIsNew(!found);
            } // end for each BRu

            // find rows to be deleted (in existing but not in userselected)
            for (ProjectAppOwnerModel o : existingOwners) {
                // isnew here means to be deleted
                boolean found = false;

                for (ProjectAppOwnerModel i : userSelectedOwners) {
                    if (o.getApplicationId().equalsIgnoreCase(i.getApplicationId())
                            && o.getArtifactName().equalsIgnoreCase(i.getArtifactName())
                            && o.getPrismId().equalsIgnoreCase(i.getPrismId())
                            && o.getUUID().equalsIgnoreCase(i.getUUID())) {
                        // match existing, no need to insert, do nothing
                        found = true;
                        break;
                    }
                } // end for each userSelected 
                o.setIsNew(!found);
            } // end for each existing
        } // end dynamic code block for BR
    }

    private static void displayProjectAppOwnerResults(List<ProjectAppOwnerModel> existingOwners,
            List<ProjectAppOwnerModel> userSelectedOwners, String artifactName) {
        // disabled.  this only logs info
        // to enable set f to false
        boolean f = true;
        if (f) {
            return;
        }

        // display to be inserted
        for (ProjectAppOwnerModel o : userSelectedOwners) {
            if (o.getIsNew()) {
                logger.error(
                        msgHeader + " userSelectedOwners " + artifactName + " " + o.getUUID() + " is tobe added..");
            } else {
                // logger.error(msgHeader + " userSelectedOwners "+ artifactName + " " + o.getUUID() + " isnot new..");
            }
        }

        // display to be deleted
        for (ProjectAppOwnerModel o : existingOwners) {
            if (o.getIsNew()) {
                logger.error(
                        msgHeader + " existingOwners " + artifactName + " " + o.getUUID() + " is tobe deleted..");
            } else {
                logger.error(
                        msgHeader + " existingOwners " + artifactName + " " + o.getUUID() + " is tobe updated..");
            }
        }

    }

    private void processProjectAppOwnersByArtifactName(List<ProjectAppOwnerModel> existingOwners,
            List<ProjectAppOwnerModel> userSelectedOwners, String artifactName, String dueDateForArtifact,
            String UUID, int impactId) {
        if (impactId == 4 && artifactName.equalsIgnoreCase(PiratesConstants.ISTExec)) {
            return;
        }

        Connection con = null;
        PreparedStatement updateRow = null;
        PreparedStatement deleteRow = null;
        PreparedStatement insertRow = null;
        PreparedStatement syncRow = null;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String today = format.format(Calendar.getInstance().getTime());

        String insertSQL = " INSERT INTO [AppProjectArtifactOwners] " + "           ([UUID] "
                + "           ,[DueDate] " + "           ,[ArtifactName] " + "           ,[PRISMId] "
                + "           ,[ApplicationName] " + "           ,[ModuleId] " + "           ,[IsPrimaryOwner] "
                + "           ,[MileStoneId] " + "           ,[DateCreated] " + "           ,[UpdatedByUUID] "
                + "           ,[SystemNote]) " + "     VALUES " + "           ( ?,?,?,?,?,?,?,?,?,?,?)  ";

        String updateSQL = " UPDATE AppProjectArtifactOwners " + "   SET DueDate = ? " + "      ,UpdatedByUUID = ? "
                + "      ,SystemNote = ? " + "       WHERE  "
                + "   UUID = ? and ArtifactName = ? and PRISMId = ? and ApplicationName = ? and ModuleId = ? and MileStoneId = ? ";

        String deleteSQL = " DELETE FROM AppProjectArtifactOwners " + "       WHERE  "
                + "   UUID = ? and ArtifactName = ? and PRISMId = ? and ApplicationName = ? and ModuleId = ? and MileStoneId = ? ";

        // we need to make sure duedates for each artifact for all applications in this project
        // to be in sync
        String syncSQL = " Update a " + " Set a.duedate = t.duedate " + " from AppProjectArtifactOwners a "
                + " join " + " ( " + " select prismid, applicationname, artifactname, duedate "
                + " from AppProjectArtifactOwners " + " Where artifactname = ? and prismid = ? "
                + " And applicationname = ? " + " and isprimaryowner = 1 " + " ) t "
                + " on a.prismid=t.prismid and a.artifactname=t.artifactname "
                + " and a.applicationname <> t.applicationname " + " where a.isprimaryowner = 1 ";

        try {
            List<String> artifactNames = new ArrayList<String>();
            String prismId = "";
            String applicationName = "";

            con = DBUtility.getDBConnection();
            con.setAutoCommit(false);
            insertRow = con.prepareStatement(insertSQL);
            // inserts
            boolean isAdd = false;
            for (ProjectAppOwnerModel o : userSelectedOwners) {
                if (o.getIsNew()) {
                    if (!isAdd)
                        isAdd = true;
                    logger.error(msgHeader + " userSelectedOwners " + artifactName + " " + o.getUUID()
                            + " is being added..");
                    insertRow.setString(1, o.getUUID());
                    insertRow.setString(2, o.getDueDate());
                    insertRow.setString(3, o.getArtifactName());
                    insertRow.setString(4, o.getPrismId());
                    insertRow.setString(5, o.getApplicationName());
                    insertRow.setInt(6, Integer.valueOf(o.getModuleId()));
                    insertRow.setInt(7, 1);
                    insertRow.setInt(8, Integer.valueOf(o.getMileStoneId()));
                    insertRow.setString(9, today);
                    insertRow.setString(10, o.getUpdatedByUUID());
                    insertRow.setString(11,
                            "Record created by " + o.getUpdatedByUUID() + " on " + o.getDateCreated());
                    insertRow.addBatch();

                    // update artifactNames list
                    if (!artifactNames.contains(o.getArtifactName())) {
                        artifactNames.add(o.getArtifactName());
                    }
                    if (prismId.isEmpty()) {
                        prismId = o.getPrismId();
                    }
                    if (applicationName.isEmpty()) {
                        applicationName = o.getApplicationName();
                    }
                }
            }
            if (isAdd)
                insertRow.executeBatch();
            if (!isAdd)
                logger.error(msgHeader + " processProjectAppOwnersByArtifactName.. nothing to insert");

            // updates
            boolean isUpdate = false;
            updateRow = con.prepareStatement(updateSQL);
            for (ProjectAppOwnerModel o : existingOwners) {
                if (o.getIsNew()) {
                    // do nothing here... 
                } else {
                    SimpleDateFormat yFormat = new SimpleDateFormat("MM/dd/yyyy");
                    Date userSelected = yFormat.parse(dueDateForArtifact);
                    Date existing = yFormat.parse(o.getDueDate());
                    if (existing.compareTo(userSelected) == 0) {
                        logger.error(msgHeader + " new duedate: " + dueDateForArtifact
                                + " is the same as existing duedate " + o.getDueDate()
                                + " , nothing to do here...");
                    } else {
                        if (!isUpdate)
                            isUpdate = true;
                        logger.error(msgHeader + " existingOwners " + artifactName + " " + o.getUUID()
                                + " is being updated..");
                        updateRow.setString(1, dueDateForArtifact);
                        updateRow.setString(2, UUID);
                        updateRow.setString(3, "Record updated by " + UUID + " on " + today);
                        updateRow.setString(4, o.getUUID());
                        updateRow.setString(5, o.getArtifactName());
                        updateRow.setString(6, o.getPrismId());
                        updateRow.setString(7, o.getApplicationName());
                        updateRow.setInt(8, Integer.valueOf(o.getModuleId()));
                        updateRow.setInt(9, Integer.valueOf(o.getMileStoneId()));
                        updateRow.addBatch();

                        // update artifactNames list
                        if (!artifactNames.contains(o.getArtifactName())) {
                            artifactNames.add(o.getArtifactName());
                        }
                        if (prismId.isEmpty()) {
                            prismId = o.getPrismId();
                        }
                        if (applicationName.isEmpty()) {
                            applicationName = o.getApplicationName();
                        }
                    }
                }
            }
            if (isUpdate)
                updateRow.executeBatch();
            if (!isUpdate)
                logger.error(msgHeader + " processProjectAppOwnersByArtifactName.. nothing to update");

            // deletes
            boolean isDelete = false;
            deleteRow = con.prepareStatement(deleteSQL);
            for (ProjectAppOwnerModel o : existingOwners) {
                if (o.getIsNew()) {
                    if (!isDelete)
                        isDelete = true;
                    logger.error(msgHeader + " existingOwners " + artifactName + " " + o.getUUID()
                            + " is being deleted..");
                    deleteRow.setString(1, o.getUUID());
                    deleteRow.setString(2, o.getArtifactName());
                    deleteRow.setString(3, o.getPrismId());
                    deleteRow.setString(4, o.getApplicationName());
                    deleteRow.setInt(5, Integer.valueOf(o.getModuleId()));
                    deleteRow.setInt(6, Integer.valueOf(o.getMileStoneId()));

                    deleteRow.addBatch();
                } else {
                    // do nothing here
                }
            }
            if (isDelete)
                deleteRow.executeBatch();
            if (!isDelete)
                logger.error(msgHeader + " processProjectAppOwnersByArtifactName.. nothing to delete");

            if (isAdd || isUpdate || isDelete) {
                // sync up same artifact, same project different application's due dates
                if (!artifactNames.isEmpty()) {
                    syncRow = con.prepareStatement(syncSQL);
                    for (String a : artifactNames) {
                        logger.error("Setting syncup parameters.. artifactname: " + a + ", prismId: " + prismId
                                + ", applicationName: " + applicationName);
                        syncRow.setString(1, a);
                        syncRow.setString(2, prismId);
                        syncRow.setString(3, applicationName);
                        syncRow.addBatch();
                    }
                    syncRow.executeBatch();
                }

                con.commit();
            } else {
                logger.error(msgHeader + " processProjectAppOwnersByArtifactName.. nothing to commit");
            }

        } catch (SQLException e) {
            if (con != null) {
                try {
                    logger.error(e.getMessage()
                            + ", processProjectAppOwnersByArtifactName.. Transaction is being rolled back.. "
                            + e.getMessage());
                    con.rollback();
                } catch (SQLException excep) {
                    logger.error(excep.getMessage()
                            + ", processProjectAppOwnersByArtifactName.. Transaction is being rolled back.."
                            + excep.getMessage());
                    try {
                        con.rollback();
                    } catch (SQLException logOrIgnore) {
                    }
                }
            }
        } catch (Exception ex) {
            logger.error(ex + ", processProjectAppOwnersByArtifactName.. Transaction is being rolled back.."
                    + ex.getMessage());
            try {
                con.rollback();
            } catch (SQLException logOrIgnore) {
            }
        } finally {
            if (updateRow != null) {
                try {
                    updateRow.close();
                } catch (SQLException e) {
                }
            }
            if (deleteRow != null) {
                try {
                    deleteRow.close();
                } catch (SQLException e) {
                }
            }
            if (insertRow != null) {
                try {
                    insertRow.close();
                } catch (SQLException e) {
                }
            }
            if (con != null) {
                try {
                    con.setAutoCommit(true);
                    con.close();
                } catch (SQLException logOrIgnore) {
                }
            }
        }
    }

    @RequestMapping(value = "/updateProjectPersonnel/{prismId}/{applicationId}", method = RequestMethod.POST)
    public String updateProjectPersonnels(@PathVariable("prismId") String prismId,
            @PathVariable("applicationId") String applicationId,
            @Valid @ModelAttribute("projectPersonnelsModelView") ProjectDetailsPersonnelModelView projectPersonnelModelView,
            HttpServletRequest request, BindingResult result) {

        if (result.hasErrors()) {
            // should return to original page with errors, but the original page is a popup!
            logger.error(msgHeader + " updateProjectPersonnels errors?: " + result.hasErrors());
        }
        // process projectapplicationModules
        String appname = DataService.getApplicationNameByPrismIdApplicationId(Integer.parseInt(applicationId),
                prismId);
        ProjectApplicationModule mod = DataService.getProjectAppModuleByPrismIdApplName(prismId, appname);

        // delete the app from project if user selects chkDelAppFromPrj
        if (request.getParameter("chkDelAppFromPrj") != null
                && request.getParameter("chkDelAppFromPrj").equalsIgnoreCase("Yes")) {
            DataService.processDeleteApplicationFromProject(prismId, appname);
            return "redirect:/projects/index/{prismId}";
        }

        String[] vars = request.getParameterValues("moduleIdsEx");
        projectPersonnelModelView.setModuleIds(vars);

        //        for(String i: vars)
        //        {
        //            logger.error(msgHeader + i);
        //        }
        //        logger.error(msgHeader + " updateProjectPersonnels getMethodology: " + projectPersonnelModelView.getMethodology());
        //        logger.error(msgHeader + " updateProjectPersonnels getModules: " + String.join(",", projectPersonnelModelView.getModuleIds()));
        //        logger.error(msgHeader + " updateProjectPersonnels getImpactTypeId: " + projectPersonnelModelView.getImpactTypeId());
        //        logger.error(msgHeader + " updateProjectPersonnels getBrDuedate: " + projectPersonnelModelView.getBrDuedate());  
        //        logger.error(msgHeader + " chkDelAppFromPrj: " + request.getParameter("chkDelAppFromPrj"));          

        // 10-18-2015: add agile to the mix, when agile, we remove all other artifacts other than IST
        // set isAgile to the correct value
        boolean isAgile = false;
        if (!projectPersonnelModelView.getMethodology().isEmpty()
                && projectPersonnelModelView.getMethodology().equalsIgnoreCase("Agile")) {
            isAgile = true;
        }
        projectPersonnelModelView.setAgile(isAgile);
        logger.error("[Merce]: isAgile is set to: " + isAgile);

        String methodology = projectPersonnelModelView.getMethodology();
        // Integer.valueOf(projectPersonnelModelView.getModuleIds()[0]); 
        int moduleId = Integer.valueOf(vars[0]);
        projectPersonnelModelView.setModuleId(moduleId);
        logger.error("[Merce]: single moduleId is: " + moduleId);
        int impactId = projectPersonnelModelView.getImpactTypeId();
        String impactDesc = HtmlUtils.htmlEscape(projectPersonnelModelView.getImpactDescription());
        // String.join(",", projectPersonnelModelView.getModuleIds());
        String moduleIds = String.join(",", vars);
        logger.error("[Merce]: multiple moduleId are: " + moduleIds);

        if (!methodology.equalsIgnoreCase(mod.getProjectMethodology())
                || !moduleIds.equalsIgnoreCase(String.join(",", mod.getModuleIds()))
                || impactId != mod.getImpactTypeId() || !impactDesc.equalsIgnoreCase(mod.getImpactDescription())) {
            // cascade to child objects in DB,
            // this will actually update all foreign keys in
            // AppProjectArtifactOwners with the correct key values
            logger.error(
                    msgHeader + " updateProjectPersonnels DO need to update methodology, module and impacttype ");
            DataService.updateProjectApplicationModules(prismId, appname, String.valueOf(moduleId),
                    String.valueOf(impactId), methodology, impactDesc, projectPersonnelModelView.getModuleIds());
        } else {
            logger.error(msgHeader
                    + " updateProjectPersonnels no need to update methodology, module and impacttype and impactdescription");
        }

        String sessionUser = (String) request.getSession().getAttribute("loginUser");

        // if TSO there's no deliverables; if TO only IST and ISTExec
        // 1   CODE
        // 2   TBL CHG
        // 3   TO
        // 4   TSO      does not have any deliverables, but we are treating it as TO as well  

        // TO has only IST and ISTExec
        DataService.initializeProjectAppOwnerByPrismId(prismId);
        List<ProjectAppOwnerModel> existingOwners = new ArrayList<ProjectAppOwnerModel>();
        List<ProjectAppOwnerModel> userSelectedOwners = new ArrayList<ProjectAppOwnerModel>();

        // US610355 item #2 allow saving of resources even it's agile
        if (impactId == 3 || impactId == 4) {
            logger.error(msgHeader + " impactId is TO, deleting prismid: " + prismId + ", appname: " + appname
                    + ", artifact: BR");
            DataService.deleteArtifactOwnerTO(prismId, appname, PiratesConstants.BR);
        } else {
            // 1. BR
            processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                    projectPersonnelModelView.getBRu(), PiratesConstants.BR, String.valueOf(moduleId), sessionUser,
                    projectPersonnelModelView.getBrDuedate());

            displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "BR");
            // ****** place BR update logic here **** //
            processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.BR,
                    projectPersonnelModelView.getBrDuedate(), sessionUser, impactId);
            // ****** end of BR logic here ****** //
        }

        if (impactId == 3 || impactId == 4) {
            logger.error(msgHeader + " impactId is TO, deleting prismid: " + prismId + ", appname: " + appname
                    + ", artifact: SR");
            DataService.deleteArtifactOwnerTO(prismId, appname, PiratesConstants.SR);
        } else {
            // 2. update SR
            processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                    projectPersonnelModelView.getSRu(), PiratesConstants.SR, String.valueOf(moduleId), sessionUser,
                    projectPersonnelModelView.getSrDuedate());

            displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "SR");
            // ****** place SR update logic here **** //
            processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.SR,
                    projectPersonnelModelView.getSrDuedate(), sessionUser, impactId);
            // ****** end of SR logic here ****** //                
        }

        if (impactId == 3 || impactId == 4) {
            logger.error(msgHeader + " impactId is TO, deleting prismid: " + prismId + ", appname: " + appname
                    + ", artifact: HLD");
            DataService.deleteArtifactOwnerTO(prismId, appname, PiratesConstants.HLD);
        } else {
            // 3. update HLD
            processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                    projectPersonnelModelView.getHLDu(), PiratesConstants.HLD, String.valueOf(moduleId),
                    sessionUser, projectPersonnelModelView.getHldDuedate());

            displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "HLD");
            // ****** place HLD update logic here **** //
            processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.HLD,
                    projectPersonnelModelView.getHldDuedate(), sessionUser, impactId);
            // ****** end of HLD logic here ****** //                     
        }

        if (impactId == 3 || impactId == 4) {
            logger.error(msgHeader + " impactId is TO, deleting prismid: " + prismId + ", appname: " + appname
                    + ", artifact: AID");
            DataService.deleteArtifactOwnerTO(prismId, appname, PiratesConstants.AID);
        } else {
            // 4. update AID
            processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                    projectPersonnelModelView.getAIDu(), PiratesConstants.AID, String.valueOf(moduleId),
                    sessionUser, projectPersonnelModelView.getAidDuedate());

            displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "AID");
            // ****** place AID update logic here **** //
            processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.AID,
                    projectPersonnelModelView.getAidDuedate(), sessionUser, impactId);
            // ****** end of AID logic here ****** //                      
        }

        if (impactId == 3 || impactId == 4) {
            logger.error(msgHeader + " impactId is TO, deleting prismid: " + prismId + ", appname: " + appname
                    + ", artifact: DES");
            DataService.deleteArtifactOwnerTO(prismId, appname, PiratesConstants.DES);
        } else {
            // 5. update DES
            processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                    projectPersonnelModelView.getDESu(), PiratesConstants.DES, String.valueOf(moduleId),
                    sessionUser, projectPersonnelModelView.getDesDuedate());

            displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "AD");
            // ****** place AD update logic here **** //
            processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.DES,
                    projectPersonnelModelView.getDesDuedate(), sessionUser, impactId);
            // ****** end of AD logic here ****** //                     
        }

        if (impactId == 3 || impactId == 4) {
            logger.error(msgHeader + " impactId is TO, deleting prismid: " + prismId + ", appname: " + appname
                    + ", artifact: DEV");
            DataService.deleteArtifactOwnerTO(prismId, appname, PiratesConstants.DEV);
        } else {
            // 6. update DEV
            processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                    projectPersonnelModelView.getDEVu(), PiratesConstants.DEV, String.valueOf(moduleId),
                    sessionUser, projectPersonnelModelView.getDevDuedate());

            displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "DEV");
            // ****** place DEV update logic here **** //
            processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.DEV,
                    projectPersonnelModelView.getDevDuedate(), sessionUser, impactId);
            // ****** end of DEV logic here ****** //                     
        }

        if (impactId == 4) {
            logger.error(msgHeader + " impactId is TSO, deleting prismid: " + prismId + ", appname: " + appname
                    + ", artifact: IST");
            DataService.deleteArtifactOwnerTO(prismId, appname, PiratesConstants.IST);
        } else {
            // 7. update IST
            processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                    projectPersonnelModelView.getISTu(), PiratesConstants.IST, String.valueOf(moduleId),
                    sessionUser, projectPersonnelModelView.getIstDuedate());

            displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "IST");
            // ****** place IST update logic here **** //
            processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.IST,
                    projectPersonnelModelView.getIstDuedate(), sessionUser, impactId);
            // ****** end of IST logic here ****** //                     
        }

        // 8. update IstExec
        processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                projectPersonnelModelView.getIstExecu(), PiratesConstants.ISTExec, String.valueOf(moduleId),
                sessionUser, projectPersonnelModelView.getIstExecDuedate());

        displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "ISTExec");
        // ****** place ISTExec update logic here **** //
        processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.ISTExec,
                projectPersonnelModelView.getIstExecDuedate(), sessionUser, impactId);
        // ****** end of ISTExec logic here ****** //                

        if (impactId == 3 || impactId == 4) {
            logger.error(msgHeader + " impactId is TO, deleting prismid: " + prismId + ", appname: " + appname
                    + ", artifact: CLOSEOUT");
            DataService.deleteArtifactOwnerTO(prismId, appname, PiratesConstants.CLOSEOUT);
        } else {
            // 9. update Closeout
            processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                    projectPersonnelModelView.getCloseOutu(), PiratesConstants.CLOSEOUT, String.valueOf(moduleId),
                    sessionUser, projectPersonnelModelView.getCloseOutDuedate());

            displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "CloseOut");
            // ****** place Closeout update logic here **** //
            processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.CLOSEOUT,
                    projectPersonnelModelView.getCloseOutDuedate(), sessionUser, impactId);
            // ****** end of Closeout logic here ****** //                   
        }

        // handle Agile artifact
        if (!isAgile) {
            logger.error(msgHeader + " isAgile is false, deleting prismid: " + prismId + ", appname: " + appname
                    + ", artifact: AGILE");
            DataService.deleteArtifactOwnerTO(prismId, appname, PiratesConstants.AGILE);
        } else {
            // 10. update Agile      
            processProjectAppOwners(existingOwners, userSelectedOwners, prismId, applicationId,
                    projectPersonnelModelView.getAgileArtifactsu(), PiratesConstants.AGILE,
                    String.valueOf(moduleId), sessionUser, projectPersonnelModelView.getAgileDuedate());

            displayProjectAppOwnerResults(existingOwners, userSelectedOwners, "Agile");
            // ****** place Agile update logic here **** //
            processProjectAppOwnersByArtifactName(existingOwners, userSelectedOwners, PiratesConstants.AGILE,
                    projectPersonnelModelView.getAgileDuedate(), sessionUser, impactId);
            // ****** end of Agile logic here ****** //                   
        }

        // prismId will be considered while expanding the placeholders
        // return "redirect:/impact_pirates/projects/index/{prismId}";
        return "redirect:/projects/index/{prismId}";
    }

    private static List<ProjectDetailsPersonnel> getProjectDetails(String prismId) {
        List<ProjectDetailsPersonnel> projectsPersonnel = new ArrayList<ProjectDetailsPersonnel>();

        // TODO:  port over to hibernate later
        // logger.error(msgHeader + "getProjectDetailsPersonnel called with prismId: "+ prismId);
        ResultSet rs = null;
        Connection conn = null;
        PreparedStatement preparedStatement = null;

        try {
            conn = DBUtility.getDBConnection();
            // SQL query command
            String SQL = " SELECT apa.ApplicationName, " + "        app.ApplicationId, "
                    + "        apa.ArtifactName, " + "        m.ModuleName, " + "        upper(apa.UUID) as UUID, "
                    + "        apa.MileStoneId, " + "        apa.ModuleId, " + "        pam.ImpactTypeId, "
                    + "        pam.ProjectMethodology, " + "        apa.DueDate, "
                    + "        isnull(pam.ImpactDescription,'') as  ImpactDescription  "
                    + "  FROM AppProjectArtifactOwners as apa  " + "  join Modules m on m.ModuleId = apa.ModuleId "
                    + "  join ProjectApplicationModules pam on pam.PRISMId = apa.PRISMId "
                    + "  and pam.ModuleId = apa.ModuleId and pam.ApplicationName = apa.ApplicationName "
                    + "  join  Applications app on app.ApplicationName = apa.ApplicationName "
                    + "  where apa.PRISMId = ? "
                    + "  order by apa.ApplicationName, apa.ArtifactName, m.ModuleName, apa.UUID ";

            preparedStatement = conn.prepareStatement(SQL);
            preparedStatement.setString(1, prismId);
            rs = preparedStatement.executeQuery();
            int rowCount = 0;

            while (rs.next()) {
                rowCount++;
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                SimpleDateFormat yFormat = new SimpleDateFormat("MM/dd/yyyy");

                String applicationName = rs.getString("ApplicationName");
                String applicationId = rs.getString("ApplicationId");
                String artifactName = rs.getString("ArtifactName");
                String moduleName = rs.getString("ModuleName");
                String uuid = rs.getString("UUID");
                String mileStoneId = rs.getString("MileStoneId");
                String moduleId = rs.getString("ModuleId");
                String impactTypeId = rs.getString("ImpactTypeId");
                String methodology = rs.getString("ProjectMethodology");
                String impactDescription = rs.getString("ImpactDescription");
                String artDueDate = rs.getString("DueDate");
                String artifactDuedate = yFormat.format(format.parse(artDueDate));

                // create a projectDetailPersonnel and add it to list
                ProjectDetailsPersonnel p = new ProjectDetailsPersonnel();
                p.setApplicationName(applicationName);
                p.setApplicationId(applicationId);
                p.setArtifactName(artifactName);
                p.setModuleName(moduleName);
                p.setUuid(uuid);
                p.setMileStoneId(mileStoneId);
                p.setModuleId(moduleId);
                p.setPrismId(prismId);
                p.setImpactTypeId(impactTypeId);
                p.setProjectMethodology(methodology);
                p.setArtifactDueDate(artifactDuedate);
                p.setImpactDescription(HtmlUtils.htmlUnescape(impactDescription));

                projectsPersonnel.add(p);
            }
            // logger.error(msgHeader + "getProjectDetailsPersonnel called, got results: "+rowCount);
        } catch (SQLException e) {
            logger.error(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (preparedStatement != null)
                    preparedStatement.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (conn != null)
                    conn.close();
            } catch (Exception e) {
            }
            ;
        }

        return projectsPersonnel;
    }

    private static String getImpactTypeById(String Id) {
        String res = "";
        Map<String, String> impacts = new HashMap<String, String>();
        ResultSet rs = null;
        Connection conn = null;
        PreparedStatement preparedStatement = null;

        try {
            conn = DBUtility.getDBConnection();
            // SQL query command
            String SQL = " SELECT [ImpactTypeId] " + "      ,[ImpactType] " + "      ,[ImpactTypeFullName] "
                    + "  FROM [ImpactTypes] ";

            preparedStatement = conn.prepareStatement(SQL);
            rs = preparedStatement.executeQuery();

            while (rs.next()) {
                int impacttypeid = rs.getInt("ImpactTypeId");
                String impacttype = rs.getString("ImpactType");
                String impacttypeFullName = rs.getString("ImpactTypeFullName");

                ImpactTypes e = new ImpactTypes();
                e.setImpactTypeId(impacttypeid);
                e.setImpactType(impacttype);
                e.setImpactTypeFullName(impacttypeFullName);
                impacts.put(String.valueOf(e.getImpactTypeId()), e.getImpactType());
            }
            res = impacts.get(Id);
            return res;
        } catch (SQLException e) {
            logger.error(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (preparedStatement != null)
                    preparedStatement.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (conn != null)
                    conn.close();
            } catch (Exception e) {
            }
            ;
        }
        //        impacts.put("1","CODE");
        //        impacts.put("2","TBL CHG");
        //        impacts.put("3","TO");
        //        impacts.put("4","TSO");
        return res;
    }

    private static int getImpactByName(String impactName) {
        List<ImpactTypes> types = getProjectImpactTypes();
        for (ImpactTypes t : types) {
            if (t.getImpactType().equalsIgnoreCase(impactName)) {
                return t.getImpactTypeId();
            }
        }
        return 0;
    }

    private static List<String> getProjectMethodologies() {
        List<String> methods = new ArrayList<String>();
        methods.add("Waterfall");
        methods.add("Agile");
        return methods;
    }

    private static List<ImpactTypes> getProjectImpactTypes() {
        List<ImpactTypes> impacts = new ArrayList<ImpactTypes>();

        // TODO:  port over to hibernate later
        // logger.error(msgHeader + "getProjectImpactTypes called. ");
        ResultSet rs = null;
        Connection conn = null;
        PreparedStatement preparedStatement = null;

        try {
            conn = DBUtility.getDBConnection();
            // SQL query command
            String SQL = " SELECT ImpactTypeId, ImpactType, ImpactTypeFullName + ' ('+ ImpactType + ')' as 'ImpactTypeFullName' "
                    + " FROM ImpactTypes ";

            preparedStatement = conn.prepareStatement(SQL);
            rs = preparedStatement.executeQuery();
            int rowCount = 0;

            while (rs.next()) {
                rowCount++;
                int impacttypeid = rs.getInt("ImpactTypeId");
                String impacttype = rs.getString("ImpactType");
                String impacttypeFullName = rs.getString("ImpactTypeFullName");

                ImpactTypes e = new ImpactTypes();
                e.setImpactTypeId(impacttypeid);
                e.setImpactType(impacttype);
                e.setImpactTypeFullName(impacttypeFullName);
                impacts.add(e);
            }
            // logger.error(msgHeader + "getProjectImpactTypes called, got results: "+rowCount);
        } catch (SQLException e) {
            logger.error(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (preparedStatement != null)
                    preparedStatement.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (conn != null)
                    conn.close();
            } catch (Exception e) {
            }
            ;
        }

        return impacts;
    }

    public static List<ProjectDetailsPersonnelModelView> getProjectDetailsPersonnelViewModel(String prismId) {
        List<ProjectDetailsPersonnel> personnels = getProjectDetails(prismId);
        List<ProjectDetailsPersonnelModelView> viewModel = new ArrayList<ProjectDetailsPersonnelModelView>();
        // SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        if (personnels == null || personnels.isEmpty()) {
            return viewModel;
        }

        if (employees == null) {
            employees = getATTEmployees_All();
        }

        // get a unique list of applicationnames
        // the initial List
        ArrayList<String> list = new ArrayList<String>();
        for (ProjectDetailsPersonnel p : personnels) {
            list.add(p.getApplicationName());
        }
        // convert the List into a Set
        Set<String> set = new HashSet<String>(list);
        // create a new List from the Set
        // now, they are unique
        ArrayList<String> resultAppNames = new ArrayList<String>(set);
        Collections.sort(resultAppNames);

        for (String appName : resultAppNames) {
            ProjectDetailsPersonnelModelView aRow = new ProjectDetailsPersonnelModelView();
            aRow.setPrismId(prismId);

            // get list of projectdetailspersonnel belong to this app
            List<ProjectDetailsPersonnel> thisAppRows = getPersonnelObjectsByAppName(personnels, appName);
            if (!thisAppRows.isEmpty()) {
                // get the applicationId value, only need to use the item 0 since all records have the same appId value
                aRow.setApplicationName(appName);
                aRow.setApplicationId(thisAppRows.get(0).getApplicationId());
                aRow.setImpactDescription(thisAppRows.get(0).getImpactDescription());

                // prefix. AGILE
                // there might be more than one owner of Agile artifacts, although we are only
                // handling the isPrimary = 1 for now
                List<ProjectDetailsPersonnel> allAgiles = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.AGILE);
                List<String> AgileNames = new ArrayList<String>();
                List<String> Agileuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no BR for this app & project, we use NA
                if (allAgiles.isEmpty()) {
                    AgileNames.add("NA");
                    Agileuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allAgiles) {
                        AgileNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        Agileuuids.add(p.getUuid());
                    }
                }

                aRow.setAgileArtifact(String.join(",", AgileNames));
                aRow.setAgileArtifactsu(Agileuuids.toArray(new String[Agileuuids.size()]));
                if (allAgiles != null && !allAgiles.isEmpty()) {
                    aRow.setAgileDuedate(allAgiles.get(0).getArtifactDueDate());
                } else {
                    aRow.setAgileDuedate("1900-01-01");
                }

                // 1. BR
                // there might be more than one owner of BR artifacts, although we are only
                // handling the isPrimary = 1 for now
                List<ProjectDetailsPersonnel> allBRs = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.BR);
                List<String> BRNames = new ArrayList<String>();
                List<String> BRuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no BR for this app & project, we use NA
                if (allBRs.isEmpty()) {
                    BRNames.add("NA");
                    BRuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allBRs) {
                        BRNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        BRuuids.add(p.getUuid());
                    }
                }

                aRow.setBR(String.join(",", BRNames));
                aRow.setBRu(BRuuids.toArray(new String[BRuuids.size()]));
                if (allBRs != null && !allBRs.isEmpty()) {
                    aRow.setBrDuedate(allBRs.get(0).getArtifactDueDate());
                } else {
                    aRow.setBrDuedate("1900-01-01");
                }

                // 2. SR
                List<ProjectDetailsPersonnel> allSRs = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.SR);
                List<String> SRNames = new ArrayList<String>();
                BRuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no SR for this app & project, we use NA
                if (allSRs.isEmpty()) {
                    SRNames.add("NA");
                    BRuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allSRs) {
                        SRNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        BRuuids.add(p.getUuid());
                    }
                }

                aRow.setSR(String.join(",", SRNames));
                aRow.setSRu(BRuuids.toArray(new String[BRuuids.size()]));

                if (allSRs != null && !allSRs.isEmpty()) {
                    aRow.setSrDuedate(allSRs.get(0).getArtifactDueDate());
                } else {
                    aRow.setSrDuedate("1900-01-01");
                }

                // 3. HLD
                List<ProjectDetailsPersonnel> allHLDs = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.HLD);
                List<String> HLDNames = new ArrayList<String>();
                BRuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no HLD for this app & project, we use NA
                if (allHLDs.isEmpty()) {
                    HLDNames.add("NA");
                    BRuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allHLDs) {
                        HLDNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        BRuuids.add(p.getUuid());
                    }
                }

                aRow.setHLD(String.join(",", HLDNames));
                aRow.setHLDu(BRuuids.toArray(new String[BRuuids.size()]));
                if (allHLDs != null && !allHLDs.isEmpty()) {
                    aRow.setHldDuedate(allHLDs.get(0).getArtifactDueDate());
                } else {
                    aRow.setHldDuedate("1900-01-01");
                }

                // 4. AID
                List<ProjectDetailsPersonnel> allAIDs = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.AID);
                List<String> AIDNames = new ArrayList<String>();
                BRuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no AID for this app & project, we use NA
                if (allAIDs.isEmpty()) {
                    AIDNames.add("NA");
                    BRuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allAIDs) {
                        AIDNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        BRuuids.add(p.getUuid());
                    }
                }

                aRow.setAID(String.join(",", AIDNames));
                aRow.setAIDu(BRuuids.toArray(new String[BRuuids.size()]));
                if (allAIDs != null && !allAIDs.isEmpty()) {
                    aRow.setAidDuedate(allAIDs.get(0).getArtifactDueDate());
                } else {
                    aRow.setAidDuedate("1900-01-01");
                }

                // 5. AD/DES
                List<ProjectDetailsPersonnel> allADs = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.DES);
                List<String> ADNames = new ArrayList<String>();
                BRuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no DES for this app & project, we use NA
                if (allADs.isEmpty()) {
                    ADNames.add("NA");
                    BRuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allADs) {
                        ADNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        BRuuids.add(p.getUuid());
                    }
                }

                aRow.setDES(String.join(",", ADNames));
                aRow.setDESu(BRuuids.toArray(new String[BRuuids.size()]));
                if (allADs != null && !allADs.isEmpty()) {
                    aRow.setDesDuedate(allADs.get(0).getArtifactDueDate());
                } else {
                    aRow.setDesDuedate("1900-01-01");
                }

                // 6. DEV
                List<ProjectDetailsPersonnel> allDEVs = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.DEV);
                List<String> DEVNames = new ArrayList<String>();
                BRuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no DES for this app & project, we use NA
                if (allDEVs.isEmpty()) {
                    DEVNames.add("NA");
                    BRuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allDEVs) {
                        DEVNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        BRuuids.add(p.getUuid());
                    }
                }

                aRow.setDEV(String.join(",", DEVNames));
                aRow.setDEVu(BRuuids.toArray(new String[BRuuids.size()]));
                if (allDEVs != null && !allDEVs.isEmpty()) {
                    aRow.setDevDuedate(allDEVs.get(0).getArtifactDueDate());
                } else {
                    aRow.setDevDuedate("1900-01-01");
                }

                // 7. IST
                List<ProjectDetailsPersonnel> allISTs = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.IST);
                List<String> ISTNames = new ArrayList<String>();
                BRuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no DES for this app & project, we use NA
                if (allISTs.isEmpty()) {
                    ISTNames.add("NA");
                    BRuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allISTs) {
                        ISTNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        BRuuids.add(p.getUuid());
                    }
                }

                aRow.setIST(String.join(",", ISTNames));
                aRow.setISTu(BRuuids.toArray(new String[BRuuids.size()]));
                if (allISTs != null && !allISTs.isEmpty()) {
                    aRow.setIstDuedate(allISTs.get(0).getArtifactDueDate());
                } else {
                    aRow.setIstDuedate("1900-01-01");
                }

                // 8. isAgile?
                String m = thisAppRows.get(0).getProjectMethodology();
                if (m != null && m.equalsIgnoreCase(PiratesConstants.WATERFALL)) {
                    aRow.setAgile(false);
                } else {
                    aRow.setAgile(true);
                }

                // 9. Module(s)
                List<String> modules = new ArrayList<String>();
                for (ProjectDetailsPersonnel p : thisAppRows) {
                    modules.add(p.getModuleName());
                }

                List<String> modulesEx = new ArrayList<String>();
                for (ProjectDetailsPersonnel p : thisAppRows) {
                    List<String> mods = DataService.getModulesForPrismIDAppName(prismId, p.getApplicationName());
                    modulesEx.addAll(mods);
                }

                // convert the List into a Set
                Set<String> setModulesEx = new HashSet<String>(modulesEx);
                // create a new List from the Set
                // now, they are unique
                ArrayList<String> uniqueModulesEx = new ArrayList<String>(setModulesEx);
                aRow.setModules(uniqueModulesEx.toArray(new String[uniqueModulesEx.size()]));

                // convert the List into a Set
                Set<String> setModules = new HashSet<String>(modules);
                // create a new List from the Set
                // now, they are unique
                ArrayList<String> uniqueModules = new ArrayList<String>(setModules);
                aRow.setModule(String.join(",", uniqueModules));

                // 10. impact type
                List<String> impactNamess = new ArrayList<String>();
                for (ProjectDetailsPersonnel p : thisAppRows) {
                    impactNamess.add(getImpactTypeById(p.getImpactTypeId()));
                }
                Set<String> setImpacts = new HashSet<String>(impactNamess);
                ArrayList<String> uniqueImpacts = new ArrayList<String>(setImpacts);
                aRow.setImpact(String.join(",", uniqueImpacts));

                // 11. ISTExec
                List<ProjectDetailsPersonnel> allISTExecs = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.ISTExec);
                List<String> ISTExecNames = new ArrayList<String>();
                BRuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no ISTExec for this app & project, we use NA
                if (allISTExecs.isEmpty() || impactNamess.get(0).equalsIgnoreCase("TSO")) {
                    ISTExecNames.add("NA");
                    BRuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allISTExecs) {
                        ISTExecNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        BRuuids.add(p.getUuid());
                    }
                }

                aRow.setIstExec(String.join(",", ISTExecNames));
                aRow.setIstExecu(BRuuids.toArray(new String[BRuuids.size()]));
                if (allISTExecs != null && !allISTExecs.isEmpty() && !impactNamess.get(0).equalsIgnoreCase("TSO")) {
                    aRow.setIstExecDuedate(allISTExecs.get(0).getArtifactDueDate());
                } else {
                    aRow.setIstExecDuedate("1900-01-01");
                }

                // 12. CloseOut
                List<ProjectDetailsPersonnel> allCloseOuts = getPersonnelObjectsByArtifactName(thisAppRows,
                        PiratesConstants.CLOSEOUT);
                List<String> CloseoutNames = new ArrayList<String>();
                BRuuids = new ArrayList<String>();

                // mchan 8/20/15, handle when no ISTExec for this app & project, we use NA
                if (allCloseOuts.isEmpty()) {
                    CloseoutNames.add("NA");
                    BRuuids.add("NA");
                } else {
                    for (ProjectDetailsPersonnel p : allCloseOuts) {
                        CloseoutNames.add(getEmployeNameByUUID(employees, p.getUuid()));
                        BRuuids.add(p.getUuid());
                    }
                }

                aRow.setCloseOut(String.join(",", CloseoutNames));
                aRow.setCloseOutu(BRuuids.toArray(new String[BRuuids.size()]));
                if (allCloseOuts != null && !allCloseOuts.isEmpty()) {
                    aRow.setCloseOutDuedate(allCloseOuts.get(0).getArtifactDueDate());
                } else {
                    aRow.setCloseOutDuedate("1900-01-01");
                }

                // add row to collection
                viewModel.add(aRow);
            }
        } // end for each unique resultApps

        return viewModel;

    }

    private static String getEmployeNameByUUID(List<ATTEmployee> employees, String uuid) {
        String rc = "";
        if (employees == null || employees.isEmpty()) {
            return rc;
        }

        for (ATTEmployee e : employees) {
            if (e.getUUID().equalsIgnoreCase(uuid)) {
                rc = e.getFullName();
                break;
            }
        }
        return rc;
    }

    private static List<ProjectAppOwnerModel> getProjectAppOwnerModelObjectByArtifactName(
            List<ProjectAppOwnerModel> list, String artifactName) {
        List<ProjectAppOwnerModel> appOwner = new ArrayList<ProjectAppOwnerModel>();
        if (list == null || list.isEmpty()) {
            return appOwner;
        }

        for (ProjectAppOwnerModel p : list) {
            if (p.getArtifactName().equalsIgnoreCase(artifactName)) {
                appOwner.add(p);
            }
        }

        return appOwner;
    }

    private static List<ProjectDetailsPersonnel> getPersonnelObjectsByArtifactName(
            List<ProjectDetailsPersonnel> list, String artifactName) {
        List<ProjectDetailsPersonnel> personnels = new ArrayList<ProjectDetailsPersonnel>();
        if (list == null || list.isEmpty()) {
            return personnels;
        }

        for (ProjectDetailsPersonnel p : list) {
            if (p.getArtifactName().equalsIgnoreCase(artifactName)) {
                personnels.add(p);
            }
        }

        return personnels;
    }

    private static List<ProjectDetailsPersonnel> getPersonnelObjectsByAppName(List<ProjectDetailsPersonnel> list,
            String applicationName) {
        List<ProjectDetailsPersonnel> personnels = new ArrayList<ProjectDetailsPersonnel>();
        if (list == null || list.isEmpty()) {
            return personnels;
        }

        for (ProjectDetailsPersonnel p : list) {
            if (p.getApplicationName().equalsIgnoreCase(applicationName)) {
                personnels.add(p);
            }
        }

        return personnels;
    }

    private static List<ProjectAppOwnerModel> getAppOwnerModelObjectsByAppName(List<ProjectAppOwnerModel> list,
            String applicationName) {
        List<ProjectAppOwnerModel> appOwner = new ArrayList<ProjectAppOwnerModel>();

        if (list == null || list.isEmpty()) {
            return appOwner;
        }

        for (ProjectAppOwnerModel p : list) {
            if (p.getApplicationName().equalsIgnoreCase(applicationName)) {
                appOwner.add(p);
            }
        }

        return appOwner;
    }

    private static List<ProjectAppOwnerModel> getProjectAppOwners(String prismId) {
        List<ProjectAppOwnerModel> rc = new ArrayList<ProjectAppOwnerModel>();

        // TODO:  port over to hibernate later
        // logger.error(msgHeader + "getProjectAppOwners called with prismId: "+ prismId);
        ResultSet rs = null;
        Connection conn = null;
        PreparedStatement preparedStatement = null;

        try {
            conn = DBUtility.getDBConnection();
            // SQL query command
            String SQL = " SELECT " + "      apa.UUID " + "      ,apa.DueDate " + "      ,apa.CompletionDate "
                    + "      ,apa.PercentageComplete " + "      ,apa.ArtifactName " + "      ,apa.PRISMId "
                    + "      ,apa.ApplicationName " + "      ,apa.ModuleId " + "      ,apa.IsPrimaryOwner "
                    + "      ,apa.MileStoneId " + "      ,apa.ExecutionPercentage "
                    + "      ,apa.ProjectCloseOutPercentage " + "      ,isnull(apa.DateCreated,'') as DateCreated "
                    + "      ,apa.UpdatedByUUID " + "      ,apa.SystemNote " + "      ,app.ApplicationId "
                    + "  FROM AppProjectArtifactOwners apa join Applications app  "
                    + "  On app.ApplicationName = apa.ApplicationName "
                    + "  Where apa.PRISMId = ? and apa.isPrimaryOwner = 1 "
                    + "  Order by apa.ApplicationName, apa.ArtifactName, apa.UUID ";

            preparedStatement = conn.prepareStatement(SQL);
            preparedStatement.setString(1, prismId);
            rs = preparedStatement.executeQuery();
            int rowCount = 0;

            while (rs.next()) {
                rowCount++;
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                SimpleDateFormat yFormat = new SimpleDateFormat("MM/dd/yyyy");
                // for percentage
                NumberFormat defaultFormat = NumberFormat.getPercentInstance();
                defaultFormat.setMinimumFractionDigits(0);

                //
                String uuid = rs.getString("UUID");
                //
                String theDueDate = rs.getString("DueDate");
                String dueDate = yFormat.format(format.parse(theDueDate));
                // 
                String theCompDate = rs.getString("CompletionDate") == null ? "1900-01-01 14:58:00.00"
                        : rs.getString("CompletionDate");
                String completionDate = yFormat.format(format.parse(theCompDate));

                //
                String pCompletedDtr = rs.getString("PercentageComplete") == null ? "0.00"
                        : rs.getString("PercentageComplete");
                double percentComplete = Double.parseDouble(
                        rs.getString("PercentageComplete") == null ? "0" : rs.getString("PercentageComplete"));
                String PercentCompleted = defaultFormat.format(percentComplete);
                //
                String artifactName = rs.getString("ArtifactName");
                //
                String applicationName = rs.getString("ApplicationName");
                //
                String moduleId = rs.getString("ModuleId");
                // 
                String isPrimary = rs.getString("IsPrimaryOwner");
                // 
                String mileStoneId = rs.getString("MileStoneId");
                //
                double ExecPercent = Double.parseDouble(
                        rs.getString("ExecutionPercentage") == null ? "0" : rs.getString("ExecutionPercentage"));
                String ExecutionPercentage = defaultFormat.format(ExecPercent);
                //
                double prjCOPercent = Double.parseDouble(rs.getString("ProjectCloseOutPercentage") == null ? "0"
                        : rs.getString("ProjectCloseOutPercentage"));
                String PrjCloseOutPercentage = defaultFormat.format(prjCOPercent);
                //
                String dCreated = rs.getString("DateCreated");
                String dateCreated = yFormat.format(format.parse(dCreated));
                //
                String updatedByUUID = rs.getString("UpdatedByUUID");
                //
                String systemNote = rs.getString("SystemNote");
                //
                String applicationId = rs.getString("ApplicationId");

                // create a projectDetailPersonnel and add it to list
                ProjectAppOwnerModel p = new ProjectAppOwnerModel();
                p.setUUID(uuid);
                p.setDueDate(dueDate);
                p.setCompletionDate(completionDate);
                p.setPercentageComplete(PercentCompleted);
                p.setPercentageCompleteStr(pCompletedDtr);
                p.setArtifactName(artifactName);
                p.setPrismId(prismId);
                p.setApplicationName(applicationName);
                p.setModuleId(moduleId);
                p.setIsPrimaryOwner(isPrimary.equalsIgnoreCase("1"));
                p.setMileStoneId(mileStoneId);
                p.setExecutionPercentage(ExecutionPercentage);
                p.setProjectCloseOutPercentage(PrjCloseOutPercentage);
                p.setDateCreated(dateCreated);
                p.setUpdatedByUUID(updatedByUUID);
                p.setSystemNote(systemNote);
                p.setApplicationId(applicationId);

                rc.add(p);
            }
            logger.error(msgHeader + "getProjectAppOwners called, got results: " + rowCount);
        } catch (SQLException e) {
            logger.error(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (preparedStatement != null)
                    preparedStatement.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (conn != null)
                    conn.close();
            } catch (Exception e) {
            }
            ;
        }

        return rc;
    }

    // project status logic
    public static List<ProjectDetailsStatusViewModel> getProjectDetailsStatus(String prismId, String uuid) {
        List<ProjectDetailsStatusViewModel> detailStatus = new ArrayList<ProjectDetailsStatusViewModel>();

        try {
            // logger.error("getProjectDetailsStatus, before calling getProjectAppOwners(prismId)");
            List<ProjectAppOwnerModel> results = getProjectAppOwners(prismId);
            // logger.error("getProjectDetailsStatus, after calling getProjectAppOwners(prismId)");

            if (!results.isEmpty()) {
                ArrayList<String> list = new ArrayList<String>();
                for (ProjectAppOwnerModel p : results) {
                    list.add(p.getApplicationName());
                }
                // convert the List into a Set
                Set<String> set = new HashSet<String>(list);
                // create a new List from the Set
                // now, they are unique
                ArrayList<String> distinctApps = new ArrayList<String>(set);
                Collections.sort(distinctApps);

                for (String app : distinctApps) {
                    int impactTypeId = DataService.getImpactTypeIdByPrismIdAndApplicationName(prismId, app);
                    boolean validateThreshold = !(impactTypeId == 4);

                    ProjectDetailsStatusViewModel aRow = new ProjectDetailsStatusViewModel();
                    List<ProjectAppOwnerModel> thisAppRows = getAppOwnerModelObjectsByAppName(results, app);

                    if (!thisAppRows.isEmpty()) {
                        aRow.setApplicationId(thisAppRows.get(0).getApplicationId());
                        aRow.setApplication(app);
                        aRow.setImpactType(impactTypeId);

                        // 1. BR
                        List<ProjectAppOwnerModel> allBRs = getProjectAppOwnerModelObjectByArtifactName(thisAppRows,
                                PiratesConstants.BR);
                        if (!allBRs.isEmpty()) {
                            aRow.setBR(allBRs.get(0).getPercentageComplete());
                            aRow.setBRheaderDueDate(allBRs.get(0).getDueDate());
                            aRow.setBRDuedate(allBRs.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allBRs.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allBRs.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setBR(aRow.getBR() + "," + h.getPercentageComplete());
                                    aRow.setBRDuedate(aRow.getBRDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setBRStr(getRowDueDatePercentageString(aRow.getBR(), aRow.getBRDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getBRheaderDueDate(), false,
                                    validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setBR("0%");
                            aRow.setBRDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setBRheaderDueDate("NA");
                            aRow.setBRStr(getRowDueDatePercentageString(aRow.getBR(), aRow.getBRDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getBRheaderDueDate(), false,
                                    validateThreshold));
                        }
                        // end of BR

                        // 2. SR
                        List<ProjectAppOwnerModel> allSRs = getProjectAppOwnerModelObjectByArtifactName(thisAppRows,
                                PiratesConstants.SR);
                        if (!allSRs.isEmpty()) {
                            aRow.setSR(allSRs.get(0).getPercentageComplete());
                            aRow.setSRheaderDueDate(allSRs.get(0).getDueDate());
                            aRow.setSRDuedate(allSRs.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allSRs.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allSRs.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setSR(aRow.getSR() + "," + h.getPercentageComplete());
                                    aRow.setSRDuedate(aRow.getSRDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setSRStr(getRowDueDatePercentageString(aRow.getSR(), aRow.getSRDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getSRheaderDueDate(), true,
                                    validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setSR("0%");
                            aRow.setSRDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setSRheaderDueDate("NA");
                            aRow.setSRStr(getRowDueDatePercentageString(aRow.getSR(), aRow.getSRDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getSRheaderDueDate(), true,
                                    validateThreshold));
                        }
                        // end of SR                        

                        // 3. HLD
                        List<ProjectAppOwnerModel> allHLDs = getProjectAppOwnerModelObjectByArtifactName(
                                thisAppRows, PiratesConstants.HLD);
                        if (!allHLDs.isEmpty()) {
                            aRow.setHLD(allHLDs.get(0).getPercentageComplete());
                            aRow.setHLDheaderDueDate(allHLDs.get(0).getDueDate());
                            aRow.setHLDDuedate(allHLDs.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allHLDs.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allHLDs.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setHLD(aRow.getHLD() + "," + h.getPercentageComplete());
                                    aRow.setHLDDuedate(aRow.getHLDDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setHLDStr(getRowDueDatePercentageString(aRow.getHLD(), aRow.getHLDDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getHLDheaderDueDate(), true,
                                    validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setHLD("0%");
                            aRow.setHLDDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setHLDheaderDueDate("NA");
                            aRow.setHLDStr(getRowDueDatePercentageString(aRow.getHLD(), aRow.getHLDDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getHLDheaderDueDate(), true,
                                    validateThreshold));
                        }
                        // end of HLD

                        // 4. AID
                        List<ProjectAppOwnerModel> allAIDs = getProjectAppOwnerModelObjectByArtifactName(
                                thisAppRows, PiratesConstants.AID);
                        if (!allAIDs.isEmpty()) {
                            aRow.setAID(allAIDs.get(0).getPercentageComplete());
                            aRow.setAIDheaderDueDate(allAIDs.get(0).getDueDate());
                            aRow.setAIDDuedate(allAIDs.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allAIDs.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allAIDs.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setAID(aRow.getAID() + "," + h.getPercentageComplete());
                                    aRow.setAIDDuedate(aRow.getAIDDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setAIDStr(getRowDueDatePercentageString(aRow.getAID(), aRow.getAIDDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getAIDheaderDueDate(), true,
                                    validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setAID("0%");
                            aRow.setAIDDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setAIDheaderDueDate("NA");
                            aRow.setAIDStr(getRowDueDatePercentageString(aRow.getAID(), aRow.getAIDDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getAIDheaderDueDate(), true,
                                    validateThreshold));
                        }
                        // end of AID

                        // 5. AD
                        List<ProjectAppOwnerModel> allADs = getProjectAppOwnerModelObjectByArtifactName(thisAppRows,
                                PiratesConstants.DES);
                        if (!allADs.isEmpty()) {
                            aRow.setDES(allADs.get(0).getPercentageComplete());
                            aRow.setDESheaderDueDate(allADs.get(0).getDueDate());
                            aRow.setDESDuedate(allADs.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allADs.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allADs.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setDES(aRow.getDES() + "," + h.getPercentageComplete());
                                    aRow.setDESDuedate(aRow.getDESDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setDESStr(getRowDueDatePercentageString(aRow.getDES(), aRow.getDESDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getDESheaderDueDate(), true,
                                    validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setDES("0%");
                            aRow.setDESDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setDESheaderDueDate("NA");
                            aRow.setDESStr(getRowDueDatePercentageString(aRow.getDES(), aRow.getDESDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getDESheaderDueDate(), true,
                                    validateThreshold));
                        }
                        // end of DES                        

                        // 6. DEV
                        List<ProjectAppOwnerModel> allDEVs = getProjectAppOwnerModelObjectByArtifactName(
                                thisAppRows, PiratesConstants.DEV);
                        if (!allDEVs.isEmpty()) {
                            aRow.setDEV(allDEVs.get(0).getPercentageComplete());
                            aRow.setDEVheaderDueDate(allDEVs.get(0).getDueDate());
                            aRow.setDEVDuedate(allDEVs.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allDEVs.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allDEVs.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setDEV(aRow.getDEV() + "," + h.getPercentageComplete());
                                    aRow.setDEVDuedate(aRow.getDEVDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setDEVStr(getRowDueDatePercentageString(aRow.getDEV(), aRow.getDEVDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getDEVheaderDueDate(), true,
                                    validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setDEV("0%");
                            aRow.setDEVDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setDEVheaderDueDate("NA");
                            aRow.setDEVStr(getRowDueDatePercentageString(aRow.getDEV(), aRow.getDEVDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getDEVheaderDueDate(), true,
                                    validateThreshold));
                        }
                        // end of DEV                        

                        // 7. IST
                        List<ProjectAppOwnerModel> allISTs = getProjectAppOwnerModelObjectByArtifactName(
                                thisAppRows, PiratesConstants.IST);
                        if (!allISTs.isEmpty()) {
                            aRow.setIST(allISTs.get(0).getPercentageComplete());
                            aRow.setISTheaderDueDate(allISTs.get(0).getDueDate());
                            aRow.setISTDuedate(allISTs.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allISTs.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allISTs.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setIST(aRow.getIST() + "," + h.getPercentageComplete());
                                    aRow.setISTDuedate(aRow.getISTDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setISTStr(getRowDueDatePercentageString(aRow.getIST(), aRow.getISTDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getISTheaderDueDate(), true,
                                    validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setIST("0%");
                            aRow.setISTDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setISTheaderDueDate("NA");
                            aRow.setISTStr(getRowDueDatePercentageString(aRow.getIST(), aRow.getISTDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getISTheaderDueDate(), true,
                                    validateThreshold));
                        }
                        // end of IST                             

                        // 8. ISTExec
                        List<ProjectAppOwnerModel> allISTExecs = getProjectAppOwnerModelObjectByArtifactName(
                                thisAppRows, PiratesConstants.ISTExec);
                        if (!allISTExecs.isEmpty() && impactTypeId != 4) {
                            aRow.setISTExec(allISTExecs.get(0).getPercentageComplete());
                            aRow.setISTExecheaderDueDate(allISTExecs.get(0).getDueDate());
                            aRow.setISTExecDuedate(allISTExecs.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allISTExecs.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allISTExecs.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setISTExec(aRow.getISTExec() + "," + h.getPercentageComplete());
                                    aRow.setISTExecDuedate(aRow.getISTExecDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setISTExecStr(getRowDueDatePercentageString(aRow.getISTExec(),
                                    aRow.getISTExecDuedate(), aRow.getUpdatedByUUID(), uuid,
                                    aRow.getISTExecheaderDueDate(), true, validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setISTExec("0%");
                            aRow.setISTExecDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setISTExecheaderDueDate("NA");
                            aRow.setISTExecStr(getRowDueDatePercentageString(aRow.getISTExec(),
                                    aRow.getISTExecDuedate(), aRow.getUpdatedByUUID(), uuid,
                                    aRow.getISTExecheaderDueDate(), true, validateThreshold));
                        }
                        // end of ISTExec 

                        // 9. CloseOut
                        List<ProjectAppOwnerModel> allCloseout = getProjectAppOwnerModelObjectByArtifactName(
                                thisAppRows, PiratesConstants.CLOSEOUT);
                        if (!allCloseout.isEmpty()) {
                            aRow.setCloseOut(allCloseout.get(0).getPercentageComplete());
                            aRow.setCloseOutheaderDueDate(allCloseout.get(0).getDueDate());
                            aRow.setCloseOutDuedate(allCloseout.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allCloseout.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allCloseout.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setCloseOut(aRow.getCloseOut() + "," + h.getPercentageComplete());
                                    aRow.setCloseOutDuedate(aRow.getCloseOutDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setCloseOutStr(getRowDueDatePercentageString(aRow.getCloseOut(),
                                    aRow.getCloseOutDuedate(), aRow.getUpdatedByUUID(), uuid,
                                    aRow.getCloseOutheaderDueDate(), true, validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setCloseOut("0%");
                            aRow.setCloseOutDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setCloseOutheaderDueDate("NA");
                            aRow.setCloseOutStr(getRowDueDatePercentageString(aRow.getCloseOut(),
                                    aRow.getCloseOutDuedate(), aRow.getUpdatedByUUID(), uuid,
                                    aRow.getCloseOutheaderDueDate(), true, validateThreshold));
                        }
                        // end of CloseOut

                        // 10. Agile
                        List<ProjectAppOwnerModel> allAgile = getProjectAppOwnerModelObjectByArtifactName(
                                thisAppRows, PiratesConstants.AGILE);
                        if (!allAgile.isEmpty()) {
                            aRow.setAgile(allAgile.get(0).getPercentageComplete());
                            aRow.setAgileheaderDueDate(allAgile.get(0).getDueDate());
                            aRow.setAgileDuedate(allAgile.get(0).getDateCreated());
                            aRow.setUpdatedByUUID(allAgile.get(0).getUpdatedByUUID());

                            // get history records
                            List<AppProjectArtifactOwnersHistory> history = getStatusHistoryListByApplicationOwner(
                                    allAgile.get(0));
                            if (!history.isEmpty()) {
                                for (AppProjectArtifactOwnersHistory h : history) {
                                    // for percentage
                                    aRow.setAgile(aRow.getAgile() + "," + h.getPercentageComplete());
                                    aRow.setAgileDuedate(aRow.getAgileDuedate() + "," + h.getDateLogged());
                                    aRow.setUpdatedByUUID(aRow.getUpdatedByUUID() + "," + h.getUpdatedByUUID());
                                }
                            } // after processing each history record
                            aRow.setAgileStr(getRowDueDatePercentageString(aRow.getAgile(), aRow.getAgileDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getAgileheaderDueDate(), true,
                                    validateThreshold));
                        } // end processing isEmpty()
                        else {
                            aRow.setAgile("0%");
                            aRow.setAgileDuedate("NA");
                            aRow.setUpdatedByUUID("NA");
                            aRow.setAgileheaderDueDate("NA");
                            aRow.setAgileStr(getRowDueDatePercentageString(aRow.getAgile(), aRow.getAgileDuedate(),
                                    aRow.getUpdatedByUUID(), uuid, aRow.getAgileheaderDueDate(), true,
                                    validateThreshold));
                        }
                        // end of Agile                        

                        aRow.setPrismId(prismId);
                        detailStatus.add(aRow);
                    } // end thisAppRow.ANY() check
                } // end distinct appName loop
            }
        } catch (Exception ex) {
            logger.error(msgHeader + "Error occurred getProjectDetailsStatuc... " + ex.getMessage());
        }

        // new code
        SimpleDateFormat yFormat = new SimpleDateFormat("MM/dd/yyyy");
        List<Date> tmpDates = new ArrayList<Date>();
        Date BR = null;
        Date SR = null;
        Date HLD = null;
        Date AID = null;
        Date AD = null;
        Date DEV = null;
        Date IST = null;
        Date ISTExec = null;
        Date CloseOut = null;
        Date Agile = null;

        // Process BR
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getBRheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getBRheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getBRheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            BR = tmpDates.get(0);
        }
        tmpDates.clear();

        // Process SR
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getSRheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getSRheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getSRheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            SR = tmpDates.get(0);
        }
        tmpDates.clear();

        // Process HLD
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getHLDheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getHLDheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getHLDheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            HLD = tmpDates.get(0);
        }
        tmpDates.clear();

        // Process AID
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getAIDheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getAIDheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getAIDheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            AID = tmpDates.get(0);
        }
        tmpDates.clear();

        // Process AD
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getDESheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getDESheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getDESheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            AD = tmpDates.get(0);
        }
        tmpDates.clear();

        // Process DEV
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getDEVheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getDEVheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getDEVheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            DEV = tmpDates.get(0);
        }
        tmpDates.clear();

        // Process IST
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getISTheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getISTheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getISTheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            IST = tmpDates.get(0);
        }
        tmpDates.clear();

        // Process ISTExec
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getISTExecheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getISTExecheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getISTExecheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            ISTExec = tmpDates.get(0);
        }
        tmpDates.clear();

        // Process Closeout
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getCloseOutheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getCloseOutheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getCloseOutheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            CloseOut = tmpDates.get(0);
        }
        tmpDates.clear();

        // Process Agile
        for (ProjectDetailsStatusViewModel i : detailStatus) {
            if (!("NA".equalsIgnoreCase(i.getAgileheaderDueDate()))) {
                try {
                    Date t = yFormat.parse(i.getAgileheaderDueDate());
                    tmpDates.add(t);
                } catch (ParseException pe) {
                    logger.error("can't parse date from value " + i.getAgileheaderDueDate()
                            + ", so skipping .. exception: " + pe.getMessage());
                }
            }
        }
        if (tmpDates.size() > 0) {
            // sort all BRduedates, pick the earliest one as the final one
            Collections.sort(tmpDates, new Comparator<Date>() {
                @Override
                public int compare(Date o1, Date o2) {
                    return o1.compareTo(o2);
                }
            });
            Agile = tmpDates.get(0);
        }
        tmpDates.clear();

        // TODO
        if (BR != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setBRheaderDueDate(yFormat.format(BR));
                }
            } catch (Exception pe) {
                logger.error("Can not convert BR from Date " + BR.toString() + ", pe: " + pe.getMessage()
                        + ".  Skipping..");
            }
        }

        if (SR != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setSRheaderDueDate(yFormat.format(SR));
                }
            } catch (Exception pe) {
                logger.error("Can not convert SR from Date " + SR.toString() + ", pe: " + pe.getMessage()
                        + ".  Skipping..");
            }
        }

        if (HLD != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setHLDheaderDueDate(yFormat.format(HLD));
                }
            } catch (Exception pe) {
                logger.error("Can not convert HLD from Date " + HLD.toString() + ", pe: " + pe.getMessage()
                        + ".  Skipping..");
            }
        }

        if (AID != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setAIDheaderDueDate(yFormat.format(AID));
                }
            } catch (Exception pe) {
                logger.error("Can not convert AID from Date " + AID.toString() + ", pe: " + pe.getMessage()
                        + ".  Skipping..");
            }
        }

        if (AD != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setDESheaderDueDate(yFormat.format(AD));
                }
            } catch (Exception pe) {
                logger.error("Can not convert AD from Date " + AD.toString() + ", pe: " + pe.getMessage()
                        + ".  Skipping..");
            }
        }

        if (DEV != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setDEVheaderDueDate(yFormat.format(DEV));
                }
            } catch (Exception pe) {
                logger.error("Can not convert DEV from Date " + DEV.toString() + ", pe: " + pe.getMessage()
                        + ".  Skipping..");
            }
        }

        if (IST != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setISTheaderDueDate(yFormat.format(IST));
                }
            } catch (Exception pe) {
                logger.error("Can not convert IST from Date " + IST.toString() + ", pe: " + pe.getMessage()
                        + ".  Skipping..");
            }
        }

        if (ISTExec != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setISTExecheaderDueDate(yFormat.format(ISTExec));
                }
            } catch (Exception pe) {
                logger.error("Can not convert ISTExec from Date " + ISTExec.toString() + ", pe: " + pe.getMessage()
                        + ".  Skipping..");
            }
        }

        if (CloseOut != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setCloseOutheaderDueDate(yFormat.format(CloseOut));
                }
            } catch (Exception pe) {
                logger.error("Can not convert CloseOut from Date " + CloseOut.toString() + ", pe: "
                        + pe.getMessage() + ".  Skipping..");
            }
        }

        if (Agile != null) {
            try {
                for (ProjectDetailsStatusViewModel i : detailStatus) {
                    i.setAgileheaderDueDate(yFormat.format(Agile));
                }
            } catch (Exception pe) {
                logger.error("Can not convert Agile from Date " + Agile.toString() + ", pe: " + pe.getMessage()
                        + ".  Skipping..");
            }
        }

        return detailStatus;
    }

    private static String getRowDueDatePercentageString(String Percentage, String Duedate, String UpdatedByUUID,
            String uuid, String headerDueDate, boolean left, boolean validateThreshold) {
        String[] datecreatedList = Duedate.split(",");
        String[] percentageList = Percentage.split(",");
        String[] uuidList = UpdatedByUUID.split(",");

        SimpleDateFormat xFormat = new SimpleDateFormat("MM/dd/yyyy");
        SimpleDateFormat yFormat = new SimpleDateFormat("MM/dd/yy");

        if (datecreatedList == null || datecreatedList.length == 0) {
            return "NA";
        }

        if (("NA".equalsIgnoreCase(datecreatedList[0])) || ("NA".equalsIgnoreCase(headerDueDate))) {
            return "NA";
        }

        if (percentageList.length != datecreatedList.length) {
            //logger.error("Error, DateCreated count does not equal Percentage count");
            return "";
        }

        try {
            // mchan: added code to evaluate if the latest updated date fits in the threashold
            // get threshold info for user, 1 = noupdate, 2 = duein
            List<Threshold> thresholds = DataService.getEmployeeThresholds(uuid);
            String warningMsg = "";

            if (thresholds != null && !thresholds.isEmpty() && validateThreshold) {
                // since we have a list of dates, we just need the max
                List<Integer> noupdates = new ArrayList<Integer>();
                List<Integer> dueins = new ArrayList<Integer>();
                String percent = percentageList[0];
                BigDecimal d = new BigDecimal(percent.trim().replace("%", "")).divide(BigDecimal.valueOf(100));
                if (d.compareTo(BigDecimal.ONE) == 0) {
                    //logger.error(d + ", is exactly one");
                } else if (d.compareTo(BigDecimal.ONE) == 1) {
                    //logger.error(d + ", is greater than one");
                } else if (d.compareTo(BigDecimal.ONE) == -1) {
                    //logger.error(d + ", is less than one");
                }

                for (Threshold t : thresholds) {
                    // process NoUpdate
                    if (PiratesConstants.NOUPDATE.equalsIgnoreCase(t.getThresholdType())) {
                        try {
                            noupdates.add(Integer.parseInt(t.getThresholdValue()));
                        } catch (NumberFormatException ex) {
                            //logger.error("Error parsing threshold value, type: NOUPDATE, value: " + t.getThresholdValue());
                        }
                    }
                    // process DueIn
                    if (PiratesConstants.DUEIN.equalsIgnoreCase(t.getThresholdType())) {
                        try {
                            dueins.add(Integer.parseInt(t.getThresholdValue()));
                        } catch (NumberFormatException ex) {
                            //logger.error("Error parsing threshold value, type: DUEIN, value: " + t.getThresholdValue());
                        }
                    }
                } // done parsing thresholds                   

                if (!noupdates.isEmpty() && (d.compareTo(BigDecimal.ONE) == -1)
                        && (!"NA".equalsIgnoreCase(datecreatedList[0])) && validateThreshold) {
                    // compare dates, last updated and today and then match it with the maxnoupdate and maxduein
                    // last updated date
                    Date lastUpdated = xFormat.parse(datecreatedList[0]);
                    Date today = new Date();
                    if (lastUpdated.before(today)) {
                        long diff = today.getTime() - lastUpdated.getTime();
                        int diffindays = (int) (diff / (24 * 60 * 60 * 1000));

                        Collections.sort(noupdates);
                        Integer[] foo = noupdates.toArray(new Integer[noupdates.size()]);
                        // now in descending order
                        ArrayUtils.reverse(foo);
                        for (Integer i : foo) {
                            if (diffindays >= i) {
                                warningMsg = "Status is static for more than " + String.valueOf(i) + " days! <br/>";
                                break;
                            }
                        }
                    } else {
                        warningMsg = "Today cannot be before LastUpdatedDate ??!";
                    }
                }

                // check artifact due in x number if days, but ignore NA
                if ((!dueins.isEmpty()) && (d.compareTo(BigDecimal.ONE) == -1)
                        && (!"NA".equalsIgnoreCase(headerDueDate))) {
                    Collections.sort(dueins);
                    Date dueDate = xFormat.parse(headerDueDate);
                    Date today = new Date();

                    if (today.before(dueDate)) {
                        // logger.error("dueDate.getTime() is: " + dueDate.getTime());
                        // logger.error("today.getTime() is: " + today.getTime());

                        long diff = dueDate.getTime() - today.getTime();
                        int diffindays = (int) (diff / (24 * 60 * 60 * 1000));
                        // logger.error("dueDate.getTime() - today.getTime() is: " + diffindays);

                        Collections.sort(dueins);
                        Integer[] foo = dueins.toArray(new Integer[dueins.size()]);
                        // now in descending order
                        ArrayUtils.reverse(foo);
                        for (Integer i : foo) {
                            if (diffindays <= i) {
                                warningMsg = warningMsg + "Artifact is due in "
                                        + (diffindays == 0 ? "less than a day"
                                                : String.valueOf(diffindays) + " days");
                                break;
                            }
                        }
                    } else {
                        // logger.error("header duedate is: " + dueDate);
                        // logger.error("today is: " + today);    
                        // logger.error("Today is NOT before due date ??");
                        warningMsg = warningMsg + "Project overdue";
                    }
                }
            } // end processing thresholds

            int i = 0;
            // display in dropdown from greatest to least, so we need to revert the array
            StringBuilder selectHtml = new StringBuilder();

            if (!warningMsg.isEmpty()) {
                selectHtml.append(
                        "<div class='dropdown'> <button style='background-color: #FF8080' class='btn btn-default dropdown-toggle' type='button' id='dropdownMenu1' data-toggle='dropdown' aria-expanded='true'>");
            } else {
                selectHtml.append(
                        "<div class='dropdown'> <button class='btn btn-default dropdown-toggle' type='button' id='dropdownMenu1' data-toggle='dropdown' aria-expanded='true'>");
            }
            selectHtml.append(yFormat.format(xFormat.parse(datecreatedList[0]))).append("&nbsp;&nbsp;")
                    .append(percentageList[0]);
            selectHtml.append("<span class='caret'></span></button>");
            selectHtml.append("<ul class='dropdown-menu' role='menu' aria-labelledby='dropdownMenu1'>");

            for (String s : datecreatedList) {
                String tmplblBRduedate = yFormat.format(xFormat.parse(s));
                // logger.error("DueDate is: " + tmplblBRduedate);
                String percentStr = percentageList[i];
                String byuuidstr = uuidList[i];
                String newUUID = getATTEmployeeObjectByUUID(byuuidstr).getFullName();
                if (i == 0 && !warningMsg.isEmpty()) {
                    if (!left) {
                        // tooltip on the right side
                        selectHtml.append("<li role='presentation'>")
                                .append("<a role='menuitem' tabindex='-1' href='#'>").append(tmplblBRduedate)
                                .append("&nbsp;&nbsp;" + percentStr + "&nbsp;")
                                .append("<span class='glyphicon glyphicon-question-sign question' id='mytimestamp' data='")
                                .append(warningMsg).append("'></span>").append("</a>").append("</li>");
                    } else {
                        // tooltip on left
                        selectHtml.append(
                                "<li role='presentation'><a role='menuitem' tabindex='-1' href='#'><span class='glyphicon glyphicon-question-sign question' id='mytimestamp' data='")
                                .append(warningMsg).append("'></span> &nbsp;").append(tmplblBRduedate)
                                .append("&nbsp;&nbsp;" + percentStr + "</a> </li>");
                    }
                } else {
                    if (!left) {
                        // tooltip on the right side
                        selectHtml.append("<li role='presentation'>")
                                .append("<a role='menuitem' tabindex='-1' href='#'>").append(tmplblBRduedate)
                                .append("&nbsp;&nbsp;" + percentStr + "&nbsp;")
                                .append("<span class='glyphicon glyphicon-question-sign question' id='mytimestamp' data='")
                                .append("Last updated by: " + newUUID).append("'></span>").append("</a>")
                                .append("</li>");
                    } else {
                        selectHtml.append(
                                "<li role='presentation'><a role='menuitem' tabindex='-1' href='#'><span class='glyphicon glyphicon-question-sign question' id='mytimestamp' data='")
                                .append("Last updated by: " + newUUID).append("'></span> &nbsp;")
                                .append(tmplblBRduedate).append("&nbsp;&nbsp;" + percentStr + "</a> </li>");
                    }
                }
                i++;
            }

            selectHtml.append("</ul>");
            selectHtml.append("</div>");
            return selectHtml.toString();
        } catch (Exception ex) {
            logger.error(msgHeader + "Error occurred getRowDueDatePercentageString... " + ex.getMessage());
        }
        return null;
    }

    private static void getAppProjectArtifactHistory() {
        // TODO:  port over to hibernate later
        artifactHistory = new ArrayList<AppProjectArtifactOwnersHistory>();
        // logger.error(msgHeader + "getAppProjectArtifactHistory called. ");
        ResultSet rs = null;
        Connection conn = null;
        PreparedStatement preparedStatement = null;

        try {
            conn = DBUtility.getDBConnection();
            // SQL query command
            String SQL = " Select UUID " + "      ,DueDate " + "      ,CompletionDate "
                    + "      ,PercentageComplete " + "      ,ArtifactName " + "      ,PRISMId "
                    + "      ,ApplicationName " + "      ,ModuleId " + "      ,IsPrimaryOwner "
                    + "      ,MileStoneId " + "      ,ExecutionPercentage " + "      ,ProjectCloseOutPercentage "
                    + "      ,DateLogged " + "      ,DateCreated " + "      ,SystemNote " + "      ,UpdatedByUUID "
                    + "  from dbo.AppProjectArtifactOwnersHistory "
                    + "  order by PRISMId, ApplicationName, ArtifactName, DateLogged desc  ";

            preparedStatement = conn.prepareStatement(SQL);

            rs = preparedStatement.executeQuery();
            int rowCount = 0;

            while (rs.next()) {
                rowCount++;

                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                SimpleDateFormat yFormat = new SimpleDateFormat("MM/dd/yyyy");
                // for percentage
                NumberFormat defaultFormat = NumberFormat.getPercentInstance();
                defaultFormat.setMinimumFractionDigits(0);
                //
                String uuid = rs.getString("UUID");
                //
                String theDueDate = rs.getString("DueDate");
                String dueDate = yFormat.format(format.parse(theDueDate));
                // 
                String theCompDate = rs.getString("CompletionDate") == null ? "1900-01-01 14:58:00.00"
                        : rs.getString("CompletionDate");
                String completionDate = yFormat.format(format.parse(theCompDate));

                //
                double percentComplete = Double.parseDouble(
                        rs.getString("PercentageComplete") == null ? "0" : rs.getString("PercentageComplete"));
                String PercentCompleted = defaultFormat.format(percentComplete);
                //
                String artifactName = rs.getString("ArtifactName");
                //
                String applicationName = rs.getString("ApplicationName");
                //
                String moduleId = rs.getString("ModuleId");
                // 
                String isPrimary = rs.getString("IsPrimaryOwner");
                // 
                String mileStoneId = rs.getString("MileStoneId");
                //
                double ExecPercent = Double.parseDouble(
                        rs.getString("ExecutionPercentage") == null ? "0" : rs.getString("ExecutionPercentage"));
                String ExecutionPercentage = defaultFormat.format(ExecPercent);
                //
                double prjCOPercent = Double.parseDouble(rs.getString("ProjectCloseOutPercentage") == null ? "0"
                        : rs.getString("ProjectCloseOutPercentage"));
                String PrjCloseOutPercentage = defaultFormat.format(prjCOPercent);
                //
                String logCreated = rs.getString("DateLogged");
                String dateLogged = yFormat.format(format.parse(logCreated));
                //
                String dCreated = rs.getString("DateCreated") == null ? rs.getString("DateLogged")
                        : rs.getString("DateCreated");
                String dateCreated = yFormat.format(format.parse(dCreated));
                //
                String updatedByUUID = rs.getString("UpdatedByUUID");
                //
                String systemNote = rs.getString("SystemNote");
                //
                String prismID = rs.getString("PRISMId");

                AppProjectArtifactOwnersHistory p = new AppProjectArtifactOwnersHistory();
                p.setUUID(uuid);
                p.setDueDate(dueDate);
                p.setCompletionDate(completionDate);
                p.setPercentageComplete(PercentCompleted);
                p.setArtifactName(artifactName);
                p.setPRISMId(prismID); // PRISMId
                p.setApplicationName(applicationName);
                p.setModuleId(moduleId);
                p.setIsPrimaryOwner(isPrimary.equalsIgnoreCase("1"));
                p.setMileStoneId(mileStoneId);
                p.setExecutionPercentage(ExecutionPercentage);
                p.setProjectCloseOutPercentage(PrjCloseOutPercentage);
                p.setDateCreated(dateCreated);
                p.setUpdatedByUUID(updatedByUUID);
                p.setSystemNote(systemNote);
                p.setDateLogged(dateLogged);

                artifactHistory.add(p);

            }
            // logger.error(msgHeader + "getStatusHistoryListByApplicationOwner called, got results: "+rowCount);
        } catch (SQLException e) {
            logger.error(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (preparedStatement != null)
                    preparedStatement.close();
            } catch (Exception e) {
            }
            ;
            try {
                if (conn != null)
                    conn.close();
            } catch (Exception e) {
            }
            ;
        }

    }

    private static List<AppProjectArtifactOwnersHistory> getStatusHistoryListByApplicationOwner(
            ProjectAppOwnerModel application) {
        if (artifactHistory == null) {
            getAppProjectArtifactHistory();
        }

        List<AppProjectArtifactOwnersHistory> results = new ArrayList<AppProjectArtifactOwnersHistory>();
        /*
        select *
        from dbo.AppProjectArtifactOwnersHistory
        where ArtifactName = ''
        and PRISMId = ''
        and ApplicationName = ''
        and ModuleId = ''
        and MileStoneId = ''
        */

        // TODO:  port over to hibernate later
        // logger.error(msgHeader + "getStatusHistoryListByApplicationOwner called. ");

        int counter = 0;
        try {
            for (AppProjectArtifactOwnersHistory h : artifactHistory) {
                if (h.getArtifactName().equalsIgnoreCase(application.getArtifactName())
                        && h.getPRISMId().equalsIgnoreCase(application.getPrismId())
                        && h.getApplicationName().equalsIgnoreCase(application.getApplicationName())
                        && h.getModuleId().equalsIgnoreCase(application.getModuleId())
                        && h.getMileStoneId().equalsIgnoreCase(application.getMileStoneId())) {
                    counter++;
                    results.add(h);
                }
            }

            // logger.error(msgHeader + "getStatusHistoryListByApplicationOwner called, got results: "+ counter);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

        return results;
    }
}