001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2013 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.rules.Rule;
023    import org.sonar.api.technicaldebt.batch.Characteristic;
024    import org.sonar.api.technicaldebt.batch.Requirement;
025    
026    import java.util.ArrayList;
027    import java.util.Collection;
028    import java.util.Collections;
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          public Collection<Measure> filter(Collection<Measure> measures) {
042            return measures;
043          }
044        };
045      }
046    
047      public static MeasuresFilter<Measure> metric(final Metric metric) {
048        return metric(metric.getKey());
049      }
050    
051      public static MeasuresFilter<Measure> metric(final String metricKey) {
052        return new MetricFilter<Measure>(metricKey) {
053    
054          public Measure filter(Collection<Measure> measures) {
055            if (measures == null) {
056              return null;
057            }
058            for (Measure measure : measures) {
059              if (measure.getClass().equals(Measure.class) &&
060                measure.getMetricKey().equals(metricKey) &&
061                measure.getCharacteristic() == null &&
062                measure.getPersonId() == null) {
063                return measure;
064              }
065            }
066            return null;
067          }
068        };
069      }
070    
071      public static MeasuresFilter<Measure> characteristic(final Metric metric, final Characteristic characteristic) {
072        return new MetricFilter<Measure>(metric) {
073    
074          public Measure filter(Collection<Measure> measures) {
075            if (measures == null) {
076              return null;
077            }
078            for (Measure measure : measures) {
079              if (measure.getClass().equals(Measure.class) &&
080                measure.getMetric().equals(metric) &&
081                measure.getPersonId() == null &&
082                isSameCharacteristic(measure, characteristic)) {
083                return measure;
084              }
085            }
086            return null;
087          }
088        };
089      }
090    
091      private static boolean isSameCharacteristic(Measure measure, final Characteristic characteristic){
092        Characteristic measureCharacteristic = measure.getCharacteristic();
093        return measureCharacteristic != null &&
094          measureCharacteristic.equals(characteristic);
095      }
096    
097      public static MeasuresFilter<Measure> requirement(final Metric metric, final Requirement requirement) {
098        return new MetricFilter<Measure>(metric) {
099    
100          public Measure filter(Collection<Measure> measures) {
101            if (measures == null) {
102              return null;
103            }
104            for (Measure measure : measures) {
105              if (measure.getClass().equals(Measure.class) &&
106                measure.getMetric().equals(metric) &&
107                measure.getPersonId() == null &&
108                isSameRequirement(measure, requirement)) {
109                return measure;
110              }
111            }
112            return null;
113          }
114        };
115      }
116    
117      private static boolean isSameRequirement(Measure measure, final Requirement requirement){
118        Requirement measureRequirement = measure.getRequirement();
119        return measureRequirement != null &&
120          measureRequirement.equals(requirement);
121      }
122    
123      /**
124       * @since 2.0
125       */
126      public static MeasuresFilter<Measure> measure(final Measure measure) {
127        return new MeasuresFilter<Measure>() {
128          public Measure filter(Collection<Measure> measures) {
129            if (measures == null) {
130              return null;
131            }
132            for (Measure m : measures) {
133              if (m.equals(measure)) {
134                return m;
135              }
136            }
137            return null;
138          }
139        };
140      }
141    
142      /**
143       * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2007
144       */
145      @Deprecated
146      public static MeasuresFilter<RuleMeasure> ruleCategory(final Metric metric, final Integer category) {
147        return new RuleCategoryFilter(metric, category);
148      }
149    
150      public static MeasuresFilter<RuleMeasure> rule(final Metric metric, final Rule rule) {
151        return new RuleFilter(metric, rule);
152      }
153    
154      /**
155       * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2007
156       */
157      @Deprecated
158      public static MeasuresFilter<Collection<RuleMeasure>> ruleCategories(final Metric metric) {
159        return new MetricFilter<Collection<RuleMeasure>>(metric) {
160    
161          public Collection<RuleMeasure> filter(Collection<Measure> measures) {
162            return Collections.emptyList();
163          }
164        };
165      }
166    
167      public static MeasuresFilter<Collection<RuleMeasure>> rules(final Metric metric) {
168        return new MetricFilter<Collection<RuleMeasure>>(metric) {
169    
170          private boolean apply(Measure measure) {
171            return measure instanceof RuleMeasure && metric.equals(measure.getMetric())
172              && measure.getPersonId() == null && ((RuleMeasure) measure).getRule() != null;
173          }
174    
175          public Collection<RuleMeasure> filter(Collection<Measure> measures) {
176            if (measures == null) {
177              return null;
178            }
179            List<RuleMeasure> result = new ArrayList<RuleMeasure>();
180            for (Measure measure : measures) {
181              if (apply(measure)) {
182                result.add((RuleMeasure) measure);
183              }
184            }
185            return result;
186          }
187        };
188      }
189    
190      /**
191       * Used for internal optimizations.
192       */
193      public abstract static class MetricFilter<M> implements MeasuresFilter<M> {
194        private final String metricKey;
195    
196        protected MetricFilter(Metric metric) {
197          this.metricKey = metric.getKey();
198        }
199    
200        protected MetricFilter(String metricKey) {
201          this.metricKey = metricKey;
202        }
203    
204        public String filterOnMetricKey() {
205          return metricKey;
206        }
207      }
208    
209      private abstract static class AbstractRuleMeasureFilter<M> extends MetricFilter<M> {
210        protected AbstractRuleMeasureFilter(Metric metric) {
211          super(metric);
212        }
213    
214        private boolean apply(Measure measure) {
215          return measure instanceof RuleMeasure
216            && filterOnMetricKey().equals(measure.getMetricKey())
217            && measure.getPersonId() == null
218            && doApply((RuleMeasure) measure);
219        }
220    
221        abstract boolean doApply(RuleMeasure ruleMeasure);
222    
223        public M filter(Collection<Measure> measures) {
224          if (measures == null) {
225            return null;
226          }
227          for (Measure measure : measures) {
228            if (apply(measure)) {
229              return (M) measure;
230            }
231          }
232          return null;
233        }
234      }
235    
236      /**
237       * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2007
238       */
239      @Deprecated
240      private static class RuleCategoryFilter extends AbstractRuleMeasureFilter<RuleMeasure> {
241    
242        protected RuleCategoryFilter(Metric metric, Integer categ) {
243          super(metric);
244        }
245    
246        @Override
247        boolean doApply(RuleMeasure measure) {
248          return false;
249        }
250      }
251    
252    
253      private static class RuleFilter extends AbstractRuleMeasureFilter<RuleMeasure> {
254        private Rule rule;
255    
256        protected RuleFilter(Metric metric, Rule rule) {
257          super(metric);
258          this.rule = rule;
259        }
260    
261        @Override
262        boolean doApply(RuleMeasure measure) {
263          return measure.getRule() != null
264            && rule.equals(measure.getRule());
265        }
266      }
267    }