/* * Copyright 2016 ThoughtWorks, Inc. * * 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 com.thoughtworks.go.config; import com.thoughtworks.go.domain.CommentRenderer; import com.thoughtworks.go.domain.ConfigErrors; import com.thoughtworks.go.domain.DefaultCommentRenderer; import com.thoughtworks.go.util.StringUtil; import com.thoughtworks.go.util.XmlUtils; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.http.client.utils.URIBuilder; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.util.Map; import java.util.regex.Pattern; /** * @understands mingle project for pipeline */ @ConfigTag("mingle") public class MingleConfig implements ParamsAttributeAware, Validatable, CommentRenderer { @ConfigAttribute(value = "baseUrl", optional = false) private String baseUrl; @ConfigAttribute(value = "projectIdentifier", optional = false) private String projectIdentifier; @ConfigSubtag private MqlCriteria mqlCriteria = new MqlCriteria(); private final ConfigErrors configErrors = new ConfigErrors(); private static final String DELIMITER = "/"; public static final String BASE_URL = "baseUrl"; public static final String PROJECT_IDENTIFIER = "projectIdentifier"; public static final String MQL_GROUPING_CONDITIONS = "mqlCriteria"; private static final String MINGLE_URL_PATTERN = "https://.+"; private static final Pattern MINGLE_URL_PATTERN_REGEX = Pattern.compile(String.format("^(%s)$", MINGLE_URL_PATTERN)); private static final String PROJECT_IDENTIFIER_PATTERN = "[^\\s]+"; private static final Pattern PROJECT_IDENTIFIER_PATTERN_REGEX = Pattern.compile(String.format("^(%s)$", PROJECT_IDENTIFIER_PATTERN)); public MingleConfig() { } public MingleConfig(String baseUrl, String projectIdentifier, String mql) { this(baseUrl, projectIdentifier); this.mqlCriteria = new MqlCriteria(mql); } public MingleConfig(String baseUrl, String projectIdentifier) { this.baseUrl = baseUrl; this.projectIdentifier = projectIdentifier; } public boolean validateTree(ValidationContext validationContext) { validate(validationContext); return errors().isEmpty(); } public void validate(ValidationContext validationContext) { if (isDefined() && XmlUtils.doesNotMatchUsingXsdRegex(MINGLE_URL_PATTERN_REGEX, baseUrl)) { configErrors.add(BASE_URL, "Should be a URL starting with https://"); } if (projectIdentifier != null && XmlUtils.doesNotMatchUsingXsdRegex(PROJECT_IDENTIFIER_PATTERN_REGEX, projectIdentifier)) { configErrors.add(PROJECT_IDENTIFIER, "Should be a valid mingle identifier."); } } public boolean isDefined() { return baseUrl != null; } public ConfigErrors errors() { return configErrors; } public void addError(String fieldName, String message) { configErrors.add(fieldName, message); } public String urlFor(String path) throws MalformedURLException, URISyntaxException { URIBuilder baseUri = new URIBuilder(baseUrl); String originalPath = baseUri.getPath(); if (originalPath == null) { originalPath = ""; } if (originalPath.endsWith(DELIMITER) && path.startsWith(DELIMITER)) { path = path.replaceFirst(DELIMITER, ""); } return baseUri.setPath(originalPath + path).toString(); } public String getProjectIdentifier() { return projectIdentifier; } public void setProjectIdentifier(String projectIdentifier) { this.projectIdentifier = projectIdentifier; } public String getQuotedMql() { String mqlString = mqlCriteria.equals(new MqlCriteria()) ? "" : mqlCriteria.getMql(); return StringUtil.quoteJavascriptString(mqlString); } public String getQuotedProjectIdentifier() { return StringUtil.quoteJavascriptString(projectIdentifier); } public String getBaseUrl() { return baseUrl; } public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; } public MqlCriteria getMqlCriteria() { return mqlCriteria; } public void setMqlCriteria(String mql) { this.mqlCriteria = new MqlCriteria(mql); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } MingleConfig that = (MingleConfig) o; if (baseUrl != null ? !baseUrl.equals(that.baseUrl) : that.baseUrl != null) { return false; } if (mqlCriteria != null ? !mqlCriteria.equals(that.mqlCriteria) : that.mqlCriteria != null) { return false; } if (projectIdentifier != null ? !projectIdentifier.equals(that.projectIdentifier) : that.projectIdentifier != null) { return false; } return true; } @Override public int hashCode() { int result = baseUrl != null ? baseUrl.hashCode() : 0; result = 31 * result + (projectIdentifier != null ? projectIdentifier.hashCode() : 0); result = 31 * result + (mqlCriteria != null ? mqlCriteria.hashCode() : 0); return result; } @Override public String toString() { return new ToStringBuilder(this). append("baseUrl", baseUrl). append("projectName", projectIdentifier). append("mqlCriteria", mqlCriteria). toString(); } public void setConfigAttributes(Object attributes) { if (attributes == null) { return; } Map attributeMap = (Map) attributes; if (attributeMap.containsKey(BASE_URL)) { baseUrl = (String) attributeMap.get(BASE_URL); } if (attributeMap.containsKey(PROJECT_IDENTIFIER)) { projectIdentifier = (String) attributeMap.get(PROJECT_IDENTIFIER); } if (attributeMap.containsKey(MQL_GROUPING_CONDITIONS)) { mqlCriteria = (mqlCriteria == null) ? new MqlCriteria() : mqlCriteria; mqlCriteria.setConfigAttributes(attributeMap.get(MQL_GROUPING_CONDITIONS)); } } public static MingleConfig create(Object attributes) { MingleConfig mingleConfig = new MingleConfig(); mingleConfig.setConfigAttributes(attributes); return mingleConfig; } public boolean isDifferentFrom(MingleConfig other) { if (baseUrl != null ? !baseUrl.equals(other.baseUrl) : other.baseUrl != null) { return false; } if (projectIdentifier != null ? !projectIdentifier.equals(other.projectIdentifier) : other.projectIdentifier != null) { return false; } return true; } public String render(String text) { try { String urlPart = urlFor(String.format("/projects/%s/cards/", projectIdentifier)); return new DefaultCommentRenderer(urlPart + "${ID}", "#(\\d+)").render(text); } catch (MalformedURLException | URISyntaxException e) { throw new RuntimeException("Could not construct the URL to generate the link.", e); } } }