de.sub.goobi.forms.ProjekteForm.java Source code

Java tutorial

Introduction

Here is the source code for de.sub.goobi.forms.ProjekteForm.java

Source

/*
 * (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
 *
 * This file is part of the Kitodo project.
 *
 * It is licensed under GNU General Public License version 3 or later.
 *
 * For the full copyright and license information, please read the
 * GPL3-License.txt file that was distributed with this source code.
 */

package de.sub.goobi.forms;

import de.intranda.commons.chart.renderer.ChartRenderer;
import de.intranda.commons.chart.results.ChartDraw.ChartType;
import de.sub.goobi.config.ConfigCore;
import de.sub.goobi.helper.Helper;
import de.sub.goobi.helper.Page;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.goobi.production.chart.IProjectTask;
import org.goobi.production.chart.IProvideProjectTaskList;
import org.goobi.production.chart.ProjectStatusDataTable;
import org.goobi.production.chart.ProjectStatusDraw;
import org.goobi.production.chart.WorkflowProjectTaskList;
import org.goobi.production.flow.statistics.StatisticsManager;
import org.goobi.production.flow.statistics.StatisticsRenderingElement;
import org.goobi.production.flow.statistics.enums.CalculationUnit;
import org.goobi.production.flow.statistics.enums.StatisticsMode;
import org.goobi.production.flow.statistics.hibernate.StatQuestProjectProgressData;
import org.goobi.production.flow.statistics.hibernate.UserProjectFilter;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.joda.time.DateTime;
import org.joda.time.Months;
import org.joda.time.Weeks;
import org.joda.time.Years;
import org.kitodo.data.database.beans.Process;
import org.kitodo.data.database.beans.Project;
import org.kitodo.data.database.beans.ProjectFileGroup;
import org.kitodo.data.database.exceptions.DAOException;
import org.kitodo.data.elasticsearch.exceptions.ResponseException;
import org.kitodo.services.ServiceManager;

public class ProjekteForm extends BasisForm {
    private static final long serialVersionUID = 6735912903249358786L;
    private static final Logger myLogger = Logger.getLogger(ProjekteForm.class);

    private Project myProjekt = new Project();
    private ProjectFileGroup myFilegroup;
    private final ServiceManager serviceManager = new ServiceManager();

    // lists accepting the preliminary actions of adding and delting filegroups
    // it needs the execution of commit fileGroups to make these changes
    // permanent
    private List<Integer> newFileGroups = new ArrayList<Integer>();
    private List<Integer> deletedFileGroups = new ArrayList<Integer>();

    private StatisticsManager statisticsManager1 = null;
    private StatisticsManager statisticsManager2 = null;
    private StatisticsManager statisticsManager3 = null;
    private StatisticsManager statisticsManager4 = null;
    private final StatQuestProjectProgressData projectProgressData = new StatQuestProjectProgressData();

    private String projectProgressImage;
    private String projectStatImages;
    private String projectStatVolumes;
    private boolean showStatistics;

    public ProjekteForm() {
        super();
    }

    // making sure its cleaned up
    @Override
    protected void finalize() {
        this.Cancel();
    }

    /**
     * this method deletes filegroups by their id's in the list.
     *
     * @param fileGroups
     *            List
     */
    private void deleteFileGroups(List<Integer> fileGroups) {
        for (Integer id : fileGroups) {
            for (ProjectFileGroup f : this.myProjekt.getProjectFileGroups()) {
                if (f.getId() == null ? id == null : f.getId().equals(id)) {
                    this.myProjekt.getProjectFileGroups().remove(f);
                    break;
                }
            }
        }
    }

    /**
     * this method flushes the newFileGroups List, thus makes them permanent and
     * deletes those marked for deleting, making the removal permanent.
     */
    private void commitFileGroups() {
        // resetting the List of new fileGroups
        this.newFileGroups = new ArrayList<Integer>();
        // deleting the fileGroups marked for deletion
        deleteFileGroups(this.deletedFileGroups);
        // resetting the List of fileGroups marked for deletion
        this.deletedFileGroups = new ArrayList<Integer>();
    }

