Package hudson.plugins.analysis.core

Source Code of hudson.plugins.analysis.core.BuildHistory

package hudson.plugins.analysis.core;

import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.Set;

import javax.annotation.CheckForNull;

import hudson.model.Result;
import hudson.model.AbstractBuild;

import hudson.plugins.analysis.util.model.AnnotationContainer;
import hudson.plugins.analysis.util.model.DefaultAnnotationContainer;
import hudson.plugins.analysis.util.model.FileAnnotation;

/**
* History of build results of a specific plug-in. The plug-in is identified by
* the corresponding {@link ResultAction} type.
*
* @author Ulli Hafner
*/
public class BuildHistory {
    /** The build to start the history from. */
    private final AbstractBuild<?, ?> baseline;
    /** Type of the action that contains the build results. */
    private final Class<? extends ResultAction<? extends BuildResult>> type;
    /** Determines whether only stable builds should be used as reference builds or not. */
    private final boolean useStableBuildAsReference;

    /**
     * Creates a new instance of {@link BuildHistory}.
     *
     * @param baseline
     *            the build to start the history from
     * @param type
     *            type of the action that contains the build results
     * @param useStableBuildAsReference
     *            determines whether only stable builds should be used as
     *            reference builds or not
     * @since 1.47
     */
    public BuildHistory(final AbstractBuild<?, ?> baseline, final Class<? extends ResultAction<? extends BuildResult>> type,
            final boolean useStableBuildAsReference) {
        this.baseline = baseline;
        this.type = type;
        this.useStableBuildAsReference = useStableBuildAsReference;
    }

    /**
     * Determines whether only stable builds should be used as reference builds
     * or not.
     *
     * @return <code>true</code> if only stable builds should be used
     */
    public boolean useOnlyStableBuildsAsReference() {
        return useStableBuildAsReference;
    }

    /**
     * Returns the time of the baseline build.
     *
     * @return the time
     */
    public Calendar getTimestamp() {
        return baseline.getTimestamp();
    }
    /**
     * Returns whether a reference build result exists.
     *
     * @return <code>true</code> if a reference build result exists.
     */
    private boolean hasReferenceResult() {
        return getReferenceAction() != null;
    }

    /**
     * Returns the annotations of the reference build.
     *
     * @return the annotations of the reference build
     */
    public AnnotationContainer getReferenceAnnotations() {
        ResultAction<? extends BuildResult> action = getReferenceAction();
        if (action != null) {
            return action.getResult().getContainer();
        }
        return new DefaultAnnotationContainer();
    }

    /**
     * Returns the action of the reference build.
     *
     * @return the action of the reference build, or <code>null</code> if no
     *         such build exists
     */
    private ResultAction<? extends BuildResult> getReferenceAction() {
        ResultAction<? extends BuildResult> action = getAction(true, useStableBuildAsReference);
        if (action == null) {
            return getPreviousAction(); // fallback, use action of previous build regardless of result
        }
        else {
            return action;
        }
    }

    private ResultAction<? extends BuildResult> getAction(final boolean isStatusRelevant) {
        return getAction(isStatusRelevant, false);
    }

    private ResultAction<? extends BuildResult> getAction(final boolean isStatusRelevant, final boolean mustBeStable) {
        for (AbstractBuild<?, ?> build = baseline.getPreviousBuild(); build != null; build = build.getPreviousBuild()) {
            ResultAction<? extends BuildResult> action = getResultAction(build);
            if (hasValidResult(build, mustBeStable, action) && isSuccessfulAction(action, isStatusRelevant)) {
                return action;
            }
        }
        return null;
    }

    private boolean isSuccessfulAction(final ResultAction<? extends BuildResult> action, final boolean isStatusRelevant) {
        return action != null && (action.isSuccessful() || !isStatusRelevant);
    }

    /**
     * Returns the result action of the specified build that should be used to
     * compute the history.
     *
     * @param build
     *            the build
     * @return the result action
     */
    @CheckForNull
    public ResultAction<? extends BuildResult> getResultAction(final AbstractBuild<?, ?> build) {
        return build.getAction(type);
    }

    /**
     * Returns the action of the previous build.
     *
     * @return the action of the previous build, or <code>null</code> if no
     *         such build exists
     */
    @CheckForNull
    private ResultAction<? extends BuildResult> getPreviousAction() {
        return getAction(false);
    }

