// Copyright (C) 2013 GerritForge www.gerritforge.com
//
// Licensed 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 mobi.jenkinsci.ci.model;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import mobi.jenkinsci.ci.addon.Utils;
import mobi.jenkinsci.model.Alignment;
import mobi.jenkinsci.model.ItemNode;
import mobi.jenkinsci.model.Layout;
import mobi.jenkinsci.net.UrlPath;
import mobi.jenkinsci.plugin.Plugin;
import com.google.common.base.Strings;
import com.google.gson.annotations.SerializedName;
public class Build extends JenkinsItem {
public int number;
public int duration;
public long timestamp;
public List<Artifact> artifacts;
public ChangeSet changeSet;
public List<HudsonAction> actions;
public String result;
public boolean building;
private Job job;
public void setJob(final Job job) {
this.job = job;
}
private final SimpleDateFormat dateFmt = new SimpleDateFormat(
"EEE, d MMM yyyy HH:mm");
public long builtSince() {
final long now = new Date().getTime();
return now - timestamp;
}
public String durationeHumanReadable() {
return humanReadableElapsed(duration / 1000);
}
public String builtSinceHumanReadable() {
final long now = new Date().getTime();
final long seconds = (now - timestamp) / 1000;
if (seconds < 0) {
return "few seconds";
}
return humanReadableElapsed(seconds);
}
private String humanReadableElapsed(long seconds) {
if (seconds > 60) {
long minutes = seconds / 60;
if (minutes > 60) {
long hours = minutes / 60;
if (hours > 24) {
long days = hours / 24;
if (days > 30) {
final long months = days / 30;
days = days % 30;
return "" + months + " months and " + days + " days";
} else {
hours = hours % 24;
return "" + days + " days and " + hours + " hours";
}
} else {
minutes = minutes % 60;
return "" + hours + " hours and " + minutes + " minutes";
}
} else {
seconds = seconds % 60;
return "" + minutes + " minutes and " + seconds + " seconds";
}
} else {
return "" + seconds + " seconds";
}
}
public class HudsonAction {
@SerializedName("failCount")
private String failCount;
@SerializedName("skipCount")
private String skipCount;
@SerializedName("totalCount")
private String totalCount;
public String getFailCount() {
return failCount;
}
public String getSkipCount() {
return skipCount;
}
public String getTotalCount() {
return totalCount;
}
}
@Override
public ItemNode toAbstractNode(final String urlPrefix) throws IOException {
final ItemNode node = new ItemNode("Build #" + number);
node.setViewTitle("Build #" + number + " of " + job.name);
node.setLayout(Layout.LIST);
node.setDescription("(" + dateFmt.format(new Date(timestamp)) + ")");
node.setDescriptionAlign(Alignment.BOTTOM);
Utils.setIconByLabel(node, result);
if (job != null) {
node.addNodes(getBuildSubNodes(job, urlPrefix, lazyLoad));
}
node.setLeaf(true);
return node;
}
public List<ItemNode> getBuildSubNodes(final Job job, final String urlPrefix,
final boolean lazyLoad) throws IOException {
final ArrayList<ItemNode> subNodes = new ArrayList<ItemNode>();
final JobInstallPackage installPackage =
new JobInstallPackage(job, this, lazyLoad);
if (installPackage.isAndroidCompatible()) {
subNodes.add(installPackage.toAbstractNode(urlPrefix));
}
if (actions != null) {
for (final HudsonAction a : actions) {
if (a.getFailCount() != null && Integer.parseInt(a.getFailCount()) > 0) {
final ItemNode failedTests = new ItemNode("Failed Tests");
failedTests.setDescription(a.getFailCount() + " failed over "
+ a.getTotalCount());
failedTests.setDescriptionAlign(Alignment.BOTTOM);
failedTests.setPath(UrlPath.normalizePath("failedtests"));
failedTests.setLayout(Layout.LIST);
failedTests.setVersion(ItemNode.API_VERSION);
failedTests.setAction("?cmd=load://" + url + "testReport");
subNodes.add(failedTests);
break;
}
}
}
final ItemNode console = new ItemNode("Build console");
console.setPath("console");
console.setIcon("?image=icons/terminal.png");
console.setAction("?web=" + urlEncode(url + "/logText/progressiveHtml")
+ "&decorate=html");
subNodes.add(console);
subNodes.add(getBuildDetail(Job.Detail.CHANGES, lazyLoad).toAbstractNode(
urlPrefix));
subNodes.add(getBuildDetail(Job.Detail.ARTIFACTS, lazyLoad).toAbstractNode(
urlPrefix));
subNodes.add(getBuildDetail(Job.Detail.FAILEDTESTS, lazyLoad)
.toAbstractNode(urlPrefix));
return subNodes;
}
@Override
public JenkinsItem getSubItem(final Plugin plugin, final String subItemPath)
throws IOException {
JenkinsItem subItem = super.getSubItem(plugin, subItemPath);
if (Strings.isNullOrEmpty(subItemPath)) {
return subItem;
}
final Job.Detail detail =
Job.Detail.valueOf(getHeadPath(subItemPath).toUpperCase());
subItem = getBuildDetail(detail, false);
if (subItem != null) {
return subItem.getSubItem(plugin, getTailPath(subItemPath));
} else {
return null;
}
}
private JenkinsItem getBuildDetail(final Job.Detail detail,
final boolean lazyLoad) {
JenkinsItem subItem = null;
switch (detail) {
case CHANGES:
subItem = new JobChanges(job, this);
break;
case ARTIFACTS:
subItem = new JobArtifacts(job, this);
break;
case FAILEDTESTS:
subItem = new JobFailedTests(job, this);
break;
case INSTALL:
subItem = new JobInstallPackage(job, this, lazyLoad);
break;
default:
return null;
}
subItem.init(client());
return subItem;
}
}