package hudson.plugins.analysis.core;
import java.util.Collection;
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.CheckForNull;
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;
/**
* 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
*/
public BuildHistory(final AbstractBuild<?, ?> baseline, final Class<? extends ResultAction<? extends BuildResult>> type) {
this.baseline = baseline;
this.type = type;
}
/**
* 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() {
for (AbstractBuild<?, ?> build = baseline.getPreviousBuild(); build != null; build = build.getPreviousBuild()) {
ResultAction<? extends BuildResult> action = build.getAction(type);
if (action != null && action.isSuccessful()) {
return action;
}
}
return getPreviousAction(); // fallback, use previous build
}
/**
* Returns whether a previous build result exists.
*
* @return <code>true</code> if a previous build result exists.
*/
public boolean hasPreviousResult() {
return getPreviousAction() != null;
}
/**
* 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() {
for (AbstractBuild<?, ?> build = baseline.getPreviousBuild(); build != null; build = build.getPreviousBuild()) {
ResultAction<? extends BuildResult> action = build.getAction(type);
if (action != null) {
return action;
}
}
return null;
}
/**
* 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();
}
}
}