package org.netmelody.cieye.spies.teamcity; import static com.google.common.collect.Collections2.filter; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newHashMap; import static org.netmelody.cieye.core.domain.Status.UNKNOWN; import java.util.Collection; import java.util.List; import java.util.Map; import org.netmelody.cieye.core.domain.Feature; import org.netmelody.cieye.core.domain.Status; import org.netmelody.cieye.core.domain.TargetDetail; import org.netmelody.cieye.core.domain.TargetDigest; import org.netmelody.cieye.core.domain.TargetDigestGroup; import org.netmelody.cieye.core.domain.TargetId; import org.netmelody.cieye.core.observation.CiSpy; import org.netmelody.cieye.core.observation.Contact; import org.netmelody.cieye.core.observation.KnownOffendersDirectory; import org.netmelody.cieye.spies.teamcity.jsondomain.Build; import org.netmelody.cieye.spies.teamcity.jsondomain.BuildType; import org.netmelody.cieye.spies.teamcity.jsondomain.BuildTypeDetail; import com.google.common.base.Predicate; public final class TeamCitySpy implements CiSpy { private final TeamCityCommunicator communicator; private final BuildTypeAnalyser buildTypeAnalyser; private final Map<TargetId, BuildType> recognisedBuildTypes = newHashMap(); public TeamCitySpy(String endpoint, KnownOffendersDirectory detective, Contact contact) { this.communicator = new TeamCityCommunicator(contact, endpoint); this.buildTypeAnalyser = new BuildTypeAnalyser(this.communicator, detective); } @Override public TargetDigestGroup targetsConstituting(Feature feature) { final Collection<BuildType> buildTypes = buildTypesFor(feature); final List<TargetDigest> digests = newArrayList(); for (BuildType buildType : buildTypes) { final TargetDigest targetDigest = new TargetDigest(communicator.endpoint() + buildType.href, buildType.webUrl(), buildType.name, UNKNOWN); digests.add(targetDigest); recognisedBuildTypes.put(targetDigest.id(), buildType); } return new TargetDigestGroup(digests); } @Override public TargetDetail statusOf(final TargetId target) { BuildType buildType = recognisedBuildTypes.get(target); if (null == buildType) { return null; } return buildTypeAnalyser.targetFrom(buildType); } @Override public boolean takeNoteOf(TargetId target, String note) { if (!recognisedBuildTypes.containsKey(target)) { return false; } final BuildTypeDetail buildTypeDetail = communicator.detailsFor(recognisedBuildTypes.get(target)); final Build lastCompletedBuild = communicator.lastCompletedBuildFor(buildTypeDetail); if (null != lastCompletedBuild && Status.BROKEN.equals(lastCompletedBuild.status())) { communicator.commentOn(lastCompletedBuild, note); } return true; } private Collection<BuildType> buildTypesFor(final Feature feature) { if (!communicator.canSpeakFor(feature)) { return newArrayList(); } final Collection<BuildType> buildTypes = communicator.buildTypes(); if (feature.name().isEmpty()) { return buildTypes; } return filter(buildTypes, withFeatureName(feature.name())); } private Predicate<BuildType> withFeatureName(final String featureName) { return new Predicate<BuildType>() { @Override public boolean apply(BuildType buildType) { return buildType.projectName.trim().equals(featureName.trim()); } }; } }