    /**
     * this needs to be executed in order to rollback adding of filegroups.
     */
    public String Cancel() {
        // flushing new fileGroups
        deleteFileGroups(this.newFileGroups);
        // resetting the List of new fileGroups
        this.newFileGroups = new ArrayList<Integer>();
        // resetting the List of fileGroups marked for deletion
        this.deletedFileGroups = new ArrayList<Integer>();
        this.projectProgressImage = null;
        this.projectStatImages = null;
        this.projectStatVolumes = null;
        return "ProjekteAlle";
    }

    public String Neu() {
        this.myProjekt = new Project();
        return "ProjekteBearbeiten";
    }

    /**
     * Save.
     *
     * @return page or empty String
     */
    public String Speichern() {
        // call this to make saving and deleting permanent
        this.commitFileGroups();
        try {
            serviceManager.getProjectService().save(this.myProjekt);
            return "ProjekteAlle";
        } catch (DAOException e) {
            Helper.setFehlerMeldung("could not save", e.getMessage());
            myLogger.error(e);
            return "";
        } catch (IOException e) {
            Helper.setFehlerMeldung("could not insert to index", e.getMessage());
            myLogger.error(e);
            return "";
        } catch (ResponseException e) {
            Helper.setFehlerMeldung("incorrect response from ElasticSearch", e.getMessage());
            myLogger.error(e);
            return "";
        }
    }

    /**
     * Apply.
     *
     * @return String
     */
    public String Apply() {
        // call this to make saving and deleting permanent
        myLogger.trace("Apply wird aufgerufen...");
        this.commitFileGroups();
        try {
            serviceManager.getProjectService().save(this.myProjekt);
            return "";
        } catch (DAOException e) {
            Helper.setFehlerMeldung("could not save", e.getMessage());
            myLogger.error(e.getMessage());
            return "";
        } catch (IOException e) {
            Helper.setFehlerMeldung("could not insert to index", e.getMessage());
            myLogger.error(e);
            return "";
        } catch (ResponseException e) {
            Helper.setFehlerMeldung("incorrect response from ElasticSearch", e.getMessage());
            myLogger.error(e);
            return "";
        }
    }

    /**
     * Remove.
     *
     * @return String
     */
    public String Loeschen() {
        if (this.myProjekt.getUsers().size() > 0) {
            Helper.setFehlerMeldung("userAssignedError");
            return "";
        } else {
            try {
                serviceManager.getProjectService().remove(this.myProjekt);
            } catch (DAOException e) {
                Helper.setFehlerMeldung("could not delete", e.getMessage());
                myLogger.error(e.getMessage());
                return "";
            } catch (IOException e) {
                Helper.setFehlerMeldung("could not delete from index", e.getMessage());
                myLogger.error(e);
            } catch (ResponseException e) {
                Helper.setFehlerMeldung("incorrect response from ElasticSearch", e.getMessage());
                myLogger.error(e);
                return "";
            }
        }
        return "ProjekteAlle";
    }

    /**
     * No filter.
     *
     * @return page or empty String
     */
    public String FilterKein() {
        try {
            Session session = Helper.getHibernateSession();
            session.clear();
            Criteria crit = session.createCriteria(Project.class);
            crit.addOrder(Order.asc("title"));
            this.page = new Page(crit, 0);
        } catch (HibernateException he) {
            Helper.setFehlerMeldung("could not read", he.getMessage());
            myLogger.error(he.getMessage());
            return "";
        }
        return "ProjekteAlle";
    }

    /**
     * No filter back.
     *
     * @return String
     */
    public String FilterKeinMitZurueck() {
        FilterKein();
        return this.zurueck;
    }

