/*
* Copyright 2017 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.domain;
import java.util.*;
import com.thoughtworks.go.config.*;
import com.thoughtworks.go.config.exceptions.PipelineGroupNotFoundException;
import com.thoughtworks.go.config.materials.PackageMaterialConfig;
import com.thoughtworks.go.config.materials.PluggableSCMMaterialConfig;
import com.thoughtworks.go.config.materials.ScmMaterialConfig;
import com.thoughtworks.go.domain.materials.MaterialConfig;
import com.thoughtworks.go.domain.packagerepository.PackageDefinition;
import com.thoughtworks.go.domain.packagerepository.PackageRepository;
import com.thoughtworks.go.domain.scm.SCM;
import com.thoughtworks.go.util.Pair;
@ConfigCollection(value = BasicPipelineConfigs.class)
public class PipelineGroups extends BaseCollection<PipelineConfigs> implements Validatable {
private final ConfigErrors configErrors = new ConfigErrors();
private Map<String, List<Pair<PipelineConfig, PipelineConfigs>>> packageToPipelineMap;
private Map<String, List<Pair<PipelineConfig, PipelineConfigs>>> pluggableSCMMaterialToPipelineMap;
public PipelineGroups() {
}
public PipelineGroups(PipelineConfigs... configses) {
for (PipelineConfigs configs : configses) {
this.add(configs);
}
}
public void update(String groupName, String pipelineName, PipelineConfig pipeline) {
for (PipelineConfigs pipelines : this) {
pipelines.update(groupName, pipeline, pipelineName);
}
}
public void addPipeline(String groupName, PipelineConfig pipeline) {
String sanitizedGroupName = BasicPipelineConfigs.sanitizedGroupName(groupName);
if (!this.hasGroup(sanitizedGroupName)) {
createNewGroup(sanitizedGroupName, pipeline);
return;
}
for (PipelineConfigs pipelines : this) {
if (pipelines.save(pipeline, sanitizedGroupName)) {
return;
}
}
}
public void addPipelineWithoutValidation(String groupName, PipelineConfig pipelineConfig) {
if (!this.hasGroup(groupName)) {
createNewGroup(groupName, pipelineConfig);
} else {
PipelineConfigs group = findGroup(groupName);
group.addWithoutValidation(pipelineConfig);
}
}
public void deletePipeline(PipelineConfig pipelineConfig) {
for (PipelineConfigs group : this) {
if(group.hasPipeline(pipelineConfig.name())){
group.remove(pipelineConfig);
return;
}
}
}
private void createNewGroup(String sanitizedGroupName, PipelineConfig pipeline) {
PipelineConfigs configs = new BasicPipelineConfigs(pipeline);
configs.setGroup(sanitizedGroupName);
this.add(0, configs);
}
public PipelineConfigs findGroup(String groupName) {
for (PipelineConfigs pipelines : this) {
if (pipelines.isNamed(groupName)) {
return pipelines;
}
}
throw new PipelineGroupNotFoundException("Failed to find the group [" + groupName + "]");
}
public boolean hasGroup(String groupName) {
try {
findGroup(groupName);
return true;
} catch (PipelineGroupNotFoundException e) {
return false;
}
}
public PipelineConfig findPipeline(String groupName, int pipelineIndex) {
return findGroup(groupName).get(pipelineIndex);
}
public void accept(PipelineGroupVisitor visitor) {
for (PipelineConfigs group : this) {
visitor.visit(group);
}
}
public String findGroupNameByPipeline(CaseInsensitiveString pipelineName) {
for (PipelineConfigs group : this) {
if (group.hasPipeline(pipelineName)) {
return group.getGroup();
}
}
return null;
}
public void validate(ValidationContext validationContext) {
Map<String, PipelineConfigs> nameToConfig = new HashMap<>();
List<PipelineConfigs> visited = new ArrayList();
for (PipelineConfigs group : this) {
group.validateNameUniqueness(nameToConfig);
}
validatePipelineNameUniqueness();
}
public void validatePipelineNameUniqueness() {
List<PipelineConfig> visited = new ArrayList<>();
HashMap<CaseInsensitiveString, Set<String>> duplicates = new HashMap<>();
for (PipelineConfigs group : this) {
for (PipelineConfig pipeline : group) {
for (PipelineConfig visitedPipeline : visited) {
if (visitedPipeline.name().equals(pipeline.name())) {
if(!duplicates.containsKey(pipeline.name())){
duplicates.put(pipeline.name(), new HashSet<>());
}
duplicates.get(pipeline.name()).add(pipeline.getOriginDisplayName());
duplicates.get(pipeline.name()).add(visitedPipeline.getOriginDisplayName());
pipeline.errors().remove(PipelineConfig.NAME);
pipeline.addError(PipelineConfig.NAME, String.format("You have defined multiple pipelines named '%s'. Pipeline names must be unique. Source(s): %s", pipeline.name(), duplicates.get(pipeline.name())));
visitedPipeline.errors().remove(PipelineConfig.NAME);
visitedPipeline.addError(PipelineConfig.NAME, String.format("You have defined multiple pipelines named '%s'. Pipeline names must be unique. Source(s): %s", pipeline.name(), duplicates.get(pipeline.name())));
}
}
visited.add(pipeline);
}
}
}
public ConfigErrors errors() {
return configErrors;
}
public void addError(String fieldName, String message) {
configErrors.add(fieldName, message);
}
public Set<MaterialConfig> getAllUniquePostCommitSchedulableMaterials() {
Set<MaterialConfig> materialConfigs = new HashSet<>();
Set<String> uniqueMaterials = new HashSet<>();
for (PipelineConfigs pipelineConfigs : this) {
for (PipelineConfig pipelineConfig : pipelineConfigs) {
for (MaterialConfig materialConfig : pipelineConfig.materialConfigs()) {
if ((materialConfig instanceof ScmMaterialConfig || materialConfig instanceof PluggableSCMMaterialConfig)
&& !materialConfig.isAutoUpdate()
&& !uniqueMaterials.contains(materialConfig.getFingerprint())) {
materialConfigs.add(materialConfig);
uniqueMaterials.add(materialConfig.getFingerprint());
}
}
}
}
return materialConfigs;
}
public Map<String, List<Pair<PipelineConfig, PipelineConfigs>>> getPackageUsageInPipelines() {
if (packageToPipelineMap == null) {
synchronized (this) {
if (packageToPipelineMap == null) {
packageToPipelineMap = new HashMap<>();
for (PipelineConfigs pipelineConfigs : this) {
for (PipelineConfig pipelineConfig : pipelineConfigs) {
for (PackageMaterialConfig packageMaterialConfig : pipelineConfig.packageMaterialConfigs()) {
String packageId = packageMaterialConfig.getPackageId();
if (!packageToPipelineMap.containsKey(packageId)) {
packageToPipelineMap.put(packageId, new ArrayList<>());
}
packageToPipelineMap.get(packageId).add(new Pair<>(pipelineConfig, pipelineConfigs));
}
}
}
}
}
}
return packageToPipelineMap;
}
public boolean canDeletePackageRepository(PackageRepository packageRepository) {
Map<String, List<Pair<PipelineConfig, PipelineConfigs>>> packageUsageInPipelines = getPackageUsageInPipelines();
for (PackageDefinition packageDefinition : packageRepository.getPackages()) {
if (packageUsageInPipelines.containsKey(packageDefinition.getId())) {
return false;
}
}
return true;
}
public Map<String, List<Pair<PipelineConfig, PipelineConfigs>>> getPluggableSCMMaterialUsageInPipelines() {
if (pluggableSCMMaterialToPipelineMap == null) {
synchronized (this) {
if (pluggableSCMMaterialToPipelineMap == null) {
pluggableSCMMaterialToPipelineMap = new HashMap<>();
for (PipelineConfigs pipelineConfigs : this) {
for (PipelineConfig pipelineConfig : pipelineConfigs) {
for (PluggableSCMMaterialConfig pluggableSCMMaterialConfig : pipelineConfig.pluggableSCMMaterialConfigs()) {
String scmId = pluggableSCMMaterialConfig.getScmId();
if (!pluggableSCMMaterialToPipelineMap.containsKey(scmId)) {
pluggableSCMMaterialToPipelineMap.put(scmId, new ArrayList<>());
}
pluggableSCMMaterialToPipelineMap.get(scmId).add(new Pair<>(pipelineConfig, pipelineConfigs));
}
}
}
}
}
}
return pluggableSCMMaterialToPipelineMap;
}
public boolean canDeletePluggableSCMMaterial(SCM scmConfig) {
Map<String, List<Pair<PipelineConfig, PipelineConfigs>>> packageUsageInPipelines = getPluggableSCMMaterialUsageInPipelines();
if (packageUsageInPipelines.containsKey(scmConfig.getId())) {
return false;
}
return true;
}
public PipelineGroups getLocal() {
PipelineGroups locals = new PipelineGroups();
for(PipelineConfigs pipelineConfigs : this)
{
PipelineConfigs local = pipelineConfigs.getLocal();
if(local != null)
locals.add(local);
}
return locals;
}
}