lt.kape1395.jenkins.ditz.IssueDiffCollector.java Source code

Java tutorial

Introduction

Here is the source code for lt.kape1395.jenkins.ditz.IssueDiffCollector.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package lt.kape1395.jenkins.ditz;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.apache.commons.collections.Predicate;

import lt.kape1395.jenkins.ditz.model.Component;
import lt.kape1395.jenkins.ditz.model.Issue;
import lt.kape1395.jenkins.ditz.model.IssueOpenPredicate;
import lt.kape1395.jenkins.ditz.model.IssueStatCategory;
import lt.kape1395.jenkins.ditz.model.IssueStats;
import lt.kape1395.jenkins.ditz.model.Project;
import lt.kape1395.jenkins.ditz.model.Release;
import lt.kape1395.jenkins.ditz.model.Issue.StatusChange;

/**
 * Calculates project statistics by comparing ditz project to
 * one from previous successful build.
 *
 * Apart from calculating statistics, status changes are set for
 * all issues. These are used when showing ditz issue details.
 *
 * @author k.petrauskas
 */
public class IssueDiffCollector implements IssueStatsCollector {
    /**
     * Logger for debugging.
     */
    private static Logger log = Logger.getLogger(IssueDiffCollector.class.getName());

    /**
     * Previous project (to compare with).
     */
    private Project baseProject;

    /**
     * Constructor.
     * @param baseProject Previous project/
     */
    public IssueDiffCollector(Project baseProject) {
        if (baseProject != null) {
            this.baseProject = baseProject;
        } else {
            this.baseProject = new Project();
        }
    }

    /**
     * Constructor for the case, when there is no previous build.
     * In this case all open issues will be new as well.
     */
    public IssueDiffCollector() {
        this(null);
    }

    /**
     * {@inheritDoc}
     */
    public void collectStatistics(Project project) {
        Set<String> issueIds = new HashSet<String>();
        Map<String, Issue> sourceIssues = new HashMap<String, Issue>();
        Map<String, Issue> targetIssues = new HashMap<String, Issue>();
        Map<String, IssueStatCategory> releaseStats = resetReleaseStats(project);
        Map<String, IssueStatCategory> componentStats = resetComponentStats(project);
        IssueStatCategory projectStats = resetProjectStats(project);

        for (Issue issue : baseProject.getIssues()) {
            issueIds.add(issue.getId());
            sourceIssues.put(issue.getId(), issue);
        }
        for (Issue issue : project.getIssues()) {
            issueIds.add(issue.getId());
            targetIssues.put(issue.getId(), issue);
        }

        for (String issueId : issueIds) {
            processIssue(project, sourceIssues.get(issueId), targetIssues.get(issueId), projectStats, releaseStats,
                    componentStats);
        }
    }

    /**
     * Reset statistics for all releases.
     * @param project Project to deal with.
     * @return Map of all releases indexed by release names.
     */
    protected Map<String, IssueStatCategory> resetReleaseStats(Project project) {
        Map<String, IssueStatCategory> releaseStats = new HashMap<String, IssueStatCategory>();
        for (Release release : project.getReleases()) {
            release.getIssueStats().reset();
            releaseStats.put(release.getName(), release);
        }
        return releaseStats;
    }

    /**
     * Reset statistics for all components.
     * @param project Project to deal with.
     * @return Map of all components indexed by component names.
     */
    protected Map<String, IssueStatCategory> resetComponentStats(Project project) {
        Map<String, IssueStatCategory> componentStats = new HashMap<String, IssueStatCategory>();
        for (Component component : project.getComponents()) {
            component.getIssueStats().reset();
            componentStats.put(component.getName(), component);
        }
        return componentStats;
    }

    /**
     * Reset project statistics.
     * @param project Project to deal with.
     * @return Project statistics (most general stats).
     */
    protected IssueStatCategory resetProjectStats(Project project) {
        project.getIssueStats().reset();
        return project;
    }

    /**
     * Process an issue by updating required statistics of
     * project, release, component, etc.
     *
     * @param project
     *      Project for which the statistics are being collected.
     * @param sourceIssue
     *      Issue as it was in the previous build.
     *      It can be null, if not existed.
     * @param targetIssue
     *      Issue as is is in the current build.
     *      It can be bull, if was closed or deleted.
     * @param projectStats
     *      Project summary statistics.
     * @param releaseStats
     *      Statistics by release.
     * @param componentStats
     *      Statistics by component.
     */
    protected void processIssue(Project project, Issue sourceIssue, Issue targetIssue,
            IssueStatCategory projectStats, Map<String, IssueStatCategory> releaseStats,
            Map<String, IssueStatCategory> componentStats) {
        Issue issue;
        IssueStats.StatField statField;

        log.fine("processIssue: src=" + sourceIssue + " dst=" + targetIssue);

        Predicate issueIsOpen = new IssueOpenPredicate();
        if (targetIssue != null) {
            targetIssue.setStatusChange(StatusChange.UNCHANGED);
        }

        if (issueIsOpen.evaluate(sourceIssue) && issueIsOpen.evaluate(targetIssue)) {
            statField = IssueStats.StatField.OPEN;
            issue = targetIssue;
            issue.setStatusChange(StatusChange.UNCHANGED);
        } else if (issueIsOpen.evaluate(sourceIssue)) {
            statField = IssueStats.StatField.CLOSED;
            issue = sourceIssue;
            if (targetIssue == null) {
                issue.setStatusChange(StatusChange.CLOSED);
                project.getIssues().add(issue);
            } else {
                targetIssue.setStatusChange(StatusChange.CLOSED);
            }
        } else if (issueIsOpen.evaluate(targetIssue)) {
            statField = IssueStats.StatField.NEW;
            issue = targetIssue;
            issue.setStatusChange(StatusChange.NEW);
        } else {
            project.getIssues().remove(targetIssue);
            return; // statistics should not be affected.
        }

        log.fine("processIssue: stat=" + statField + " " + issue);

        addToCategory(issue.getReleaseName(), releaseStats, statField);
        addToCategory(issue.getComponentName(), componentStats, statField);
        projectStats.getIssueStats().increment(statField);
    }

    /**
     * Add issue to a category by incrementing corresponding statistic field.
     * @param categoryName      Name of the category to deal with.
     * @param categories        List of all categories.
     * @param statisticsField   Field to be incremented.
     */
    protected void addToCategory(String categoryName, Map<String, IssueStatCategory> categories,
            IssueStats.StatField statisticsField) {

        if (categoryName == null) {
            return;
        }

        IssueStatCategory category = categories.get(categoryName);
        if (category == null) {
            return;
        }

        category.getIssueStats().increment(statisticsField);
    }

}