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 }