001/*-----------------------------------------------------------------------+ 002 | com.teamscale.index 003 | | 004 $Id$ 005 | | 006 | Copyright (c) 2009-2013 CQSE GmbH | 007 +-----------------------------------------------------------------------*/ 008package org.conqat.engine.service.shared.data; 009 010import java.io.Serializable; 011import java.util.Objects; 012 013import javax.annotation.Nullable; 014 015import org.conqat.lib.commons.js_export.ExportToJavaScript; 016import org.conqat.lib.commons.string.StringUtils; 017 018import com.fasterxml.jackson.annotation.JsonCreator; 019import com.fasterxml.jackson.annotation.JsonProperty; 020import com.teamscale.commons.lang.ToStringHelpers; 021 022/** 023 * Information about a blacklisted finding. 024 * 025 * <strong>This class is used for communication with IDE clients (via the @link 026 * {@link org.conqat.engine.service.shared.client.IdeServiceClient}, special 027 * care has to be taken when changing its signature!</strong> 028 */ 029@ExportToJavaScript 030public class FindingBlacklistInfo implements Serializable { 031 032 /** Serial version UID. */ 033 private static final long serialVersionUID = 1; 034 035 /** The name of the JSON property name for {@link #findingId}. */ 036 private static final String FINDING_ID_PROPERTY = "findingId"; 037 038 /** The name of the JSON property name for {@link #timestamp}. */ 039 private static final String TIMESTAMP_PROPERTY = "timestamp"; 040 041 /** The name of the JSON property name for {@link #user}. */ 042 private static final String USER_PROPERTY = "user"; 043 044 /** The name of the JSON property name for {@link #rationale}. */ 045 private static final String RATIONALE_PROPERTY = "rationale"; 046 047 /** The name of the JSON property name for {@link #type}. */ 048 private static final String TYPE_PROPERTY = "type"; 049 050 /** The ID of the blacklisted finding */ 051 @JsonProperty(FINDING_ID_PROPERTY) 052 private final String findingId; 053 054 /** The time when the finding was blacklisted */ 055 @JsonProperty(TIMESTAMP_PROPERTY) 056 private final long timestamp; 057 058 /** The name of the user who blacklisted the finding */ 059 @JsonProperty(USER_PROPERTY) 060 private final String user; 061 062 /** A rationale why the finding was blacklisted */ 063 @JsonProperty(RATIONALE_PROPERTY) 064 private final String rationale; 065 066 @JsonProperty(TYPE_PROPERTY) 067 @Nullable 068 private final EFindingBlacklistType type; 069 070 /** Copy constructor. */ 071 public FindingBlacklistInfo(FindingBlacklistInfo info) { 072 this.findingId = info.findingId; 073 this.timestamp = info.timestamp; 074 this.user = info.user; 075 this.rationale = info.rationale; 076 this.type = info.type; 077 } 078 079 /** Constructor. */ 080 @JsonCreator 081 public FindingBlacklistInfo(@JsonProperty(FINDING_ID_PROPERTY) String findingId, 082 @JsonProperty(TIMESTAMP_PROPERTY) long timestamp, @JsonProperty(USER_PROPERTY) String user, 083 @JsonProperty(RATIONALE_PROPERTY) String rationale, 084 @JsonProperty(TYPE_PROPERTY) EFindingBlacklistType type) { 085 this.findingId = findingId; 086 this.timestamp = timestamp; 087 this.user = user; 088 this.rationale = rationale; 089 this.type = type; 090 } 091 092 /** Clones this FindingBlacklistInfo but uses the given findingId. */ 093 public FindingBlacklistInfo cloneWithNewFindingId(String findingId) { 094 return new FindingBlacklistInfo(findingId, timestamp, user, rationale, type); 095 } 096 097 /** Clones this FindingBlacklistInfo but uses the given findingId. */ 098 public FindingBlacklistInfo cloneWithNewType(EFindingBlacklistType newType) { 099 return new FindingBlacklistInfo(findingId, timestamp, user, rationale, newType); 100 } 101 102 /** 103 * Ensures that the type of blacklisting is set. If it is null it is tried to 104 * heuristically derive the type from the rationale. The default is 105 * {@link EFindingBlacklistType#TOLERATION}. 106 */ 107 public static FindingBlacklistInfo ensureBlacklistTypeSet(FindingBlacklistInfo blacklistInfo) { 108 if (blacklistInfo.getType() != null) { 109 return blacklistInfo; 110 } 111 String rationale = blacklistInfo.getRationale(); 112 if (!StringUtils.isEmpty(rationale) && rationale.toLowerCase().contains("false") 113 && rationale.toLowerCase().contains("positive")) { 114 return blacklistInfo.cloneWithNewType(EFindingBlacklistType.FALSE_POSITIVE); 115 } 116 return blacklistInfo.cloneWithNewType(EFindingBlacklistType.TOLERATION); 117 } 118 119 /** Returns the finding id. */ 120 public String getFindingId() { 121 return findingId; 122 } 123 124 /** Returns the timestamp. */ 125 public long getTimestamp() { 126 return timestamp; 127 } 128 129 /** Returns the user who blacklisted the finding. */ 130 public String getUser() { 131 return user; 132 } 133 134 /** Returns the rationale. */ 135 public String getRationale() { 136 return rationale; 137 } 138 139 /** 140 * Returns the blacklist type. This can be <code>null</code> for backwards 141 * compatibility 142 */ 143 public EFindingBlacklistType getType() { 144 return type; 145 } 146 147 @Override 148 public final boolean equals(Object obj) { 149 if (obj instanceof FindingBlacklistInfo) { 150 FindingBlacklistInfo other = (FindingBlacklistInfo) obj; 151 return Objects.equals(findingId, other.findingId) && Objects.equals(rationale, other.rationale) 152 && timestamp == other.timestamp && Objects.equals(user, other.user) 153 && Objects.equals(type, other.type); 154 } 155 return false; 156 } 157 158 @Override 159 public final int hashCode() { 160 return Objects.hash(findingId, rationale, timestamp, user, type); 161 } 162 163 @Override 164 public String toString() { 165 return ToStringHelpers.toReflectiveStringHelper(this).toString(); 166 } 167}