    /**
     * Add file group.
     *
     * @return String
     */
    public String filegroupAdd() {
        this.myFilegroup = new ProjectFileGroup();
        this.myFilegroup.setProject(this.myProjekt);
        this.newFileGroups.add(this.myFilegroup.getId());
        return this.zurueck;
    }

    /**
     * Save file group.
     *
     * @return page
     */
    public String filegroupSave() {
        if (this.myProjekt.getProjectFileGroups() == null) {
            this.myProjekt.setProjectFileGroups(new ArrayList<ProjectFileGroup>());
        }
        if (!this.myProjekt.getProjectFileGroups().contains(this.myFilegroup)) {
            this.myProjekt.getProjectFileGroups().add(this.myFilegroup);
        }

        return "jeniaClosePopupFrameWithAction";
    }

    public String filegroupEdit() {
        return this.zurueck;
    }

    /**
     * Delete file group.
     *
     * @return page
     */
    public String filegroupDelete() {
        // to be deleted fileGroups ids are listed
        // and deleted after a commit
        this.deletedFileGroups.add(this.myFilegroup.getId());
        return "ProjekteBearbeiten";
    }

    /*
     * Getter und Setter
     */

    public Project getMyProjekt() {
        return this.myProjekt;
    }

    /**
     * Set my project.
     *
     * @param inProjekt
     *            Project object
     */
    public void setMyProjekt(Project inProjekt) {
        // has to be called if a page back move was done
        this.Cancel();
        this.myProjekt = inProjekt;
    }

    /**
     * The need to commit deleted fileGroups only after the save action requires
     * a filter, so that those filegroups marked for delete are not shown
     * anymore.
     *
     * @return modified ArrayList
     */
    public ArrayList<ProjectFileGroup> getFileGroupList() {
        ArrayList<ProjectFileGroup> filteredFileGroupList = new ArrayList<>(this.myProjekt.getProjectFileGroups());

        for (Integer id : this.deletedFileGroups) {
            for (ProjectFileGroup f : this.myProjekt.getProjectFileGroups()) {
                if (f.getId() == null ? id == null : f.getId().equals(id)) {
                    filteredFileGroupList.remove(f);
                    break;
                }
            }
        }
        return filteredFileGroupList;
    }

    public ProjectFileGroup getMyFilegroup() {
        return this.myFilegroup;
    }

    public void setMyFilegroup(ProjectFileGroup myFilegroup) {
        this.myFilegroup = myFilegroup;
    }

    /**
     * Get statistic manager 1.
     *
     * @return instance of {@link StatisticsMode#PRODUCTION}
     *         {@link StatisticsManager}
     */

    public StatisticsManager getStatisticsManager1() {
        if (this.statisticsManager1 == null) {
            this.statisticsManager1 = new StatisticsManager(StatisticsMode.PRODUCTION,
                    new UserProjectFilter(this.myProjekt.getId()),
                    FacesContext.getCurrentInstance().getViewRoot().getLocale());
        }
        return this.statisticsManager1;
    }

    /**
     * Get statistic manager 2.
     *
     * @return instance of {@link StatisticsMode#THROUGHPUT}
     *         {@link StatisticsManager}
     */
    public StatisticsManager getStatisticsManager2() {
        if (this.statisticsManager2 == null) {
            this.statisticsManager2 = new StatisticsManager(StatisticsMode.THROUGHPUT,
                    new UserProjectFilter(this.myProjekt.getId()),
                    FacesContext.getCurrentInstance().getViewRoot().getLocale());
        }
        return this.statisticsManager2;
    }

    /**
     * Get statistic manager 3.
     *
     * @return instance of {@link StatisticsMode#CORRECTIONS}
     *         {@link StatisticsManager}
     */
    public StatisticsManager getStatisticsManager3() {
        if (this.statisticsManager3 == null) {
            this.statisticsManager3 = new StatisticsManager(StatisticsMode.CORRECTIONS,
                    new UserProjectFilter(this.myProjekt.getId()),
                    FacesContext.getCurrentInstance().getViewRoot().getLocale());
        }
        return this.statisticsManager3;
    }

