]> source.dussan.org Git - sonarqube.git/blob
39426294ce552c5f5ed10e553eccbd4a4bc87049
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2024 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.ce.task.projectanalysis.component;
21
22 import com.google.common.collect.ImmutableMap;
23 import java.util.HashMap;
24 import java.util.Map;
25 import java.util.Optional;
26 import javax.annotation.CheckForNull;
27
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;
32
33 /**
34  * Holds the reference to the root of the {@link Component} tree for the current CE run.
35  */
36 public class TreeRootHolderImpl implements MutableTreeRootHolder {
37   @CheckForNull
38   private Map<Integer, Component> componentsByRef = null;
39   @CheckForNull
40   private Map<Integer, Component> extendedComponentsByRef = null;
41   @CheckForNull
42   private Map<String, Component> componentsByUuid = null;
43   private int size = 0;
44   private Component root = null;
45   private Component extendedTreeRoot = null;
46
47   @Override
48   public boolean isEmpty() {
49     return this.root == null;
50   }
51
52   @Override
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");
57     return this;
58   }
59
60   @Override
61   public Component getRoot() {
62     checkInitialized();
63     return this.root;
64   }
65
66   @Override
67   public Component getReportTreeRoot() {
68     checkInitialized();
69     return this.extendedTreeRoot;
70   }
71
72   @Override
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)));
76   }
77
78   @Override
79   public Component getComponentByUuid(String uuid) {
80     checkInitialized();
81     ensureComponentByRefAndUuidArePopulated();
82     return componentsByUuid.get(uuid);
83   }
84
85   @Override
86   public Optional<Component> getOptionalComponentByRef(int ref) {
87     checkInitialized();
88     ensureComponentByRefAndUuidArePopulated();
89     return Optional.ofNullable(componentsByRef.get(ref));
90   }
91
92   @Override
93   public Component getReportTreeComponentByRef(int ref) {
94     checkInitialized();
95     ensureExtendedComponentByRefIsPopulated();
96     Component c = extendedComponentsByRef.get(ref);
97     if (c == null) {
98       throw new IllegalArgumentException(String.format("Component with ref '%s' can't be found", ref));
99     }
100     return c;
101   }
102
103   @Override
104   public int getSize() {
105     checkInitialized();
106     ensureComponentByRefAndUuidArePopulated();
107     return size;
108   }
109
110   private void ensureExtendedComponentByRefIsPopulated() {
111     if (extendedComponentsByRef != null) {
112       return;
113     }
114
115     final ImmutableMap.Builder<Integer, Component> builder = ImmutableMap.builder();
116     new DepthTraversalTypeAwareCrawler(
117       new TypeAwareVisitorAdapter(CrawlerDepthLimit.FILE, POST_ORDER) {
118         @Override
119         public void visitAny(Component component) {
120           if (component.getReportAttributes().getRef() != null) {
121             builder.put(component.getReportAttributes().getRef(), component);
122           }
123         }
124       }).visit(this.extendedTreeRoot);
125     this.extendedComponentsByRef = builder.build();
126   }
127
128   private void ensureComponentByRefAndUuidArePopulated() {
129     if (componentsByRef != null && componentsByUuid != null) {
130       return;
131     }
132
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) {
137         @Override
138         public void visitAny(Component component) {
139           size++;
140           if (component.getReportAttributes().getRef() != null) {
141             builderByRef.put(component.getReportAttributes().getRef(), component);
142           }
143           if (isNotBlank(component.getUuid())) {
144             builderByUuid.put(component.getUuid(), component);
145           }
146         }
147       }).visit(this.root);
148     this.componentsByRef = builderByRef.build();
149     this.componentsByUuid = ImmutableMap.copyOf(builderByUuid);
150   }
151
152   private void checkInitialized() {
153     checkState(this.root != null, "Holder has not been initialized yet");
154   }
155 }