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     */
020    package org.sonar.api.batch.sensor.issue.internal;
021    
022    import com.google.common.base.Preconditions;
023    import com.google.common.base.Strings;
024    import org.sonar.api.batch.fs.InputDir;
025    import org.sonar.api.batch.fs.InputFile;
026    import org.sonar.api.batch.fs.InputPath;
027    import org.sonar.api.batch.sensor.SensorStorage;
028    import org.sonar.api.batch.sensor.internal.DefaultStorable;
029    import org.sonar.api.batch.sensor.issue.Issue;
030    import org.sonar.api.rule.RuleKey;
031    import org.sonar.api.utils.internal.Uuids;
032    
033    import javax.annotation.CheckForNull;
034    import javax.annotation.Nullable;
035    
036    public class DefaultIssue extends DefaultStorable implements Issue {
037    
038      private static final String INPUT_DIR_SHOULD_BE_NON_NULL = "InputDir should be non null";
039      private static final String INPUT_FILE_SHOULD_BE_NON_NULL = "InputFile should be non null";
040      private static final String ON_FILE_OR_ON_DIR_ALREADY_CALLED = "onFile or onDir already called";
041      private static final String ON_PROJECT_ALREADY_CALLED = "onProject already called";
042      private String key;
043      private boolean onProject = false;
044      private InputPath path;
045      private RuleKey ruleKey;
046      private String message;
047      private Integer line;
048      private Double effortToFix;
049      private Severity overridenSeverity;
050    
051      public DefaultIssue() {
052        super(null);
053        this.key = Uuids.create();
054      }
055    
056      public DefaultIssue(SensorStorage storage) {
057        super(storage);
058        this.key = Uuids.create();
059      }
060    
061      @Override
062      public DefaultIssue ruleKey(RuleKey ruleKey) {
063        this.ruleKey = ruleKey;
064        return this;
065      }
066    
067      @Override
068      public DefaultIssue onFile(InputFile file) {
069        Preconditions.checkState(!this.onProject, ON_PROJECT_ALREADY_CALLED);
070        Preconditions.checkState(this.path == null, ON_FILE_OR_ON_DIR_ALREADY_CALLED);
071        Preconditions.checkNotNull(file, INPUT_FILE_SHOULD_BE_NON_NULL);
072        this.path = file;
073        return this;
074      }
075    
076      @Override
077      public DefaultIssue onDir(InputDir dir) {
078        Preconditions.checkState(!this.onProject, ON_PROJECT_ALREADY_CALLED);
079        Preconditions.checkState(this.path == null, ON_FILE_OR_ON_DIR_ALREADY_CALLED);
080        Preconditions.checkNotNull(dir, INPUT_DIR_SHOULD_BE_NON_NULL);
081        this.path = dir;
082        return this;
083      }
084    
085      @Override
086      public DefaultIssue onProject() {
087        Preconditions.checkState(!this.onProject, ON_PROJECT_ALREADY_CALLED);
088        Preconditions.checkState(this.path == null, ON_FILE_OR_ON_DIR_ALREADY_CALLED);
089        this.onProject = true;
090        return this;
091      }
092    
093      @Override
094      public DefaultIssue atLine(int line) {
095        Preconditions.checkState(this.path != null && this.path instanceof InputFile, "atLine should be called after onFile");
096        this.line = line;
097        return this;
098      }
099    
100      @Override
101      public DefaultIssue effortToFix(@Nullable Double effortToFix) {
102        this.effortToFix = effortToFix;
103        return this;
104      }
105    
106      @Override
107      public DefaultIssue message(String message) {
108        this.message = message;
109        return this;
110      }
111    
112      @Override
113      public Issue overrideSeverity(@Nullable Severity severity) {
114        this.overridenSeverity = severity;
115        return this;
116      }
117    
118      @Override
119      public RuleKey ruleKey() {
120        return this.ruleKey;
121      }
122    
123      @CheckForNull
124      @Override
125      public InputPath inputPath() {
126        return this.path;
127      }
128    
129      @Override
130      public Integer line() {
131        return this.line;
132      }
133    
134      @Override
135      public String message() {
136        return this.message;
137      }
138    
139      @Override
140      public Severity overridenSeverity() {
141        return this.overridenSeverity;
142      }
143    
144      @Override
145      public Double effortToFix() {
146        return this.effortToFix;
147      }
148    
149      public String key() {
150        return this.key;
151      }
152    
153      @Override
154      public void doSave() {
155        Preconditions.checkNotNull(this.ruleKey, "ruleKey is mandatory on issue");
156        Preconditions.checkState(!Strings.isNullOrEmpty(key), "Fail to generate issue key");
157        storage.store(this);
158      }
159    
160      /**
161       * For testing only.
162       */
163      public DefaultIssue withKey(String key) {
164        this.key = key;
165        return this;
166      }
167    
168      @Override
169      public boolean equals(Object o) {
170        if (this == o) {
171          return true;
172        }
173        if (o == null || getClass() != o.getClass()) {
174          return false;
175        }
176        DefaultIssue that = (DefaultIssue) o;
177        return !key.equals(that.key);
178      }
179    
180      @Override
181      public int hashCode() {
182        return key.hashCode();
183      }
184    
185    }