package com.smartcodeltd.jenkinsci.plugins.buildmonitor.viewmodel;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.smartcodeltd.jenkinsci.plugins.buildmonitor.facade.RelativeLocation;
import com.smartcodeltd.jenkinsci.plugins.buildmonitor.viewmodel.duration.Duration;
import com.smartcodeltd.jenkinsci.plugins.buildmonitor.viewmodel.features.Feature;
import hudson.model.Job;
import hudson.model.Result;
import hudson.model.Run;
import hudson.util.RunList;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
import static java.lang.String.format;
/**
* @author Jan Molak
*/
@JsonSerialize(using = JobViewSerialiser.class)
public class JobView {
private final Date systemTime;
private final Job<?, ?> job;
private final boolean isPipelineJob;
private final RelativeLocation relative;
private final List<Feature> features = newArrayList();
public static JobView of(Job<?, ?> job, List<Feature> features, boolean isPipelineJob) {
return new JobView(job, features, isPipelineJob, RelativeLocation.of(job), new Date());
}
public JobView(Job<?, ?> job, List<Feature> features, boolean isPipelineJob, RelativeLocation relative, Date systemTime) {
this.job = job;
this.isPipelineJob = isPipelineJob;
this.relative = relative;
this.systemTime = systemTime;
for (Feature feature : features) {
this.features.add(feature.of(this));
}
}
public List<Feature> features() {
return ImmutableList.copyOf(features);
}
public <F extends Feature> F which(Class<F> requestedFeature) {
for (Feature feature : features) {
if (feature.getClass() == requestedFeature) {
return (F) feature;
}
}
throw new RuntimeException(format("%s is not a feature of this project: '%s'", requestedFeature.getSimpleName(), job.getName()));
}
public String name() {
return relative.name();
}
public String url() {
return relative.url();
}
public String status() {
return CssStatus.of(this);
}
public String estimatedDuration() {
return formatted(lastBuild().estimatedDuration());
}
public String timeElapsedSinceLastBuild() {
return formatted(lastCompletedBuild().timeElapsedSince());
}
private String formatted(Duration duration) {
return null != duration
? duration.value()
: "";
}
public int progress() {
return lastBuild().progress();
}
public boolean isDisabled() {
return ! (isJobBuildable() || isJobExternal());
}
private boolean isJobBuildable() {
return job.isBuildable();
}
private boolean isJobExternal() {
return job instanceof hudson.model.ViewJob;
}
public boolean isRunning() {
return lastBuild().isRunning();
}
public Result lastResult() {
return lastCompletedBuild().result();
}
// todo track by job.hashCode messes up the animation
public int hashCode() {
return Objects.hashCode(job.hashCode());
}
@Override
public boolean equals(Object obj) {
return Objects.equal(job, obj);
}
@Override
public String toString() {
return name();
}
// --
@SuppressWarnings("unchecked")
public List<BuildViewModel> currentBuilds() {
List<BuildViewModel> currentBuilds = newArrayList();
RunList<Run<?, ?>> runList = ((RunList<Run<?, ?>>)job.getNewBuilds()).filter(BuildingPredicate.INSTANCE);
for (Iterator<Run<?, ?>> i = runList.iterator(); i.hasNext(); ) {
currentBuilds.add(buildViewOf(i.next()));
}
return currentBuilds;
}
public BuildViewModel lastBuild() {
return buildViewOf(job.getLastBuild());
}
public BuildViewModel lastCompletedBuild() {
BuildViewModel previousBuild = lastBuild();
while (previousBuild.isRunning() && previousBuild.hasPreviousBuild()) {
previousBuild = previousBuild.previousBuild();
}
return previousBuild;
}
private BuildViewModel buildViewOf(Run<?, ?> build) {
if (null == build) {
return new NullBuildView();
}
return BuildView.of(build, isPipelineJob, relative, systemTime);
}
}