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