]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7394 Fix update of custom rule active parameters
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 2 May 2016 13:32:18 +0000 (15:32 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 3 May 2016 12:26:30 +0000 (14:26 +0200)
server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java
server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java
sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java
sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleParamDtoFunctions.java [new file with mode: 0644]

index 64b7afe59d4e102664054dc02cd3563387ecec20..a031895eadf7e928f34eb91085d629ff213142dd 100644 (file)
  */
 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<String> paramKeys = newArrayList();
 
       // Load active rules and its parameters in cache
-      Multimap<RuleDto, ActiveRuleDto> activeRules = ArrayListMultimap.create();
-      Multimap<ActiveRuleDto, ActiveRuleParamDto> 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<ActiveRuleDto, ActiveRuleParamDto> 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<ActiveRuleDto, ActiveRuleParamDto> getActiveRuleParamsByActiveRule(DbSession dbSession, RuleDto customRule) {
+    List<ActiveRuleDto> activeRuleDtos = dbClient.activeRuleDao().selectByRule(dbSession, customRule);
+    Map<Integer, ActiveRuleDto> activeRuleById = from(activeRuleDtos).uniqueIndex(ActiveRuleDtoToId.INSTANCE);
+    List<Integer> activeRuleIds = from(activeRuleDtos)
+      .transform(ActiveRuleDtoToId.INSTANCE)
+      .toList();
+    List<ActiveRuleParamDto> activeRuleParamDtos = dbClient.activeRuleDao().selectParamsByActiveRuleIds(dbSession, activeRuleIds);
+    return from(activeRuleParamDtos)
+      .index(new ActiveRuleParamToActiveRule(activeRuleById));
+  }
+
   private void deleteOrUpdateParameters(DbSession dbSession, RuleUpdate update, RuleDto customRule, List<String> paramKeys,
-    Multimap<RuleDto, ActiveRuleDto> activeRules, Multimap<ActiveRuleDto, ActiveRuleParamDto> activeRuleParams) {
+    Multimap<ActiveRuleDto, ActiveRuleParamDto> 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<ActiveRuleDto, ActiveRuleParamDto> activeRuleParamsByActiveRule){
+    from(activeRuleParamsByActiveRule.keySet())
+      .filter(new UpdateOrInsertActiveRuleParams(dbSession, dbClient, ruleParamDto, activeRuleParamsByActiveRule))
+      .toList();
+  }
+
+  private void deleteActiveRuleParams(DbSession dbSession, String key, Collection<ActiveRuleParamDto> activeRuleParamDtos){
+    from(activeRuleParamDtos)
+      .filter(new DeleteActiveRuleParams(dbSession, dbClient, key))
+      .toList();
+  }
+
+  private static class ActiveRuleParamToActiveRule implements Function<ActiveRuleParamDto, ActiveRuleDto> {
+    private final Map<Integer, ActiveRuleDto> activeRuleById;
+
+    private ActiveRuleParamToActiveRule(Map<Integer, ActiveRuleDto> activeRuleById) {
+      this.activeRuleById = activeRuleById;
+    }
+
+    @Override
+    public ActiveRuleDto apply(@Nonnull ActiveRuleParamDto input) {
+      return activeRuleById.get(input.getActiveRuleId());
+    }
+  }
+
+  private static class UpdateOrInsertActiveRuleParams implements Predicate<ActiveRuleDto> {
+    private final DbSession dbSession;
+    private final DbClient dbClient;
+    private final RuleParamDto ruleParamDto;
+    private final Multimap<ActiveRuleDto, ActiveRuleParamDto> activeRuleParams;
+
+    private UpdateOrInsertActiveRuleParams(DbSession dbSession, DbClient dbClient, RuleParamDto ruleParamDto, Multimap<ActiveRuleDto, ActiveRuleParamDto> activeRuleParams) {
+      this.dbSession = dbSession;
+      this.dbClient = dbClient;
+      this.ruleParamDto = ruleParamDto;
+      this.activeRuleParams = activeRuleParams;
+    }
+
+    @Override
+    public boolean apply(@Nonnull ActiveRuleDto activeRuleDto) {
+      Map<String, ActiveRuleParamDto> 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<ActiveRuleParamDto> {
+    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) {
index bdf2ad817b6ae74f170fa59d2a80b3dd7ad68c49..a8945a6004a18348a36bff65f69b0cd24bdfafc4 100644 (file)
@@ -471,8 +471,7 @@ public class RuleUpdaterMediumTest {
     // Verify active rule parameters has been updated
     List<ActiveRuleParamDto> 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<String, ActiveRuleParamDto> activeRuleParamsByKey = ActiveRuleParamDto.groupByKey(activeRuleParams);
     assertThat(activeRuleParamsByKey.get("regex").getValue()).isEqualTo("b.*");
     assertThat(activeRuleParamsByKey.get("message").getValue()).isEqualTo("a message");
index fd9db72143b1c8ca170acdd38b3d9bf8b426eb90..07bf2d770d638a7f76aa14490adfb1ae11ec5c8b 100644 (file)
@@ -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 (file)
index 0000000..b77279e
--- /dev/null
@@ -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<ActiveRuleParamDto, String> {
+    INSTANCE;
+
+    @Override
+    public String apply(@Nonnull ActiveRuleParamDto input) {
+      return input.getKey();
+    }
+  }
+
+}