3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info 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.ce.task.projectanalysis.component;
22 import com.google.common.collect.ImmutableMap;
23 import java.util.HashMap;
25 import java.util.Optional;
26 import javax.annotation.CheckForNull;
28 import static com.google.common.base.Preconditions.checkState;
29 import static java.util.Objects.requireNonNull;
30 import static org.apache.commons.lang.StringUtils.isNotBlank;
31 import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER;
34 * Holds the reference to the root of the {@link Component} tree for the current CE run.
36 public class TreeRootHolderImpl implements MutableTreeRootHolder {
38 private Map<Integer, Component> componentsByRef = null;
40 private Map<Integer, Component> extendedComponentsByRef = null;
42 private Map<String, Component> componentsByUuid = null;
44 private Component root = null;
45 private Component extendedTreeRoot = null;
48 public boolean isEmpty() {
49 return this.root == null;
53 public MutableTreeRootHolder setRoots(Component root, Component reportRoot) {
54 checkState(this.root == null, "root can not be set twice in holder");
55 this.root = requireNonNull(root, "root can not be null");
56 this.extendedTreeRoot = requireNonNull(reportRoot, "extended tree root can not be null");
61 public Component getRoot() {
67 public Component getReportTreeRoot() {
69 return this.extendedTreeRoot;
73 public Component getComponentByRef(int ref) {
74 return getOptionalComponentByRef(ref)
75 .orElseThrow(() -> new IllegalArgumentException(String.format("Component with ref '%s' can't be found", ref)));
79 public Component getComponentByUuid(String uuid) {
81 ensureComponentByRefAndUuidArePopulated();
82 return componentsByUuid.get(uuid);
86 public Optional<Component> getOptionalComponentByRef(int ref) {
88 ensureComponentByRefAndUuidArePopulated();
89 return Optional.ofNullable(componentsByRef.get(ref));
93 public Component getReportTreeComponentByRef(int ref) {
95 ensureExtendedComponentByRefIsPopulated();
96 Component c = extendedComponentsByRef.get(ref);
98 throw new IllegalArgumentException(String.format("Component with ref '%s' can't be found", ref));
104 public int getSize() {
106 ensureComponentByRefAndUuidArePopulated();
110 private void ensureExtendedComponentByRefIsPopulated() {
111 if (extendedComponentsByRef != null) {
115 final ImmutableMap.Builder<Integer, Component> builder = ImmutableMap.builder();
116 new DepthTraversalTypeAwareCrawler(
117 new TypeAwareVisitorAdapter(CrawlerDepthLimit.FILE, POST_ORDER) {
119 public void visitAny(Component component) {
120 if (component.getReportAttributes().getRef() != null) {
121 builder.put(component.getReportAttributes().getRef(), component);
124 }).visit(this.extendedTreeRoot);
125 this.extendedComponentsByRef = builder.build();
128 private void ensureComponentByRefAndUuidArePopulated() {
129 if (componentsByRef != null && componentsByUuid != null) {
133 final ImmutableMap.Builder<Integer, Component> builderByRef = ImmutableMap.builder();
134 final Map<String, Component> builderByUuid = new HashMap<>();
135 new DepthTraversalTypeAwareCrawler(
136 new TypeAwareVisitorAdapter(CrawlerDepthLimit.FILE, POST_ORDER) {
138 public void visitAny(Component component) {
140 if (component.getReportAttributes().getRef() != null) {
141 builderByRef.put(component.getReportAttributes().getRef(), component);
143 if (isNotBlank(component.getUuid())) {
144 builderByUuid.put(component.getUuid(), component);
148 this.componentsByRef = builderByRef.build();
149 this.componentsByUuid = ImmutableMap.copyOf(builderByUuid);
152 private void checkInitialized() {
153 checkState(this.root != null, "Holder has not been initialized yet");