001/*
002 * SonarQube
003 * Copyright (C) 2009-2016 SonarSource SA
004 * mailto:contact AT sonarsource DOT com
005 *
006 * This program 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 * This program 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 java.util.ArrayList;
023import java.util.Collection;
024import java.util.List;
025import org.sonar.api.rule.RuleKey;
026import org.sonar.api.rules.Rule;
027
028/**
029 * @since 1.10
030 */
031public final class MeasuresFilters {
032
033  private MeasuresFilters() {
034  }
035
036  public static MeasuresFilter<Collection<Measure>> all() {
037    return new MeasuresFilter<Collection<Measure>>() {
038      @Override
039      public Collection<Measure> filter(Collection<Measure> measures) {
040        Collection<Measure> all = new ArrayList<>();
041        for (Measure measure : measures) {
042          if (measure != null) {
043            all.add(measure);
044          }
045        }
046        return all;
047      }
048    };
049  }
050
051  public static MeasuresFilter<Measure> metric(final org.sonar.api.batch.measure.Metric<?> metric) {
052    return metric(metric.key());
053  }
054
055  public static MeasuresFilter<Measure> metric(final String metricKey) {
056    return new MetricFilter<Measure>(metricKey) {
057      @Override
058      public Measure filter(Collection<Measure> measures) {
059        if (measures == null) {
060          return null;
061        }
062        for (Measure measure : measures) {
063          if (measure.getClass().equals(Measure.class) &&
064            measure.getMetricKey().equals(metricKey) &&
065            measure.getPersonId() == null) {
066            return measure;
067          }
068        }
069        return null;
070      }
071    };
072  }
073
074  /**
075   * @since 2.0
076   */
077  public static MeasuresFilter<Measure> measure(final Measure measure) {
078    return new MeasuresFilter<Measure>() {
079      @Override
080      public Measure filter(Collection<Measure> measures) {
081        if (measures == null) {
082          return null;
083        }
084        for (Measure m : measures) {
085          if (m.equals(measure)) {
086            return m;
087          }
088        }
089        return null;
090      }
091    };
092  }
093
094  public static MeasuresFilter<RuleMeasure> rule(final Metric metric, final RuleKey ruleKey) {
095    return new RuleFilter(metric, ruleKey);
096  }
097
098  public static MeasuresFilter<RuleMeasure> rule(final Metric metric, final Rule rule) {
099    return rule(metric, rule.ruleKey());
100  }
101
102  public static MeasuresFilter<Collection<RuleMeasure>> rules(final Metric metric) {
103    return new MetricFilter<Collection<RuleMeasure>>(metric) {
104
105      private boolean apply(Measure measure) {
106        return measure instanceof RuleMeasure && metric.equals(measure.getMetric())
107          && measure.getPersonId() == null && ((RuleMeasure) measure).ruleKey() != null;
108      }
109
110      @Override
111      public Collection<RuleMeasure> filter(Collection<Measure> measures) {
112        if (measures == null) {
113          return null;
114        }
115        List<RuleMeasure> result = new ArrayList<>();
116        for (Measure measure : measures) {
117          if (apply(measure)) {
118            result.add((RuleMeasure) measure);
119          }
120        }
121        return result;
122      }
123    };
124  }
125
126  /**
127   * Used for internal optimizations.
128   */
129  public abstract static class MetricFilter<M> implements MeasuresFilter<M> {
130    private final String metricKey;
131
132    protected MetricFilter(Metric metric) {
133      this.metricKey = metric.getKey();
134    }
135
136    protected MetricFilter(String metricKey) {
137      this.metricKey = metricKey;
138    }
139
140    public String filterOnMetricKey() {
141      return metricKey;
142    }
143  }
144
145  /**
146   * @deprecated since 5.2. The measures related to rules are computed on server side by Compute Engine.
147   */
148  @Deprecated
149  private abstract static class AbstractRuleMeasureFilter<M> extends MetricFilter<M> {
150    protected AbstractRuleMeasureFilter(Metric metric) {
151      super(metric);
152    }
153
154    private boolean apply(Measure measure) {
155      return measure instanceof RuleMeasure
156        && filterOnMetricKey().equals(measure.getMetricKey())
157        && measure.getPersonId() == null
158        && doApply((RuleMeasure) measure);
159    }
160
161    abstract boolean doApply(RuleMeasure ruleMeasure);
162
163    @Override
164    public M filter(Collection<Measure> measures) {
165      if (measures == null) {
166        return null;
167      }
168      for (Measure measure : measures) {
169        if (apply(measure)) {
170          return (M) measure;
171        }
172      }
173      return null;
174    }
175  }
176
177  /**
178   * @deprecated since 5.2. Useless by design because of Compute Engine
179   */
180  @Deprecated
181  private static class RuleFilter extends AbstractRuleMeasureFilter<RuleMeasure> {
182    private RuleKey ruleKey;
183
184    protected RuleFilter(Metric metric, RuleKey ruleKey) {
185      super(metric);
186      this.ruleKey = ruleKey;
187    }
188
189    @Override
190    boolean doApply(RuleMeasure measure) {
191      return measure.ruleKey() != null
192        && ruleKey.equals(measure.ruleKey());
193    }
194  }
195}