123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911 |
- /*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
- package org.sonar.db.issue;
-
- import com.google.common.base.Joiner;
- import com.google.common.base.Preconditions;
- import com.google.common.base.Splitter;
- import com.google.common.collect.ImmutableSet;
- import com.google.protobuf.InvalidProtocolBufferException;
- import java.io.Serializable;
- import java.util.Collection;
- import java.util.Date;
- import java.util.HashSet;
- import java.util.Map;
- import java.util.Optional;
- import java.util.Set;
- import java.util.stream.Collectors;
- import javax.annotation.CheckForNull;
- import javax.annotation.Nullable;
- import org.apache.commons.lang.builder.ToStringBuilder;
- import org.apache.commons.lang.builder.ToStringStyle;
- import org.jetbrains.annotations.NotNull;
- import org.sonar.api.issue.impact.Severity;
- import org.sonar.api.issue.impact.SoftwareQuality;
- import org.sonar.api.rule.RuleKey;
- import org.sonar.api.rules.CleanCodeAttribute;
- import org.sonar.api.rules.RuleType;
- import org.sonar.api.utils.Duration;
- import org.sonar.core.issue.DefaultIssue;
- import org.sonar.core.issue.status.IssueStatus;
- import org.sonar.core.util.Uuids;
- import org.sonar.db.component.ComponentDto;
- import org.sonar.db.protobuf.DbIssues;
- import org.sonar.db.rule.RuleDto;
-
- import static com.google.common.base.Preconditions.checkArgument;
- import static java.lang.String.format;
- import static java.util.stream.Collectors.toUnmodifiableMap;
- import static org.sonar.api.utils.DateUtils.dateToLong;
- import static org.sonar.api.utils.DateUtils.longToDate;
-
- public final class IssueDto implements Serializable {
-
- public static final int AUTHOR_MAX_SIZE = 255;
- private static final char STRING_LIST_SEPARATOR = ',';
- private static final Joiner STRING_LIST_JOINER = Joiner.on(STRING_LIST_SEPARATOR).skipNulls();
- private static final Splitter STRING_LIST_SPLITTER = Splitter.on(STRING_LIST_SEPARATOR).trimResults().omitEmptyStrings();
-
- private int type;
- private String kee;
- private String componentUuid;
- private String projectUuid;
- private String ruleUuid;
- private String severity;
- private boolean manualSeverity;
- private String message;
- private byte[] messageFormattings;
- private Integer line;
- private Double gap;
- private Long effort;
- private String status;
- private String resolution;
- private String checksum;
- private String assigneeUuid;
- private String assigneeLogin;
- private String authorLogin;
- private String securityStandards;
- private byte[] locations;
- private long createdAt;
- private long updatedAt;
- private boolean quickFixAvailable;
- private boolean isNewCodeReferenceIssue;
- private String ruleDescriptionContextKey;
-
- // functional dates stored as Long
- private Long issueCreationDate;
- private Long issueUpdateDate;
- private Long issueCloseDate;
-
- /**
- * Temporary date used only during scan
- */
- private Long selectedAt;
-
- // joins
- private String ruleKey;
- private String ruleRepo;
- private boolean isExternal;
- private String language;
- private String componentKey;
- private String projectKey;
- private String filePath;
- private String tags;
- private String codeVariants;
- // populate only when retrieving closed issue for issue tracking
- private String closedChangeData;
-
- private Set<ImpactDto> impacts = new HashSet<>();
-
- //non-persisted fields
- private Set<ImpactDto> ruleDefaultImpacts = new HashSet<>();
- private CleanCodeAttribute cleanCodeAttribute;
- private CleanCodeAttribute ruleCleanCodeAttribute;
-
- public IssueDto() {
- // nothing to do
- }
-
- /**
- * On batch side, component keys and uuid are useless
- */
- public static IssueDto toDtoForComputationInsert(DefaultIssue issue, String ruleUuid, long now) {
- return new IssueDto()
- .setKee(issue.key())
- .setType(issue.type())
- .setLine(issue.line())
- .setLocations((DbIssues.Locations) issue.getLocations())
- .setMessage(issue.message())
- .setMessageFormattings((DbIssues.MessageFormattings) issue.getMessageFormattings())
- .setGap(issue.gap())
- .setEffort(issue.effortInMinutes())
- .setResolution(issue.resolution())
- .setStatus(issue.status())
- .setSeverity(issue.severity())
- .setManualSeverity(issue.manualSeverity())
- .setChecksum(issue.checksum())
- .setAssigneeUuid(issue.assignee())
- .setRuleUuid(ruleUuid)
- .setRuleKey(issue.ruleKey().repository(), issue.ruleKey().rule())
- .setExternal(issue.isFromExternalRuleEngine())
- .setTags(issue.tags())
- .setRuleDescriptionContextKey(issue.getRuleDescriptionContextKey().orElse(null))
- .setComponentUuid(issue.componentUuid())
- .setComponentKey(issue.componentKey())
- .setProjectUuid(issue.projectUuid())
- .setProjectKey(issue.projectKey())
- .setAuthorLogin(issue.authorLogin())
- .setIssueCreationDate(issue.creationDate())
- .setIssueCloseDate(issue.closeDate())
- .setIssueUpdateDate(issue.updateDate())
- .setSelectedAt(issue.selectedAt())
- .setQuickFixAvailable(issue.isQuickFixAvailable())
- .setIsNewCodeReferenceIssue(issue.isNewCodeReferenceIssue())
- .setCodeVariants(issue.codeVariants())
- .replaceAllImpacts(mapToImpactDto(issue.impacts()))
- .setCleanCodeAttribute(issue.getCleanCodeAttribute())
- // technical dates
- .setCreatedAt(now)
- .setUpdatedAt(now);
- }
-
- @NotNull
- private static Set<ImpactDto> mapToImpactDto(Map<SoftwareQuality, Severity> impacts) {
- return impacts.entrySet().stream().map(e -> new ImpactDto()
- .setUuid(Uuids.createFast())
- .setSoftwareQuality(e.getKey())
- .setSeverity(e.getValue()))
- .collect(Collectors.toSet());
- }
-
- /**
- * On server side, we need component keys and uuid
- */
- public static IssueDto toDtoForServerInsert(DefaultIssue issue, ComponentDto component, ComponentDto project, String ruleUuid, long now) {
- return toDtoForComputationInsert(issue, ruleUuid, now)
- .setComponent(component)
- .setProject(project);
- }
-
- public static IssueDto toDtoForUpdate(DefaultIssue issue, long now) {
- // Invariant fields, like key and rule, can't be updated
- return new IssueDto()
- .setKee(issue.key())
- .setType(issue.type())
- .setLine(issue.line())
- .setLocations((DbIssues.Locations) issue.getLocations())
- .setMessage(issue.message())
- .setMessageFormattings((DbIssues.MessageFormattings) issue.getMessageFormattings())
- .setGap(issue.gap())
- .setEffort(issue.effortInMinutes())
- .setResolution(issue.resolution())
- .setStatus(issue.status())
- .setSeverity(issue.severity())
- .setChecksum(issue.checksum())
- .setManualSeverity(issue.manualSeverity())
- .setAssigneeUuid(issue.assignee())
- .setAuthorLogin(issue.authorLogin())
- .setRuleKey(issue.ruleKey().repository(), issue.ruleKey().rule())
- .setExternal(issue.isFromExternalRuleEngine())
- .setTags(issue.tags())
- .setRuleDescriptionContextKey(issue.getRuleDescriptionContextKey().orElse(null))
- .setComponentUuid(issue.componentUuid())
- .setComponentKey(issue.componentKey())
- .setProjectUuid(issue.projectUuid())
- .setProjectKey(issue.projectKey())
- .setIssueCreationDate(issue.creationDate())
- .setIssueCloseDate(issue.closeDate())
- .setIssueUpdateDate(issue.updateDate())
- .setSelectedAt(issue.selectedAt())
- .setQuickFixAvailable(issue.isQuickFixAvailable())
- .setIsNewCodeReferenceIssue(issue.isNewCodeReferenceIssue())
- .setCodeVariants(issue.codeVariants())
- .replaceAllImpacts(mapToImpactDto(issue.impacts()))
- .setCleanCodeAttribute(issue.getCleanCodeAttribute())
- // technical date
- .setUpdatedAt(now);
- }
-
- public String getKey() {
- return getKee();
- }
-
- public String getKee() {
- return kee;
- }
-
- public IssueDto setKee(String s) {
- this.kee = s;
- return this;
- }
-
- public IssueDto setComponent(ComponentDto component) {
- this.componentKey = component.getKey();
- this.componentUuid = component.uuid();
- this.filePath = component.path();
- return this;
- }
-
- /**
- * The project branch where the issue is located.
- * Note that the name is misleading - it should be branch.
- */
- public IssueDto setProject(ComponentDto branch) {
- this.projectKey = branch.getKey();
- this.projectUuid = branch.uuid();
- return this;
- }
-
- public String getRuleUuid() {
- return ruleUuid;
- }
-
- /**
- * please use setRule(RuleDto rule)
- */
- public IssueDto setRuleUuid(String ruleUuid) {
- this.ruleUuid = ruleUuid;
- return this;
- }
-
- @CheckForNull
- public String getSeverity() {
- return severity;
- }
-
- public IssueDto setSeverity(@Nullable String s) {
- checkArgument(s == null || s.length() <= 10, "Value is too long for issue severity: %s", s);
- this.severity = s;
- return this;
- }
-
- public boolean isManualSeverity() {
- return manualSeverity;
- }
-
- public IssueDto setManualSeverity(boolean manualSeverity) {
- this.manualSeverity = manualSeverity;
- return this;
- }
-
- @CheckForNull
- public String getMessage() {
- return message;
- }
-
- public IssueDto setMessage(@Nullable String s) {
- checkArgument(s == null || s.length() <= 4000, "Value is too long for issue message: %s", s);
- this.message = s;
- return this;
- }
-
- public byte[] getMessageFormattings() {
- return messageFormattings;
- }
-
- public IssueDto setMessageFormattings(byte[] messageFormattings) {
- this.messageFormattings = messageFormattings;
- return this;
- }
-
- public IssueDto setMessageFormattings(@Nullable DbIssues.MessageFormattings messageFormattings) {
- if (messageFormattings == null) {
- this.messageFormattings = null;
- } else {
- this.messageFormattings = messageFormattings.toByteArray();
- }
- return this;
- }
-
- @CheckForNull
- public DbIssues.MessageFormattings parseMessageFormattings() {
- if (messageFormattings != null) {
- try {
- return DbIssues.MessageFormattings.parseFrom(messageFormattings);
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalStateException(format("Fail to read ISSUES.MESSAGE_FORMATTINGS [KEE=%s]", kee), e);
- }
- }
- return null;
- }
-
- @CheckForNull
- public Integer getLine() {
- return line;
- }
-
- public IssueDto setLine(@Nullable Integer i) {
- checkArgument(i == null || i >= 0, "Value of issue line must be positive: %d", i);
- this.line = i;
- return this;
- }
-
- @CheckForNull
- public Double getGap() {
- return gap;
- }
-
- public IssueDto setGap(@Nullable Double d) {
- checkArgument(d == null || d >= 0, "Value of issue gap must be positive: %d", d);
- this.gap = d;
- return this;
- }
-
- @CheckForNull
- public Long getEffort() {
- return effort;
- }
-
- public IssueDto setEffort(@Nullable Long l) {
- checkArgument(l == null || l >= 0, "Value of issue effort must be positive: %d", l);
- this.effort = l;
- return this;
- }
-
- public String getStatus() {
- return status;
- }
-
- public IssueStatus getIssueStatus() {
- checkArgument(status != null, "Status must be initialized to retrieve issue status");
- return IssueStatus.of(status, resolution);
- }
-
- public IssueDto setStatus(@Nullable String s) {
- checkArgument(s == null || s.length() <= 20, "Value is too long for issue status: %s", s);
- this.status = s;
- return this;
- }
-
- @CheckForNull
- public String getResolution() {
- return resolution;
- }
-
- public IssueDto setResolution(@Nullable String s) {
- checkArgument(s == null || s.length() <= 20, "Value is too long for issue resolution: %s", s);
- this.resolution = s;
- return this;
- }
-
- @CheckForNull
- public String getChecksum() {
- return checksum;
- }
-
- public IssueDto setChecksum(@Nullable String s) {
- checkArgument(s == null || s.length() <= 1000, "Value is too long for issue checksum: %s", s);
- this.checksum = s;
- return this;
- }
-
- @CheckForNull
- public String getAssigneeUuid() {
- return assigneeUuid;
- }
-
- public IssueDto setAssigneeUuid(@Nullable String s) {
- checkArgument(s == null || s.length() <= 255, "Value is too long for issue assigneeUuid: %s", s);
- this.assigneeUuid = s;
- return this;
- }
-
- @CheckForNull
- public String getAssigneeLogin() {
- return assigneeLogin;
- }
-
- public IssueDto setAssigneeLogin(@Nullable String s) {
- this.assigneeLogin = s;
- return this;
- }
-
- @CheckForNull
- public String getAuthorLogin() {
- return authorLogin;
- }
-
- public IssueDto setAuthorLogin(@Nullable String s) {
- checkArgument(s == null || s.length() <= AUTHOR_MAX_SIZE, "Value is too long for issue author login: %s", s);
- this.authorLogin = s;
- return this;
- }
-
- public IssueDto setSecurityStandards(@Nullable String s) {
- this.securityStandards = s;
- return this;
- }
-
- public Set<String> getSecurityStandards() {
- return RuleDto.deserializeSecurityStandardsString(securityStandards);
- }
-
- /**
- * Technical date
- */
- public long getCreatedAt() {
- return createdAt;
- }
-
- public IssueDto setCreatedAt(long createdAt) {
- this.createdAt = createdAt;
- return this;
- }
-
- /**
- * Technical date
- */
- public long getUpdatedAt() {
- return updatedAt;
- }
-
- public IssueDto setUpdatedAt(long updatedAt) {
- this.updatedAt = updatedAt;
- return this;
- }
-
- public Long getIssueCreationTime() {
- return issueCreationDate;
- }
-
- public IssueDto setIssueCreationTime(Long time) {
- this.issueCreationDate = time;
- return this;
- }
-
- public Date getIssueCreationDate() {
- return longToDate(issueCreationDate);
- }
-
- public IssueDto setIssueCreationDate(@Nullable Date d) {
- this.issueCreationDate = dateToLong(d);
- return this;
- }
-
- public Long getIssueUpdateTime() {
- return issueUpdateDate;
- }
-
- public IssueDto setIssueUpdateTime(Long time) {
- this.issueUpdateDate = time;
- return this;
- }
-
- public Date getIssueUpdateDate() {
- return longToDate(issueUpdateDate);
- }
-
- public IssueDto setIssueUpdateDate(@Nullable Date d) {
- this.issueUpdateDate = dateToLong(d);
- return this;
- }
-
- public Long getIssueCloseTime() {
- return issueCloseDate;
- }
-
- public IssueDto setIssueCloseTime(Long time) {
- this.issueCloseDate = time;
- return this;
- }
-
- public Date getIssueCloseDate() {
- return longToDate(issueCloseDate);
- }
-
- public IssueDto setIssueCloseDate(@Nullable Date d) {
- this.issueCloseDate = dateToLong(d);
- return this;
- }
-
- public String getRule() {
- return ruleKey;
- }
-
- public IssueDto setRule(RuleDto rule) {
- Preconditions.checkNotNull(rule.getUuid(), "Rule must be persisted.");
- this.ruleUuid = rule.getUuid();
- this.ruleKey = rule.getRuleKey();
- this.ruleRepo = rule.getRepositoryKey();
- this.language = rule.getLanguage();
- this.isExternal = rule.isExternal();
- this.cleanCodeAttribute = rule.getCleanCodeAttribute();
- return this;
- }
-
- public String getRuleRepo() {
- return ruleRepo;
- }
-
- public RuleKey getRuleKey() {
- return RuleKey.of(ruleRepo, ruleKey);
- }
-
- public String getLanguage() {
- return language;
- }
-
- /**
- * Should only be used to persist in E/S
- * <p/>
- * Please use {@link #setRule(RuleDto)} instead
- */
- public IssueDto setLanguage(String language) {
- this.language = language;
- return this;
- }
-
- public boolean isExternal() {
- return isExternal;
- }
-
- public IssueDto setExternal(boolean external) {
- isExternal = external;
- return this;
- }
-
- public String getComponentKey() {
- return componentKey;
- }
-
- /**
- * Should only be used to persist in E/S
- * <p/>
- * Please use {@link #setComponent(ComponentDto)} instead
- */
- public IssueDto setComponentKey(String componentKey) {
- this.componentKey = componentKey;
- return this;
- }
-
- /**
- * Can be null on Views or Devs
- */
- @CheckForNull
- public String getComponentUuid() {
- return componentUuid;
- }
-
- /**
- * Should only be used to persist in E/S
- * <p/>
- * Please use {@link #setComponent(ComponentDto)} instead
- */
- public IssueDto setComponentUuid(@Nullable String s) {
- checkArgument(s == null || s.length() <= 50, "Value is too long for column ISSUES.COMPONENT_UUID: %s", s);
- this.componentUuid = s;
- return this;
- }
-
- /**
- * Used by the issue tracking mechanism, but it should used the component uuid instead
- */
- public String getProjectKey() {
- return projectKey;
- }
-
- /**
- * Should only be used to persist in E/S
- * <p/>
- * Please use {@link #setProject(ComponentDto)} instead
- */
- public IssueDto setProjectKey(String projectKey) {
- this.projectKey = projectKey;
- return this;
- }
-
- /**
- * The project branch where the issue is located.
- * Note that the name is misleading - it should be 'branchUuid'.
- */
- public String getProjectUuid() {
- return projectUuid;
- }
-
- /**
- * This is branch uuid, not a project uuid. The naming is wrong, the javadoc is right.
- * Please use {@link #setProject(ComponentDto)} instead
- */
- public IssueDto setProjectUuid(String s) {
- checkArgument(s.length() <= 50, "Value is too long for column ISSUES.PROJECT_UUID: %s", s);
- this.projectUuid = s;
- return this;
- }
-
- @CheckForNull
- public Long getSelectedAt() {
- return selectedAt;
- }
-
- public IssueDto setSelectedAt(@Nullable Long d) {
- this.selectedAt = d;
- return this;
- }
-
- /**
- * Should only be used to persist in E/S
- * <p/>
- * Please use {@link #setRule(RuleDto)} instead
- */
- public IssueDto setRuleKey(String repo, String rule) {
- this.ruleRepo = repo;
- this.ruleKey = rule;
- return this;
- }
-
- /**
- * Should only be used to persist in E/S
- * <p/>
- * Please use {@link #setProject(ComponentDto)} instead
- */
- public String getFilePath() {
- return filePath;
- }
-
- /**
- * Should only be used to persist in E/S
- * <p/>
- * Please use {@link #setProject(ComponentDto)} instead
- */
- public IssueDto setFilePath(String filePath) {
- this.filePath = filePath;
- return this;
- }
-
- public Set<String> getTags() {
- return ImmutableSet.copyOf(STRING_LIST_SPLITTER.split(tags == null ? "" : tags));
- }
-
- public IssueDto setTags(@Nullable Collection<String> tags) {
- if (tags == null || tags.isEmpty()) {
- setTagsString(null);
- } else {
- setTagsString(STRING_LIST_JOINER.join(tags));
- }
- return this;
- }
-
- public IssueDto setTagsString(@Nullable String s) {
- checkArgument(s == null || s.length() <= 4000, "Value is too long for column ISSUES.TAGS: %s", s);
- this.tags = s;
- return this;
- }
-
- public String getTagsString() {
- return tags;
- }
-
- public Set<String> getCodeVariants() {
- return ImmutableSet.copyOf(STRING_LIST_SPLITTER.split(codeVariants == null ? "" : codeVariants));
- }
-
- public String getCodeVariantsString() {
- return codeVariants;
- }
-
- public IssueDto setCodeVariants(@Nullable Collection<String> codeVariants) {
- if (codeVariants == null || codeVariants.isEmpty()) {
- setCodeVariantsString(null);
- } else {
- setCodeVariantsString(STRING_LIST_JOINER.join(codeVariants));
- }
- return this;
- }
-
- public IssueDto setCodeVariantsString(@Nullable String codeVariants) {
- checkArgument(codeVariants == null || codeVariants.length() <= 4000,
- "Value is too long for column ISSUES.CODE_VARIANTS: %codeVariants", codeVariants);
- this.codeVariants = codeVariants;
- return this;
- }
-
- @CheckForNull
- public byte[] getLocations() {
- return locations;
- }
-
- @CheckForNull
- public DbIssues.Locations parseLocations() {
- if (locations != null) {
- try {
- return DbIssues.Locations.parseFrom(locations);
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalStateException(format("Fail to read ISSUES.LOCATIONS [KEE=%s]", kee), e);
- }
- }
- return null;
- }
-
- public IssueDto setLocations(@Nullable byte[] locations) {
- this.locations = locations;
- return this;
- }
-
- public IssueDto setLocations(@Nullable DbIssues.Locations locations) {
- if (locations == null) {
- this.locations = null;
- } else {
- this.locations = locations.toByteArray();
- }
- return this;
- }
-
- public boolean isQuickFixAvailable() {
- return quickFixAvailable;
- }
-
- public IssueDto setQuickFixAvailable(boolean quickFixAvailable) {
- this.quickFixAvailable = quickFixAvailable;
- return this;
- }
-
- public boolean isNewCodeReferenceIssue() {
- return isNewCodeReferenceIssue;
- }
-
- public IssueDto setIsNewCodeReferenceIssue(boolean isNewCodeReferenceIssue) {
- this.isNewCodeReferenceIssue = isNewCodeReferenceIssue;
- return this;
- }
-
- public int getType() {
- return type;
- }
-
- public IssueDto setType(int type) {
- this.type = type;
- return this;
- }
-
- public IssueDto setType(RuleType type) {
- this.type = type.getDbConstant();
- return this;
- }
-
- @CheckForNull
- public CleanCodeAttribute getEffectiveCleanCodeAttribute() {
- if (cleanCodeAttribute != null) {
- return cleanCodeAttribute;
- }
- return ruleCleanCodeAttribute;
- }
-
- public IssueDto setCleanCodeAttribute(CleanCodeAttribute cleanCodeAttribute) {
- this.cleanCodeAttribute = cleanCodeAttribute;
- return this;
- }
-
- public IssueDto setRuleCleanCodeAttribute(CleanCodeAttribute ruleCleanCodeAttribute) {
- this.ruleCleanCodeAttribute = ruleCleanCodeAttribute;
- return this;
- }
-
- public Optional<String> getClosedChangeData() {
- return Optional.ofNullable(closedChangeData);
- }
-
- public Optional<String> getOptionalRuleDescriptionContextKey() {
- return Optional.ofNullable(ruleDescriptionContextKey);
- }
-
- public IssueDto setRuleDescriptionContextKey(@Nullable String ruleDescriptionContextKey) {
- this.ruleDescriptionContextKey = ruleDescriptionContextKey;
- return this;
- }
-
- /**
- * Return impacts defined on this issue.
- *
- * @return Collection of impacts
- */
- public Set<ImpactDto> getImpacts() {
- return impacts;
- }
-
- public IssueDto addImpact(ImpactDto impact) {
- impacts.stream().filter(impactDto -> impactDto.getSoftwareQuality() == impact.getSoftwareQuality()).findFirst()
- .ifPresent(impactDto -> {
- throw new IllegalStateException(format("Impact already defined on issue for Software Quality [%s]", impact.getSoftwareQuality()));
- });
-
- impacts.add(impact);
- return this;
- }
-
-
- public IssueDto setRuleDefaultImpacts(Set<ImpactDto> ruleDefaultImpacts) {
- this.ruleDefaultImpacts = new HashSet<>(ruleDefaultImpacts);
- return this;
- }
-
-
- public IssueDto replaceAllImpacts(Collection<ImpactDto> newImpacts) {
- Set<SoftwareQuality> newSoftwareQuality = newImpacts.stream().map(ImpactDto::getSoftwareQuality).collect(Collectors.toSet());
- if (newSoftwareQuality.size() != newImpacts.size()) {
- throw new IllegalStateException("Impacts must have unique Software Quality values");
- }
- impacts.clear();
- impacts.addAll(newImpacts);
- return this;
- }
-
- Set<ImpactDto> getRuleDefaultImpacts() {
- return ruleDefaultImpacts;
- }
-
- /**
- * Returns effective impacts defined on this issue along with default ones.
- *
- * @return Unmodifiable Map of impacts
- */
- public Map<SoftwareQuality, Severity> getEffectiveImpacts() {
- return impacts.isEmpty() ? toImpactMap(ruleDefaultImpacts) : toImpactMap(impacts);
- }
-
- private static Map<SoftwareQuality, Severity> toImpactMap(Collection<ImpactDto> impacts) {
- return impacts.stream()
- .collect(toUnmodifiableMap(ImpactDto::getSoftwareQuality, ImpactDto::getSeverity));
- }
-
- @Override
- public String toString() {
- return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
- }
-
- public DefaultIssue toDefaultIssue() {
- DefaultIssue issue = new DefaultIssue();
- issue.setKey(kee);
- issue.setType(RuleType.valueOf(type));
- issue.setStatus(status);
- issue.setResolution(resolution);
- issue.setMessage(message);
- issue.setMessageFormattings(parseMessageFormattings());
- issue.setGap(gap);
- issue.setEffort(effort != null ? Duration.create(effort) : null);
- issue.setLine(line);
- issue.setChecksum(checksum);
- issue.setSeverity(severity);
- issue.setAssigneeUuid(assigneeUuid);
- issue.setAssigneeLogin(assigneeLogin);
- issue.setComponentKey(componentKey);
- issue.setComponentUuid(componentUuid);
- issue.setProjectUuid(projectUuid);
- issue.setProjectKey(projectKey);
- issue.setManualSeverity(manualSeverity);
- issue.setRuleKey(getRuleKey());
- issue.setTags(getTags());
- issue.setRuleDescriptionContextKey(ruleDescriptionContextKey);
- issue.setLanguage(language);
- issue.setAuthorLogin(authorLogin);
- issue.setNew(false);
- issue.setCreationDate(longToDate(issueCreationDate));
- issue.setCloseDate(longToDate(issueCloseDate));
- issue.setUpdateDate(longToDate(issueUpdateDate));
- issue.setSelectedAt(selectedAt);
- issue.setLocations(parseLocations());
- issue.setIsFromExternalRuleEngine(isExternal);
- issue.setQuickFixAvailable(quickFixAvailable);
- issue.setIsNewCodeReferenceIssue(isNewCodeReferenceIssue);
- issue.setCodeVariants(getCodeVariants());
- issue.setCleanCodeAttribute(cleanCodeAttribute);
- impacts.forEach(i -> issue.addImpact(i.getSoftwareQuality(), i.getSeverity()));
- return issue;
- }
- }
|