3 * Copyright (C) 2009-2016 SonarSource SA
4 * mailto:contact AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.computation.task.projectanalysis.component;
22 import com.google.common.annotations.VisibleForTesting;
23 import com.google.common.base.Optional;
24 import com.google.common.base.Supplier;
25 import java.util.function.Function;
26 import javax.annotation.CheckForNull;
27 import javax.annotation.Nullable;
28 import org.sonar.db.component.ComponentDto;
29 import org.sonar.scanner.protocol.output.ScannerReport;
31 import static com.google.common.collect.Iterables.toArray;
32 import static java.lang.String.format;
33 import static org.apache.commons.lang.StringUtils.trimToNull;
34 import static org.sonar.core.component.ComponentKeys.createEffectiveKey;
35 import static org.sonar.core.component.ComponentKeys.createKey;
36 import static org.sonar.core.util.stream.Collectors.toList;
38 public class ComponentRootBuilder {
39 private final Function<String, String> uuidSupplier;
40 private final Function<Integer, ScannerReport.Component> scannerComponentSupplier;
41 private final Supplier<Optional<ComponentDto>> projectDtoSupplier;
43 private final String branch;
45 public ComponentRootBuilder(@Nullable String branch,
46 Function<String, String> uuidSupplier,
47 Function<Integer, ScannerReport.Component> scannerComponentSupplier,
48 Supplier<Optional<ComponentDto>> projectDtoSupplier) {
49 this.uuidSupplier = uuidSupplier;
50 this.scannerComponentSupplier = scannerComponentSupplier;
51 this.projectDtoSupplier = projectDtoSupplier;
55 public Component build(ScannerReport.Component reportProject, String projectKey) {
56 return buildComponent(reportProject, projectKey);
59 private ComponentImpl buildComponent(ScannerReport.Component reportComponent, String latestModuleKey) {
60 switch (reportComponent.getType()) {
62 return createCommonBuilder(reportComponent, latestModuleKey, latestModuleKey)
63 .setName(nameOfProject(reportComponent, latestModuleKey, projectDtoSupplier))
66 String moduleKey = createKey(reportComponent.getKey(), branch);
67 return buildOtherComponent(reportComponent, moduleKey, moduleKey);
70 return buildOtherComponent(reportComponent, createEffectiveKey(latestModuleKey, reportComponent.getPath()), latestModuleKey);
72 throw new IllegalArgumentException(format("Unsupported component type '%s'", reportComponent.getType()));
76 private ComponentImpl buildOtherComponent(ScannerReport.Component reportComponent, String componentKey, String latestModuleKey) {
77 return createCommonBuilder(reportComponent, componentKey, latestModuleKey)
78 .setName(nameOfOthers(reportComponent, componentKey))
82 private ComponentImpl.Builder createCommonBuilder(ScannerReport.Component reportComponent, String componentKey, String latestModuleKey) {
83 return ComponentImpl.builder(convertType(reportComponent.getType()))
84 .setUuid(uuidSupplier.apply(componentKey))
86 .setDescription(trimToNull(reportComponent.getDescription()))
87 .setFileAttributes(createFileAttributes(reportComponent))
88 .setReportAttributes(createReportAttributes(reportComponent))
89 .addChildren(toArray(buildChildren(reportComponent, latestModuleKey), Component.class));
92 private Iterable<Component> buildChildren(ScannerReport.Component component, String latestModuleKey) {
93 return component.getChildRefList()
95 .map(componentRef -> buildComponent(scannerComponentSupplier.apply(componentRef), latestModuleKey))
96 .collect(toList(component.getChildRefList().size()));
99 private static String nameOfProject(ScannerReport.Component project, String projectKey, Supplier<Optional<ComponentDto>> projectDtoSupplier) {
100 String name = trimToNull(project.getName());
102 return projectDtoSupplier.get().transform(ComponentDto::name).or(projectKey);
107 private static String nameOfOthers(ScannerReport.Component reportComponent, String componentKey) {
108 String name = trimToNull(reportComponent.getName());
109 return name == null ? componentKey : name;
113 static ReportAttributes createReportAttributes(ScannerReport.Component component) {
114 return ReportAttributes.newBuilder(component.getRef())
115 .setPath(trimToNull(component.getPath()))
116 .setVersion(trimToNull(component.getVersion()))
122 static FileAttributes createFileAttributes(ScannerReport.Component component) {
123 if (component.getType() != ScannerReport.Component.ComponentType.FILE) {
127 return new FileAttributes(
128 component.getIsTest(),
129 trimToNull(component.getLanguage()));
133 static Component.Type convertType(ScannerReport.Component.ComponentType type) {
136 return Component.Type.PROJECT;
138 return Component.Type.MODULE;
140 return Component.Type.DIRECTORY;
142 return Component.Type.FILE;
144 throw new IllegalArgumentException("Unsupported ComponentType value " + type);