    /**
     * Get statistic manager 4.
     *
     * @return instance of {@link StatisticsMode#STORAGE}
     *         {@link StatisticsManager}
     */
    public StatisticsManager getStatisticsManager4() {
        if (this.statisticsManager4 == null) {
            this.statisticsManager4 = new StatisticsManager(StatisticsMode.STORAGE,
                    new UserProjectFilter(this.myProjekt.getId()),
                    FacesContext.getCurrentInstance().getViewRoot().getLocale());
        }
        return this.statisticsManager4;
    }

    /**
     * generates values for count of volumes and images for statistics.
     */
    @SuppressWarnings("rawtypes")
    public void GenerateValuesForStatistics() {
        Criteria crit = Helper.getHibernateSession().createCriteria(Process.class)
                .add(Restrictions.eq("projekt", this.myProjekt));
        ProjectionList pl = Projections.projectionList();
        pl.add(Projections.sum("sortHelperImages"));
        pl.add(Projections.count("sortHelperImages"));
        crit.setProjection(pl);
        List list = crit.list();
        Long images = 0l;
        Long volumes = 0l;
        for (Object obj : list) {
            Object[] row = (Object[]) obj;
            images = (Long) row[0];
            volumes = (Long) row[1];
        }
        this.myProjekt.setNumberOfPages(images.intValue());
        this.myProjekt.setNumberOfVolumes(volumes.intValue());
    }

    /**
     * calculate pages per volume depending on given values, requested multiple
     * times via ajax.
     *
     * @return Integer of calculation
     */
    public Integer getCalcImagesPerVolume() {
        int volumes = this.myProjekt.getNumberOfVolumes();
        int pages = this.myProjekt.getNumberOfPages();
        if (volumes == 0) {
            return pages;
        }
        int i = pages / volumes;
        return i;
    }

    /**
     * get calculated duration from start and end date.
     *
     * @return String of duration
     */
    public Integer getCalcDuration() {
        DateTime start = new DateTime(this.myProjekt.getStartDate().getTime());
        DateTime end = new DateTime(this.myProjekt.getEndDate().getTime());
        return Months.monthsBetween(start, end).getMonths();
    }

    /**
     * calculate throughput of volumes per year.
     *
     * @return calculation
     */

    public Integer getCalcThroughputPerYear() {
        DateTime start = new DateTime(this.myProjekt.getStartDate().getTime());
        DateTime end = new DateTime(this.myProjekt.getEndDate().getTime());
        int years = Years.yearsBetween(start, end).getYears();
        if (years < 1) {
            years = 1;
        }
        return this.myProjekt.getNumberOfVolumes() / years;
    }

    /**
     * calculate throughput of pages per year.
     *
     * @return calculation
     */
    public Integer getCalcThroughputPagesPerYear() {
        DateTime start = new DateTime(this.myProjekt.getStartDate().getTime());
        DateTime end = new DateTime(this.myProjekt.getEndDate().getTime());
        int years = Years.yearsBetween(start, end).getYears();
        if (years < 1) {
            years = 1;
        }
        return this.myProjekt.getNumberOfPages() / years;
    }

    /**
     * calculate throughput of volumes per quarter.
     *
     * @return calculation
     */

    public Integer getCalcThroughputPerQuarter() {
        int month = getCalcDuration();
        if (month < 1) {
            month = 1;
        }
        return this.myProjekt.getNumberOfVolumes() * 3 / month;
    }

    /**
     * calculate throughput of pages per quarter.
     *
     * @return calculation
     */
    public Integer getCalcTroughputPagesPerQuarter() {
        int month = getCalcDuration();
        if (month < 1) {
            month = 1;
        }
        return this.myProjekt.getNumberOfPages() * 3 / month;
    }

