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.ce.measure.test;
021
022import com.google.common.base.Function;
023import com.google.common.base.Predicate;
024import com.google.common.collect.FluentIterable;
025import com.google.common.collect.ImmutableSet;
026import java.util.Arrays;
027import java.util.List;
028import java.util.Set;
029import javax.annotation.Nonnull;
030import javax.annotation.Nullable;
031import org.sonar.api.ce.measure.MeasureComputer;
032import org.sonar.api.measures.CoreMetrics;
033import org.sonar.api.measures.Metric;
034
035import static com.google.common.base.Preconditions.checkArgument;
036import static java.util.Objects.requireNonNull;
037
038public class TestMeasureComputerDefinition implements MeasureComputer.MeasureComputerDefinition {
039
040  private final Set<String> inputMetricKeys;
041  private final Set<String> outputMetrics;
042
043  private TestMeasureComputerDefinition(MeasureComputerDefinitionBuilderImpl builder) {
044    this.inputMetricKeys = ImmutableSet.copyOf(builder.inputMetricKeys);
045    this.outputMetrics = ImmutableSet.copyOf(builder.outputMetrics);
046  }
047
048  @Override
049  public Set<String> getInputMetrics() {
050    return inputMetricKeys;
051  }
052
053  @Override
054  public Set<String> getOutputMetrics() {
055    return outputMetrics;
056  }
057
058  public static class MeasureComputerDefinitionBuilderImpl implements Builder {
059
060    private String[] inputMetricKeys = new String[] {};
061    private String[] outputMetrics;
062
063    @Override
064    public Builder setInputMetrics(String... inputMetrics) {
065      this.inputMetricKeys = validateInputMetricKeys(inputMetrics);
066      return this;
067    }
068
069    @Override
070    public Builder setOutputMetrics(String... outputMetrics) {
071      this.outputMetrics = validateOutputMetricKeys(outputMetrics);
072      return this;
073    }
074
075    @Override
076    public MeasureComputer.MeasureComputerDefinition build() {
077      validateInputMetricKeys(this.inputMetricKeys);
078      validateOutputMetricKeys(this.outputMetrics);
079      return new TestMeasureComputerDefinition(this);
080    }
081
082    private static String[] validateInputMetricKeys(@Nullable String[] inputMetrics) {
083      requireNonNull(inputMetrics, "Input metrics cannot be null");
084      checkNotNull(inputMetrics);
085      return inputMetrics;
086    }
087
088    private static String[] validateOutputMetricKeys(@Nullable String[] outputMetrics) {
089      requireNonNull(outputMetrics, "Output metrics cannot be null");
090      checkArgument(outputMetrics.length > 0, "At least one output metric must be defined");
091      FluentIterable.from(CoreMetrics.getMetrics()).transform(MetricToKey.INSTANCE).filter(new MatchMetricKey(outputMetrics)).size();
092      checkNotNull(outputMetrics);
093      return outputMetrics;
094    }
095
096    private static void checkNotNull(String[] metrics) {
097      for (String metric : metrics) {
098        requireNonNull(metric, "Null metric is not allowed");
099      }
100    }
101  }
102
103  private enum MetricToKey implements Function<Metric, String> {
104    INSTANCE;
105
106    @Override
107    public String apply(@Nonnull Metric input) {
108      return input.getKey();
109    }
110  }
111
112  private static class MatchMetricKey implements Predicate<String> {
113
114    private final List<String> metrics;
115
116    public MatchMetricKey(String[] metrics) {
117      this.metrics = Arrays.asList(metrics);
118    }
119
120    @Override
121    public boolean apply(@Nonnull String metric) {
122      checkArgument(!metrics.contains(metric), "Core metrics are not allowed");
123      return true;
124    }
125  }
126}