]> source.dussan.org Git - sonarqube.git/blob
453f987127d49f3d1453b30d3ad20f43d0e36844
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 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.duplication;
21
22 import com.google.common.base.Function;
23 import com.google.common.collect.ArrayListMultimap;
24 import com.google.common.collect.Multimap;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import javax.annotation.CheckForNull;
28 import javax.annotation.Nonnull;
29 import org.junit.rules.ExternalResource;
30 import org.sonar.ce.task.projectanalysis.component.Component;
31 import org.sonar.ce.task.projectanalysis.component.ComponentProvider;
32 import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
33 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderComponentProvider;
34 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
35
36 import static com.google.common.base.Preconditions.checkArgument;
37 import static com.google.common.collect.FluentIterable.from;
38 import static java.util.Objects.requireNonNull;
39
40 public class DuplicationRepositoryRule extends ExternalResource implements DuplicationRepository {
41   @CheckForNull
42   private final ComponentProvider componentProvider;
43   private DuplicationRepositoryImpl delegate;
44   private final Multimap<Component, TextBlock> componentRefsWithInnerDuplications = ArrayListMultimap.create();
45   private final Multimap<Component, TextBlock> componentRefsWithInProjectDuplications = ArrayListMultimap.create();
46   private final Multimap<Component, TextBlock> componentRefsWithCrossProjectDuplications = ArrayListMultimap.create();
47
48   private DuplicationRepositoryRule(TreeRootHolder treeRootHolder) {
49     this.componentProvider = new TreeRootHolderComponentProvider(treeRootHolder);
50   }
51
52   public DuplicationRepositoryRule() {
53     this.componentProvider = null;
54   }
55
56   public static DuplicationRepositoryRule create(TreeRootHolderRule treeRootHolder) {
57     return new DuplicationRepositoryRule(treeRootHolder);
58   }
59
60   public static DuplicationRepositoryRule create() {
61     return new DuplicationRepositoryRule();
62   }
63
64   @Override
65   protected void before() {
66     this.delegate = new DuplicationRepositoryImpl();
67   }
68
69   @Override
70   protected void after() {
71     if (this.componentProvider != null) {
72       this.componentProvider.reset();
73     }
74     this.componentRefsWithInnerDuplications.clear();
75     this.componentRefsWithInProjectDuplications.clear();
76     this.componentRefsWithCrossProjectDuplications.clear();
77     this.delegate = null;
78   }
79
80   public Iterable<Duplication> getDuplications(int fileRef) {
81     ensureComponentProviderInitialized();
82
83     return delegate.getDuplications(componentProvider.getByRef(fileRef));
84   }
85
86   public void add(int fileRef, Duplication duplication) {
87     ensureComponentProviderInitialized();
88
89     delegate.add(componentProvider.getByRef(fileRef), duplication);
90   }
91
92   public DuplicationRepositoryRule addDuplication(int fileRef, TextBlock original, TextBlock... duplicates) {
93     ensureComponentProviderInitialized();
94     Component component = componentProvider.getByRef(fileRef);
95     checkArgument(!componentRefsWithInnerDuplications.containsEntry(component, original), "Inner duplications for file %s and original %s already set", fileRef, original);
96     checkArgument(!componentRefsWithInProjectDuplications.containsEntry(component, original),
97       "InProject duplications for file %s and original %s already set. Use add(int, Duplication) instead", fileRef, original);
98
99     componentRefsWithInnerDuplications.put(component, original);
100     delegate.add(
101       component,
102       new Duplication(
103         original,
104         from(Arrays.asList(duplicates)).transform(TextBlockToInnerDuplicate.INSTANCE)));
105
106     return this;
107   }
108
109   public DuplicationRepositoryRule addDuplication(int fileRef, TextBlock original, int otherFileRef, TextBlock duplicate) {
110     ensureComponentProviderInitialized();
111     Component component = componentProvider.getByRef(fileRef);
112     checkArgument(!componentRefsWithInProjectDuplications.containsEntry(component, original), "InProject duplications for file %s and original %s already set", fileRef, original);
113     checkArgument(!componentRefsWithInnerDuplications.containsEntry(component, original),
114       "Inner duplications for file %s and original %s already set. Use add(int, Duplication) instead", fileRef, original);
115
116     componentRefsWithInProjectDuplications.put(component, original);
117     delegate.add(component,
118       new Duplication(
119         original,
120         Collections.singletonList(new InProjectDuplicate(componentProvider.getByRef(otherFileRef), duplicate))));
121
122     return this;
123   }
124
125   public DuplicationRepositoryRule addExtendedProjectDuplication(int fileRef, TextBlock original, int otherFileRef, TextBlock duplicate) {
126     ensureComponentProviderInitialized();
127     Component component = componentProvider.getByRef(fileRef);
128     checkArgument(!componentRefsWithCrossProjectDuplications.containsEntry(component, original), "CrossProject duplications for file %s and original %s already set", fileRef);
129
130     componentRefsWithCrossProjectDuplications.put(component, original);
131     delegate.add(componentProvider.getByRef(fileRef),
132       new Duplication(
133         original,
134         Collections.singletonList(new InExtendedProjectDuplicate(componentProvider.getByRef(otherFileRef), duplicate))));
135
136     return this;
137   }
138
139   public DuplicationRepositoryRule addCrossProjectDuplication(int fileRef, TextBlock original, String otherFileKey, TextBlock duplicate) {
140     ensureComponentProviderInitialized();
141     Component component = componentProvider.getByRef(fileRef);
142     checkArgument(!componentRefsWithCrossProjectDuplications.containsEntry(component, original), "CrossProject duplications for file %s and original %s already set", fileRef);
143
144     componentRefsWithCrossProjectDuplications.put(component, original);
145     delegate.add(componentProvider.getByRef(fileRef),
146       new Duplication(
147         original,
148         Collections.singletonList(new CrossProjectDuplicate(otherFileKey, duplicate))));
149
150     return this;
151   }
152
153   @Override
154   public Iterable<Duplication> getDuplications(Component file) {
155     return delegate.getDuplications(file);
156   }
157
158   @Override
159   public void add(Component file, Duplication duplication) {
160     TextBlock original = duplication.getOriginal();
161     checkArgument(!componentRefsWithInnerDuplications.containsEntry(file, original), "Inner duplications for file %s and original %s already set", file, original);
162     checkArgument(!componentRefsWithInProjectDuplications.containsEntry(file, original), "InProject duplications for file %s and original %s already set", file, original);
163     checkArgument(!componentRefsWithCrossProjectDuplications.containsEntry(file, original), "CrossProject duplications for file %s and original %s already set", file, original);
164
165     delegate.add(file, duplication);
166   }
167
168   private void ensureComponentProviderInitialized() {
169     requireNonNull(this.componentProvider, "Methods with component reference can not be used unless a TreeRootHolder has been provided when instantiating the rule");
170     this.componentProvider.ensureInitialized();
171   }
172
173   private enum TextBlockToInnerDuplicate implements Function<TextBlock, Duplicate> {
174     INSTANCE;
175
176     @Override
177     @Nonnull
178     public Duplicate apply(@Nonnull TextBlock input) {
179       return new InnerDuplicate(input);
180     }
181   }
182 }