com.fdu.jira.plugin.report.timesheet.TimeSheet.java Source code

Java tutorial

Introduction

Here is the source code for com.fdu.jira.plugin.report.timesheet.TimeSheet.java

Source

/*
 * Copyright (c) 2002-2004
 * All rights reserved.
 */
package com.fdu.jira.plugin.report.timesheet;

import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.bc.JiraServiceContext;
import com.atlassian.jira.bc.JiraServiceContextImpl;
import com.atlassian.jira.bc.filter.SearchRequestService;
import com.atlassian.jira.bc.issue.util.VisibilityValidator;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.config.properties.ApplicationProperties;
import com.atlassian.jira.datetime.DateTimeFormatter;
import com.atlassian.jira.datetime.DateTimeFormatterFactory;
import com.atlassian.jira.datetime.DateTimeStyle;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.comparator.IssueKeyComparator;
import com.atlassian.jira.issue.comparator.UserComparator;
import com.atlassian.jira.issue.fields.FieldManager;
import com.atlassian.jira.issue.search.SearchException;
import com.atlassian.jira.issue.search.SearchProvider;
import com.atlassian.jira.issue.search.SearchRequest;
import com.atlassian.jira.issue.search.SearchResults;
import com.atlassian.jira.issue.worklog.Worklog;
import com.atlassian.jira.issue.worklog.WorklogManager;
import com.atlassian.jira.plugin.report.impl.AbstractReport;
import com.atlassian.jira.project.Project;
import com.atlassian.jira.security.JiraAuthenticationContext;
import com.atlassian.jira.security.PermissionManager;
import com.atlassian.jira.security.Permissions;
import com.atlassian.jira.timezone.TimeZoneManager;
import com.atlassian.jira.user.util.UserManager;
import com.atlassian.jira.user.util.UserUtil;
import com.atlassian.jira.util.I18nHelper;
import com.atlassian.jira.util.ParameterUtils;
import com.atlassian.jira.web.FieldVisibilityManager;
import com.atlassian.jira.web.action.ProjectActionSupport;
import com.atlassian.jira.web.bean.I18nBean;
import com.atlassian.jira.web.bean.PagerFilter;
import com.atlassian.upm.license.storage.lib.ThirdPartyPluginLicenseStorageManager;
import com.fdu.jira.plugin.report.pivot.Pivot;
import com.fdu.jira.util.LicenseUtil;
import com.fdu.jira.util.TextUtil;
import com.fdu.jira.util.WeekPortletHeader;
import com.fdu.jira.util.WorklogUtil;
import com.atlassian.crowd.embedded.api.User;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.ofbiz.core.entity.DelegatorInterface;
import org.ofbiz.core.entity.EntityExpr;
import org.ofbiz.core.entity.EntityOperator;
import org.ofbiz.core.entity.GenericEntityException;
import org.ofbiz.core.entity.GenericValue;
import org.ofbiz.core.util.UtilMisc;

import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.*;

/**
 * Generate a summary of worked hours in a specified period. The time period is
 * divided by the specifed value for display.
 */
public class TimeSheet extends AbstractReport {
    private static final Logger log = Logger.getLogger(TimeSheet.class);

    // A collection of interval start dates - correlating with the timeSpents
    // collection.    
    private List<WeekPortletHeader> weekDays = new ArrayList<WeekPortletHeader>();

    private Map<Issue, List<Worklog>> allWorkLogs = new Hashtable<Issue, List<Worklog>>();
    private Map<String, List<Worklog>> allWorklogsByUser = new LinkedHashMap<String, List<Worklog>>();
    private Map<User, Map<Issue, Map<Worklog, Long>>> weekWorkLog = new TreeMap<User, Map<Issue, Map<Worklog, Long>>>(
            new UserComparator());

