/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* 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 jetbrains.buildServer.server.restcontrib.cctray.model;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import jetbrains.buildServer.ServiceLocator;
import jetbrains.buildServer.serverSide.*;
/**
*
Java class for anonymous complex type.
*
* The following schema fragment specifies the expected content contained within this class.
*
*
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}NMTOKEN" />
* <attribute name="activity" use="required">
* <simpleType>
* <restriction base="{http://www.w3.org/2001/XMLSchema}NMTOKEN">
* <enumeration value="Sleeping"/>
* <enumeration value="Building"/>
* <enumeration value="CheckingModifications"/>
* </restriction>
* </simpleType>
* </attribute>
* <attribute name="lastBuildStatus" use="required">
* <simpleType>
* <restriction base="{http://www.w3.org/2001/XMLSchema}NMTOKEN">
* <enumeration value="Exception"/>
* <enumeration value="Success"/>
* <enumeration value="Failure"/>
* <enumeration value="Unknown"/>
* </restriction>
* </simpleType>
* </attribute>
* <attribute name="lastBuildLabel" use="required" type="{http://www.w3.org/2001/XMLSchema}NMTOKEN" />
* <attribute name="lastBuildTime" use="required" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
* <attribute name="nextBuildTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
* <attribute name="webUrl" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* </restriction>
* </complexContent>
* </complexType>
*
*/
@XmlType(name = "", namespace = "http://cctray")
public class Project {
private SBuildType myBuildType;
protected ServiceLocator myServiceLocator;
public Project() {
}
public Project(ServiceLocator serviceLocator, SBuildType buildType) {
this.myServiceLocator = serviceLocator;
myBuildType = buildType;
}
/**
* Gets the value of the name property.
*
* @return possible object is
* {@link String }
*/
@XmlAttribute(name = "name", required = true)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@XmlSchemaType(name = "NMTOKEN")
public String getName() {
return myBuildType.getFullName();
}
/**
* Gets the value of the activity property.
*
* @return possible object is
* {@link String }
*/
@XmlAttribute(name = "activity", required = true)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
public String getActivity() {
final List runningBuilds = myBuildType.getRunningBuilds();
if (runningBuilds.size() > 0) {
return "Building";
}
if (TeamCityProperties.getBoolean("rest.cctray.extendedActivity")) {
// if (myBuildType.isInQueue()) {
// return "Waiting in queue"; // non standard, makes cctray hanging
// }
if (myBuildType.isPaused()) {
return "Paused"; // non standard
}
if (myBuildType.getPendingChanges().size() > 0) {
return "Has pending changes"; // non standard
}
}
return "Sleeping";
}
/**
* Gets the value of the lastBuildStatus property.
*
* @return possible object is
* {@link String }
*/
@XmlAttribute(name = "lastBuildStatus", required = true)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
public String getLastBuildStatus() {
if (myBuildType.getStatus().isFailed()) {
return "Failure";
}
if (myBuildType.getStatus().isSuccessful()) {
return "Success";
}
return "Unknown";
}
/**
* Gets the value of the lastBuildLabel property.
*
* @return possible object is
* {@link String }
*/
@XmlAttribute(name = "lastBuildLabel", required = true)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@XmlSchemaType(name = "NMTOKEN")
public String getLastBuildLabel() {
final SFinishedBuild lastBuild = myBuildType.getLastChangesFinished();
if (lastBuild == null) {
// is this OK?
return null;
}
return String.valueOf(lastBuild.getBuildNumber());
}
/**
* Gets the value of the lastBuildTime property.
*
* @return possible object is
* {@link javax.xml.datatype.XMLGregorianCalendar }
*/
@XmlAttribute(name = "lastBuildTime", required = true)
@XmlSchemaType(name = "dateTime")
public String getLastBuildTime() {
final SFinishedBuild lastBuild = myBuildType.getLastChangesFinished();
if (lastBuild == null) {
// is this OK?
return null;
}
return getFormattedTime(lastBuild.getStartDate());
}
/**
* Gets the value of the nextBuildTime property.
*
* @return possible object is
* {@link javax.xml.datatype.XMLGregorianCalendar }
*/
@XmlAttribute(name = "nextBuildTime")
@XmlSchemaType(name = "dateTime")
public String getNextBuildTime() {
final List queuedBuilds = myBuildType.getQueuedBuilds(null);
for (SQueuedBuild build : queuedBuilds) {
if (!build.isPersonal()) {
final BuildEstimates estimate = build.getBuildEstimates();
if (estimate != null) {
final TimeInterval interval = estimate.getTimeInterval();
if (interval != null && isValid(interval)) {
return getFormattedTime(interval.getStartPoint().getAbsoluteTime());
}
}
}
}
//todo: get next VCS checking/scheduled time
return null;
}
private String getFormattedTime(final Date date) {
final String withoutTimezone = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ENGLISH)).format(date);
final String timezone = (new SimpleDateFormat("Z", Locale.ENGLISH)).format(date);
String modifiedTimezone = "Z";
if (timezone.length() == 5) {
modifiedTimezone = timezone.substring(0, 3) + ":" + timezone.substring(3);
}
return withoutTimezone + modifiedTimezone;
}
private static boolean isValid(final TimeInterval interval) {
// todo (TeamCity) can return some huge number for some reason: TW-19894
final long fromNow_ms = interval.getStartPoint().getAbsoluteTime().getTime() - (new Date()).getTime();
return 0 <= fromNow_ms && fromNow_ms <= 1000 * 60 * 60 * 24 * 100;
}
/**
* Gets the value of the webUrl property.
*
* @return possible object is
* {@link String }
*/
@XmlAttribute(name = "webUrl", required = true)
public String getWebUrl() {
final WebLinks webLinks = myServiceLocator.getSingletonService(WebLinks.class);
return webLinks.getConfigurationHomePageUrl(myBuildType);
}
}