]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7330 DefaultRuleFinder is now using only RuleDao
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 22 Feb 2016 14:29:18 +0000 (15:29 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 29 Feb 2016 12:26:54 +0000 (13:26 +0100)
server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRuleFinder.java
server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderMediumTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderTest.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java
sonar-db/src/main/java/org/sonar/db/rule/RuleMapper.java
sonar-db/src/main/resources/org/sonar/db/rule/RuleMapper.xml
sonar-db/src/test/java/org/sonar/db/rule/RuleDaoTest.java
sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/shared.xml

index 21306469fba452c674c26a44141907faa5c8d55d..d6aaa74bcfc2006fe6f185a5607dcd1c2fa70b59 100644 (file)
  */
 package org.sonar.server.rule;
 
-import com.google.common.collect.ImmutableList;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableListMultimap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rules.RuleFinder;
 import org.sonar.api.rules.RulePriority;
-import org.sonar.server.rule.index.RuleDoc;
-import org.sonar.server.rule.index.RuleIndex;
-import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.search.Result;
-
-import javax.annotation.CheckForNull;
-
-import java.util.Collection;
-import java.util.List;
-import org.sonar.server.user.UserSession;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.rule.RuleDao;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.db.rule.RuleParamDto;
+import org.sonar.markdown.Markdown;
 
 import static com.google.common.collect.Lists.newArrayList;
 
@@ -44,22 +48,27 @@ import static com.google.common.collect.Lists.newArrayList;
  */
 public class DefaultRuleFinder implements RuleFinder {
 
-  private final RuleIndex index;
-  private final UserSession userSession;
+  private final DbClient dbClient;
+  private final RuleDao ruleDao;
 
-  public DefaultRuleFinder(IndexClient indexes, UserSession userSession) {
-    this.userSession = userSession;
-    this.index = indexes.get(RuleIndex.class);
+  public DefaultRuleFinder(DbClient dbClient) {
+    this.dbClient = dbClient;
+    this.ruleDao = dbClient.ruleDao();
   }
 
   @Override
   @CheckForNull
   public org.sonar.api.rules.Rule findById(int ruleId) {
-    Rule rule = index.getById(ruleId);
-    if (rule != null && rule.status() != RuleStatus.REMOVED) {
-      return toRule(rule);
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      Optional<RuleDto> rule = ruleDao.selectById(ruleId, dbSession);
+      if (rule.isPresent() && rule.get().getStatus() != RuleStatus.REMOVED) {
+        return toRule(rule.get(), ruleDao.selectRuleParamsByRuleKey(dbSession, rule.get().getKey()));
+      }
+      return null;
+    } finally {
+      dbClient.closeSession(dbSession);
     }
-    return null;
   }
 
   public Collection<org.sonar.api.rules.Rule> findByIds(Collection<Integer> ruleIds) {
@@ -67,10 +76,14 @@ public class DefaultRuleFinder implements RuleFinder {
     if (ruleIds.isEmpty()) {
       return rules;
     }
-    for (Rule rule : index.getByIds(ruleIds)) {
-      rules.add(toRule(rule));
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      List<RuleDto> ruleDtos = ruleDao.selectByIds(dbSession, new ArrayList<>(ruleIds));
+      return convertToRuleApi(dbSession, ruleDtos);
+    } finally {
+      dbClient.closeSession(dbSession);
     }
-    return rules;
   }
 
   public Collection<org.sonar.api.rules.Rule> findByKeys(Collection<RuleKey> ruleKeys) {
@@ -78,20 +91,29 @@ public class DefaultRuleFinder implements RuleFinder {
     if (ruleKeys.isEmpty()) {
       return rules;
     }
-    for (Rule rule : index.getByKeys(ruleKeys)) {
-      rules.add(toRule(rule));
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      List<RuleDto> ruleDtos = ruleDao.selectByKeys(dbSession, new ArrayList<>(ruleKeys));
+      return convertToRuleApi(dbSession, ruleDtos);
+    } finally {
+      dbClient.closeSession(dbSession);
     }
-    return rules;
   }
 
   @Override
   @CheckForNull
   public org.sonar.api.rules.Rule findByKey(RuleKey key) {
-    Rule rule = index.getNullableByKey(key);
-    if (rule != null && rule.status() != RuleStatus.REMOVED) {
-      return toRule(rule);
-    } else {
-      return null;
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      Optional<RuleDto> rule = ruleDao.selectByKey(dbSession, key);
+      if (rule.isPresent() && rule.get().getStatus() != RuleStatus.REMOVED) {
+        return toRule(rule.get(), ruleDao.selectRuleParamsByRuleKey(dbSession, rule.get().getKey()));
+      } else {
+        return null;
+      }
+    } finally {
+      dbClient.closeSession(dbSession);
     }
   }
 
@@ -103,61 +125,97 @@ public class DefaultRuleFinder implements RuleFinder {
 
   @Override
   public final org.sonar.api.rules.Rule find(org.sonar.api.rules.RuleQuery query) {
-    Result<Rule> result = index.search(toQuery(query), new QueryContext(userSession));
-    if (!result.getHits().isEmpty()) {
-      return toRule(result.getHits().get(0));
-    } else {
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      List<RuleDto> rules = ruleDao.selectByQuery(dbSession, query);
+      if (!rules.isEmpty()) {
+        RuleDto rule = rules.get(0);
+        return toRule(rule, ruleDao.selectRuleParamsByRuleKey(dbSession, rule.getKey()));
+      }
       return null;
+    } finally {
+      dbClient.closeSession(dbSession);
     }
   }
 
   @Override
   public final Collection<org.sonar.api.rules.Rule> findAll(org.sonar.api.rules.RuleQuery query) {
-    List<org.sonar.api.rules.Rule> rules = newArrayList();
-    for (Rule rule : index.search(toQuery(query), new QueryContext(userSession)).getHits()) {
-      rules.add(toRule(rule));
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      List<RuleDto> rules = ruleDao.selectByQuery(dbSession, query);
+      if (rules.isEmpty()) {
+        return Collections.emptyList();
+      }
+      return convertToRuleApi(dbSession, rules);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private Collection<org.sonar.api.rules.Rule> convertToRuleApi(DbSession dbSession, List<RuleDto> ruleDtos) {
+    List<org.sonar.api.rules.Rule> rules = new ArrayList<>();
+    List<RuleKey> ruleKeys = FluentIterable.from(ruleDtos).transform(RuleDtoToKey.INSTANCE).toList();
+    List<RuleParamDto> ruleParamDtos = ruleDao.selectRuleParamsByRuleKeys(dbSession, ruleKeys);
+    ImmutableListMultimap<Integer, RuleParamDto> ruleParamByRuleId = FluentIterable.from(ruleParamDtos).index(RuleParamDtoToRuleId.INSTANCE);
+    for (RuleDto rule : ruleDtos) {
+      rules.add(toRule(rule, ruleParamByRuleId.get(rule.getId())));
     }
     return rules;
   }
 
-  private org.sonar.api.rules.Rule toRule(Rule rule) {
+  private org.sonar.api.rules.Rule toRule(RuleDto rule, List<RuleParamDto> params) {
+    String severity = rule.getSeverityString();
+    String description = rule.getDescription();
+    RuleDto.Format descriptionFormat = rule.getDescriptionFormat();
+
     org.sonar.api.rules.Rule apiRule = new org.sonar.api.rules.Rule();
     apiRule
-      .setName(rule.name())
-      .setLanguage(rule.language())
-      .setKey(rule.key().rule())
-      .setConfigKey(rule.internalKey())
+      .setName(rule.getName())
+      .setLanguage(rule.getLanguage())
+      .setKey(rule.getRuleKey())
+      .setConfigKey(rule.getConfigKey())
       .setIsTemplate(rule.isTemplate())
-      .setCreatedAt(rule.createdAt())
-      .setUpdatedAt(rule.updatedAt())
-      .setDescription(rule.htmlDescription())
-      .setRepositoryKey(rule.key().repository())
-      .setSeverity(rule.severity() != null ? RulePriority.valueOf(rule.severity()) : null)
-      .setStatus(rule.status().name())
-      .setTags(rule.tags().toArray(new String[rule.tags().size()]))
-      .setId(((RuleDoc) rule).id());
+      .setCreatedAt(new Date(rule.getCreatedAtInMs()))
+      .setUpdatedAt(new Date(rule.getUpdatedAtInMs()))
+      .setRepositoryKey(rule.getRepositoryKey())
+      .setSeverity(severity != null ? RulePriority.valueOf(severity) : null)
+      .setStatus(rule.getStatus().name())
+      .setTags(rule.getTags().toArray(new String[rule.getTags().size()]))
+      .setId((rule.getId()));
+    if (description != null && descriptionFormat != null) {
+      if (RuleDto.Format.HTML.equals(descriptionFormat)) {
+        apiRule.setDescription(description);
+      } else {
+        apiRule.setDescription(Markdown.convertToHtml(description));
+      }
+    }
 
     List<org.sonar.api.rules.RuleParam> apiParams = newArrayList();
-    for (RuleParam param : rule.params()) {
-      apiParams.add(new org.sonar.api.rules.RuleParam(apiRule, param.key(), param.description(), param.type().type())
-        .setDefaultValue(param.defaultValue()));
+    for (RuleParamDto param : params) {
+      apiParams.add(new org.sonar.api.rules.RuleParam(apiRule, param.getName(), param.getDescription(), param.getType())
+        .setDefaultValue(param.getDefaultValue()));
     }
     apiRule.setParams(apiParams);
 
     return apiRule;
   }
 
-  private RuleQuery toQuery(org.sonar.api.rules.RuleQuery apiQuery) {
-    RuleQuery query = new RuleQuery();
-    if (apiQuery.getConfigKey() != null) {
-      query.setInternalKey(apiQuery.getConfigKey());
-    }
-    if (apiQuery.getKey() != null) {
-      query.setRuleKey(apiQuery.getKey());
+  private enum RuleDtoToKey implements Function<RuleDto, RuleKey> {
+    INSTANCE;
+
+    @Override
+    public RuleKey apply(@Nonnull RuleDto input) {
+      return input.getKey();
     }
-    if (apiQuery.getRepositoryKey() != null) {
-      query.setRepositories(ImmutableList.of(apiQuery.getRepositoryKey()));
+  }
+
+  private enum RuleParamDtoToRuleId implements Function<RuleParamDto, Integer> {
+    INSTANCE;
+
+    @Override
+    public Integer apply(@Nonnull RuleParamDto input) {
+      return input.getRuleId();
     }
-    return query;
   }
+
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderMediumTest.java
deleted file mode 100644 (file)
index 4048132..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * 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.server.rule;
-
-import java.util.Collections;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleQuery;
-import org.sonar.db.DbSession;
-import org.sonar.db.rule.RuleDto;
-import org.sonar.db.rule.RuleTesting;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.assertj.core.api.Assertions.assertThat;
-
-@Deprecated
-public class DefaultRuleFinderMediumTest {
-
-  @ClassRule
-  public static ServerTester tester = new ServerTester();
-  @org.junit.Rule
-  public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
-
-  private DbClient dbClient;
-  private DefaultRuleFinder finder;
-  private DbSession session;
-
-  @Before
-  public void setUp() {
-    finder = tester.get(DefaultRuleFinder.class);
-    dbClient = tester.get(DbClient.class);
-    session = dbClient.openSession(false);
-  }
-
-  /**
-   * Testing with ids required data to be identical to all tests
-   */
-  @BeforeClass
-  public static void setupClass() {
-    tester.clearDbAndIndexes();
-    DbSession session = tester.get(DbClient.class).openSession(false);
-    tester.get(DbClient.class).deprecatedRuleDao().insert(session,
-      new RuleDto()
-        .setName("Check Header")
-        .setConfigKey("Checker/Treewalker/HeaderCheck")
-        .setRuleKey("com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck")
-        .setRepositoryKey("checkstyle")
-        .setSeverity(4)
-        .setStatus(RuleStatus.READY),
-      new RuleDto()
-        .setName("Disabled checked")
-        .setConfigKey("Checker/Treewalker/DisabledCheck")
-        .setRuleKey("DisabledCheck")
-        .setRepositoryKey("checkstyle")
-        .setSeverity(4)
-        .setStatus(RuleStatus.REMOVED),
-      new RuleDto()
-        .setName("Check Annotation")
-        .setConfigKey("Checker/Treewalker/AnnotationUseStyleCheck")
-        .setRuleKey("com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck")
-        .setRepositoryKey("checkstyle")
-        .setSeverity(4)
-        .setStatus(RuleStatus.READY),
-      new RuleDto()
-        .setName("Call Super First")
-        .setConfigKey("rulesets/android.xml/CallSuperFirst")
-        .setRuleKey("CallSuperFirst")
-        .setRepositoryKey("pmd")
-        .setSeverity(2)
-        .setStatus(RuleStatus.READY),
-      RuleTesting.newManualRule("Manual_Rule").setName("Manual Rule")
-      );
-    session.commit();
-    session.close();
-  }
-
-  @After
-  public void after() {
-    session.close();
-  }
-
-  @Test
-  public void should_success_finder_wrap() {
-
-    // has Id
-    assertThat(finder.findById(1).getId()).isEqualTo(1);
-
-    // should_find_by_id
-    assertThat(finder.findById(3).getConfigKey()).isEqualTo("Checker/Treewalker/AnnotationUseStyleCheck");
-
-    // should_not_find_disabled_rule_by_id
-    assertThat(finder.findById(2)).isNull();
-
-    // should_find_by_ids
-    assertThat(finder.findByIds(newArrayList(2, 3))).hasSize(2);
-
-    // should_find_by_key
-    Rule rule = finder.findByKey("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck");
-    assertThat(rule).isNotNull();
-    assertThat(rule.getKey()).isEqualTo(("com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"));
-    assertThat(rule.isEnabled()).isTrue();
-
-    // find_should_return_null_if_no_results
-    assertThat(finder.findByKey("checkstyle", "unknown")).isNull();
-    assertThat(finder.find(RuleQuery.create().withRepositoryKey("checkstyle").withConfigKey("unknown"))).isNull();
-
-    // find_repository_rules
-    assertThat(finder.findAll(RuleQuery.create().withRepositoryKey("checkstyle"))).hasSize(2);
-
-    // find_all_enabled
-    assertThat(finder.findAll(RuleQuery.create())).extracting("id").containsOnly(1, 3, 4, 5);
-    assertThat(finder.findAll(RuleQuery.create())).hasSize(4);
-
-    // do_not_find_disabled_rules
-    assertThat(finder.findByKey("checkstyle", "DisabledCheck")).isNull();
-
-    // do_not_find_unknown_rules
-    assertThat(finder.findAll(RuleQuery.create().withRepositoryKey("unknown_repository"))).isEmpty();
-
-    // should_find_by_ids_empty
-    tester.clearDbAndIndexes();
-    assertThat(finder.findByIds(Collections.<Integer>emptyList())).isEmpty();
-  }
-
-  @Test
-  public void find_ids_including_removed_rule() {
-    // find rule with id 2 is REMOVED
-    assertThat(finder.findByIds(newArrayList(2))).hasSize(1);
-  }
-
-  @Test
-  public void find_keys_including_removed_rule() {
-    assertThat(finder.findByKeys(newArrayList(RuleKey.of("checkstyle", "DisabledCheck")))).hasSize(1);
-
-    // find rule with id 2 is REMOVED
-    assertThat(finder.findByKeys(newArrayList(RuleKey.of("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck")))).hasSize(1);
-
-    assertThat(finder.findByKeys(Collections.<RuleKey>emptyList())).isEmpty();
-  }
-
-  @Test
-  public void find_id_return_null_on_removed_rule() {
-    // find rule with id 2 is REMOVED
-    assertThat(finder.findById(2)).isNull();
-  }
-
-  @Test
-  public void find_all_not_include_removed_rule() {
-    // find rule with id 2 is REMOVED
-    assertThat(finder.findAll(RuleQuery.create())).extracting("id").containsOnly(1, 3, 4, 5);
-  }
-
-  @Test
-  public void find_manual_rule() {
-    // find by id
-    assertThat(finder.findById(5)).isNotNull();
-
-    // find by key
-    Rule rule = finder.findByKey("manual", "Manual_Rule");
-    assertThat(rule).isNotNull();
-    assertThat(rule.isEnabled()).isTrue();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderTest.java
new file mode 100644 (file)
index 0000000..c1fe6eb
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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.server.rule;
+
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleQuery;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.db.rule.RuleTesting;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultRuleFinderTest {
+
+  @org.junit.Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  DbClient dbClient = dbTester.getDbClient();
+  DbSession session = dbTester.getSession();
+
+  RuleDto rule1 = new RuleDto()
+    .setName("Check Header")
+    .setConfigKey("Checker/Treewalker/HeaderCheck")
+    .setRuleKey("com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck")
+    .setRepositoryKey("checkstyle")
+    .setSeverity(4)
+    .setStatus(RuleStatus.READY);
+
+  RuleDto rule2 = new RuleDto()
+    .setName("Disabled checked")
+    .setConfigKey("Checker/Treewalker/DisabledCheck")
+    .setRuleKey("DisabledCheck")
+    .setRepositoryKey("checkstyle")
+    .setSeverity(4)
+    .setStatus(RuleStatus.REMOVED);
+
+  RuleDto rule3 = new RuleDto()
+    .setName("Check Annotation")
+    .setConfigKey("Checker/Treewalker/AnnotationUseStyleCheck")
+    .setRuleKey("com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck")
+    .setRepositoryKey("checkstyle")
+    .setSeverity(4)
+    .setStatus(RuleStatus.READY);
+
+  RuleDto rule4 = new RuleDto()
+    .setName("Call Super First")
+    .setConfigKey("rulesets/android.xml/CallSuperFirst")
+    .setRuleKey("CallSuperFirst")
+    .setRepositoryKey("pmd")
+    .setSeverity(2)
+    .setStatus(RuleStatus.READY);
+
+  RuleDto manualRule = RuleTesting.newManualRule("Manual_Rule").setName("Manual Rule");
+
+  DefaultRuleFinder underTest = new DefaultRuleFinder(dbClient);
+
+  @Before
+  public void setup() {
+    dbClient.ruleDao().insert(session, rule1);
+    dbClient.ruleDao().insert(session, rule2);
+    dbClient.ruleDao().insert(session, rule3);
+    dbClient.ruleDao().insert(session, rule4);
+    dbClient.ruleDao().insert(session, manualRule);
+    session.commit();
+  }
+
+  @Test
+  public void should_success_finder_wrap() {
+    // has Id
+    assertThat(underTest.findById(rule1.getId()).getId()).isEqualTo(rule1.getId());
+
+    // should_find_by_id
+    assertThat(underTest.findById(rule3.getId()).getConfigKey()).isEqualTo("Checker/Treewalker/AnnotationUseStyleCheck");
+
+    // should_not_find_disabled_rule_by_id
+    assertThat(underTest.findById(rule2.getId())).isNull();
+
+    // should_find_by_ids
+    assertThat(underTest.findByIds(newArrayList(rule2.getId(), rule3.getId()))).hasSize(2);
+
+    // should_find_by_key
+    Rule rule = underTest.findByKey("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck");
+    assertThat(rule).isNotNull();
+    assertThat(rule.getKey()).isEqualTo(("com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"));
+    assertThat(rule.isEnabled()).isTrue();
+
+    // find_should_return_null_if_no_results
+    assertThat(underTest.findByKey("checkstyle", "unknown")).isNull();
+    assertThat(underTest.find(RuleQuery.create().withRepositoryKey("checkstyle").withConfigKey("unknown"))).isNull();
+
+    // find_repository_rules
+    assertThat(underTest.findAll(RuleQuery.create().withRepositoryKey("checkstyle"))).hasSize(2);
+
+    // find_all_enabled
+    assertThat(underTest.findAll(RuleQuery.create())).extracting("id").containsOnly(rule1.getId(), rule3.getId(), rule4.getId(), manualRule.getId());
+    assertThat(underTest.findAll(RuleQuery.create())).hasSize(4);
+
+    // do_not_find_disabled_rules
+    assertThat(underTest.findByKey("checkstyle", "DisabledCheck")).isNull();
+
+    // do_not_find_unknown_rules
+    assertThat(underTest.findAll(RuleQuery.create().withRepositoryKey("unknown_repository"))).isEmpty();
+  }
+
+  @Test
+  public void find_ids_including_removed_rule() {
+    // find rule with id 2 is REMOVED
+    assertThat(underTest.findByIds(newArrayList(rule2.getId()))).hasSize(1);
+  }
+
+  @Test
+  public void find_keys_including_removed_rule() {
+    assertThat(underTest.findByKeys(newArrayList(RuleKey.of("checkstyle", "DisabledCheck")))).hasSize(1);
+
+    // find rule with id 2 is REMOVED
+    assertThat(underTest.findByKeys(newArrayList(RuleKey.of("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck")))).hasSize(1);
+
+    assertThat(underTest.findByKeys(Collections.<RuleKey>emptyList())).isEmpty();
+  }
+
+  @Test
+  public void find_id_return_null_on_removed_rule() {
+    // find rule with id 2 is REMOVED
+    assertThat(underTest.findById(rule2.getId())).isNull();
+  }
+
+  @Test
+  public void find_all_not_include_removed_rule() {
+    // find rule with id 2 is REMOVED
+    assertThat(underTest.findAll(RuleQuery.create())).extracting("id").containsOnly(rule1.getId(), rule3.getId(), rule4.getId(), manualRule.getId());
+  }
+
+  @Test
+  public void find_manual_rule() {
+    // find by id
+    assertThat(underTest.findById(manualRule.getId())).isNotNull();
+
+    // find by key
+    Rule rule = underTest.findByKey("manual", "Manual_Rule");
+    assertThat(rule).isNotNull();
+    assertThat(rule.isEnabled()).isTrue();
+  }
+
+}
index 3c79e9dfc992288a29790208f5406700444cb7ba..9eb3e3893ddeb1c2b5f8f83c528efaa016ff54ce 100644 (file)
@@ -23,15 +23,14 @@ import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import java.util.List;
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import org.apache.ibatis.session.ResultHandler;
 import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RuleQuery;
 import org.sonar.db.Dao;
 import org.sonar.db.DatabaseUtils;
 import org.sonar.db.DbSession;
 import org.sonar.db.RowNotFoundException;
 
-import static java.util.Collections.emptyList;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.sonar.db.DatabaseUtils.executeLargeInputs;
 
@@ -58,16 +57,8 @@ public class RuleDao implements Dao {
     return Optional.fromNullable(mapper(session).selectById(id));
   }
 
-  public List<RuleDto> selectByIds(final DbSession dbSession, List<Integer> ids) {
-    if (ids.isEmpty()) {
-      return emptyList();
-    }
-    return DatabaseUtils.executeLargeInputs(ids, new Function<List<Integer>, List<RuleDto>>() {
-      @Override
-      public List<RuleDto> apply(@Nullable List<Integer> input) {
-        return mapper(dbSession).selectByIds(input);
-      }
-    });
+  public List<RuleDto> selectByIds(DbSession session, List<Integer> ids) {
+    return executeLargeInputs(ids, new IdToDto(mapper(session)));
   }
 
   /**
@@ -94,6 +85,10 @@ public class RuleDao implements Dao {
     return mapper(session).selectAll();
   }
 
+  public List<RuleDto> selectByQuery(DbSession session, RuleQuery ruleQuery){
+    return mapper(session).selectByQuery(ruleQuery);
+  }
+
   public void insert(DbSession session, RuleDto dto) {
     mapper(session).insert(dto);
   }
@@ -119,6 +114,19 @@ public class RuleDao implements Dao {
     }
   }
 
+  private static class IdToDto implements Function<List<Integer>, List<RuleDto>> {
+    private final RuleMapper mapper;
+
+    private IdToDto(RuleMapper mapper) {
+      this.mapper = mapper;
+    }
+
+    @Override
+    public List<RuleDto> apply(@Nonnull List<Integer> partitionOfIds) {
+      return mapper.selectByIds(partitionOfIds);
+    }
+  }
+
   /**
    * RuleParams
    */
@@ -127,16 +135,12 @@ public class RuleDao implements Dao {
     return mapper(session).selectParamsByRuleKey(key);
   }
 
-  public List<RuleParamDto> selectRuleParamsByRuleIds(final DbSession dbSession, List<Integer> ruleIds) {
-    if (ruleIds.isEmpty()) {
-      return emptyList();
-    }
-    return DatabaseUtils.executeLargeInputs(ruleIds, new Function<List<Integer>, List<RuleParamDto>>() {
-      @Override
-      public List<RuleParamDto> apply(@Nonnull List<Integer> input) {
-        return mapper(dbSession).selectParamsByRuleIds(input);
-      }
-    });
+  public List<RuleParamDto> selectRuleParamsByRuleKeys(DbSession session, List<RuleKey> ruleKeys) {
+    return executeLargeInputs(ruleKeys, new KeyToRuleParamDto(mapper(session)));
+  }
+
+  public List<RuleParamDto> selectRuleParamsByRuleIds(DbSession dbSession, List<Integer> ruleIds) {
+    return DatabaseUtils.executeLargeInputs(ruleIds, new IdToRuleParamDto(mapper(dbSession)));
   }
 
   public void insertRuleParam(DbSession session, RuleDto rule, RuleParamDto param) {
@@ -157,4 +161,30 @@ public class RuleDao implements Dao {
     mapper(session).deleteParameter(ruleParameterId);
   }
 
+  private static class KeyToRuleParamDto implements Function<List<RuleKey>, List<RuleParamDto>> {
+    private final RuleMapper mapper;
+
+    private KeyToRuleParamDto(RuleMapper mapper) {
+      this.mapper = mapper;
+    }
+
+    @Override
+    public List<RuleParamDto> apply(@Nonnull List<RuleKey> partitionOfKeys) {
+      return mapper.selectParamsByRuleKeys(partitionOfKeys);
+    }
+  }
+
+  private static class IdToRuleParamDto implements Function<List<Integer>, List<RuleParamDto>> {
+    private final RuleMapper mapper;
+
+    private IdToRuleParamDto(RuleMapper mapper) {
+      this.mapper = mapper;
+    }
+
+    @Override
+    public List<RuleParamDto> apply(@Nonnull List<Integer> partitionOfIds) {
+      return mapper.selectParamsByRuleIds(partitionOfIds);
+    }
+  }
 }
+
index 6471993d00cba77281f0fca494618328f75ec842..f2bc49ffb0c40a216944641f683d9641e4966ce6 100644 (file)
@@ -25,6 +25,7 @@ import javax.annotation.Nullable;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.session.ResultHandler;
 import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RuleQuery;
 
 public interface RuleMapper {
 
@@ -42,7 +43,7 @@ public interface RuleMapper {
 
   RuleDto selectById(long id);
 
-  List<RuleDto> selectByIds(@Param("ruleIds") List<Integer> ids);
+  List<RuleDto> selectByIds(@Param("ids") List<Integer> ids);
 
   RuleDto selectByKey(RuleKey ruleKey);
 
@@ -50,6 +51,8 @@ public interface RuleMapper {
 
   RuleDto selectByName(String name);
 
+  List<RuleDto> selectByQuery(@Param("query") RuleQuery ruleQuery);
+
   void update(RuleDto rule);
 
   void batchInsert(RuleDto rule);
@@ -62,6 +65,8 @@ public interface RuleMapper {
 
   List<RuleParamDto> selectParamsByRuleKey(RuleKey ruleKey);
 
+  List<RuleParamDto> selectParamsByRuleKeys(@Param("ruleKeys") List<RuleKey> ruleKeys);
+
   RuleParamDto selectParamByRuleAndKey(@Param("ruleId") Integer ruleId, @Param("key") String key);
 
   void insertParameter(RuleParamDto param);
index d34b00c4fe789baeef6c867cb6abeaa57f3d84a9..3673dc55619bc3e47e42b0bdb9fb58ca48803553 100644 (file)
     from rules r WHERE r.id=#{id}
   </select>
 
-  <select id="selectByIds" parameterType="Integer" resultType="Rule">
-    select
+  <select id="selectByIds" parameterType="map" resultType="Rule">
+    SELECT
     <include refid="selectColumns"/>
-    from rules r WHERE r.id in
-    <foreach collection="ruleIds" index="index" item="id" open="(" separator="," close=")">
-      #{id}
+    FROM rules r
+    WHERE
+    <foreach collection="ids" index="index" item="id" open="" separator=" or " close="">
+      r.id=#{id}
     </foreach>
   </select>
 
     where (r.characteristic_id=#{subCharacteristicId} or r.default_characteristic_id=#{subCharacteristicId})
   </select>
 
+  <select id="selectByQuery" parameterType="map" resultType="Rule">
+    SELECT
+    <include refid="selectColumns"/>
+    FROM rules r
+    <where>
+      AND r.status != 'REMOVED'
+      <if test="query.repositoryKey!=null">
+        AND r.plugin_name = #{query.repositoryKey}
+      </if>
+      <if test="query.key!=null">
+        AND r.plugin_rule_key = #{query.key}
+      </if>
+      <if test="query.configKey!=null">
+        AND r.plugin_config_key = #{query.configKey}
+      </if>
+    </where>
+    ORDER BY r.updated_at_ms DESC
+  </select>
+
   <update id="update" parameterType="Rule">
     UPDATE rules SET
     plugin_rule_key=#{ruleKey},
     AND r.plugin_name=#{repository} AND r.plugin_rule_key=#{rule}
   </select>
 
+  <select id="selectParamsByRuleKeys" resultType="RuleParam" parameterType="map">
+    SELECT
+    <include refid="paramColumns"/>
+    FROM rules_parameters p
+    INNER JOIN rules r ON r.id=p.rule_id
+    WHERE
+    <foreach collection="ruleKeys" index="index" item="ruleKey" open="" separator=" or " close="">
+      (r.plugin_name=#{ruleKey.repository} AND r.plugin_rule_key=#{ruleKey.rule})
+    </foreach>
+  </select>
+
   <select id="selectParamByRuleAndKey" resultType="RuleParam">
     SELECT
     <include refid="paramColumns"/>
index 4a09e16219afde3ac4cc4b9dccb7cc767bea995b..28208807e43c81e71d641b80eaa6353b6f50bdd8 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.db.rule;
 import com.google.common.base.Optional;
 import com.google.common.collect.Iterables;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import org.apache.ibatis.session.ResultContext;
@@ -33,6 +34,7 @@ import org.junit.rules.ExpectedException;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleQuery;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
@@ -41,6 +43,7 @@ import org.sonar.db.RowNotFoundException;
 import org.sonar.test.DbTests;
 
 import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.guava.api.Assertions.assertThat;
 
@@ -76,6 +79,17 @@ public class RuleDaoTest {
     assertThat(ruleDtoOptional.get().getId()).isEqualTo(1);
   }
 
+  @Test
+  public void selectByIds() {
+    dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+    assertThat(underTest.selectByIds(dbTester.getSession(), asList(1))).hasSize(1);
+    assertThat(underTest.selectByIds(dbTester.getSession(), asList(1,2))).hasSize(2);
+    assertThat(underTest.selectByIds(dbTester.getSession(), asList(1,2,3))).hasSize(2);
+
+    assertThat(underTest.selectByIds(dbTester.getSession(), asList(123))).isEmpty();
+  }
+
   @Test
   public void selectOrFailByKey() {
     dbTester.prepareDbUnit(getClass(), "shared.xml");
@@ -135,7 +149,7 @@ public class RuleDaoTest {
 
     List<RuleDto> ruleDtos = underTest.selectAll(dbTester.getSession());
 
-    assertThat(ruleDtos).extracting("id").containsOnly(1, 2);
+    assertThat(ruleDtos).extracting("id").containsOnly(1, 2, 10);
   }
 
   @Test
@@ -171,6 +185,19 @@ public class RuleDaoTest {
     assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle");
   }
 
+
+  @Test
+  public void select_by_query() {
+    dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+    assertThat(underTest.selectByQuery(dbTester.getSession(), RuleQuery.create())).hasSize(2);
+    assertThat(underTest.selectByQuery(dbTester.getSession(), RuleQuery.create().withKey("S001"))).hasSize(1);
+    assertThat(underTest.selectByQuery(dbTester.getSession(), RuleQuery.create().withConfigKey("S1"))).hasSize(1);
+    assertThat(underTest.selectByQuery(dbTester.getSession(), RuleQuery.create().withRepositoryKey("java"))).hasSize(2);
+    assertThat(underTest.selectByQuery(dbTester.getSession(),
+      RuleQuery.create().withKey("S001").withConfigKey("S1").withRepositoryKey("java"))).hasSize(1);
+  }
+
   @Test
   public void insert() throws Exception {
     RuleDto newRule = new RuleDto()
@@ -303,6 +330,19 @@ public class RuleDaoTest {
     assertThat(ruleDto.getRuleId()).isEqualTo(1);
   }
 
+  @Test
+  public void select_parameters_by_rule_keys() {
+    dbTester.prepareDbUnit(getClass(), "select_parameters_by_rule_key.xml");
+
+    assertThat(underTest.selectRuleParamsByRuleKeys(dbTester.getSession(),
+      Arrays.asList(RuleKey.of("checkstyle", "AvoidNull"), RuleKey.of("unused", "Unused"))
+    )).hasSize(2);
+
+    assertThat(underTest.selectRuleParamsByRuleKeys(dbTester.getSession(),
+      singletonList(RuleKey.of("unknown", "Unknown"))
+    )).isEmpty();
+  }
+
   @Test
   public void insert_parameter() {
     dbTester.prepareDbUnit(getClass(), "insert_parameter.xml");
index ff4211adfceec5784711321f20d1e48797c6da54..94c54d474374f8024fed37af99c1b067e9790785 100644 (file)
          created_at="2014-05-10" updated_at="2014-05-11"
          created_at_ms="1500000000000" updated_at_ms="1600000000000"
   />
+
+  <rules id="10" name="Removed" plugin_rule_key="S003"
+         plugin_config_key="S3" plugin_name="java" description="[null]" priority="4" status="REMOVED"
+         is_template="[false]" template_id="[null]"
+         tags="[null]" system_tags="[null]"
+         created_at="2014-05-10" updated_at="2014-05-11"
+         created_at_ms="1500000000000" updated_at_ms="1600000000000"
+  />
+
 </dataset>