From 116d1f01a872b83be5aedf8a700be10556c091d8 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 2 May 2016 15:32:18 +0200 Subject: [PATCH] SONAR-7394 Fix update of custom rule active parameters --- .../org/sonar/server/rule/RuleUpdater.java | 125 ++++++++++++++---- .../server/rule/RuleUpdaterMediumTest.java | 3 +- .../db/qualityprofile/ActiveRuleDao.java | 6 +- .../ActiveRuleParamDtoFunctions.java | 40 ++++++ 4 files changed, 143 insertions(+), 31 deletions(-) create mode 100644 sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleParamDtoFunctions.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java index 64b7afe59d4..a031895eadf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java @@ -19,15 +19,19 @@ */ package org.sonar.server.rule; +import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; import com.google.common.base.Strings; -import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Set; +import javax.annotation.Nonnull; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.sonar.api.rule.RuleStatus; @@ -38,13 +42,16 @@ import org.sonar.api.utils.System2; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.qualityprofile.ActiveRuleDto; +import org.sonar.db.qualityprofile.ActiveRuleDtoFunctions.ActiveRuleDtoToId; import org.sonar.db.qualityprofile.ActiveRuleParamDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleParamDto; import org.sonar.server.rule.index.RuleIndexer; import org.sonar.server.user.UserSession; +import static com.google.common.collect.FluentIterable.from; import static com.google.common.collect.Lists.newArrayList; +import static org.sonar.db.qualityprofile.ActiveRuleParamDtoFunctions.ActiveRuleDtoParamToKey; @ServerSide public class RuleUpdater { @@ -238,22 +245,25 @@ public class RuleUpdater { List paramKeys = newArrayList(); // Load active rules and its parameters in cache - Multimap activeRules = ArrayListMultimap.create(); - Multimap activeRuleParams = ArrayListMultimap.create(); - for (ActiveRuleDto activeRuleDto : dbClient.activeRuleDao().selectByRule(dbSession, customRule)) { - activeRules.put(customRule, activeRuleDto); - for (ActiveRuleParamDto activeRuleParamDto : dbClient.activeRuleDao().selectParamsByActiveRuleId(dbSession, activeRuleDto.getId())) { - activeRuleParams.put(activeRuleDto, activeRuleParamDto); - } - } - + Multimap activeRuleParamsByActiveRule = getActiveRuleParamsByActiveRule(dbSession, customRule); // Browse custom rule parameters to create, update or delete them - deleteOrUpdateParameters(dbSession, update, customRule, paramKeys, activeRules, activeRuleParams); + deleteOrUpdateParameters(dbSession, update, customRule, paramKeys, activeRuleParamsByActiveRule); } } + private Multimap getActiveRuleParamsByActiveRule(DbSession dbSession, RuleDto customRule) { + List activeRuleDtos = dbClient.activeRuleDao().selectByRule(dbSession, customRule); + Map activeRuleById = from(activeRuleDtos).uniqueIndex(ActiveRuleDtoToId.INSTANCE); + List activeRuleIds = from(activeRuleDtos) + .transform(ActiveRuleDtoToId.INSTANCE) + .toList(); + List activeRuleParamDtos = dbClient.activeRuleDao().selectParamsByActiveRuleIds(dbSession, activeRuleIds); + return from(activeRuleParamDtos) + .index(new ActiveRuleParamToActiveRule(activeRuleById)); + } + private void deleteOrUpdateParameters(DbSession dbSession, RuleUpdate update, RuleDto customRule, List paramKeys, - Multimap activeRules, Multimap activeRuleParams) { + Multimap activeRuleParamsByActiveRule) { for (RuleParamDto ruleParamDto : dbClient.ruleDao().selectRuleParamsByRuleKey(dbSession, update.getRuleKey())) { String key = ruleParamDto.getName(); String value = Strings.emptyToNull(update.parameter(key)); @@ -264,34 +274,93 @@ public class RuleUpdater { if (value != null) { // Update linked active rule params or create new one - for (ActiveRuleDto activeRuleDto : activeRules.get(customRule)) { - for (ActiveRuleParamDto activeRuleParamDto : activeRuleParams.get(activeRuleDto)) { - if (activeRuleParamDto.getKey().equals(key)) { - dbClient.activeRuleDao().updateParam(dbSession, activeRuleDto, activeRuleParamDto.setValue(value)); - } else { - dbClient.activeRuleDao().insertParam(dbSession, activeRuleDto, ActiveRuleParamDto.createFor(ruleParamDto).setValue(value)); - } - } - } + updateOrInsertActiveRuleParams(dbSession, ruleParamDto, activeRuleParamsByActiveRule); } else { // Delete linked active rule params - for (ActiveRuleDto activeRuleDto : activeRules.get(customRule)) { - for (ActiveRuleParamDto activeRuleParamDto : activeRuleParams.get(activeRuleDto)) { - if (activeRuleParamDto.getKey().equals(key)) { - dbClient.activeRuleDao().deleteParam(dbSession, activeRuleDto, activeRuleParamDto); - } - } - } + deleteActiveRuleParams(dbSession, key, activeRuleParamsByActiveRule.values()); } paramKeys.add(key); } } + private void updateOrInsertActiveRuleParams(DbSession dbSession, RuleParamDto ruleParamDto, Multimap activeRuleParamsByActiveRule){ + from(activeRuleParamsByActiveRule.keySet()) + .filter(new UpdateOrInsertActiveRuleParams(dbSession, dbClient, ruleParamDto, activeRuleParamsByActiveRule)) + .toList(); + } + + private void deleteActiveRuleParams(DbSession dbSession, String key, Collection activeRuleParamDtos){ + from(activeRuleParamDtos) + .filter(new DeleteActiveRuleParams(dbSession, dbClient, key)) + .toList(); + } + + private static class ActiveRuleParamToActiveRule implements Function { + private final Map activeRuleById; + + private ActiveRuleParamToActiveRule(Map activeRuleById) { + this.activeRuleById = activeRuleById; + } + + @Override + public ActiveRuleDto apply(@Nonnull ActiveRuleParamDto input) { + return activeRuleById.get(input.getActiveRuleId()); + } + } + + private static class UpdateOrInsertActiveRuleParams implements Predicate { + private final DbSession dbSession; + private final DbClient dbClient; + private final RuleParamDto ruleParamDto; + private final Multimap activeRuleParams; + + private UpdateOrInsertActiveRuleParams(DbSession dbSession, DbClient dbClient, RuleParamDto ruleParamDto, Multimap activeRuleParams) { + this.dbSession = dbSession; + this.dbClient = dbClient; + this.ruleParamDto = ruleParamDto; + this.activeRuleParams = activeRuleParams; + } + + @Override + public boolean apply(@Nonnull ActiveRuleDto activeRuleDto) { + Map activeRuleParamByKey = from(activeRuleParams.get(activeRuleDto)) + .uniqueIndex(ActiveRuleDtoParamToKey.INSTANCE); + ActiveRuleParamDto activeRuleParamDto = activeRuleParamByKey.get(ruleParamDto.getName()); + if (activeRuleParamDto != null) { + dbClient.activeRuleDao().updateParam(dbSession, activeRuleDto, activeRuleParamDto.setValue(ruleParamDto.getDefaultValue())); + } else { + dbClient.activeRuleDao().insertParam(dbSession, activeRuleDto, ActiveRuleParamDto.createFor(ruleParamDto).setValue(ruleParamDto.getDefaultValue())); + } + return true; + } + } + + private static class DeleteActiveRuleParams implements Predicate { + private final DbSession dbSession; + private final DbClient dbClient; + private final String key; + + public DeleteActiveRuleParams(DbSession dbSession, DbClient dbClient, String key) { + this.dbSession = dbSession; + this.dbClient = dbClient; + this.key = key; + } + + @Override + public boolean apply(@Nonnull ActiveRuleParamDto activeRuleParamDto) { + if (activeRuleParamDto.getKey().equals(key)) { + dbClient.activeRuleDao().deleteParamById(dbSession, activeRuleParamDto.getId()); + } + return true; + } + } + /** * Data loaded before update */ private static class Context { private RuleDto rule; + } private void update(DbSession session, RuleDto rule) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java index bdf2ad817b6..a8945a6004a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java @@ -471,8 +471,7 @@ public class RuleUpdaterMediumTest { // Verify active rule parameters has been updated List activeRuleParams = db.activeRuleDao().selectParamsByActiveRuleId(dbSession, activeRuleDto.getId()); - // FIXME why 4 parameters are returned ??? (This issue already exists in 5.4) - // assertThat(activeRuleParams).hasSize(2); + assertThat(activeRuleParams).hasSize(2); Map activeRuleParamsByKey = ActiveRuleParamDto.groupByKey(activeRuleParams); assertThat(activeRuleParamsByKey.get("regex").getValue()).isEqualTo("b.*"); assertThat(activeRuleParamsByKey.get("message").getValue()).isEqualTo("a message"); diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java index fd9db72143b..07bf2d770d6 100644 --- a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java @@ -150,7 +150,11 @@ public class ActiveRuleDao implements Dao { public void deleteParam(DbSession session, ActiveRuleDto activeRule, ActiveRuleParamDto activeRuleParam) { Preconditions.checkNotNull(activeRule.getId(), ACTIVE_RULE_IS_NOT_PERSISTED); Preconditions.checkNotNull(activeRuleParam.getId(), ACTIVE_RULE_PARAM_IS_NOT_PERSISTED); - mapper(session).deleteParameter(activeRuleParam.getId()); + deleteParamById(session, activeRuleParam.getId()); + } + + public void deleteParamById(DbSession session, int id){ + mapper(session).deleteParameter(id); } public void deleteParamByKeyAndName(DbSession session, ActiveRuleKey key, String param) { diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleParamDtoFunctions.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleParamDtoFunctions.java new file mode 100644 index 00000000000..b77279ea656 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleParamDtoFunctions.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.qualityprofile; + +import com.google.common.base.Function; +import javax.annotation.Nonnull; + +public class ActiveRuleParamDtoFunctions { + + private ActiveRuleParamDtoFunctions() { + // Only static methods + } + + public enum ActiveRuleDtoParamToKey implements Function { + INSTANCE; + + @Override + public String apply(@Nonnull ActiveRuleParamDto input) { + return input.getKey(); + } + } + +} -- 2.39.5