    private Map<Issue, Map<Date, Long>> weekWorkLogShort = new TreeMap<Issue, Map<Date, Long>>(
            new IssueKeyComparator());
    private Map<User, Map<Date, Long>> userWorkLogShort = new TreeMap<User, Map<Date, Long>>(new UserComparator());
    private Map<Long, Long> weekTotalTimeSpents = new Hashtable<Long, Long>();
    private Map<User, Map<Long, Long>> userWeekTotalTimeSpents = new Hashtable<User, Map<Long, Long>>();
    private Map<User, Map<Issue, Long>> userIssueTotalTimeSpents = new Hashtable<User, Map<Issue, Long>>();
    private Map<Project, Map<Date, Long>> projectTimeSpents = new Hashtable<Project, Map<Date, Long>>();

    /**
    * <p>Variable that contains the project times grouped by a specific field.</p>
    * <p>This Variable represents/contains tree nested maps [project to [fieldname to [date to time]]]</p>
    */
    private Map<Project, Map<String, Map<Date, Long>>> projectGroupedByFieldTimeSpents = new Hashtable<Project, Map<String, Map<Date, Long>>>();
    private PermissionManager permissionManager;
    private IssueManager issueManager;
    private WorklogManager worklogManager;
    private UserUtil userUtil;
    private SearchProvider searchProvider;
    private VisibilityValidator visibilityValidator;
    private FieldVisibilityManager fieldVisibilityManager;
    private SearchRequestService searchRequestService;

    private final JiraAuthenticationContext authenticationContext;

    private final ApplicationProperties applicationProperties;

    private final DateTimeFormatterFactory dateTimeFormatterFactory;

    private TimeZoneManager timeZoneManager;

    private final ThirdPartyPluginLicenseStorageManager licenseManager;

    public Map<Long, Long> getWeekTotalTimeSpents() {
        return weekTotalTimeSpents;
    }

    public Map<User, Map<Date, Long>> getUserWorkLog() {
        return userWorkLogShort;
    }

    public Map<Issue, Map<Date, Long>> getWeekWorkLogShort() {
        return weekWorkLogShort;
    }

    public Map<User, Map<Issue, Map<Worklog, Long>>> getWeekWorkLog() {
        return weekWorkLog;
    }

    public List<WeekPortletHeader> getWeekDays() {
        return weekDays;
    }

    private int maxPeriod = 62; // 2 months in days

    public TimeSheet(DateTimeFormatterFactory dateTimeFormatterFactory, ApplicationProperties applicationProperties,
            PermissionManager permissionManager, WorklogManager worklogManager, IssueManager issueManager,
            SearchProvider searchProvider, VisibilityValidator visibilityValidator,
            FieldVisibilityManager fieldVisibilityManager, UserUtil userUtil,
            SearchRequestService searchRequestService, JiraAuthenticationContext authenticationContext,
            TimeZoneManager timeZoneManager, ThirdPartyPluginLicenseStorageManager licenseManager) {
        this.applicationProperties = applicationProperties;
        this.permissionManager = permissionManager;
        this.worklogManager = worklogManager;
        this.issueManager = issueManager;
        this.searchProvider = searchProvider;
        this.visibilityValidator = visibilityValidator;
        this.fieldVisibilityManager = fieldVisibilityManager;
        this.userUtil = userUtil;
        this.searchRequestService = searchRequestService;
        this.authenticationContext = authenticationContext;
        this.dateTimeFormatterFactory = dateTimeFormatterFactory;
        this.timeZoneManager = timeZoneManager;
        this.licenseManager = licenseManager;

        // maxPeriod limit
        String maxPeriodInDays = applicationProperties
                .getDefaultBackedString("jira.timesheet.plugin.maxPeriodInDays");
        if (maxPeriodInDays != null) {
            try {
                maxPeriod = Integer.valueOf(maxPeriodInDays);
            } catch (NumberFormatException e) {
                log.error("Invalid maxPeriodInDays number: " + maxPeriodInDays);
            }
        }
    }

    // Retrieve time user has spent for period
    public void getTimeSpents(User remoteUser, Date startDate, Date endDate, String targetUserName,
            boolean excelView, String priority, String[] targetGroups, Long projectId, Long filterId,
            Boolean showWeekends, Boolean showUsers, String groupByField)

