001/*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 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.batch.sensor.issue.internal;
021
022import com.google.common.base.Function;
023import com.google.common.base.Preconditions;
024import com.google.common.collect.ImmutableList;
025import com.google.common.collect.Lists;
026import java.util.ArrayList;
027import java.util.Arrays;
028import java.util.List;
029import javax.annotation.Nullable;
030import org.sonar.api.batch.rule.Severity;
031import org.sonar.api.batch.sensor.internal.DefaultStorable;
032import org.sonar.api.batch.sensor.internal.SensorStorage;
033import org.sonar.api.batch.sensor.issue.Issue;
034import org.sonar.api.batch.sensor.issue.IssueLocation;
035import org.sonar.api.batch.sensor.issue.NewIssue;
036import org.sonar.api.batch.sensor.issue.NewIssueLocation;
037import org.sonar.api.rule.RuleKey;
038
039import static java.lang.String.format;
040
041public class DefaultIssue extends DefaultStorable implements Issue, NewIssue {
042
043  private static final class ToFlow implements Function<List<IssueLocation>, Flow> {
044    @Override
045    public Flow apply(final List<IssueLocation> input) {
046      return new Flow() {
047        @Override
048        public List<IssueLocation> locations() {
049          return ImmutableList.copyOf(input);
050        }
051      };
052    }
053  }
054
055  private RuleKey ruleKey;
056  private Double effortToFix;
057  private Severity overriddenSeverity;
058  private IssueLocation primaryLocation;
059  private List<List<IssueLocation>> flows = new ArrayList<>();
060
061  public DefaultIssue() {
062    super(null);
063  }
064
065  public DefaultIssue(SensorStorage storage) {
066    super(storage);
067  }
068
069  @Override
070  public DefaultIssue forRule(RuleKey ruleKey) {
071    this.ruleKey = ruleKey;
072    return this;
073  }
074
075  @Override
076  public DefaultIssue effortToFix(@Nullable Double effortToFix) {
077    Preconditions.checkArgument(effortToFix == null || effortToFix >= 0, format("Effort to fix must be greater than or equal 0 (got %s)", effortToFix));
078    this.effortToFix = effortToFix;
079    return this;
080  }
081
082  @Override
083  public DefaultIssue overrideSeverity(@Nullable Severity severity) {
084    this.overriddenSeverity = severity;
085    return this;
086  }
087
088  @Override
089  public NewIssueLocation newLocation() {
090    return new DefaultIssueLocation();
091  }
092
093  @Override
094  public DefaultIssue at(NewIssueLocation primaryLocation) {
095    Preconditions.checkArgument(primaryLocation != null, "Cannot use a location that is null");
096    Preconditions.checkState(this.primaryLocation == null, "at() already called");
097    this.primaryLocation = (DefaultIssueLocation) primaryLocation;
098    return this;
099  }
100
101  @Override
102  public NewIssue addLocation(NewIssueLocation secondaryLocation) {
103    flows.add(Arrays.asList((IssueLocation) secondaryLocation));
104    return this;
105  }
106
107  @Override
108  public DefaultIssue addFlow(Iterable<NewIssueLocation> locations) {
109    List<IssueLocation> flowAsList = new ArrayList<>();
110    for (NewIssueLocation issueLocation : locations) {
111      flowAsList.add((DefaultIssueLocation) issueLocation);
112    }
113    flows.add(flowAsList);
114    return this;
115  }
116
117  @Override
118  public RuleKey ruleKey() {
119    return this.ruleKey;
120  }
121
122  @Override
123  public Severity overriddenSeverity() {
124    return this.overriddenSeverity;
125  }
126
127  @Override
128  public Double effortToFix() {
129    return this.effortToFix;
130  }
131
132  @Override
133  public IssueLocation primaryLocation() {
134    return primaryLocation;
135  }
136
137  @Override
138  public List<Flow> flows() {
139    return Lists.transform(this.flows, new ToFlow());
140  }
141
142  @Override
143  public void doSave() {
144    Preconditions.checkNotNull(this.ruleKey, "ruleKey is mandatory on issue");
145    Preconditions.checkState(primaryLocation != null, "Primary location is mandatory on every issue");
146    storage.store(this);
147  }
148
149}