001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * SonarQube is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.api.measures;
021
022 import org.sonar.api.rule.RuleKey;
023 import org.sonar.api.rules.Rule;
024 import org.sonar.api.technicaldebt.batch.Characteristic;
025 import org.sonar.api.technicaldebt.batch.Requirement;
026
027 import java.util.ArrayList;
028 import java.util.Collection;
029 import java.util.List;
030
031 /**
032 * @since 1.10
033 */
034 public final class MeasuresFilters {
035
036 private MeasuresFilters() {
037 }
038
039 public static MeasuresFilter<Collection<Measure>> all() {
040 return new MeasuresFilter<Collection<Measure>>() {
041 @Override
042 public Collection<Measure> filter(Collection<Measure> measures) {
043 Collection<Measure> all = new ArrayList<Measure>();
044 for (Measure measure : measures) {
045 if (measure != null) {
046 all.add(measure);
047 }
048 }
049 return all;
050 }
051 };
052 }
053
054 public static MeasuresFilter<Measure> metric(final org.sonar.api.batch.measure.Metric<?> metric) {
055 return metric(metric.key());
056 }
057
058 public static MeasuresFilter<Measure> metric(final String metricKey) {
059 return new MetricFilter<Measure>(metricKey) {
060 @Override
061 public Measure filter(Collection<Measure> measures) {
062 if (measures == null) {
063 return null;
064 }
065 for (Measure measure : measures) {
066 if (measure.getClass().equals(Measure.class) &&
067 measure.getMetricKey().equals(metricKey) &&
068 measure.getCharacteristic() == null &&
069 measure.getPersonId() == null) {
070 return measure;
071 }
072 }
073 return null;
074 }
075 };
076 }
077
078 public static MeasuresFilter<Measure> characteristic(final Metric metric, final Characteristic characteristic) {
079 return new MetricFilter<Measure>(metric) {
080
081 @Override
082 public Measure filter(Collection<Measure> measures) {
083 if (measures == null) {
084 return null;
085 }
086 for (Measure measure : measures) {
087 if (measure.getClass().equals(Measure.class) &&
088 measure.getMetric().equals(metric) &&
089 measure.getPersonId() == null &&
090 isSameCharacteristic(measure, characteristic)) {
091 return measure;
092 }
093 }
094 return null;
095 }
096 };
097 }
098
099 private static boolean isSameCharacteristic(Measure measure, final Characteristic characteristic) {
100 Characteristic measureCharacteristic = measure.getCharacteristic();
101 return measureCharacteristic != null &&
102 measureCharacteristic.equals(characteristic);
103 }
104
105 /**
106 * @deprecated since 4.3
107 */
108 @Deprecated
109 public static MeasuresFilter<Measure> requirement(final Metric metric, final Requirement requirement) {
110 return new MetricFilter<Measure>(metric) {
111
112 @Override
113 public Measure filter(Collection<Measure> measures) {
114 if (measures == null) {
115 return null;
116 }
117 for (Measure measure : measures) {
118 if (measure.getClass().equals(Measure.class) &&
119 measure.getMetric().equals(metric) &&
120 measure.getPersonId() == null &&
121 isSameRequirement(measure, requirement)) {
122 return measure;
123 }
124 }
125 return null;
126 }
127 };
128 }
129
130 private static boolean isSameRequirement(Measure measure, final Requirement requirement) {
131 Requirement measureRequirement = measure.getRequirement();
132 return measureRequirement != null &&
133 measureRequirement.equals(requirement);
134 }
135
136 /**
137 * @since 2.0
138 */
139 public static MeasuresFilter<Measure> measure(final Measure measure) {
140 return new MeasuresFilter<Measure>() {
141 @Override
142 public Measure filter(Collection<Measure> measures) {
143 if (measures == null) {
144 return null;
145 }
146 for (Measure m : measures) {
147 if (m.equals(measure)) {
148 return m;
149 }
150 }
151 return null;
152 }
153 };
154 }
155
156 public static MeasuresFilter<RuleMeasure> rule(final Metric metric, final RuleKey ruleKey) {
157 return new RuleFilter(metric, ruleKey);
158 }
159
160 public static MeasuresFilter<RuleMeasure> rule(final Metric metric, final Rule rule) {
161 return rule(metric, rule.ruleKey());
162 }
163
164 public static MeasuresFilter<Collection<RuleMeasure>> rules(final Metric metric) {
165 return new MetricFilter<Collection<RuleMeasure>>(metric) {
166
167 private boolean apply(Measure measure) {
168 return measure instanceof RuleMeasure && metric.equals(measure.getMetric())
169 && measure.getPersonId() == null && ((RuleMeasure) measure).ruleKey() != null;
170 }
171
172 @Override
173 public Collection<RuleMeasure> filter(Collection<Measure> measures) {
174 if (measures == null) {
175 return null;
176 }
177 List<RuleMeasure> result = new ArrayList<RuleMeasure>();
178 for (Measure measure : measures) {
179 if (apply(measure)) {
180 result.add((RuleMeasure) measure);
181 }
182 }
183 return result;
184 }
185 };
186 }
187
188 /**
189 * Used for internal optimizations.
190 */
191 public abstract static class MetricFilter<M> implements MeasuresFilter<M> {
192 private final String metricKey;
193
194 protected MetricFilter(Metric metric) {
195 this.metricKey = metric.getKey();
196 }
197
198 protected MetricFilter(String metricKey) {
199 this.metricKey = metricKey;
200 }
201
202 public String filterOnMetricKey() {
203 return metricKey;
204 }
205 }
206
207 private abstract static class AbstractRuleMeasureFilter<M> extends MetricFilter<M> {
208 protected AbstractRuleMeasureFilter(Metric metric) {
209 super(metric);
210 }
211
212 private boolean apply(Measure measure) {
213 return measure instanceof RuleMeasure
214 && filterOnMetricKey().equals(measure.getMetricKey())
215 && measure.getPersonId() == null
216 && doApply((RuleMeasure) measure);
217 }
218
219 abstract boolean doApply(RuleMeasure ruleMeasure);
220
221 @Override
222 public M filter(Collection<Measure> measures) {
223 if (measures == null) {
224 return null;
225 }
226 for (Measure measure : measures) {
227 if (apply(measure)) {
228 return (M) measure;
229 }
230 }
231 return null;
232 }
233 }
234
235 private static class RuleFilter extends AbstractRuleMeasureFilter<RuleMeasure> {
236 private RuleKey ruleKey;
237
238 protected RuleFilter(Metric metric, RuleKey ruleKey) {
239 super(metric);
240 this.ruleKey = ruleKey;
241 }
242
243 @Override
244 boolean doApply(RuleMeasure measure) {
245 return measure.ruleKey() != null
246 && ruleKey.equals(measure.ruleKey());
247 }
248 }
249 }