            throws SearchException, GenericEntityException {

        JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(remoteUser);
        TimeZone timezone = timeZoneManager.getLoggedInUserTimeZone();

        Set<Long> filteredIssues = new TreeSet<Long>();
        if (filterId != null) {
            log.info("Using filter: " + filterId);
            SearchRequest filter = searchRequestService.getFilter(jiraServiceContext, filterId);
            if (filter != null) { // not logged in
                SearchResults issues = searchProvider.search(filter.getQuery(), remoteUser,
                        PagerFilter.getUnlimitedFilter());
                for (Iterator<Issue> i = issues.getIssues().iterator(); i.hasNext();) {
                    Issue value = i.next();
                    filteredIssues.add(value.getId());
                }
            }
        }

        EntityExpr startExpr = new EntityExpr("startdate", EntityOperator.GREATER_THAN_EQUAL_TO,
                new Timestamp(startDate.getTime()));
        EntityExpr endExpr = new EntityExpr("startdate", EntityOperator.LESS_THAN,
                new Timestamp(endDate.getTime()));
        List<EntityExpr> entityExprs = UtilMisc.toList(startExpr, endExpr);
        Set<String> assigneeIds = null;
        if (targetGroups != null && targetGroups.length > 0
                && permissionManager.hasPermission(Permissions.USER_PICKER, remoteUser)) {
            Set<User> users = userUtil.getAllUsersInGroupNames(Arrays.asList(targetGroups));
            assigneeIds = new TreeSet<String>();
            for (User user : users) {
                assigneeIds.add(user.getName());
                // TIME-156: risky :-\
                assigneeIds.add(user.getName().toLowerCase());
            }
            log.info("Searching worklogs created since '" + startDate + "', till '" + endDate + "', by group '"
                    + Arrays.asList(targetGroups) + "'");
        } else {
            EntityExpr userExpr = new EntityExpr("author", EntityOperator.EQUALS, targetUserName);
            entityExprs.add(userExpr);

            log.info("Searching worklogs created since '" + startDate + "', till '" + endDate + "', by '"
                    + targetUserName + "'");
        }

        List<String> orderBy = new ArrayList<String>();
        orderBy.add("author");
        orderBy.add("created");
        orderBy.add("issue");

        List<GenericValue> worklogs = ComponentManager.getComponent(DelegatorInterface.class).findByAnd("Worklog",
                entityExprs, orderBy);

        List<Worklog> worklogObjects = new ArrayList<Worklog>();

        for (Iterator<GenericValue> worklogsIterator = worklogs.iterator(); worklogsIterator.hasNext();) {
            GenericValue genericWorklog = worklogsIterator.next();
            Worklog worklog = WorklogUtil.convertToWorklog(genericWorklog, worklogManager, issueManager);

            boolean isValidVisibility = visibilityValidator.isValidVisibilityData(jiraServiceContext, "worklog",
                    worklog.getIssue(), worklog.getGroupLevel(),
                    worklog.getRoleLevelId() != null ? worklog.getRoleLevelId().toString() : null);
            if (!isValidVisibility) {
                continue;
            }

            Issue issue = issueManager.getIssueObject(genericWorklog.getLong("issue"));

            if ((filterId != null && !filteredIssues.contains(issue.getId()))
                    || (assigneeIds != null && !assigneeIds.contains(worklog.getAuthor()))) {
                continue;
            }

            Project project = issue.getProjectObject();

            if (priority != null && priority.length() != 0 && !issue.getString("priority").equals(priority)) {
                continue; // exclude issues with other priorities than (if) selected
            }

            if (projectId != null && !project.getId().equals(projectId)) {
                continue; // exclude issues from other projects than (if) selected
            }

            User workedUser = userUtil.getUserObject(genericWorklog.getString("author"));

            if (workedUser == null) {
                continue; // TIME-221: user may have been deleted
            }

            Date dateCreated = worklog.getStartDate();

            Calendar cal = Calendar.getInstance(timezone);
            cal.setTimeInMillis(dateCreated.getTime());
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MILLISECOND, 0);

            Date dateOfTheDay = cal.getTime();
            Long dateCreatedLong = cal.getTimeInMillis();

            WeekPortletHeader weekDay = new WeekPortletHeader(cal); // timeZone addjusted
            if (showWeekends != null && !showWeekends.booleanValue() && weekDay.isNonBusinessDay()) {
                continue; // exclude worklogs and issues that were started on weekends if no weekends desired to show
            }

            long spent;

            if (!permissionManager.hasPermission(Permissions.BROWSE, issue, remoteUser)) {
                continue; // exclude issues that users can't (shouldn't be
                          // allowed to) see
            }

            if (excelView) {
                // excel view shows complete work log
                worklogObjects.add(worklog);
            } else {
                // html view shows summary hours per issue for each user
                // per entry (report)

                // per issue (portlet)
                Map<Date, Long> weekTimeSpents = weekWorkLogShort.get(issue);
                if (weekTimeSpents == null) {
                    weekTimeSpents = new Hashtable<Date, Long>();
                    weekWorkLogShort.put(issue, weekTimeSpents); // portlet
                }

                spent = worklog.getTimeSpent();
                Long dateSpent = weekTimeSpents.get(dateOfTheDay);

                if (dateSpent != null) {
                    spent += dateSpent;
                }

                weekTimeSpents.put(dateOfTheDay, spent);

                // per user (group portlet)
                updateUserWorkLog(worklog, workedUser, dateOfTheDay);

                // per project per day                
                Map<Date, Long> projectWorkLog = projectTimeSpents.get(project);
                if (projectWorkLog == null) {
                    projectWorkLog = new Hashtable<Date, Long>();
                    projectTimeSpents.put(project, projectWorkLog);
                }

                spent = worklog.getTimeSpent();

                Long projectSpent = projectWorkLog.get(dateOfTheDay);

                if (projectSpent != null) {
                    spent += projectSpent;
                }

                projectWorkLog.put(dateOfTheDay, spent);

                // per project and field
                calculateTimesForProjectGroupedByField(groupByField, worklog, issue, project, dateOfTheDay);

                // total per day
                spent = worklog.getTimeSpent();
                dateSpent = weekTotalTimeSpents.get(dateCreatedLong);
                if (dateSpent != null) {
                    spent += dateSpent;
                }
                weekTotalTimeSpents.put(dateCreatedLong, spent);

                spent = worklog.getTimeSpent();
                if (showUsers != null && showUsers.booleanValue()) { // is nul in portlet
                    Map<Issue, Map<Worklog, Long>> userWorkLog = weekWorkLog.get(workedUser);
                    if (userWorkLog == null) {
                        userWorkLog = new TreeMap<Issue, Map<Worklog, Long>>(new IssueProjectComparator<Issue>());
                        weekWorkLog.put(workedUser, userWorkLog);
                    }
                    Map<Worklog, Long> issueWorkLog = userWorkLog.get(issue);
                    if (issueWorkLog == null) {
                        issueWorkLog = new Hashtable<Worklog, Long>();
                        userWorkLog.put(issue, issueWorkLog);
                    }
                    issueWorkLog.put(worklog, spent);

                    // totals per user/week
                    Map<Long, Long> userTotalTimeSpents = userWeekTotalTimeSpents.get(workedUser);
                    if (userTotalTimeSpents == null) {
                        userTotalTimeSpents = new HashMap<Long, Long>();
                        userWeekTotalTimeSpents.put(workedUser, userTotalTimeSpents);
                    }
                    Long weekDaySpent = userTotalTimeSpents.get(dateCreatedLong);
                    if (weekDaySpent != null) {
                        spent += weekDaySpent;
                    }
                    userTotalTimeSpents.put(dateCreatedLong, spent);

                    // totals per user/issue
                    spent = worklog.getTimeSpent();
                    Map<Issue, Long> issueTotalTimeSpents = userIssueTotalTimeSpents.get(workedUser);
                    if (issueTotalTimeSpents == null) {
                        issueTotalTimeSpents = new HashMap<Issue, Long>();
                        userIssueTotalTimeSpents.put(workedUser, issueTotalTimeSpents);
                    }
                    Long issueSpent = issueTotalTimeSpents.get(issue);
                    if (issueSpent != null) {
                        spent += issueSpent;
                    }
                    issueTotalTimeSpents.put(issue, spent);
                }
            }
        }
        if (excelView)
            allWorklogsByUser = getWorklogMapByUser(worklogObjects);

