package slacknotifications.teamcity.settings;
import com.intellij.openapi.util.text.StringUtil;
import jetbrains.buildServer.serverSide.SBuildType;
import org.jdom.DataConversionException;
import org.jdom.Element;
import slacknotifications.teamcity.BuildState;
import slacknotifications.teamcity.BuildStateEnum;
import slacknotifications.teamcity.TeamCityIdResolver;
import slacknotifications.teamcity.settings.converter.SlackNotificationBuildStateConverter;
import java.util.*;
import static slacknotifications.teamcity.BuildStateEnum.*;
public class SlackNotificationConfig {
private static final String ENABLED = "enabled";
private static final String TOKEN = "token";
private static final String CHANNEL = "channel";
private static final String TEAM_NAME = "teamName";
private static final String CHANNEL_ENABLED_MESSAGE = "mention-channel-enabled";
private static final String SLACK_USER_ENABLED_MESSAGE = "mention-slack-user-enabled";
private static final String STATES = "states";
private static final String BUILD_TYPES = "build-types";
private static final String ENABLED_FOR_ALL = "enabled-for-all";
private static final String ENABLED_FOR_SUBPROJECTS = "enabled-for-subprojects";
private static final String BOT_NAME = "botName";
private static final String CUSTOM_TEMPLATES = "custom-templates";
private static final String CONTENT = "content";
private static final String ICON_URL = "iconUrl";
private static final String SHOW_BUILD_AGENT = "showBuildAgent";
private static final String SHOW_COMMITS = "showCommits";
private static final String SHOW_COMMITTERS = "showCommitters";
private static final String MAX_COMMITS_TO_DISPLAY = "maxCommitsToDisplay";
private static final String SHOW_FAILURE_REASON = "showFailureReason";
private Boolean enabled = true;
private String uniqueKey = "";
private String apiToken;
private String channel;
private String teamName;
private BuildState states = new BuildState();
private SortedMap<String, CustomMessageTemplate> templates;
private Boolean allBuildTypesEnabled = true;
private Boolean subProjectsEnabled = true;
private Set<String> enabledBuildTypesSet = new HashSet<String>();
private boolean mentionChannelEnabled;
private boolean mentionSlackUserEnabled;
private boolean customContent;
private SlackNotificationContentConfig content;
@SuppressWarnings("unchecked")
public SlackNotificationConfig(Element e) {
this.content = new SlackNotificationContentConfig();
int Min = 1000000, Max = 1000000000;
Integer Rand = Min + (int)(Math.random() * ((Max - Min) + 1));
this.uniqueKey = Rand.toString();
this.templates = new TreeMap<String,CustomMessageTemplate>();
if (e.getAttribute(TOKEN) != null){
this.setToken(e.getAttributeValue(TOKEN));
}
if (e.getAttribute(CHANNEL) != null){
this.setChannel(e.getAttributeValue(CHANNEL));
}
if (e.getAttribute(TEAM_NAME) != null){
this.setTeamName(e.getAttributeValue(TEAM_NAME));
}
if (e.getAttribute(ENABLED) != null){
this.setEnabled(Boolean.parseBoolean(e.getAttributeValue(ENABLED)));
}
if (e.getAttribute("statemask") != null){
this.setBuildStates(SlackNotificationBuildStateConverter.convert(Integer.parseInt(e.getAttributeValue("statemask"))));
}
if (e.getAttribute("key") != null){
this.setUniqueKey(e.getAttributeValue("key"));
}
if (e.getAttribute(CHANNEL_ENABLED_MESSAGE) != null){
this.setMentionChannelEnabled(Boolean.parseBoolean(e.getAttributeValue("mention-channel-enabled")));
}
if (e.getAttribute(SLACK_USER_ENABLED_MESSAGE) != null){
this.setMentionSlackUserEnabled(Boolean.parseBoolean(e.getAttributeValue("mention-slack-user-enabled")));
}
if(e.getChild(STATES) != null){
Element eStates = e.getChild(STATES);
List<Element> statesList = eStates.getChildren("state");
if (!statesList.isEmpty()){
for(Element eState : statesList)
{
try {
states.setEnabled(BuildStateEnum.findBuildState(eState.getAttributeValue("type")),
eState.getAttribute(ENABLED).getBooleanValue());
} catch (DataConversionException e1) {e1.printStackTrace();}
}
}
}
if(e.getChild(BUILD_TYPES) != null){
Element eTypes = e.getChild(BUILD_TYPES);
if (eTypes.getAttribute(ENABLED_FOR_ALL) != null){
try {
this.enableForAllBuildsInProject(eTypes.getAttribute(ENABLED_FOR_ALL).getBooleanValue());
} catch (DataConversionException e1) {e1.printStackTrace();}
}
if (eTypes.getAttribute(ENABLED_FOR_SUBPROJECTS) != null){
try {
this.enableForSubProjects(eTypes.getAttribute(ENABLED_FOR_SUBPROJECTS).getBooleanValue());
} catch (DataConversionException e1) {e1.printStackTrace();}
}
if (!isEnabledForAllBuildsInProject()){
List<Element> typesList = eTypes.getChildren("build-type");
if (!typesList.isEmpty()){
for(Element eType : typesList)
{
if (eType.getAttributeValue("id")!= null){
enabledBuildTypesSet.add(eType.getAttributeValue("id"));
}
}
}
}
}
if(e.getChild(CUSTOM_TEMPLATES) != null){
Element eParams = e.getChild(CUSTOM_TEMPLATES);
List<Element> templateList = eParams.getChildren("custom-template");
if (!templateList.isEmpty()){
for(Element eParam : templateList)
{
this.templates.put(
eParam.getAttributeValue(CustomMessageTemplate.TYPE),
CustomMessageTemplate.create(
eParam.getAttributeValue(CustomMessageTemplate.TYPE),
eParam.getAttributeValue(CustomMessageTemplate.TEMPLATE),
Boolean.parseBoolean(eParam.getAttributeValue(CustomMessageTemplate.ENABLED))
)
);
}
}
}
if(e.getChild(CONTENT) != null) {
setHasCustomContent(true);
Element eContent = e.getChild(CONTENT);
this.content.setEnabled(true);
if (eContent.getAttribute(ICON_URL) != null){
this.content.setIconUrl(eContent.getAttributeValue(ICON_URL));
}
if (eContent.getAttribute(BOT_NAME) != null){
this.content.setBotName(eContent.getAttributeValue(BOT_NAME));
}
if (eContent.getAttribute(SHOW_BUILD_AGENT) != null){
this.content.setShowBuildAgent(Boolean.parseBoolean(eContent.getAttributeValue(SHOW_BUILD_AGENT)));
}
if (eContent.getAttribute("showElapsedBuildTime") != null){
this.content.setShowElapsedBuildTime(Boolean.parseBoolean(eContent.getAttributeValue("showElapsedBuildTime")));
}
if (eContent.getAttribute(SHOW_COMMITS) != null){
this.content.setShowCommits(Boolean.parseBoolean(eContent.getAttributeValue(SHOW_COMMITS)));
}
if (eContent.getAttribute(SHOW_COMMITTERS) != null){
this.content.setShowCommitters(Boolean.parseBoolean(eContent.getAttributeValue(SHOW_COMMITTERS)));
}
if (eContent.getAttribute(MAX_COMMITS_TO_DISPLAY) != null){
this.content.setMaxCommitsToDisplay(Integer.parseInt(eContent.getAttributeValue(MAX_COMMITS_TO_DISPLAY)));
}
if (eContent.getAttribute(SHOW_FAILURE_REASON) != null){
this.content.setShowFailureReason(Boolean.parseBoolean(eContent.getAttributeValue(SHOW_FAILURE_REASON)));
}
}
}
/**
* SlackNotificationsConfig constructor. Unchecked version. Use with caution!!
* This constructor does not check if the payloadFormat is valid.
* It will still allow you to add the format, but the slacknotifications might not
* fire at runtime if the payloadFormat configured is not available.
*
* @param channel
* @param enabled
* @param states
*/
public SlackNotificationConfig(String token,
String channel,
String teamName,
Boolean enabled,
BuildState states,
boolean buildTypeAllEnabled,
boolean buildTypeSubProjects,
Set<String> enabledBuildTypes,
boolean mentionChannelEnabled,
boolean mentionSlackUserEnabled) {
this.content = new SlackNotificationContentConfig();
int Min = 1000000, Max = 1000000000;
Integer Rand = Min + (int) (Math.random() * ((Max - Min) + 1));
this.uniqueKey = Rand.toString();
this.templates = new TreeMap<String, CustomMessageTemplate>();
this.setToken(token);
this.setChannel(channel);
this.setTeamName(teamName);
this.setEnabled(enabled);
this.setBuildStates(states);
this.subProjectsEnabled = buildTypeSubProjects;
this.allBuildTypesEnabled = buildTypeAllEnabled;
this.setMentionChannelEnabled(mentionChannelEnabled);
this.setMentionSlackUserEnabled(mentionSlackUserEnabled);
if (!this.allBuildTypesEnabled) {
this.enabledBuildTypesSet = enabledBuildTypes;
}
}
public Element getAsElement(){
Element el = new Element("slackNotification");
el.setAttribute(CHANNEL, this.getChannel());
if(StringUtil.isNotEmpty(this.getToken())) {
el.setAttribute(TOKEN, this.getToken());
}
if(StringUtil.isNotEmpty(this.getTeamName())) {
el.setAttribute(TEAM_NAME, this.getTeamName());
}
el.setAttribute(ENABLED, String.valueOf(this.enabled));
el.setAttribute(CHANNEL_ENABLED_MESSAGE, String.valueOf(this.getMentionChannelEnabled()));
el.setAttribute(SLACK_USER_ENABLED_MESSAGE, String.valueOf(this.getMentionSlackUserEnabled()));
Element statesEl = new Element(STATES);
for (BuildStateEnum state : states.getStateSet()){
Element e = new Element("state");
e.setAttribute("type", state.getShortName());
e.setAttribute(ENABLED, Boolean.toString(states.enabled(state)));
statesEl.addContent(e);
}
el.addContent(statesEl);
Element buildsEl = new Element(BUILD_TYPES);
buildsEl.setAttribute(ENABLED_FOR_ALL, Boolean.toString(isEnabledForAllBuildsInProject()));
buildsEl.setAttribute(ENABLED_FOR_SUBPROJECTS, Boolean.toString(isEnabledForSubProjects()));
if (!this.enabledBuildTypesSet.isEmpty()){
for (String i : enabledBuildTypesSet){
Element e = new Element("build-type");
e.setAttribute("id", i);
buildsEl.addContent(e);
}
}
el.addContent(buildsEl);
if (this.templates.size() > 0){
Element templatesEl = new Element(CUSTOM_TEMPLATES);
for (CustomMessageTemplate t : this.templates.values()){
templatesEl.addContent(t.getAsElement());
}
el.addContent(templatesEl);
}
if(this.hasCustomContent()){
Element customContentEl = new Element(CONTENT);
customContentEl.setAttribute(ICON_URL, this.content.getIconUrl());
customContentEl.setAttribute(BOT_NAME, this.content.getBotName());
customContentEl.setAttribute(MAX_COMMITS_TO_DISPLAY, Integer.toString(this.content.getMaxCommitsToDisplay()));
customContentEl.setAttribute(SHOW_BUILD_AGENT, this.content.getShowBuildAgent().toString());
customContentEl.setAttribute("showElapsedBuildTime", this.content.getShowElapsedBuildTime().toString());
customContentEl.setAttribute(SHOW_COMMITS, this.content.getShowCommits().toString());
customContentEl.setAttribute(SHOW_COMMITTERS, this.content.getShowCommitters().toString());
customContentEl.setAttribute(SHOW_FAILURE_REASON, this.content.getShowFailureReason().toString());
el.addContent(customContentEl);
}
return el;
}
// Getters and Setters..
public boolean isEnabledForBuildType(SBuildType sBuildType){
// If allBuildTypes enabled, return true, otherwise return whether the build is in the list of enabled buildTypes.
return isEnabledForAllBuildsInProject() || enabledBuildTypesSet.contains(TeamCityIdResolver.getInternalBuildId(sBuildType));
}
boolean isSpecificBuildTypeEnabled(SBuildType sBuildType){
// Just check if this build type is only enabled for a specific build.
return enabledBuildTypesSet.contains(TeamCityIdResolver.getInternalBuildId(sBuildType));
}
public String getBuildTypeCountAsFriendlyString() {
if (this.allBuildTypesEnabled && !this.subProjectsEnabled) {
return "All builds";
} else if (this.allBuildTypesEnabled) {
return "All builds & Sub-Projects";
}
String subProjectsString = "";
if (this.subProjectsEnabled) {
subProjectsString = " & All Sub-Project builds";
}
int enabledBuildTypeCount = this.enabledBuildTypesSet.size();
if (enabledBuildTypeCount == 1) {
return enabledBuildTypeCount + " build" + subProjectsString;
}
return enabledBuildTypeCount + " builds" + subProjectsString;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public BuildState getBuildStates() {
return states;
}
public void setBuildStates(BuildState states) {
this.states = states;
}
public String getToken() {
return apiToken;
}
public void setToken(String apiToken) {
this.apiToken = apiToken;
}
public String getChannel() {
return channel;
}
public void setChannel(String channel) {
this.channel = channel;
}
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
public String getUniqueKey() {
return uniqueKey;
}
public void setUniqueKey(String uniqueKey) {
this.uniqueKey = uniqueKey;
}
public String getEnabledListAsString(){
if (!this.enabled){
return "Disabled";
} else if (states.allEnabled()){
return "All Build Events";
} else if (states.noneEnabled()) {
return "None";
} else {
String enabledStates = "";
if (states.enabled(BuildStateEnum.BUILD_STARTED)){
enabledStates += ", Build Started";
}
// if (BuildState.enabled(BuildState.BUILD_FINISHED,this.statemask)){
// enabledStates += ", Build Completed";
// }
// if (BuildState.enabled(BuildState.BUILD_CHANGED_STATUS,this.statemask)){
// enabledStates += ", Build Changed Status";
// }
if (states.enabled(BuildStateEnum.BUILD_INTERRUPTED)){
enabledStates += ", Build Interrupted";
}
if (states.enabled(BuildStateEnum.BEFORE_BUILD_FINISHED)){
enabledStates += ", Build Almost Completed";
}
if (states.enabled(BuildStateEnum.RESPONSIBILITY_CHANGED)){
enabledStates += ", Build Responsibility Changed";
}
if (states.enabled(BuildStateEnum.BUILD_FAILED)){
if (states.enabled(BuildStateEnum.BUILD_BROKEN)){
enabledStates += ", Build Broken";
} else {
enabledStates += ", Build Failed";
}
}
if (states.enabled(BuildStateEnum.BUILD_SUCCESSFUL)){
if (states.enabled(BuildStateEnum.BUILD_FIXED)){
enabledStates += ", Build Fixed";
} else {
enabledStates += ", Build Successful";
}
}
if (enabledStates.length() > 0){
return enabledStates.substring(1);
} else {
return "None";
}
}
}
public String getSlackNotificationEnabledAsChecked() {
if (this.enabled){
return "checked ";
}
return "";
}
public String getStateAllAsChecked() {
if (states.allEnabled()){
return "checked ";
}
return "";
}
public String getStateBuildStartedAsChecked() {
if (states.enabled(BUILD_STARTED)){
return "checked ";
}
return "";
}
public String getStateBuildFinishedAsChecked() {
if (states.enabled(BUILD_FINISHED)){
return "checked ";
}
return "";
}
public String getStateBeforeFinishedAsChecked() {
if (states.enabled(BEFORE_BUILD_FINISHED)){
return "checked ";
}
return "";
}
public String getStateResponsibilityChangedAsChecked() {
if (states.enabled(RESPONSIBILITY_CHANGED)){
return "checked ";
}
return "";
}
public String getStateBuildInterruptedAsChecked() {
if (states.enabled(BUILD_INTERRUPTED)){
return "checked ";
}
return "";
}
public String getStateBuildSuccessfulAsChecked() {
if (states.enabled(BUILD_SUCCESSFUL)){
return "checked ";
}
return "";
}
public String getStateBuildFixedAsChecked() {
if (states.enabled(BUILD_FIXED)){
return "checked ";
}
return "";
}
public String getStateBuildFailedAsChecked() {
if (states.enabled(BUILD_FAILED)){
return "checked ";
}
return "";
}
public String getStateBuildBrokenAsChecked() {
if (states.enabled(BUILD_BROKEN)){
return "checked ";
}
return "";
}
public Boolean isEnabledForAllBuildsInProject() {
return allBuildTypesEnabled;
}
public void enableForAllBuildsInProject(Boolean allBuildTypesEnabled) {
this.allBuildTypesEnabled = allBuildTypesEnabled;
}
public Boolean isEnabledForSubProjects() {
return subProjectsEnabled;
}
public void enableForSubProjects(Boolean subProjectsEnabled) {
this.subProjectsEnabled = subProjectsEnabled;
}
public void clearAllEnabledBuildsInProject(){
this.enabledBuildTypesSet.clear();
}
public void enableBuildInProject(String buildTypeId) {
this.enabledBuildTypesSet.add(buildTypeId);
}
public void setMentionChannelEnabled(boolean mentionChannelEnabled) {
this.mentionChannelEnabled = mentionChannelEnabled;
}
public boolean getMentionChannelEnabled() {
return mentionChannelEnabled;
}
public void setMentionSlackUserEnabled(boolean mentionSlackUserEnabled) {
this.mentionSlackUserEnabled = mentionSlackUserEnabled;
}
public boolean getMentionSlackUserEnabled() {
return mentionSlackUserEnabled;
}
public boolean hasCustomContent() {
return customContent;
}
public void setHasCustomContent(boolean customContent) {
this.customContent = customContent;
}
public SlackNotificationContentConfig getContent() {
return content;
}
public void setContent(SlackNotificationContentConfig content) {
this.content = content;
}
}