package org.netmelody.cieye.spies.teamcity;
import static com.google.common.collect.Iterables.find;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.netmelody.cieye.core.domain.Feature;
import org.netmelody.cieye.core.observation.Contact;
import org.netmelody.cieye.spies.teamcity.jsondomain.Build;
import org.netmelody.cieye.spies.teamcity.jsondomain.BuildDetail;
import org.netmelody.cieye.spies.teamcity.jsondomain.BuildType;
import org.netmelody.cieye.spies.teamcity.jsondomain.BuildTypeDetail;
import org.netmelody.cieye.spies.teamcity.jsondomain.BuildTypes;
import org.netmelody.cieye.spies.teamcity.jsondomain.Builds;
import org.netmelody.cieye.spies.teamcity.jsondomain.Change;
import org.netmelody.cieye.spies.teamcity.jsondomain.ChangeDetail;
import org.netmelody.cieye.spies.teamcity.jsondomain.Investigation;
import org.netmelody.cieye.spies.teamcity.jsondomain.Investigations;
import org.netmelody.cieye.spies.teamcity.jsondomain.Project;
import org.netmelody.cieye.spies.teamcity.jsondomain.ProjectDetail;
import org.netmelody.cieye.spies.teamcity.jsondomain.TeamCityProjects;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
public final class TeamCityCommunicator {
private final Contact contact;
private final String endpoint;
private final String prefix;
public TeamCityCommunicator(Contact contact, String endpoint) {
this.contact = contact;
this.endpoint = endpoint;
this.prefix = (contact.privileged() ? "/httpAuth" : "/guestAuth") + "/app/rest";
}
public String endpoint() {
return this.endpoint;
}
public boolean canSpeakFor(Feature feature) {
return endpoint.equals(feature.endpoint());
}
public Collection<Project> projects() {
return makeTeamCityRestCall(endpoint + prefix + "/projects", TeamCityProjects.class).project();
}
public Collection<BuildType> buildTypes() {
return makeTeamCityRestCall(endpoint + prefix + "/buildTypes", BuildTypes.class).buildType();
}
public Collection<BuildType> buildTypesFor(Project projectDigest) {
return makeTeamCityRestCall(endpoint + projectDigest.href, ProjectDetail.class).buildTypes.buildType();
}
public BuildTypeDetail detailsFor(BuildType buildType) {
return makeTeamCityRestCall(endpoint + buildType.href, BuildTypeDetail.class);
}
public Build lastCompletedBuildFor(BuildTypeDetail buildTypeDetail) {
final Builds completedBuilds = makeTeamCityRestCall(endpoint + buildTypeDetail.builds.href, Builds.class);
if (null == completedBuilds.build() || completedBuilds.build().isEmpty()) {
return null;
}
return find(completedBuilds.build(), primaryBranchBuilds);
}
public List<Build> runningBuildsFor(BuildType buildType) {
return makeTeamCityRestCall(endpoint + prefix + "/builds/?locator=running:true,buildType:id:" + buildType.id, Builds.class).build();
}
public List<Investigation> investigationsOf(BuildType buildType) {
return makeTeamCityRestCall(endpoint + buildType.href + "/investigations", Investigations.class).investigation();
}
public BuildDetail detailsOf(Build build) {
return makeTeamCityRestCall(endpoint + build.href, BuildDetail.class);
}
public void commentOn(Build lastCompletedBuild, String note) {
contact.doPut(endpoint + lastCompletedBuild.href + "/comment", note);
}
public List<Change> changesOf(BuildDetail buildDetail) {
final JsonElement json = contact.makeJsonRestCall(endpoint + buildDetail.changes.href);
final JsonElement change = json.isJsonObject() ? json.getAsJsonObject().get("change") : JsonNull.INSTANCE;
if (null == change || !(change.isJsonArray() || change.isJsonObject())) {
return ImmutableList.of();
}
final Gson gson = new Gson();
final List<Change> changes = new ArrayList<Change>();
final Iterable<JsonElement> changesJson = change.isJsonArray() ? change.getAsJsonArray() : ImmutableList.of(change);
for (JsonElement jsonElement : changesJson) {
changes.add(gson.fromJson(jsonElement, Change.class));
}
return changes;
}
public ChangeDetail detailedChangesOf(Change change) {
return makeTeamCityRestCall(endpoint + change.href, ChangeDetail.class);
}
private <T> T makeTeamCityRestCall(String url, Class<T> type) {
return contact.makeJsonRestCall(url, type);
}
private static final Predicate<Build> primaryBranchBuilds = new Predicate<Build>() {
@Override public boolean apply(Build input) {
return input.defaultBranch == null || input.defaultBranch;
}
};
}