    /**
     * calculate throughput of volumes per month.
     *
     * @return calculation
     */
    public Integer getCalcThroughputPerMonth() {
        int month = getCalcDuration();
        if (month < 1) {
            month = 1;
        }
        return this.myProjekt.getNumberOfVolumes() / month;
    }

    /**
     * calculate throughput of pages per month.
     *
     * @return calculation
     */
    public Integer getCalcThroughputPagesPerMonth() {
        int month = getCalcDuration();
        if (month < 1) {
            month = 1;
        }
        return this.myProjekt.getNumberOfPages() / month;
    }

    private Double getThroughputPerDay() {
        DateTime start = new DateTime(this.myProjekt.getStartDate().getTime());
        DateTime end = new DateTime(this.myProjekt.getEndDate().getTime());
        Weeks weeks = Weeks.weeksBetween(start, end);
        myLogger.trace(weeks.getWeeks());
        int days = (weeks.getWeeks() * 5);

        if (days < 1) {
            days = 1;
        }
        double back = (double) this.myProjekt.getNumberOfVolumes() / (double) days;
        return back;
    }

    /**
     * calculate throughput of volumes per day.
     *
     * @return calculation
     */

    public Integer getCalcThroughputPerDay() {
        return Math.round(this.getThroughputPerDay().floatValue());
    }

    /**
     * calculate throughput of pages per day.
     *
     * @return calculation
     */

    private Double getThroughputPagesPerDay() {
        DateTime start = new DateTime(this.myProjekt.getStartDate().getTime());
        DateTime end = new DateTime(this.myProjekt.getEndDate().getTime());

        Weeks weeks = Weeks.weeksBetween(start, end);
        int days = (weeks.getWeeks() * 5);
        if (days < 1) {
            days = 1;
        }
        double back = (double) this.myProjekt.getNumberOfPages() / (double) days;
        return back;
    }

    /**
     * calculate throughput of pages per day.
     *
     * @return calculation
     */
    public Integer getCalcPagesPerDay() {
        return Math.round(this.getThroughputPagesPerDay().floatValue());
    }

    /**
     * Get project progress interface.
     *
     * @return a StatQuestThroughputCommonFlow for the generation of project
     *         progress data
     */
    public StatQuestProjectProgressData getProjectProgressInterface() {
        synchronized (this.projectProgressData) {
            try {
                this.projectProgressData
                        .setCommonWorkflow(serviceManager.getProjectService().getWorkFlow(this.myProjekt));
                this.projectProgressData.setCalculationUnit(CalculationUnit.volumes);
                this.projectProgressData.setRequiredDailyOutput(this.getThroughputPerDay());
                this.projectProgressData.setTimeFrame(this.getMyProjekt().getStartDate(),
                        this.getMyProjekt().getEndDate());
                this.projectProgressData.setDataSource(new UserProjectFilter(this.myProjekt.getId()));

                if (this.projectProgressImage == null) {
                    this.projectProgressImage = "";
                }
            } catch (Exception e) {
                // this.projectProgressData = null;
            }
        }
        return this.projectProgressData;
    }

    /**
     * Get progress calculated.
     *
     * @return true if calculation is finished
     */

    public Boolean getIsProgressCalculated() {
        if (this.projectProgressData == null) {
            return false;
        }
        return this.projectProgressData.isDataComplete();
    }

    /**
     * Get project progress image.
     *
     * @return path to rendered image of statistics
     */
    public String getProjectProgressImage() {

        if (this.projectProgressImage == null || this.projectProgressData == null
                || this.projectProgressData.hasChanged()) {
            try {
                calcProgressCharts();
            } catch (Exception e) {
                Helper.setFehlerMeldung("noImageRendered");
            }
        }
        return this.projectProgressImage;
    }

