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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  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.db.issue;
  21. import com.google.common.base.Joiner;
  22. import com.google.common.base.MoreObjects;
  23. import com.google.common.base.Preconditions;
  24. import com.google.common.base.Splitter;
  25. import com.google.common.collect.ImmutableSet;
  26. import com.google.protobuf.InvalidProtocolBufferException;
  27. import java.io.Serializable;
  28. import java.util.Collection;
  29. import java.util.Date;
  30. import java.util.Optional;
  31. import java.util.Set;
  32. import javax.annotation.CheckForNull;
  33. import javax.annotation.Nullable;
  34. import org.apache.commons.lang.builder.ToStringBuilder;
  35. import org.apache.commons.lang.builder.ToStringStyle;
  36. import org.sonar.api.rule.RuleKey;
  37. import org.sonar.api.rules.RuleType;
  38. import org.sonar.api.utils.Duration;
  39. import org.sonar.api.utils.KeyValueFormat;
  40. import org.sonar.core.issue.DefaultIssue;
  41. import org.sonar.db.component.ComponentDto;
  42. import org.sonar.db.protobuf.DbIssues;
  43. import org.sonar.db.rule.RuleDefinitionDto;
  44. import static com.google.common.base.Preconditions.checkArgument;
  45. import static org.sonar.api.utils.DateUtils.dateToLong;
  46. import static org.sonar.api.utils.DateUtils.longToDate;
  47. public final class IssueDto implements Serializable {
  48. public static final int AUTHOR_MAX_SIZE = 255;
  49. private static final char TAGS_SEPARATOR = ',';
  50. private static final Joiner TAGS_JOINER = Joiner.on(TAGS_SEPARATOR).skipNulls();
  51. private static final Splitter TAGS_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings();
  52. private int type;
  53. private String kee;
  54. private String componentUuid;
  55. private String projectUuid;
  56. private String ruleUuid;
  57. private String severity;
  58. private boolean manualSeverity;
  59. private String message;
  60. private Integer line;
  61. private Double gap;
  62. private Long effort;
  63. private String status;
  64. private String resolution;
  65. private String checksum;
  66. private String assigneeUuid;
  67. private String assigneeLogin;
  68. private String authorLogin;
  69. private String issueAttributes;
  70. private String securityStandards;
  71. private byte[] locations;
  72. private long createdAt;
  73. private long updatedAt;
  74. // functional dates stored as Long
  75. private Long issueCreationDate;
  76. private Long issueUpdateDate;
  77. private Long issueCloseDate;
  78. /**
  79. * Temporary date used only during scan
  80. */
  81. private Long selectedAt;
  82. // joins
  83. private String ruleKey;
  84. private String ruleRepo;
  85. private boolean isExternal;
  86. private String language;
  87. private String componentKey;
  88. private String moduleUuid;
  89. private String moduleUuidPath;
  90. private String projectKey;
  91. private String filePath;
  92. private String tags;
  93. // populate only when retrieving closed issue for issue tracking
  94. private String closedChangeData;
  95. public IssueDto() {
  96. // nothing to do
  97. }
  98. /**
  99. * On batch side, component keys and uuid are useless
  100. */
  101. public static IssueDto toDtoForComputationInsert(DefaultIssue issue, String ruleUuid, long now) {
  102. return new IssueDto()
  103. .setKee(issue.key())
  104. .setType(issue.type())
  105. .setLine(issue.line())
  106. .setLocations((DbIssues.Locations) issue.getLocations())
  107. .setMessage(issue.message())
  108. .setGap(issue.gap())
  109. .setEffort(issue.effortInMinutes())
  110. .setResolution(issue.resolution())
  111. .setStatus(issue.status())
  112. .setSeverity(issue.severity())
  113. .setManualSeverity(issue.manualSeverity())
  114. .setChecksum(issue.checksum())
  115. .setAssigneeUuid(issue.assignee())
  116. .setRuleUuid(ruleUuid)
  117. .setRuleKey(issue.ruleKey().repository(), issue.ruleKey().rule())
  118. .setExternal(issue.isFromExternalRuleEngine())
  119. .setTags(issue.tags())
  120. .setComponentUuid(issue.componentUuid())
  121. .setComponentKey(issue.componentKey())
  122. .setModuleUuid(issue.moduleUuid())
  123. .setModuleUuidPath(issue.moduleUuidPath())
  124. .setProjectUuid(issue.projectUuid())
  125. .setProjectKey(issue.projectKey())
  126. .setIssueAttributes(KeyValueFormat.format(issue.attributes()))
  127. .setAuthorLogin(issue.authorLogin())
  128. .setIssueCreationDate(issue.creationDate())
  129. .setIssueCloseDate(issue.closeDate())
  130. .setIssueUpdateDate(issue.updateDate())
  131. .setSelectedAt(issue.selectedAt())
  132. // technical dates
  133. .setCreatedAt(now)
  134. .setUpdatedAt(now);
  135. }
  136. /**
  137. * On server side, we need component keys and uuid
  138. */
  139. public static IssueDto toDtoForServerInsert(DefaultIssue issue, ComponentDto component, ComponentDto project, String ruleUuid, long now) {
  140. return toDtoForComputationInsert(issue, ruleUuid, now)
  141. .setComponent(component)
  142. .setProject(project);
  143. }
  144. public static IssueDto toDtoForUpdate(DefaultIssue issue, long now) {
  145. // Invariant fields, like key and rule, can't be updated
  146. return new IssueDto()
  147. .setKee(issue.key())
  148. .setType(issue.type())
  149. .setLine(issue.line())
  150. .setLocations((DbIssues.Locations) issue.getLocations())
  151. .setMessage(issue.message())
  152. .setGap(issue.gap())
  153. .setEffort(issue.effortInMinutes())
  154. .setResolution(issue.resolution())
  155. .setStatus(issue.status())
  156. .setSeverity(issue.severity())
  157. .setChecksum(issue.checksum())
  158. .setManualSeverity(issue.manualSeverity())
  159. .setAssigneeUuid(issue.assignee())
  160. .setIssueAttributes(KeyValueFormat.format(issue.attributes()))
  161. .setAuthorLogin(issue.authorLogin())
  162. .setRuleKey(issue.ruleKey().repository(), issue.ruleKey().rule())
  163. .setExternal(issue.isFromExternalRuleEngine())
  164. .setTags(issue.tags())
  165. .setComponentUuid(issue.componentUuid())
  166. .setComponentKey(issue.componentKey())
  167. .setModuleUuid(issue.moduleUuid())
  168. .setModuleUuidPath(issue.moduleUuidPath())
  169. .setProjectUuid(issue.projectUuid())
  170. .setProjectKey(issue.projectKey())
  171. .setIssueCreationDate(issue.creationDate())
  172. .setIssueCloseDate(issue.closeDate())
  173. .setIssueUpdateDate(issue.updateDate())
  174. .setSelectedAt(issue.selectedAt())
  175. // technical date
  176. .setUpdatedAt(now);
  177. }
  178. public String getKey() {
  179. return getKee();
  180. }
  181. public String getKee() {
  182. return kee;
  183. }
  184. public IssueDto setKee(String s) {
  185. this.kee = s;
  186. return this;
  187. }
  188. public IssueDto setComponent(ComponentDto component) {
  189. this.componentKey = component.getDbKey();
  190. this.componentUuid = component.uuid();
  191. this.moduleUuid = component.moduleUuid();
  192. this.moduleUuidPath = component.moduleUuidPath();
  193. this.filePath = component.path();
  194. return this;
  195. }
  196. public IssueDto setProject(ComponentDto project) {
  197. this.projectKey = project.getDbKey();
  198. this.projectUuid = project.uuid();
  199. return this;
  200. }
  201. public String getRuleUuid() {
  202. return ruleUuid;
  203. }
  204. /**
  205. * please use setRule(RuleDto rule)
  206. */
  207. public IssueDto setRuleUuid(String ruleUuid) {
  208. this.ruleUuid = ruleUuid;
  209. return this;
  210. }
  211. @CheckForNull
  212. public String getSeverity() {
  213. return severity;
  214. }
  215. public IssueDto setSeverity(@Nullable String s) {
  216. checkArgument(s == null || s.length() <= 10, "Value is too long for issue severity: %s", s);
  217. this.severity = s;
  218. return this;
  219. }
  220. public boolean isManualSeverity() {
  221. return manualSeverity;
  222. }
  223. public IssueDto setManualSeverity(boolean manualSeverity) {
  224. this.manualSeverity = manualSeverity;
  225. return this;
  226. }
  227. @CheckForNull
  228. public String getMessage() {
  229. return message;
  230. }
  231. public IssueDto setMessage(@Nullable String s) {
  232. checkArgument(s == null || s.length() <= 4000, "Value is too long for issue message: %s", s);
  233. this.message = s;
  234. return this;
  235. }
  236. @CheckForNull
  237. public Integer getLine() {
  238. return line;
  239. }
  240. public IssueDto setLine(@Nullable Integer i) {
  241. checkArgument(i == null || i >= 0, "Value of issue line must be positive: %d", i);
  242. this.line = i;
  243. return this;
  244. }
  245. @CheckForNull
  246. public Double getGap() {
  247. return gap;
  248. }
  249. public IssueDto setGap(@Nullable Double d) {
  250. checkArgument(d == null || d >= 0, "Value of issue gap must be positive: %d", d);
  251. this.gap = d;
  252. return this;
  253. }
  254. @CheckForNull
  255. public Long getEffort() {
  256. return effort;
  257. }
  258. public IssueDto setEffort(@Nullable Long l) {
  259. checkArgument(l == null || l >= 0, "Value of issue effort must be positive: %d", l);
  260. this.effort = l;
  261. return this;
  262. }
  263. public String getStatus() {
  264. return status;
  265. }
  266. public IssueDto setStatus(@Nullable String s) {
  267. checkArgument(s == null || s.length() <= 20, "Value is too long for issue status: %s", s);
  268. this.status = s;
  269. return this;
  270. }
  271. @CheckForNull
  272. public String getResolution() {
  273. return resolution;
  274. }
  275. public IssueDto setResolution(@Nullable String s) {
  276. checkArgument(s == null || s.length() <= 20, "Value is too long for issue resolution: %s", s);
  277. this.resolution = s;
  278. return this;
  279. }
  280. @CheckForNull
  281. public String getChecksum() {
  282. return checksum;
  283. }
  284. public IssueDto setChecksum(@Nullable String s) {
  285. checkArgument(s == null || s.length() <= 1000, "Value is too long for issue checksum: %s", s);
  286. this.checksum = s;
  287. return this;
  288. }
  289. @CheckForNull
  290. public String getAssigneeUuid() {
  291. return assigneeUuid;
  292. }
  293. public IssueDto setAssigneeUuid(@Nullable String s) {
  294. checkArgument(s == null || s.length() <= 255, "Value is too long for issue assigneeUuid: %s", s);
  295. this.assigneeUuid = s;
  296. return this;
  297. }
  298. @CheckForNull
  299. public String getAssigneeLogin() {
  300. return assigneeLogin;
  301. }
  302. public IssueDto setAssigneeLogin(@Nullable String s) {
  303. this.assigneeLogin = s;
  304. return this;
  305. }
  306. @CheckForNull
  307. public String getAuthorLogin() {
  308. return authorLogin;
  309. }
  310. public IssueDto setAuthorLogin(@Nullable String s) {
  311. checkArgument(s == null || s.length() <= AUTHOR_MAX_SIZE, "Value is too long for issue author login: %s", s);
  312. this.authorLogin = s;
  313. return this;
  314. }
  315. @CheckForNull
  316. public String getIssueAttributes() {
  317. return issueAttributes;
  318. }
  319. public IssueDto setIssueAttributes(@Nullable String s) {
  320. checkArgument(s == null || s.length() <= 4000, "Value is too long for issue attributes: %s", s);
  321. this.issueAttributes = s;
  322. return this;
  323. }
  324. public IssueDto setSecurityStandards(@Nullable String s) {
  325. this.securityStandards = s;
  326. return this;
  327. }
  328. public Set<String> getSecurityStandards() {
  329. return RuleDefinitionDto.deserializeSecurityStandardsString(securityStandards);
  330. }
  331. /**
  332. * Technical date
  333. */
  334. public long getCreatedAt() {
  335. return createdAt;
  336. }
  337. public IssueDto setCreatedAt(long createdAt) {
  338. this.createdAt = createdAt;
  339. return this;
  340. }
  341. /**
  342. * Technical date
  343. */
  344. public long getUpdatedAt() {
  345. return updatedAt;
  346. }
  347. public IssueDto setUpdatedAt(long updatedAt) {
  348. this.updatedAt = updatedAt;
  349. return this;
  350. }
  351. public Long getIssueCreationTime() {
  352. return issueCreationDate;
  353. }
  354. public IssueDto setIssueCreationTime(Long time) {
  355. this.issueCreationDate = time;
  356. return this;
  357. }
  358. public Date getIssueCreationDate() {
  359. return longToDate(issueCreationDate);
  360. }
  361. public IssueDto setIssueCreationDate(@Nullable Date d) {
  362. this.issueCreationDate = dateToLong(d);
  363. return this;
  364. }
  365. public Long getIssueUpdateTime() {
  366. return issueUpdateDate;
  367. }
  368. public IssueDto setIssueUpdateTime(Long time) {
  369. this.issueUpdateDate = time;
  370. return this;
  371. }
  372. public Date getIssueUpdateDate() {
  373. return longToDate(issueUpdateDate);
  374. }
  375. public IssueDto setIssueUpdateDate(@Nullable Date d) {
  376. this.issueUpdateDate = dateToLong(d);
  377. return this;
  378. }
  379. public Long getIssueCloseTime() {
  380. return issueCloseDate;
  381. }
  382. public IssueDto setIssueCloseTime(Long time) {
  383. this.issueCloseDate = time;
  384. return this;
  385. }
  386. public Date getIssueCloseDate() {
  387. return longToDate(issueCloseDate);
  388. }
  389. public IssueDto setIssueCloseDate(@Nullable Date d) {
  390. this.issueCloseDate = dateToLong(d);
  391. return this;
  392. }
  393. public String getRule() {
  394. return ruleKey;
  395. }
  396. public IssueDto setRule(RuleDefinitionDto rule) {
  397. Preconditions.checkNotNull(rule.getUuid(), "Rule must be persisted.");
  398. this.ruleUuid = rule.getUuid();
  399. this.ruleKey = rule.getRuleKey();
  400. this.ruleRepo = rule.getRepositoryKey();
  401. this.language = rule.getLanguage();
  402. this.isExternal = rule.isExternal();
  403. return this;
  404. }
  405. public String getRuleRepo() {
  406. return ruleRepo;
  407. }
  408. public RuleKey getRuleKey() {
  409. return RuleKey.of(ruleRepo, ruleKey);
  410. }
  411. public String getLanguage() {
  412. return language;
  413. }
  414. /**
  415. * Should only be used to persist in E/S
  416. * <p/>
  417. * Please use {@link #setRule(RuleDefinitionDto)} instead
  418. */
  419. public IssueDto setLanguage(String language) {
  420. this.language = language;
  421. return this;
  422. }
  423. public boolean isExternal() {
  424. return isExternal;
  425. }
  426. public IssueDto setExternal(boolean external) {
  427. isExternal = external;
  428. return this;
  429. }
  430. public String getComponentKey() {
  431. return componentKey;
  432. }
  433. /**
  434. * Should only be used to persist in E/S
  435. * <p/>
  436. * Please use {@link #setComponent(ComponentDto)} instead
  437. */
  438. public IssueDto setComponentKey(String componentKey) {
  439. this.componentKey = componentKey;
  440. return this;
  441. }
  442. /**
  443. * Can be null on Views or Devs
  444. */
  445. @CheckForNull
  446. public String getComponentUuid() {
  447. return componentUuid;
  448. }
  449. /**
  450. * Should only be used to persist in E/S
  451. * <p/>
  452. * Please use {@link #setComponent(ComponentDto)} instead
  453. */
  454. public IssueDto setComponentUuid(@Nullable String s) {
  455. checkArgument(s == null || s.length() <= 50, "Value is too long for column ISSUES.COMPONENT_UUID: %s", s);
  456. this.componentUuid = s;
  457. return this;
  458. }
  459. @CheckForNull
  460. public String getModuleUuid() {
  461. return moduleUuid;
  462. }
  463. /**
  464. * Should only be used to persist in E/S
  465. * <p/>
  466. * Please use {@link #setComponent(ComponentDto)} instead
  467. */
  468. public IssueDto setModuleUuid(@Nullable String moduleUuid) {
  469. this.moduleUuid = moduleUuid;
  470. return this;
  471. }
  472. @CheckForNull
  473. public String getModuleUuidPath() {
  474. return moduleUuidPath;
  475. }
  476. /**
  477. * Should only be used to persist in E/S
  478. * <p/>
  479. * Please use {@link #setComponent(ComponentDto)} instead
  480. */
  481. public IssueDto setModuleUuidPath(@Nullable String moduleUuidPath) {
  482. this.moduleUuidPath = moduleUuidPath;
  483. return this;
  484. }
  485. /**
  486. * Used by the issue tracking mechanism, but it should used the component uuid instead
  487. */
  488. public String getProjectKey() {
  489. return projectKey;
  490. }
  491. /**
  492. * Should only be used to persist in E/S
  493. * <p/>
  494. * Please use {@link #setProject(ComponentDto)} instead
  495. */
  496. public IssueDto setProjectKey(String projectKey) {
  497. this.projectKey = projectKey;
  498. return this;
  499. }
  500. public String getProjectUuid() {
  501. return projectUuid;
  502. }
  503. /**
  504. * Should only be used to persist in E/S
  505. * <p/>
  506. * Please use {@link #setProject(ComponentDto)} instead
  507. */
  508. public IssueDto setProjectUuid(String s) {
  509. checkArgument(s.length() <= 50, "Value is too long for column ISSUES.PROJECT_UUID: %s", s);
  510. this.projectUuid = s;
  511. return this;
  512. }
  513. @CheckForNull
  514. public Long getSelectedAt() {
  515. return selectedAt;
  516. }
  517. public IssueDto setSelectedAt(@Nullable Long d) {
  518. this.selectedAt = d;
  519. return this;
  520. }
  521. /**
  522. * Should only be used to persist in E/S
  523. * <p/>
  524. * Please use {@link #setRule(RuleDefinitionDto)} instead
  525. */
  526. public IssueDto setRuleKey(String repo, String rule) {
  527. this.ruleRepo = repo;
  528. this.ruleKey = rule;
  529. return this;
  530. }
  531. /**
  532. * Should only be used to persist in E/S
  533. * <p/>
  534. * Please use {@link #setProject(ComponentDto)} instead
  535. */
  536. public String getFilePath() {
  537. return filePath;
  538. }
  539. /**
  540. * Should only be used to persist in E/S
  541. * <p/>
  542. * Please use {@link #setProject(ComponentDto)} instead
  543. */
  544. public IssueDto setFilePath(String filePath) {
  545. this.filePath = filePath;
  546. return this;
  547. }
  548. public Set<String> getTags() {
  549. return ImmutableSet.copyOf(TAGS_SPLITTER.split(tags == null ? "" : tags));
  550. }
  551. public IssueDto setTags(@Nullable Collection<String> tags) {
  552. if (tags == null || tags.isEmpty()) {
  553. setTagsString(null);
  554. } else {
  555. setTagsString(TAGS_JOINER.join(tags));
  556. }
  557. return this;
  558. }
  559. public IssueDto setTagsString(@Nullable String s) {
  560. checkArgument(s == null || s.length() <= 4000, "Value is too long for column ISSUES.TAGS: %s", s);
  561. this.tags = s;
  562. return this;
  563. }
  564. public String getTagsString() {
  565. return tags;
  566. }
  567. @CheckForNull
  568. public byte[] getLocations() {
  569. return locations;
  570. }
  571. @CheckForNull
  572. public DbIssues.Locations parseLocations() {
  573. if (locations != null) {
  574. try {
  575. return DbIssues.Locations.parseFrom(locations);
  576. } catch (InvalidProtocolBufferException e) {
  577. throw new IllegalStateException(String.format("Fail to read ISSUES.LOCATIONS [KEE=%s]", kee), e);
  578. }
  579. }
  580. return null;
  581. }
  582. public IssueDto setLocations(@Nullable byte[] locations) {
  583. this.locations = locations;
  584. return this;
  585. }
  586. public IssueDto setLocations(@Nullable DbIssues.Locations locations) {
  587. if (locations == null) {
  588. this.locations = null;
  589. } else {
  590. this.locations = locations.toByteArray();
  591. }
  592. return this;
  593. }
  594. public int getType() {
  595. return type;
  596. }
  597. public IssueDto setType(int type) {
  598. this.type = type;
  599. return this;
  600. }
  601. public IssueDto setType(RuleType type) {
  602. this.type = type.getDbConstant();
  603. return this;
  604. }
  605. public Optional<String> getClosedChangeData() {
  606. return Optional.ofNullable(closedChangeData);
  607. }
  608. @Override
  609. public String toString() {
  610. return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
  611. }
  612. public DefaultIssue toDefaultIssue() {
  613. DefaultIssue issue = new DefaultIssue();
  614. issue.setKey(kee);
  615. issue.setType(RuleType.valueOf(type));
  616. issue.setStatus(status);
  617. issue.setResolution(resolution);
  618. issue.setMessage(message);
  619. issue.setGap(gap);
  620. issue.setEffort(effort != null ? Duration.create(effort) : null);
  621. issue.setLine(line);
  622. issue.setChecksum(checksum);
  623. issue.setSeverity(severity);
  624. issue.setAssigneeUuid(assigneeUuid);
  625. issue.setAttributes(KeyValueFormat.parse(MoreObjects.firstNonNull(issueAttributes, "")));
  626. issue.setComponentKey(componentKey);
  627. issue.setComponentUuid(componentUuid);
  628. issue.setModuleUuid(moduleUuid);
  629. issue.setModuleUuidPath(moduleUuidPath);
  630. issue.setProjectUuid(projectUuid);
  631. issue.setProjectKey(projectKey);
  632. issue.setManualSeverity(manualSeverity);
  633. issue.setRuleKey(getRuleKey());
  634. issue.setTags(getTags());
  635. issue.setLanguage(language);
  636. issue.setAuthorLogin(authorLogin);
  637. issue.setNew(false);
  638. issue.setCreationDate(longToDate(issueCreationDate));
  639. issue.setCloseDate(longToDate(issueCloseDate));
  640. issue.setUpdateDate(longToDate(issueUpdateDate));
  641. issue.setSelectedAt(selectedAt);
  642. issue.setLocations(parseLocations());
  643. issue.setIsFromExternalRuleEngine(isExternal);
  644. return issue;
  645. }
  646. }