    /**
     * Returns the reference build or <code>null</code> if there is no such
     * build.
     *
     * @return the reference build
     * @since 1.20
     * @see #hasReferenceBuild()
     */
    @CheckForNull
    public AbstractBuild<?, ?> getReferenceBuild() {
        ResultAction<? extends BuildResult> action = getReferenceAction();
        if (action != null) {
            AbstractBuild<?, ?> build = action.getBuild();
            if (hasValidResult(build)) {
                return build;
            }
        }
        return null;
    }

    private boolean hasValidResult(final AbstractBuild<?, ?> build) {
        return hasValidResult(build, false, null);
    }

    private boolean hasValidResult(final AbstractBuild<?, ?> build, final boolean mustBeStable, @CheckForNull final ResultAction<? extends BuildResult> action) {
        Result result = build.getResult();

        if (result == null) {
            return false;
        }
        if (mustBeStable) {
            return result == Result.SUCCESS;
        }
        return result.isBetterThan(Result.FAILURE) || isPluginCauseForFailure(action);
    }

    private boolean isPluginCauseForFailure(@CheckForNull final ResultAction<? extends BuildResult> action) {
        if (action == null) {
            return false;
        }
        else {
            return action.getResult().getPluginResult().isWorseOrEqualTo(Result.FAILURE);
        }
    }

    /**
     * Returns whether a reference build is available to compare the results
     * with.
     *
     * @return <code>true</code> if a reference build exists, <code>false</code>
     *         otherwise
     * @since 1.20
     */
    public boolean hasReferenceBuild() {
        return getReferenceBuild() != null;
    }

    /**
     * Returns whether a previous build result exists.
     *
     * @return <code>true</code> if a previous build result exists.
     * @see #isEmpty()
     */
    public boolean hasPreviousResult() {
        return getPreviousAction() != null;
    }

    /**
     * Returns whether there is no history available, i.e. the current build is
     * the first valid one.
     *
     * @return <code>true</code> if there is no previous build available
     * @see #hasPreviousResult()
     */
    public boolean isEmpty() {
        return !hasPreviousResult();
    }

    /**
     * Returns the baseline action.
     *
     * @return the baseline action
     * @see #hasPreviousResult()
     * @throws NoSuchElementException
     *             if there is no previous result
     */
    public ResultAction<? extends BuildResult> getBaseline() {
        return getResultAction(baseline);
    }

    /**
     * Returns the previous build result.
     *
     * @return the previous build result
     * @see #hasPreviousResult()
     * @throws NoSuchElementException
     *             if there is no previous result
     */
    public BuildResult getPreviousResult() {
        ResultAction<? extends BuildResult> action = getPreviousAction();
        if (action != null) {
            return action.getResult();
        }
        throw new NoSuchElementException("No previous result available");
    }

    /**
     * Returns the new warnings as a difference between the specified collection
     * of warnings and the warnings of the reference build.
     *
     * @param annotations
     *            the warnings in the current build
     * @return the difference "current build" - "reference build"
     */
    public Collection<FileAnnotation> getNewWarnings(final Set<FileAnnotation> annotations) {
        if (hasReferenceResult()) {
            return AnnotationDifferencer.getNewAnnotations(annotations, getReferenceAnnotations().getAnnotations());
        }
        else {
            return annotations;
        }
    }

    /**
     * Returns the fixed warnings as a difference between the warnings of the
     * reference build and the specified collection of warnings.
     *
     * @param annotations
     *            the warnings in the current build
     * @return the difference "reference build" - "current build"
     */
    public Collection<FileAnnotation> getFixedWarnings(final Set<FileAnnotation> annotations) {
        if (hasReferenceResult()) {
            return AnnotationDifferencer.getFixedAnnotations(annotations, getReferenceAnnotations().getAnnotations());
        }
        else {
            return Collections.emptyList();
        }
    }

    /**
     * Returns the health descriptor used for the builds.
     *
     * @return the health descriptor
     */
    public AbstractHealthDescriptor getHealthDescriptor() {
        return getBaseline().getHealthDescriptor();
    }

    /**
     * Creates a new instance of {@link BuildHistory}.
     *
     * @param baseline
     *            the build to start the history from
     * @param type
     *            type of the action that contains the build results
     * @deprecated use {@link #BuildHistory(AbstractBuild, Class, boolean)}
     */
    @Deprecated
    public BuildHistory(final AbstractBuild<?, ?> baseline, final Class<? extends ResultAction<? extends BuildResult>> type) {
        this(baseline, type, false);
    }
}
TOP

Related Classes of hudson.plugins.analysis.core.BuildHistory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.