    private void calcProgressCharts() {
        if (this.getProjectProgressInterface().isDataComplete()) {
            ChartRenderer cr = new ChartRenderer();
            cr.setChartType(ChartType.LINE);
            cr.setDataTable(this.projectProgressData.getSelectedTable());
            BufferedImage bi = (BufferedImage) cr.getRendering();
            this.projectProgressImage = System.currentTimeMillis() + ".png";
            String localImagePath = ConfigCore.getTempImagesPathAsCompleteDirectory();

            File outputfile = new File(localImagePath + this.projectProgressImage);
            try {
                ImageIO.write(bi, "png", outputfile);
            } catch (IOException e) {
                myLogger.debug("couldn't write project progress chart to file", e);
            }
        }
    }

    /**
     * Static Statistics.
     */
    public String getProjectStatImages() throws IOException, InterruptedException {
        if (this.projectStatImages == null) {
            this.projectStatImages = System.currentTimeMillis() + "images.png";
            calcProjectStats(this.projectStatImages, true);
        }
        return this.projectStatImages;
    }

    /**
     * Get project stat volumes.
     *
     * @return string of image file projectStatVolumes
     */

    public String getProjectStatVolumes() throws IOException, InterruptedException {
        if (this.projectStatVolumes == null) {
            this.projectStatVolumes = System.currentTimeMillis() + "volumes.png";
            calcProjectStats(this.projectStatVolumes, false);
        }
        return this.projectStatVolumes;
    }

    private synchronized void calcProjectStats(String inName, Boolean countImages) throws IOException {
        int width = 750;
        Date start = this.myProjekt.getStartDate();
        Date end = this.myProjekt.getEndDate();

        Integer inMax;
        if (countImages) {
            inMax = this.myProjekt.getNumberOfPages();
        } else {
            inMax = this.myProjekt.getNumberOfVolumes();
        }

        ProjectStatusDataTable pData = new ProjectStatusDataTable(this.myProjekt.getTitle(), start, end);

        IProvideProjectTaskList ptl = new WorkflowProjectTaskList();

        List<? extends IProjectTask> tasklist = ptl.calculateProjectTasks(this.myProjekt, countImages, inMax);
        for (IProjectTask pt : tasklist) {
            pData.addTask(pt);
        }

        // Determine height of the image
        int height = ProjectStatusDraw.getImageHeight(pData.getNumberOfTasks());

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();
        g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);

        ProjectStatusDraw projectStatusDraw = new ProjectStatusDraw(pData, g2d, width, height);
        projectStatusDraw.paint();

        // write image to temporary file
        String localImagePath = ConfigCore.getTempImagesPathAsCompleteDirectory();
        File outputfile = new File(localImagePath + inName);
        ImageIO.write(image, "png", outputfile);
    }

    private StatisticsRenderingElement myCurrentTable;

    public void setMyCurrentTable(StatisticsRenderingElement myCurrentTable) {
        this.myCurrentTable = myCurrentTable;
    }

    public StatisticsRenderingElement getMyCurrentTable() {
        return this.myCurrentTable;
    }

    /**
     * Create excel.
     */
    public void CreateExcel() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (!facesContext.getResponseComplete()) {

            /*
             * Vorbereiten der Header-Informationen
             */
            HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
            try {
                ServletContext servletContext = (ServletContext) facesContext.getExternalContext().getContext();
                String contentType = servletContext.getMimeType("export.xls");
                response.setContentType(contentType);
                response.setHeader("Content-Disposition", "attachment;filename=\"export.xls\"");
                ServletOutputStream out = response.getOutputStream();
                HSSFWorkbook wb = (HSSFWorkbook) this.myCurrentTable.getExcelRenderer().getRendering();
                wb.write(out);
                out.flush();
                facesContext.responseComplete();

            } catch (IOException e) {

            }
        }
    }

    /**
     * Getter for showStatistics.
     *
     * @return the showStatistics
     */
    public boolean getShowStatistics() {
        return this.showStatistics;
    }

    /**
     * Setter for showStatistics.
     *
     * @param showStatistics
     *            the showStatistics to set
     */
    public void setShowStatistics(boolean showStatistics) {
        this.showStatistics = showStatistics;
    }

}