import org.sonar.db.qualityprofile.ActiveRuleDto;
import org.sonar.db.qualityprofile.ActiveRuleKey;
import org.sonar.db.qualityprofile.QProfileChangeDto;
+import org.sonar.db.rule.RuleDefinitionDto;
public class ActiveRuleChange {
private final Type type;
private final ActiveRuleKey key;
+ private final int ruleId;
private String severity = null;
private ActiveRule.Inheritance inheritance = null;
private final Map<String, String> parameters = new HashMap<>();
- public ActiveRuleChange(Type type, ActiveRuleDto activeRule) {
+ public ActiveRuleChange(Type type, ActiveRuleDto activeRule, RuleDefinitionDto ruleDefinition) {
this.type = type;
this.key = activeRule.getKey();
+ this.ruleId = ruleDefinition.getId();
this.activeRule = activeRule;
}
- public ActiveRuleChange(Type type, ActiveRuleKey key) {
+ public ActiveRuleChange(Type type, ActiveRuleKey key, RuleDefinitionDto ruleDefinition) {
this.type = type;
this.key = key;
+ this.ruleId = ruleDefinition.getId();
}
public ActiveRuleKey getKey() {
return key;
}
+ public int getRuleId() {
+ return ruleId;
+ }
+
public Type getType() {
return type;
}
dto.setRulesProfileUuid(getKey().getRuleProfileUuid());
dto.setLogin(login);
Map<String, String> data = new HashMap<>();
- data.put("ruleKey", getKey().getRuleKey().toString());
+ data.put("ruleId", String.valueOf(getRuleId()));
parameters.entrySet().stream()
.filter(param -> !param.getKey().isEmpty())
return MoreObjects.toStringHelper(this)
.add("type", type)
.add("key", key)
+ .add("ruleId", ruleId)
.add("severity", severity)
.add("inheritance", inheritance)
.add("parameters", parameters)
List<ActiveRuleParamDto> paramDtos = insertActiveRuleParams(dbSession, activeRule, ruleKey, dto);
- ActiveRuleChange change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, dto);
+ ActiveRuleChange change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, dto, ruleDefinitionDto);
change.setSeverity(dto.getSeverityString());
paramDtos.forEach(paramDto -> change.setParameter(paramDto.getKey(), paramDto.getValue()));
return change;
List<Integer> activeRuleIds = new ArrayList<>();
db.activeRuleDao().selectByRuleIdOfAllOrganizations(dbSession, rule.getId()).forEach(ar -> {
activeRuleIds.add(ar.getId());
- changes.add(new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, ar));
+ changes.add(new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, ar, rule));
});
db.activeRuleDao().deleteByIds(dbSession, activeRuleIds);
changes.addAll(ruleActivator.deactivate(dbSession, context, activeRule.getRuleKey(), true));
} else if (ActiveRuleDto.OVERRIDES.equals(activeRule.getInheritance())) {
+ context.reset(activeRule.getRuleKey());
activeRule.setInheritance(null);
activeRule.setUpdatedAt(system2.now());
db.activeRuleDao().update(dbSession, activeRule);
- changes.add(new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRule).setInheritance(null));
+ changes.add(new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRule, context.getRule().get()).setInheritance(null));
}
}
return changes;
return changes;
}
// new activation
- change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, activeRuleKey);
+ change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, activeRuleKey, rule);
applySeverityAndParamToChange(activation, context, change);
if (context.isCascading() || isSameAsParent(change, context)) {
change.setInheritance(ActiveRule.Inheritance.INHERITED);
// propagating to descendants, but child profile already overrides rule -> stop propagation
return changes;
}
- change = new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRuleKey);
+ change = new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRuleKey, rule);
if (context.isCascading() && activeRule.get().getInheritance() == null) {
// activate on child, then on parent -> mark child as overriding parent
change.setInheritance(ActiveRule.Inheritance.OVERRIDES);
ActiveRuleChange change;
checkRequest(force || context.isCascading() || activeRule.get().getInheritance() == null, "Cannot deactivate inherited rule '%s'", context.getRule().get().getKey());
- change = new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, activeRule.get());
+ change = new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, activeRule.get(), context.getRule().get());
changes.add(change);
persist(change, context, dbSession);
*/
package org.sonar.server.qualityprofile.ws;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
import org.sonar.api.resources.Languages;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ws.Request;
.prop("authorLogin", change.getUserLogin())
.prop("authorName", change.getUserName())
.prop("action", change.getType())
- .prop("ruleKey", change.getRuleKey() == null ? null : change.getRuleKey().toString())
- .prop("ruleName", change.getRuleName());
+ .prop("ruleKey", change.getRuleKey().map(RuleKey::toString).orElse(null))
+ .prop("ruleName", change.getRuleName().orElse(null));
writeParameters(json, change);
json.endObject();
}
.stream()
.collect(java.util.stream.Collectors.toMap(UserDto::getLogin, UserDto::getName));
- Set<RuleKey> ruleKeys = changes.stream().filter(c -> c.ruleKey != null).map(c -> c.ruleKey).collect(MoreCollectors.toSet());
- Map<RuleKey, String> ruleNamesByKeys = dbClient.ruleDao()
- .selectDefinitionByKeys(dbSession, Lists.newArrayList(ruleKeys))
+ Set<Integer> ruleIds = changes.stream()
+ .map(c -> c.ruleId)
+ .filter(Objects::nonNull)
+ .collect(MoreCollectors.toSet());
+ Map<Integer, RuleDefinitionDto> ruleDefinitionsById = dbClient.ruleDao()
+ .selectDefinitionByIds(dbSession, Lists.newArrayList(ruleIds))
.stream()
- .collect(java.util.stream.Collectors.toMap(RuleDefinitionDto::getKey, RuleDefinitionDto::getName));
+ .collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getId));
changes.forEach(c -> {
c.userName = userNamesByLogins.get(c.userLogin);
- c.ruleName = ruleNamesByKeys.get(c.ruleKey);
+ RuleDefinitionDto ruleDefinitionDto = ruleDefinitionsById.get(c.ruleId);
+ if (ruleDefinitionDto != null) {
+ c.ruleKey = ruleDefinitionDto.getKey();
+ c.ruleName = ruleDefinitionDto.getName();
+ }
});
}
private String userLogin;
private String userName;
private String inheritance;
+ private Integer ruleId;
private RuleKey ruleKey;
private String ruleName;
private final Map<String, String> params = new HashMap<>();
private Change() {
}
- @VisibleForTesting
- Change(String key, String type, long at, @Nullable String severity, @Nullable String userLogin,
- @Nullable String userName, @Nullable String inheritance, @Nullable RuleKey ruleKey, @Nullable String ruleName) {
- this.key = key;
- this.type = type;
- this.at = at;
- this.severity = severity;
- this.userLogin = userLogin;
- this.userName = userName;
- this.inheritance = inheritance;
- this.ruleKey = ruleKey;
- this.ruleName = ruleName;
- }
-
public String getKey() {
return key;
}
return inheritance;
}
- public RuleKey getRuleKey() {
- return ruleKey;
+ public Optional<Integer> getRuleId() {
+ return Optional.ofNullable(ruleId);
}
- @CheckForNull
- public String getRuleName() {
- return ruleName;
+ public Optional<RuleKey> getRuleKey() {
+ return Optional.ofNullable(ruleKey);
+ }
+
+ public Optional<String> getRuleName() {
+ return Optional.ofNullable(ruleName);
}
public long getCreatedAt() {
change.at = dto.getCreatedAt();
// see content of data in class org.sonar.server.qualityprofile.ActiveRuleChange
change.severity = data.get("severity");
- String ruleKey = data.get("ruleKey");
- if (ruleKey != null) {
- change.ruleKey = RuleKey.parse(ruleKey);
+ String ruleId = data.get("ruleId");
+ if (ruleId != null) {
+ change.ruleId = Integer.parseInt(ruleId);
}
change.inheritance = data.get("inheritance");
data.entrySet().stream()
*/
package org.sonar.server.qualityprofile;
+import java.util.Random;
import org.junit.Test;
import org.sonar.api.rule.RuleKey;
import org.sonar.db.qualityprofile.ActiveRuleKey;
import org.sonar.db.qualityprofile.QProfileChangeDto;
import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.rule.RuleDefinitionDto;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.db.qualityprofile.QualityProfileTesting.newQualityProfileDto;
public void toDto() {
QProfileDto profile = newQualityProfileDto();
ActiveRuleKey key = ActiveRuleKey.of(profile, RuleKey.of("P1", "R1"));
- ActiveRuleChange underTest = new ActiveRuleChange(ACTIVATED, key);
+ int ruleId = new Random().nextInt(963);
+ ActiveRuleChange underTest = new ActiveRuleChange(ACTIVATED, key, new RuleDefinitionDto().setId(ruleId));
QProfileChangeDto result = underTest.toDto(A_LOGIN);
assertThat(result.getChangeType()).isEqualTo(ACTIVATED.name());
assertThat(result.getRulesProfileUuid()).isEqualTo(profile.getRulesProfileUuid());
assertThat(result.getLogin()).isEqualTo(A_LOGIN);
+ assertThat(result.getDataAsMap().get("ruleId")).isEqualTo(String.valueOf(ruleId));
}
}
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.rule.Severity;
-import org.sonar.api.rules.RulePriority;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
import org.sonar.api.utils.System2;
QProfileChangeQuery changeQuery = new QProfileChangeQuery(profile.getKee());
QProfileChangeDto change = db.getDbClient().qProfileChangeDao().selectByQuery(dbSession, changeQuery).stream()
- .filter(c -> c.getDataAsMap().get("ruleKey").equals(rule.getKey().toString()))
+ .filter(c -> c.getDataAsMap().get("ruleId").equals(String.valueOf(rule.getId())))
.findFirst()
.get();
assertThat(change.getChangeType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED.name());
assertThat(change.getDataAsMap().get("severity")).isEqualTo(expectedSeverity);
}
- private static void activeRule(RulesProfile apiProfile, RuleDefinitionDto rule, RulePriority severity) {
- apiProfile.activateRule(org.sonar.api.rules.Rule.create(rule.getRepositoryKey(), rule.getRuleKey()), severity);
- }
-
private QProfileDto verifyProfileInDb(OrganizationDto organization, BuiltInQProfile builtIn) {
QProfileDto profileOnOrg1 = db.getDbClient().qualityProfileDao().selectByNameAndLanguage(dbSession, organization, builtIn.getName(), builtIn.getLanguage());
assertThat(profileOnOrg1.getLanguage()).isEqualTo(builtIn.getLanguage());
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
+import java.util.Random;
import org.assertj.core.groups.Tuple;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.server.notification.NotificationManager;
import org.sonar.server.qualityprofile.BuiltInQualityProfilesNotification.Profile;
private Tuple addProfile(Multimap<QProfileName, ActiveRuleChange> profiles, Languages languages, ActiveRuleChange.Type type) {
String profileName = randomLowerCaseText();
+ int ruleId1 = new Random().nextInt(952);
+ int ruleId2 = new Random().nextInt(952);
Language language = newLanguage(randomLowerCaseText(), randomLowerCaseText());
languages.add(language);
profiles.putAll(new QProfileName(language.getKey(), profileName),
- asList(new ActiveRuleChange(type, ActiveRuleKey.parse("qp:repo:rule1")), new ActiveRuleChange(type, ActiveRuleKey.parse("qp:repo:rule2"))));
+ asList(new ActiveRuleChange(
+ type,
+ ActiveRuleKey.parse("qp:repo:rule1"), new RuleDefinitionDto().setId(ruleId1)),
+ new ActiveRuleChange(type, ActiveRuleKey.parse("qp:repo:rule2"), new RuleDefinitionDto().setId(ruleId2))));
return tuple(profileName, language.getKey(), language.getName(), 2);
}
ActiveRuleDto ar2 = db.qualityProfiles().activateRule(profile2, rule1);
ActiveRuleDto ar3 = db.qualityProfiles().activateRule(profile2, rule2);
- commitAndIndex(ar1, ar2);
+ commitAndIndex(rule1, ar1, ar2);
verifyOnlyIndexed(ar1, ar2);
assertThatEsQueueTableIsEmpty();
ActiveRuleDto ar = db.qualityProfiles().activateRule(profile1, rule1);
es.lockWrites(INDEX_TYPE_ACTIVE_RULE);
- commitAndIndex(ar);
+ commitAndIndex(rule1, ar);
EsQueueDto expectedItem = EsQueueDto.create(INDEX_TYPE_ACTIVE_RULE.format(), "" + ar.getId(), "activeRuleId", ar.getRuleKey().toString());
assertThatEsQueueContainsExactly(expectedItem);
assertThat(es.countDocuments(INDEX_TYPE_ACTIVE_RULE)).isEqualTo(1);
db.getDbClient().activeRuleDao().delete(db.getSession(), ar.getKey());
- commitAndIndex(ar);
+ commitAndIndex(rule1, ar);
assertThat(es.countDocuments(INDEX_TYPE_ACTIVE_RULE)).isEqualTo(0);
assertThatEsQueueTableIsEmpty();
.containsExactlyInAnyOrder(Tuple.tuple(expected.getDocId(), expected.getDocIdType(), expected.getDocRouting()));
}
- private void commitAndIndex(ActiveRuleDto... ar) {
+ private void commitAndIndex(RuleDefinitionDto rule, ActiveRuleDto... ar) {
underTest.commitAndIndex(db.getSession(), stream(ar)
- .map(a -> new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, a))
+ .map(a -> new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, a, rule))
.collect(Collectors.toList()));
}
import org.sonar.server.ws.WsActionTester;
import org.sonar.test.JsonAssert;
+import static java.lang.String.valueOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY;
insertChange(profile, c -> c.setRulesProfileUuid(profileUuid)
.setLogin(user1.getLogin())
.setChangeType(ActiveRuleChange.Type.ACTIVATED.name())
- .setData(ImmutableMap.of("severity", "CRITICAL", "ruleKey", rule1.getKey().toString())));
+ .setData(ImmutableMap.of("severity", "CRITICAL", "ruleId", valueOf(rule1.getId()))));
system2.setNow(DateUtils.parseDateTime("2015-02-23T17:58:18+0100").getTime());
RuleDefinitionDto rule2 = dbTester.rules().insert(RuleKey.of("squid", "S2162"), r -> r.setName("\"equals\" methods should be symmetric and work for subclasses"));
QProfileChangeDto change2 = insertChange(profile, c -> c.setRulesProfileUuid(profileUuid)
.setLogin(user2.getLogin())
.setChangeType(ActiveRuleChange.Type.DEACTIVATED.name())
- .setData(ImmutableMap.of("ruleKey", rule2.getKey().toString())));
+ .setData(ImmutableMap.of("ruleId", valueOf(rule2.getId()))));
system2.setNow(DateUtils.parseDateTime("2014-09-12T15:20:46+0200").getTime());
RuleDefinitionDto rule3 = dbTester.rules().insert(RuleKey.of("squid", "S00101"), r -> r.setName("Class names should comply with a naming convention"));
QProfileChangeDto change3 = insertChange(profile, c -> c.setRulesProfileUuid(profileUuid)
.setLogin(user3.getLogin())
.setChangeType(ActiveRuleChange.Type.ACTIVATED.name())
- .setData(ImmutableMap.of("severity", "MAJOR", "param_format", "^[A-Z][a-zA-Z0-9]*$", "ruleKey", rule3.getKey().toString())));
+ .setData(ImmutableMap.of("severity", "MAJOR", "param_format", "^[A-Z][a-zA-Z0-9]*$", "ruleId", valueOf(rule3.getId()))));
dbTester.commit();
@Test
public void return_change_with_all_fields() {
QProfileDto profile = dbTester.qualityProfiles().insert(organization);
+ RuleDefinitionDto rule1 = dbTester.rules().insert(RuleKey.of("java", "S001"));
+
Map<String, Object> data = ImmutableMap.of(
- "ruleKey", "java:S001",
+ "ruleId", valueOf(rule1.getId()),
"severity", "MINOR",
"inheritance", ActiveRule.Inheritance.INHERITED.name(),
"param_foo", "foo_value",