org.cgiar.ccafs.ap.action.projects.ProjectDescriptionAction.java Source code

Java tutorial

Introduction

Here is the source code for org.cgiar.ccafs.ap.action.projects.ProjectDescriptionAction.java

Source

/*****************************************************************
 * This file is part of CCAFS Planning and Reporting Platform.
 * CCAFS P&R is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * at your option) any later version.
 * CCAFS P&R is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with CCAFS P&R. If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************/
package org.cgiar.ccafs.ap.action.projects;

import org.cgiar.ccafs.ap.action.BaseAction;
import org.cgiar.ccafs.ap.config.APConstants;
import org.cgiar.ccafs.ap.data.manager.BudgetManager;
import org.cgiar.ccafs.ap.data.manager.HistoryManager;
import org.cgiar.ccafs.ap.data.manager.IPProgramManager;
import org.cgiar.ccafs.ap.data.manager.LiaisonInstitutionManager;
import org.cgiar.ccafs.ap.data.manager.ProjectCofinancingLinkageManager;
import org.cgiar.ccafs.ap.data.manager.ProjectManager;
import org.cgiar.ccafs.ap.data.manager.UserManager;
import org.cgiar.ccafs.ap.data.model.IPProgram;
import org.cgiar.ccafs.ap.data.model.LiaisonInstitution;
import org.cgiar.ccafs.ap.data.model.Project;
import org.cgiar.ccafs.ap.data.model.ProjectStatusEnum;
import org.cgiar.ccafs.ap.data.model.User;
import org.cgiar.ccafs.ap.util.FileManager;
import org.cgiar.ccafs.ap.validation.projects.ProjectDescriptionValidator;
import org.cgiar.ccafs.utils.APConfig;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProjectDescriptionAction extends BaseAction {

    private static Logger LOG = LoggerFactory.getLogger(ProjectDescriptionAction.class);
    private static final long serialVersionUID = 2845669913596494699L;

    // Manager
    private ProjectManager projectManager;
    private IPProgramManager ipProgramManager;
    private LiaisonInstitutionManager liaisonInstitutionManager;
    private UserManager userManager;
    private BudgetManager budgetManager;
    private HistoryManager historyManager;
    private ProjectCofinancingLinkageManager linkedProjectManager;

    // Model for the front-end
    private List<IPProgram> ipProgramRegions;
    private List<IPProgram> ipProgramFlagships;
    private List<LiaisonInstitution> liaisonInstitutions;
    private Map<String, String> projectStauses;
    private List<User> allOwners;
    private Map<String, String> projectTypes;

    // Model for the back-end
    private Project previousProject;
    private Project project;
    private int projectID;

    // These variables can contain either the information of the project workplan or the bilateral contract proposal
    private File file;
    private File fileReporting;
    private String fileContentType;
    private String fileFileName;
    private String fileReportingFileName;

    private ProjectDescriptionValidator validator;

    @Inject
    public ProjectDescriptionAction(APConfig config, ProjectManager projectManager,
            IPProgramManager ipProgramManager, UserManager userManager, BudgetManager budgetManager,
            LiaisonInstitutionManager liaisonInstitutionManager,
            ProjectCofinancingLinkageManager linkedCoreProjectManager, HistoryManager historyManager,
            ProjectDescriptionValidator validator) {
        super(config);
        this.projectManager = projectManager;
        this.ipProgramManager = ipProgramManager;
        this.userManager = userManager;
        this.budgetManager = budgetManager;
        this.liaisonInstitutionManager = liaisonInstitutionManager;
        this.linkedProjectManager = linkedCoreProjectManager;
        this.historyManager = historyManager;
        this.validator = validator;
    }

    public List<User> getAllOwners() {
        return allOwners;
    }

    /**
     * Return the absolute path where the bilateral contract is or should be located.
     * 
     * @return complete path where the image is stored
     */
    private String getAnnualReportAbsolutePath() {
        return config.getUploadsBaseFolder() + File.separator + this.getAnualReportRelativePath() + File.separator;
    }

    private String getAnualReportRelativePath() {
        return config.getProjectsBaseFolder() + File.separator + project.getId() + File.separator
                + config.getAnualReportFolder() + File.separator;
    }

    public String getAnualReportURL() {
        return config.getDownloadURL() + "/" + this.getAnualReportRelativePath().replace('\\', '/');
    }

    /**
     * Return the absolute path where the bilateral contract is or should be located.
     * 
     * @return complete path where the image is stored
     */
    private String getBilateralContractAbsolutePath() {
        return config.getUploadsBaseFolder() + File.separator + this.getBilateralProposalRelativePath()
                + File.separator;
    }

    public String getBilateralContractURL() {
        return config.getDownloadURL() + "/" + this.getBilateralProposalRelativePath().replace('\\', '/');
    }

    private String getBilateralProposalRelativePath() {
        return config.getProjectsBaseFolder() + File.separator + project.getId() + File.separator
                + config.getBilateralProjectContractProposalFolder() + File.separator;
    }

    /**
     * This method returns a composed name with the Acronym and Name.
     * e.g. FP4: Policies and Institutions for Climate-Resilient Food Systems
     * 
     * @param ipProgramId is the program identifier.
     * @return the composed name described above.
     */
    public String getComposedName(int ipProgramId) {
        for (IPProgram p : ipProgramFlagships) {
            if (p.getId() == ipProgramId) {
                return p.getAcronym() + ": " + p.getName();
            }
        }
        return null;
    }

    public int getEndYear() {
        return config.getEndYear();
    }

    public File getFile() {
        return file;
    }

    public String getFileContentType() {
        return fileContentType;
    }

    public String getFileFileName() {
        return fileFileName;
    }

    public File getFileReporting() {
        return fileReporting;
    }

    public String getFileReportingFileName() {
        return fileReportingFileName;
    }

    /**
     * This method returns an array of flagship ids depending on the project.flagships attribute.
     * 
     * @return an array of integers.
     */
    public int[] getFlagshipIds() {
        if (this.project.getFlagships() != null) {
            int[] ids = new int[this.project.getFlagships().size()];
            for (int c = 0; c < ids.length; c++) {
                ids[c] = this.project.getFlagships().get(c).getId();
            }
            return ids;
        }
        return null;
    }

    public List<IPProgram> getIpProgramFlagships() {
        return ipProgramFlagships;
    }

    public List<IPProgram> getIpProgramRegions() {
        return ipProgramRegions;
    }

    public List<LiaisonInstitution> getLiaisonInstitutions() {
        return liaisonInstitutions;
    }

    public Project getProject() {
        return project;
    }

    public int getProjectID() {
        return projectID;
    }

    public String getProjectRequest() {
        return APConstants.PROJECT_REQUEST_ID;
    }

    public Map<String, String> getProjectStauses() {
        return projectStauses;
    }

    public Map<String, String> getProjectTypes() {
        return projectTypes;
    }

    /**
     * This method returns an array of region ids depending on the project.regions attribute.
     * 
     * @return an array of integers.
     */
    public int[] getRegionIds() {
        if (this.project.getRegions() != null) {
            int[] ids = new int[this.project.getRegions().size()];
            for (int c = 0; c < ids.length; c++) {
                ids[c] = this.project.getRegions().get(c).getId();
            }
            return ids;
        }
        return null;
    }

    public int getStartYear() {
        return config.getStartYear();
    }

    private String getWorkplanRelativePath() {
        return config.getProjectsBaseFolder() + File.separator + project.getId() + File.separator
                + config.getProjectWorkplanFolder() + File.separator;
    }

    public String getWorkplanURL() {
        return config.getDownloadURL() + "/" + this.getWorkplanRelativePath().replace('\\', '/');
    }

    /**
     * Return the absolute path where the work plan is or should be located.
     * 
     * @param workplan name
     * @return complete path where the image is stored
     */
    private String getWorplansAbsolutePath() {
        return config.getUploadsBaseFolder() + File.separator + this.getWorkplanRelativePath() + File.separator;
    }

    public boolean isNewProject() {
        return project.isNew(config.getCurrentPlanningStartDate());
    }

    @Override
    public String next() {
        String result = this.save();
        if (result.equals(BaseAction.SUCCESS)) {
            return BaseAction.NEXT;
        } else {
            return result;
        }
    }

    @Override
    public void prepare() throws Exception {

        super.prepare();

        try {
            projectID = Integer
                    .parseInt(StringUtils.trim(this.getRequest().getParameter(APConstants.PROJECT_REQUEST_ID)));
        } catch (NumberFormatException e) {
            LOG.error("-- prepare() > There was an error parsing the project identifier '{}'.", projectID, e);
            projectID = -1;
            return; // Stop here and go to execute method.
        }

        // Getting the information for the Project Owner Contact Persons for the View
        allOwners = userManager.getAllOwners();

        // Getting the information of the Regions program for the View
        ipProgramRegions = ipProgramManager.getProgramsByType(APConstants.REGION_PROGRAM_TYPE);

        // Getting the information of the Flagships program for the View
        ipProgramFlagships = ipProgramManager.getProgramsByType(APConstants.FLAGSHIP_PROGRAM_TYPE);

        // Get the list of institutions that can be management liaison of a project.
        liaisonInstitutions = liaisonInstitutionManager.getLiaisonInstitutions();

        projectStauses = new HashMap<>();
        List<ProjectStatusEnum> list = Arrays.asList(ProjectStatusEnum.values());
        for (ProjectStatusEnum projectStatusEnum : list) {
            projectStauses.put(projectStatusEnum.getStatusId(), projectStatusEnum.getStatus());
        }
        // Getting project
        project = projectManager.getProject(projectID);
        if (project != null) {
            // Getting the information of the Flagships Program associated with the project
            project.setRegions(ipProgramManager.getProjectFocuses(projectID, APConstants.REGION_PROGRAM_TYPE));
            // Getting the information of the Regions Program associated with the project
            project.setFlagships(ipProgramManager.getProjectFocuses(projectID, APConstants.FLAGSHIP_PROGRAM_TYPE));
        }

        // If project is CCAFS cofounded, we should load the core projects linked to it.
        if (!project.isBilateralProject()) {
            project.setLinkedProjects(linkedProjectManager.getLinkedBilateralProjects(projectID));
        } else {
            project.setLinkedProjects(linkedProjectManager.getLinkedCoreProjects(projectID));
        }

        projectTypes = new HashMap<>();
        projectTypes.put(APConstants.PROJECT_CORE, this.getText("planning.projectDescription.projectType.core"));
        projectTypes.put(APConstants.PROJECT_BILATERAL,
                this.getText("planning.projectDescription.projectType.bilateral"));
        projectTypes.put(APConstants.PROJECT_CCAFS_COFUNDED,
                this.getText("planning.projectDescription.projectType.cofounded"));
        projectTypes.put(APConstants.PROJECT_BILATERAL,
                this.getText("planning.projectDescription.projectType.bilateral"));

        // If the user is not admin or the project owner, we should keep some information
        // unmutable
        previousProject = new Project();
        previousProject.setId(project.getId());
        previousProject.setTitle(project.getTitle());
        previousProject.setLiaisonInstitution(project.getLiaisonInstitution());
        previousProject.setOwner(project.getOwner());
        previousProject.setStartDate(project.getStartDate());
        previousProject.setEndDate(project.getEndDate());
        previousProject.setSummary(project.getSummary());
        previousProject.setFlagships(project.getFlagships());
        previousProject.setRegions(project.getRegions());
        previousProject.setType(project.getType());
        previousProject.setWorkplanRequired(project.isWorkplanRequired());
        previousProject.setBilateralContractRequired(project.isBilateralContractRequired());
        previousProject.setWorkplanName(project.getWorkplanName());
        previousProject.setBilateralContractProposalName(project.getBilateralContractProposalName());
        previousProject.setAnnualReportDonor(project.getAnnualReportDonor());

        if (project.getLinkedProjects() != null) {
            List<Project> linkedProjects = new ArrayList<>();
            for (Project p : project.getLinkedProjects()) {
                linkedProjects.add(new Project(p.getId()));
            }

            previousProject.setLinkedProjects(linkedProjects);
        }

        super.setHistory(historyManager.getProjectDescriptionHistory(project.getId()));

        if (this.isHttpPost()) {
            if (project.getLinkedProjects() != null) {
                project.getLinkedProjects().clear();
            }

        }
        // Initializing Section Statuses:
        this.initializeProjectSectionStatuses(project, this.getCycleName());
    }

    @Override
    public String save() {
        if (this.hasProjectPermission("update", projectID)) {
            // If the user can edit the dates, delete the budgets that correspond to years that are not linked to the
            // project anymore to prevent errors in the project budget section.
            if (this.hasProjectPermission("startDate", projectID)
                    || this.hasProjectPermission("endDate", projectID)) {
                List<Integer> currentYears = project.getAllYears();
                List<Integer> previousYears = previousProject.getAllYears();
                for (Integer previousYear : previousYears) {
                    if (!currentYears.contains(previousYear)) {
                        budgetManager.deleteBudgetsByYear(projectID, previousYear.intValue(), this.getCurrentUser(),
                                this.getJustification());
                    }
                }
                budgetManager.deleteBudgetsFromUnexistentYears(projectID);
            }

            // Update only the values to which the user is authorized to modify
            if (this.hasProjectPermission("title", projectID)) {
                previousProject.setTitle(project.getTitle());
            }

            if (this.hasProjectPermission("managementLiaison", projectID)) {
                previousProject.setLiaisonInstitution(project.getLiaisonInstitution());
                previousProject.setOwner(project.getOwner());
            }

            if (this.hasProjectPermission("startDate", projectID)) {
                previousProject.setStartDate(project.getStartDate());
            }

            if (this.hasProjectPermission("endDate", projectID)) {
                previousProject.setEndDate(project.getEndDate());
            }

            if (this.hasProjectPermission("workplan", projectID)) {
                previousProject.setWorkplanRequired(project.isWorkplanRequired());
                // previousProject.setBilateralContractRequired(project.isBilateralContractRequired());
            }

            if (!project.isBilateralProject() && previousProject.isWorkplanRequired()) {
                if (file != null) {
                    if (previousProject.getWorkplanName() != null) {
                        FileManager.deleteFile(this.getWorplansAbsolutePath() + previousProject.getWorkplanName());
                    }

                    previousProject.setWorkplanName(fileFileName);
                    FileManager.copyFile(file, this.getWorplansAbsolutePath() + previousProject.getWorkplanName());
                } else {

                    previousProject.setWorkplanName(project.getWorkplanName());
                    if (project.getWorkplanName() != null && project.getWorkplanName().isEmpty()) {
                        FileManager.deleteFile(this.getWorplansAbsolutePath() + previousProject.getWorkplanName());
                        previousProject.setWorkplanName("");
                    }
                }
            } else if (previousProject.isBilateralProject()) {
                if (file != null) {
                    if (previousProject.getBilateralContractProposalName() != null) {
                        FileManager.deleteFile(this.getBilateralContractAbsolutePath()
                                + previousProject.getBilateralContractProposalName());
                    }

                    previousProject.setBilateralContractProposalName(fileFileName);
                    FileManager.copyFile(file, this.getBilateralContractAbsolutePath()
                            + previousProject.getBilateralContractProposalName());
                } else {

                    if (previousProject.getBilateralContractProposalName() != null
                            && previousProject.getBilateralContractProposalName().isEmpty()) {
                        FileManager.deleteFile(this.getBilateralContractAbsolutePath()
                                + previousProject.getBilateralContractProposalName());
                        previousProject.setBilateralContractProposalName("");
                    }
                }
            }

            // TODO - Update the type of projects and all the implications.
            // previousProject.setType(project.getType());

            if (previousProject.isBilateralProject()) {
                if (this.hasProjectPermission("bilateralContract", projectID)) {
                    if (file != null) {
                        FileManager.deleteFile(this.getBilateralContractAbsolutePath()
                                + previousProject.getBilateralContractProposalName());
                        FileManager.copyFile(file, this.getBilateralContractAbsolutePath()
                                + previousProject.getBilateralContractProposalName());
                        previousProject.setBilateralContractProposalName(fileFileName);
                    } else {
                        previousProject
                                .setBilateralContractProposalName(project.getBilateralContractProposalName());
                        if (project.getBilateralContractProposalName() != null
                                && project.getBilateralContractProposalName().isEmpty()) {
                            previousProject.setBilateralContractProposalName("");
                            FileManager.deleteFile(this.getWorplansAbsolutePath()
                                    + previousProject.getBilateralContractProposalName());
                        }
                    }
                }
                if (this.getCycleName().equals(APConstants.REPORTING_SECTION)) {
                    if (fileReporting != null) {
                        FileManager.deleteFile(
                                this.getAnnualReportAbsolutePath() + previousProject.getAnnualReportDonor());
                        FileManager.copyFile(fileReporting,
                                this.getAnnualReportAbsolutePath() + fileReportingFileName);
                        previousProject.setAnnualReportDonor(fileReportingFileName);
                    } else {
                        previousProject.setAnnualReportDonor(project.getAnnualReportDonor());
                        if (project.getAnnualReportDonor() != null && !project.getAnnualReportDonor().isEmpty()) {

                            FileManager.deleteFile(
                                    this.getAnnualReportAbsolutePath() + previousProject.getAnnualReportDonor());
                            previousProject.setAnnualReportDonor("");
                        }
                    }
                }
            }

            if (this.hasProjectPermission("summary", projectID)) {
                previousProject.setSummary(project.getSummary());
            }

            // Save the information
            int result = projectManager.saveProjectDescription(previousProject, this.getCurrentUser(),
                    this.getJustification());
            if (project.getLinkedProjects().isEmpty()) {
                project.setCofinancing(false);
            } else {
                project.setCofinancing(true);
            }
            projectManager.updateProjectCofinancing(project);
            if (result < 0) {
                this.addActionError(this.getText("saving.problem"));
                LOG.warn("There was a problem saving the project description.");
                return BaseAction.INPUT;
            }

            // Save the regions and flagships

            if (this.hasProjectPermission("flagships", projectID)) {
                List<IPProgram> previousFlagships = previousProject.getFlagships();
                List<IPProgram> flagships = project.getFlagships();
                boolean saved = true;

                // TODO - To allow de-select flagships and regions we need to make
                // validations in the project outcomes

                // Save only the new flagships
                for (IPProgram flagship : flagships) {
                    if (!previousFlagships.contains(flagship)) {
                        saved = ipProgramManager.saveProjectFocus(project.getId(), flagship.getId(),
                                this.getCurrentUser(), this.getJustification());
                    }
                }

                if (!saved) {
                    this.addActionError(this.getText("saving.problem"));
                    LOG.warn("There was a problem saving the project flagships.");
                    return BaseAction.INPUT;
                }
            }

            if (this.hasProjectPermission("regions", projectID)) {
                List<IPProgram> previousRegions = previousProject.getRegions();
                boolean saved = true;

                // Save only the new regions
                for (IPProgram region : project.getRegions()) {
                    if (!previousRegions.contains(region)) {
                        saved = saved && ipProgramManager.saveProjectFocus(project.getId(), region.getId(),
                                this.getCurrentUser(), this.getJustification());
                    }
                }

                if (!saved) {
                    this.addActionError(this.getText("saving.problem"));
                    LOG.warn("There was a problem saving the project regions.");
                    return BaseAction.INPUT;
                }
            }

            // Save the contributing core projects if any
            List<Integer> linkedProjectsToDelete = new ArrayList<>();
            for (Project p : previousProject.getLinkedProjects()) {
                if (!project.getLinkedProjects().contains(p)) {
                    linkedProjectsToDelete.add(p.getId());
                }
            }

            if (!linkedProjectsToDelete.isEmpty()) {
                if (project.isBilateralProject()) {
                    linkedProjectManager.deletedLinkedCoreProjects(project, linkedProjectsToDelete,
                            this.getCurrentUser(), this.getJustification());
                } else {
                    linkedProjectManager.deletedLinkedBilateralProjects(project, linkedProjectsToDelete,
                            this.getCurrentUser(), this.getJustification());
                }
            }

            // Then save the new core projects linked
            if (!project.getLinkedProjects().isEmpty()) {
                if (previousProject.isBilateralProject()) {
                    linkedProjectManager.saveLinkedCoreProjects(project, this.getCurrentUser(),
                            this.getJustification());
                } else {
                    linkedProjectManager.saveLinkedBilateralProjects(project, this.getCurrentUser(),
                            this.getJustification());
                }
            }

            // Adjust the type of all projects according to their links with other projects.
            projectManager.updateProjectTypes();

            // Get the validation messages and append them to the save message
            Collection<String> messages = this.getActionMessages();
            if (!messages.isEmpty()) {
                String validationMessage = messages.iterator().next();
                this.setActionMessages(null);
                this.addActionWarning(this.getText("saving.saved") + validationMessage);
            } else {
                this.addActionMessage(this.getText("saving.saved"));
            }
            return SUCCESS;
        }
        return NOT_AUTHORIZED;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public void setFileContentType(String fileContentType) {
        this.fileContentType = fileContentType;
    }

    public void setFileFileName(String fileFileName) {
        this.fileFileName = fileFileName;
    }

    public void setFileReporting(File fileReporting) {
        this.fileReporting = fileReporting;
    }

    public void setFileReportingFileName(String fileReportingFileName) {
        this.fileReportingFileName = fileReportingFileName;
    }

    public void setIpProgramFlagships(List<IPProgram> ipProgramFlagships) {
        this.ipProgramFlagships = ipProgramFlagships;
    }

    public void setIpProgramRegions(List<IPProgram> ipProgramRegions) {
        this.ipProgramRegions = ipProgramRegions;
    }

    public void setProject(Project project) {
        this.project = project;
    }

    public void setProjectID(int projectID) {
        this.projectID = projectID;
    }

    public void setStatusProject(Map<String, String> projectStauses) {
        this.projectStauses = projectStauses;
    }

    @Override
    public void validate() {
        if (save) {
            if (!project.isBilateralProject() && project.isWorkplanRequired()) {
                if (file != null) {
                    project.setWorkplanName(fileFileName);
                }
            }
            if (project.isBilateralProject()) {

                if (file != null) {
                    project.setBilateralContractProposalName(fileFileName);
                }
            }
            validator.validate(this, project, this.getCycleName());
        }
    }
}