001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2009 SonarSource SA
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar 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     * Sonar 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
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.api.measures;
021    
022    import org.sonar.api.rules.Rule;
023    import org.sonar.api.rules.RulePriority;
024    
025    import java.util.ArrayList;
026    import java.util.Collection;
027    import java.util.List;
028    
029    /**
030     * @since 1.10
031     */
032    public final class MeasuresFilters {
033    
034      private MeasuresFilters() {
035      }
036    
037      public static MeasuresFilter<Collection<Measure>> all() {
038        return new MeasuresFilter<Collection<Measure>>() {
039          public Collection<Measure> filter(Collection<Measure> measures) {
040            return measures;
041          }
042        };
043      }
044    
045      public static MeasuresFilter<Measure> metric(final Metric metric) {
046        return new MetricFilter<Measure>(metric) {
047    
048          public Measure filter(Collection<Measure> measures) {
049            if (measures == null) {
050              return null;
051            }
052            for (Measure measure : measures) {
053              if (measure.getClass().equals(Measure.class) &&
054                  measure.getMetric().equals(metric)) {
055                return measure;
056              }
057            }
058            return null;
059          }
060        };
061      }
062    
063      /**
064       * @since 2.0
065       */
066      public static MeasuresFilter<Measure> measure(final Measure measure) {
067        return new MeasuresFilter<Measure>() {
068          public Measure filter(Collection<Measure> measures) {
069            if (measures==null) {
070              return null;
071            }
072            for (Measure m : measures) {
073              if (m.equals(measure)) {
074                return m;
075              }
076            }
077            return null;
078          }
079        };
080      }
081    
082      public static MeasuresFilter<RuleMeasure> rulePriority(final Metric metric, final RulePriority priority) {
083        return new RulePriorityFilter(metric, priority);
084      }
085    
086      public static MeasuresFilter<RuleMeasure> ruleCategory(final Metric metric, final Integer category) {
087        return new RuleCategoryFilter(metric, category);
088      }
089    
090      public static MeasuresFilter<RuleMeasure> rule(final Metric metric, final Rule rule) {
091        return new RuleFilter(metric, rule);
092      }
093    
094      public static MeasuresFilter<Collection<RuleMeasure>> ruleCategories(final Metric metric) {
095        return new MetricFilter<Collection<RuleMeasure>>(metric) {
096    
097          private boolean apply(Measure measure) {
098            return measure instanceof RuleMeasure
099                && metric.equals(measure.getMetric())
100                && ((RuleMeasure) measure).getRule() == null
101                && ((RuleMeasure) measure).getRuleCategory() != null;
102          }
103    
104          public Collection<RuleMeasure> filter(Collection<Measure> measures) {
105            List<RuleMeasure> result = new ArrayList<RuleMeasure>();
106            if (measures != null) {
107              for (Measure measure : measures) {
108                if (apply(measure)) {
109                  result.add((RuleMeasure) measure);
110                }
111              }
112            }
113            return result;
114          }
115        };
116      }
117    
118      public static MeasuresFilter<Collection<RuleMeasure>> rules(final Metric metric) {
119        return new MetricFilter<Collection<RuleMeasure>>(metric) {
120    
121          private boolean apply(Measure measure) {
122            return measure instanceof RuleMeasure
123                && metric.equals(measure.getMetric())
124                && ((RuleMeasure) measure).getRule() != null;
125          }
126    
127          public Collection<RuleMeasure> filter(Collection<Measure> measures) {
128            if (measures == null) {
129              return null;
130            }
131            List<RuleMeasure> result = new ArrayList<RuleMeasure>();
132            for (Measure measure : measures) {
133              if (apply(measure)) {
134                result.add((RuleMeasure) measure);
135              }
136            }
137            return result;
138          }
139        };
140      }
141    
142      /**
143       * Used for internal optimizations.
144       */
145      public static abstract class MetricFilter<M> implements MeasuresFilter<M> {
146        private final Metric metric;
147    
148        protected MetricFilter(Metric metric) {
149          this.metric = metric;
150        }
151    
152        public Metric filterOnMetric() {
153          return metric;
154        }
155      }
156    
157      private abstract static class AbstractRuleMeasureFilter<M> extends MetricFilter<M> {
158        protected AbstractRuleMeasureFilter(Metric metric) {
159          super(metric);
160        }
161    
162        private boolean apply(Measure measure) {
163          return measure instanceof RuleMeasure
164              && filterOnMetric().equals(measure.getMetric())
165              && doApply((RuleMeasure) measure);
166        }
167    
168        abstract boolean doApply(RuleMeasure ruleMeasure);
169    
170        public M filter(Collection<Measure> measures) {
171          if (measures == null) {
172            return null;
173          }
174          for (Measure measure : measures) {
175            if (apply(measure)) {
176              return (M) measure;
177            }
178          }
179          return null;
180        }
181      }
182    
183      private static class RulePriorityFilter extends AbstractRuleMeasureFilter<RuleMeasure> {
184        private RulePriority priority;
185    
186        protected RulePriorityFilter(Metric metric, RulePriority priority) {
187          super(metric);
188          this.priority = priority;
189        }
190    
191        @Override
192        boolean doApply(RuleMeasure measure) {
193          return measure.getRule() == null
194              && measure.getRuleCategory() == null
195              && priority.equals(measure.getRulePriority());
196        }
197      }
198    
199      private static class RuleCategoryFilter extends AbstractRuleMeasureFilter<RuleMeasure> {
200        private Integer categ;
201    
202        protected RuleCategoryFilter(Metric metric, Integer categ) {
203          super(metric);
204          this.categ = categ;
205        }
206    
207        @Override
208        boolean doApply(RuleMeasure measure) {
209          return measure.getRule() == null
210              && categ.equals(measure.getRuleCategory())
211              && measure.getRulePriority() == null;
212        }
213      }
214    
215    
216      private static class RuleFilter extends AbstractRuleMeasureFilter<RuleMeasure> {
217        private Rule rule;
218    
219        protected RuleFilter(Metric metric, Rule rule) {
220          super(metric);
221          this.rule = rule;
222        }
223    
224        @Override
225        boolean doApply(RuleMeasure measure) {
226          return measure.getRule() != null
227              && rule.equals(measure.getRule());
228        }
229      }
230    }