        // fill dates (ordered list) and week days (corresponding to each date)
        Calendar calendarDate = Calendar.getInstance(timezone);
        calendarDate.setTimeInMillis(startDate.getTime());
        Calendar today = Calendar.getInstance(timezone);

        while (endDate.after(calendarDate.getTime())) {
            WeekPortletHeader wph = new WeekPortletHeader((Calendar) calendarDate.clone());

            String businessDay = "";
            if (calendarDate.get(Calendar.DATE) == today.get(Calendar.DATE)
                    && calendarDate.get(Calendar.MONTH) == today.get(Calendar.MONTH)
                    && calendarDate.get(Calendar.YEAR) == today.get(Calendar.YEAR)) {
                businessDay = "toDay";
            } else if (wph.isNonBusinessDay() || wph.isHoliday()) {
                businessDay = "nonBusinessDay";
            }

            wph.setWeekDayCSS(businessDay); //rowHeaderDark redText red-highlight

            if (showWeekends == null || showWeekends.booleanValue() || !wph.isNonBusinessDay()) { // check if allowed to show weekends and if this it is a weekend
                weekDays.add(wph);
            }
            calendarDate.add(Calendar.DAY_OF_YEAR, 1);
        }
    }

    private Map<String, List<Worklog>> getWorklogMapByUser(List<Worklog> worklogObjects) {
        TreeMap<String, List<Worklog>> presult = new TreeMap<String, List<Worklog>>();
        for (Worklog w : worklogObjects) {
            List<Worklog> worklogs = presult.get(w.getAuthor());
            if (worklogs == null) {
                worklogs = new ArrayList<Worklog>();
                presult.put(w.getAuthor(), worklogs);
            }
            worklogs.add(w);
        }
        LinkedHashMap<String, List<Worklog>> result = new LinkedHashMap<String, List<Worklog>>();
        List<Map.Entry<String, List<Worklog>>> keyList = new ArrayList<Map.Entry<String, List<Worklog>>>(
                presult.entrySet());
        final UserManager userManager = ComponentAccessor.getUserManager();
        if (userManager != null)
            Collections.sort(keyList, new Comparator<Map.Entry<String, List<Worklog>>>() {
                public int compare(Map.Entry<String, List<Worklog>> e1, Map.Entry<String, List<Worklog>> e2) {
                    User user1 = userManager.getUser(e1.getKey());
                    User user2 = userManager.getUser(e2.getKey());
                    String userFullName1 = (user1 != null) ? user1.getDisplayName() : e1.getKey();
                    String userFullName2 = (user1 != null) ? user2.getDisplayName() : e2.getKey();
                    return userFullName1.compareTo(userFullName2);
                }
            });
        for (Map.Entry<String, List<Worklog>> e : keyList) {
            result.put(e.getKey(), e.getValue());
        }
        return result;
    }

    private void updateUserWorkLog(Worklog worklog, User workedUser, Date dateOfTheDay) {
        long spent;
        Map<Date, Long> dateToWorkMap = userWorkLogShort.get(workedUser);
        if (dateToWorkMap == null) {
            dateToWorkMap = new HashMap<Date, Long>();
            userWorkLogShort.put(workedUser, dateToWorkMap); // portlet
        }

        spent = worklog.getTimeSpent();
        Long dateSpent = dateToWorkMap.get(dateOfTheDay);

        if (dateSpent != null) {
            spent += dateSpent;
        }
        dateToWorkMap.put(dateOfTheDay, spent);
    }

    /**
     * Calculates the times spend per project, grouped by a field.
     * <p/>
     * Stores results in {@link #projectGroupedByFieldTimeSpents}.
     *
     * @param groupByFieldID - id of the field the group by should base on
     * @param worklog        - reference to for-loop variable from @see #getTimeSpents
     * @param issue          - reference to for-loop variable from @see #getTimeSpents
     * @param project        - reference to for-loop variable from @see #getTimeSpents
     * @param dateOfTheDay   - reference to for-loop variable from @see #getTimeSpents
     */
    private void calculateTimesForProjectGroupedByField(String groupByFieldID, Worklog worklog, Issue issue,
            Project project, Date dateOfTheDay) {
        long spent;

        if (groupByFieldID != null) {

            // Set field value
            String fieldValue = TextUtil.getFieldValue(groupByFieldID, issue,
                    dateTimeFormatterFactory.formatter().forLoggedInUser());

            // dimension Project to field
            Map<String, Map<Date, Long>> projectToFieldWorkLog = projectGroupedByFieldTimeSpents.get(project);
            if (projectToFieldWorkLog == null) {
                projectToFieldWorkLog = new Hashtable<String, Map<Date, Long>>();
                projectGroupedByFieldTimeSpents.put(project, projectToFieldWorkLog);
            }

            // dimension Field to Time
            Map<Date, Long> fieldToTimeWorkLog = projectToFieldWorkLog.get(fieldValue);
            if (fieldToTimeWorkLog == null) {
                fieldToTimeWorkLog = new Hashtable<Date, Long>();
                projectToFieldWorkLog.put(fieldValue, fieldToTimeWorkLog);
            }

            spent = worklog.getTimeSpent();
            Long projectGroupedSpent = fieldToTimeWorkLog.get(dateOfTheDay);
            if (projectGroupedSpent != null) {
                spent += projectGroupedSpent;
            }

            fieldToTimeWorkLog.put(dateOfTheDay, spent);
        }
    }

    // Generate the report
    public String generateReport(ProjectActionSupport action, Map params, boolean excelView) throws Exception {
        User remoteUser = authenticationContext.getLoggedInUser();
        I18nBean i18nBean = new I18nBean(remoteUser);
        TimeZone timezone = timeZoneManager.getLoggedInUserTimeZone();

        // Retrieve the start and end date specified by the user
        Date endDate = Pivot.getEndDate(params, i18nBean, timezone);
        Date startDate = Pivot.getStartDate(params, i18nBean, endDate, timezone);

        User targetUser = ParameterUtils.getUserParam(params, "targetUser");
        String priority = ParameterUtils.getStringParam(params, "priority");
        String[] targetGroups = ParameterUtils.getStringArrayParam(params, "targetGroup");
        if (targetGroups != null)
            try {
                for (int i = 0; i < targetGroups.length; ++i) {
                    // TIME-158 workaround: this must be handled by application server instead or this may be bug in Jira gadgets
                    String targetGroup = new String(
                            StringEscapeUtils.unescapeHtml(targetGroups[i]).getBytes("ISO-8859-1"),
                            applicationProperties.getEncoding());
                    targetGroups[i] = targetGroup;
                }
            } catch (UnsupportedEncodingException e) {
                // safe to ignore
            }

        Long projectId = null;
        if (!"".equals(ParameterUtils.getStringParam(params, "project"))) {
            projectId = ParameterUtils.getLongParam(params, "project");
        }

        Long filterId = ParameterUtils.getLongParam(params, "filterid");

        Boolean showWeekends = null;
        if ("true".equalsIgnoreCase(ParameterUtils.getStringParam(params, "weekends")))
            showWeekends = new Boolean(true);
        else
            showWeekends = new Boolean(false);

        Boolean showUsers = null;
        if ("true".equalsIgnoreCase(ParameterUtils.getStringParam(params, "showUsers")))
            showUsers = new Boolean(true);
        else
            showUsers = new Boolean(false);

        if (targetUser == null) {
            targetUser = remoteUser;
        }

        // read ID of the 'group by' field from parameter map
        String groupByField = ParameterUtils.getStringParam(params, "groupByField");
        if (groupByField != null) {
            if (groupByField.trim().length() == 0) {
                groupByField = null;
            } else if (ComponentManager.getComponentInstanceOfType(FieldManager.class)
                    .getField(groupByField) == null) {
                log.error("GroupByField ' " + groupByField + "' does not exist");
                groupByField = null;
            }
        }

        // get time spents
        if (remoteUser != null) {
            getTimeSpents(remoteUser, startDate, endDate, targetUser.getName(), excelView, priority, targetGroups,
                    projectId, filterId, showWeekends, showUsers, groupByField);
        }

        // Pass the issues to the velocity template
        Map<String, Object> velocityParams = new HashMap<String, Object>();
        velocityParams.put("startDate", startDate);
        velocityParams.put("endDate", endDate);
        velocityParams.put("weekDays", weekDays);
        velocityParams.put("targetUser", targetUser);
        velocityParams.put("priority", priority);
        velocityParams.put("targetGroup", Arrays.toString(targetGroups));
        velocityParams.put("projectId", projectId);
        velocityParams.put("filterId", filterId);
        velocityParams.put("showWeekends", showWeekends);
        velocityParams.put("showUsers", showUsers);
        velocityParams.put("groupByField", groupByField);
        List<String> moreFields = ParameterUtils.getListParam(params, "moreFields");
        if (moreFields == null) {
            moreFields = new ArrayList<String>();
            String moreField = ParameterUtils.getStringParam(params, "moreFields");
            if (moreField != null && !moreFields.isEmpty()) {
                moreFields.add(moreField);
            }
        }
        velocityParams.put("moreFields", moreFields);

        if (excelView) {
            velocityParams.put("allWorklogsByUser", allWorklogsByUser);
            //velocityParams.put("allWorkLogs", allWorkLogs);
        } else {
            if (showUsers.booleanValue()) {
                velocityParams.put("weekWorkLog", weekWorkLog);
            } else {
                velocityParams.put("weekWorkLog", weekWorkLogShort);
            }
            velocityParams.put("weekTotalTimeSpents", weekTotalTimeSpents);
            velocityParams.put("userWeekTotalTimeSpents", userWeekTotalTimeSpents);
            velocityParams.put("userIssueTotalTimeSpents", userIssueTotalTimeSpents);
            velocityParams.put("projectTimeSpents", projectTimeSpents);
            velocityParams.put("projectGroupedTimeSpents", projectGroupedByFieldTimeSpents);
        }
        velocityParams.put("groupByField", groupByField);
        DateTimeFormatter outlookDate = dateTimeFormatterFactory.formatter().withStyle(DateTimeStyle.DATE)
                .forLoggedInUser().withZone(timezone);
        velocityParams.put("outlookDate", outlookDate);
        velocityParams.put("fieldVisibility", fieldVisibilityManager);
        velocityParams.put("textUtil", new TextUtil(i18nBean, timezone));
        velocityParams.put("license", LicenseUtil.getStatus(licenseManager));

        return descriptor.getHtml(excelView ? "excel" : "view", velocityParams);
    }

    // Validate the parameters set by the user.
    public void validate(ProjectActionSupport action, Map params) {
        // nothing to do, all parameters are optional,
        // and there is no longer restriction for one month period

        User remoteUser = authenticationContext.getLoggedInUser();
        I18nHelper i18nBean = new I18nBean(remoteUser);

        // startDate before endDate

        Date startDate = ParameterUtils.getDateParam(params, "startDate", i18nBean.getLocale());
        Date endDate = ParameterUtils.getDateParam(params, "endDate", i18nBean.getLocale());

        if (startDate == null || endDate == null) {
            return; // nothing to validate
        }

        // The end date must be after the start date
        if (endDate.before(startDate)) {
            action.addError("endDate", action.getText("report.timesheet.before.startdate"));
        }

        // maxPeriod

        Calendar c = Calendar.getInstance();
        c.setTime(startDate);
        c.add(Calendar.DAY_OF_MONTH, maxPeriod);

        // The end date must be after the start date
        if (c.getTime().before(endDate)) {
            action.addError("endDate", action.getText("report.timesheet.maxperiod"));
        }
    }

    public boolean isExcelViewSupported() {
        return true;
    }

    // Generate html report
    public String generateReportHtml(ProjectActionSupport action, Map params) throws Exception {
        return generateReport(action, params, false);
    }

    // Generate excel, report
    public String generateReportExcel(ProjectActionSupport action, Map params) throws Exception {
        return generateReport(action, params, true);
    }

}