You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Rule.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.api.rules;
  21. import java.util.ArrayList;
  22. import java.util.Date;
  23. import java.util.LinkedHashSet;
  24. import java.util.List;
  25. import java.util.Set;
  26. import javax.annotation.CheckForNull;
  27. import javax.annotation.Nullable;
  28. import org.apache.commons.lang.StringUtils;
  29. import org.apache.commons.lang.builder.EqualsBuilder;
  30. import org.apache.commons.lang.builder.HashCodeBuilder;
  31. import org.apache.commons.lang.builder.ToStringBuilder;
  32. import org.apache.commons.lang.builder.ToStringStyle;
  33. import org.sonar.api.rule.RuleKey;
  34. import org.sonar.check.Cardinality;
  35. import static java.util.Arrays.asList;
  36. import static java.util.Collections.unmodifiableSet;
  37. public class Rule {
  38. /**
  39. * @since 3.6
  40. */
  41. public static final String STATUS_BETA = "BETA";
  42. /**
  43. * @since 3.6
  44. */
  45. public static final String STATUS_DEPRECATED = "DEPRECATED";
  46. /**
  47. * @since 3.6
  48. */
  49. public static final String STATUS_READY = "READY";
  50. /**
  51. * For internal use only.
  52. *
  53. * @since 3.6
  54. */
  55. public static final String STATUS_REMOVED = "REMOVED";
  56. /**
  57. * List of available status
  58. *
  59. * @since 3.6
  60. */
  61. private static final Set<String> STATUS_LIST = unmodifiableSet(new LinkedHashSet<>(asList(STATUS_READY, STATUS_BETA, STATUS_DEPRECATED, STATUS_REMOVED)));
  62. /**
  63. * The default priority given to a rule if not explicitly set
  64. */
  65. public static final RulePriority DEFAULT_PRIORITY = RulePriority.MAJOR;
  66. private String name;
  67. private String key;
  68. private String configKey;
  69. private RulePriority priority = DEFAULT_PRIORITY;
  70. private String description;
  71. private String pluginName;
  72. private boolean isTemplate = false;
  73. private String status = STATUS_READY;
  74. private String language;
  75. private Rule template = null;
  76. private List<RuleParam> params = new ArrayList<>();
  77. private Date createdAt;
  78. private Date updatedAt;
  79. private String tags;
  80. private String systemTags;
  81. /**
  82. * @deprecated since 2.3. Use the factory method {@link #create()}
  83. */
  84. @Deprecated
  85. public Rule() {
  86. }
  87. /**
  88. * Creates rule with minimum set of info
  89. *
  90. * @param pluginName the plugin name indicates which plugin the rule belongs to
  91. * @param key the key should be unique within a plugin, but it is even more careful for the time being that it is unique across the
  92. * application
  93. * @deprecated since 2.3. Use the factory method {@link #create()}
  94. */
  95. @Deprecated
  96. public Rule(String pluginName, String key) {
  97. this.pluginName = pluginName;
  98. this.key = key;
  99. this.configKey = key;
  100. }
  101. /**
  102. * @deprecated since 8.4. Use {@link #ruleKey()} instead
  103. */
  104. @Deprecated
  105. public Integer getId() {
  106. throw new UnsupportedOperationException("This method is no longer supported");
  107. }
  108. public String getName() {
  109. return name;
  110. }
  111. /**
  112. * Sets the rule name
  113. */
  114. public Rule setName(String name) {
  115. this.name = removeNewLineCharacters(name);
  116. return this;
  117. }
  118. public String getKey() {
  119. return key;
  120. }
  121. /**
  122. * Sets the rule key
  123. */
  124. public Rule setKey(String key) {
  125. this.key = key;
  126. return this;
  127. }
  128. public String getConfigKey() {
  129. return configKey;
  130. }
  131. /**
  132. * Sets the configuration key
  133. */
  134. public Rule setConfigKey(String configKey) {
  135. this.configKey = configKey;
  136. return this;
  137. }
  138. public String getDescription() {
  139. return description;
  140. }
  141. /**
  142. * Sets the rule description
  143. */
  144. public Rule setDescription(String description) {
  145. this.description = StringUtils.strip(description);
  146. return this;
  147. }
  148. public Boolean isEnabled() {
  149. return !STATUS_REMOVED.equals(status);
  150. }
  151. public List<RuleParam> getParams() {
  152. return params;
  153. }
  154. public RuleParam getParam(String key) {
  155. for (RuleParam param : params) {
  156. if (StringUtils.equals(key, param.getKey())) {
  157. return param;
  158. }
  159. }
  160. return null;
  161. }
  162. /**
  163. * Sets the rule parameters
  164. */
  165. public Rule setParams(List<RuleParam> params) {
  166. this.params.clear();
  167. for (RuleParam param : params) {
  168. param.setRule(this);
  169. this.params.add(param);
  170. }
  171. return this;
  172. }
  173. public RuleParam createParameter() {
  174. RuleParam parameter = new RuleParam()
  175. .setRule(this);
  176. params.add(parameter);
  177. return parameter;
  178. }
  179. public RuleParam createParameter(String key) {
  180. RuleParam parameter = new RuleParam()
  181. .setKey(key)
  182. .setRule(this);
  183. params.add(parameter);
  184. return parameter;
  185. }
  186. /**
  187. * @since 2.5
  188. */
  189. public RulePriority getSeverity() {
  190. return priority;
  191. }
  192. /**
  193. * @param severity severity to set, if null, uses the default priority.
  194. * @since 2.5
  195. */
  196. public Rule setSeverity(@Nullable RulePriority severity) {
  197. if (severity == null) {
  198. this.priority = DEFAULT_PRIORITY;
  199. } else {
  200. this.priority = severity;
  201. }
  202. return this;
  203. }
  204. public String getRepositoryKey() {
  205. return pluginName;
  206. }
  207. public Rule setRepositoryKey(String s) {
  208. this.pluginName = s;
  209. return this;
  210. }
  211. public Rule setUniqueKey(String repositoryKey, String key) {
  212. return setRepositoryKey(repositoryKey).setKey(key).setConfigKey(key);
  213. }
  214. /**
  215. * @since 4.4
  216. */
  217. public boolean isTemplate() {
  218. return isTemplate;
  219. }
  220. /**
  221. * @since 4.4
  222. */
  223. public Rule setIsTemplate(boolean isTemplate) {
  224. this.isTemplate = isTemplate;
  225. return this;
  226. }
  227. /**
  228. * @deprecated since 4.4, use {@link #isTemplate()}
  229. */
  230. @Deprecated
  231. public Cardinality getCardinality() {
  232. return isTemplate ? Cardinality.MULTIPLE : Cardinality.SINGLE;
  233. }
  234. /**
  235. * @deprecated since 4.4, use {@link #setIsTemplate(boolean)}
  236. */
  237. @Deprecated
  238. public Rule setCardinality(Cardinality c) {
  239. this.isTemplate = Cardinality.MULTIPLE.equals(c);
  240. return this;
  241. }
  242. /**
  243. * @deprecated since 4.4, use {@link #getTemplate()}
  244. */
  245. @Deprecated
  246. public Rule getParent() {
  247. return getTemplate();
  248. }
  249. /**
  250. * @deprecated since 4.4, use {@link #setTemplate(Rule)}}
  251. */
  252. @Deprecated
  253. public Rule setParent(Rule parent) {
  254. return setTemplate(parent);
  255. }
  256. /**
  257. * @since 4.4
  258. */
  259. public Rule getTemplate() {
  260. return template;
  261. }
  262. /**
  263. * @since 4.4
  264. */
  265. public Rule setTemplate(Rule template) {
  266. this.template = template;
  267. return this;
  268. }
  269. /**
  270. * @since 3.6
  271. */
  272. public String getStatus() {
  273. return status;
  274. }
  275. /**
  276. * @since 3.6
  277. */
  278. public Rule setStatus(String status) {
  279. if (!STATUS_LIST.contains(status)) {
  280. throw new IllegalStateException("The status of a rule can only contain : " + String.join(", ", STATUS_LIST));
  281. }
  282. this.status = status;
  283. return this;
  284. }
  285. /**
  286. * @since 3.6
  287. */
  288. public Date getCreatedAt() {
  289. return createdAt;
  290. }
  291. /**
  292. * @since 3.6
  293. */
  294. public Rule setCreatedAt(Date d) {
  295. this.createdAt = d;
  296. return this;
  297. }
  298. /**
  299. * @since 3.6
  300. */
  301. public Date getUpdatedAt() {
  302. return updatedAt;
  303. }
  304. /**
  305. * @since 3.6
  306. */
  307. public Rule setUpdatedAt(Date updatedAt) {
  308. this.updatedAt = updatedAt;
  309. return this;
  310. }
  311. /**
  312. * @since 3.6
  313. */
  314. public String getLanguage() {
  315. return language;
  316. }
  317. /**
  318. * For internal use only.
  319. *
  320. * @since 3.6
  321. */
  322. public Rule setLanguage(String language) {
  323. this.language = language;
  324. return this;
  325. }
  326. /**
  327. * For definition of rule only
  328. */
  329. public String[] getTags() {
  330. return tags == null ? new String[0] : StringUtils.split(tags, ',');
  331. }
  332. /**
  333. * For definition of rule only
  334. */
  335. public Rule setTags(String[] tags) {
  336. this.tags = tags == null ? null : StringUtils.join(tags, ',');
  337. return this;
  338. }
  339. /**
  340. * For internal use
  341. */
  342. public String[] getSystemTags() {
  343. return systemTags == null ? new String[0] : StringUtils.split(systemTags, ',');
  344. }
  345. public Rule setSystemTags(String[] tags) {
  346. this.systemTags = tags == null ? null : StringUtils.join(tags, ',');
  347. return this;
  348. }
  349. @Override
  350. public boolean equals(Object obj) {
  351. if (!(obj instanceof Rule)) {
  352. return false;
  353. }
  354. if (this == obj) {
  355. return true;
  356. }
  357. Rule other = (Rule) obj;
  358. return new EqualsBuilder()
  359. .append(pluginName, other.getRepositoryKey())
  360. .append(key, other.getKey())
  361. .isEquals();
  362. }
  363. @Override
  364. public int hashCode() {
  365. return new HashCodeBuilder(17, 37)
  366. .append(pluginName)
  367. .append(key)
  368. .toHashCode();
  369. }
  370. @Override
  371. public String toString() {
  372. // Note that ReflectionToStringBuilder will not work here - see SONAR-3077
  373. return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
  374. .append("name", name)
  375. .append("key", key)
  376. .append("configKey", configKey)
  377. .append("plugin", pluginName)
  378. .append("severity", priority)
  379. .append("isTemplate", isTemplate())
  380. .append("status", status)
  381. .append("language", language)
  382. .append("template", template)
  383. .toString();
  384. }
  385. @CheckForNull
  386. private static String removeNewLineCharacters(@Nullable String text) {
  387. String removedCRLF = StringUtils.remove(text, "\n");
  388. removedCRLF = StringUtils.remove(removedCRLF, "\r");
  389. removedCRLF = StringUtils.remove(removedCRLF, "\n\r");
  390. removedCRLF = StringUtils.remove(removedCRLF, "\r\n");
  391. return removedCRLF;
  392. }
  393. public static Rule create() {
  394. return new Rule();
  395. }
  396. /**
  397. * Create with all required fields
  398. */
  399. public static Rule create(String repositoryKey, String key, String name) {
  400. return new Rule().setUniqueKey(repositoryKey, key).setName(name);
  401. }
  402. /**
  403. * Create with all required fields
  404. *
  405. * @since 2.10
  406. */
  407. public static Rule create(String repositoryKey, String key) {
  408. return new Rule().setUniqueKey(repositoryKey, key);
  409. }
  410. /**
  411. * @since 3.6
  412. */
  413. public RuleKey ruleKey() {
  414. return RuleKey.of(getRepositoryKey(), getKey());
  415. }
  416. }