diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2016-02-22 15:29:18 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2016-02-29 13:26:54 +0100 |
commit | b4d0c0deb09b79541fb4522f9d3d1772ade46da9 (patch) | |
tree | 321e2742446a931826f96fd172924fa34ae64258 | |
parent | 88ef557f33215c01836bd39fcafdf91e6f8f017b (diff) | |
download | sonarqube-b4d0c0deb09b79541fb4522f9d3d1772ade46da9.tar.gz sonarqube-b4d0c0deb09b79541fb4522f9d3d1772ade46da9.zip |
SONAR-7330 DefaultRuleFinder is now using only RuleDao
8 files changed, 438 insertions, 284 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRuleFinder.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRuleFinder.java index 21306469fba..d6aaa74bcfc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRuleFinder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRuleFinder.java @@ -19,23 +19,27 @@ */ 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 index 40481326fc5..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderMediumTest.java +++ /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 index 00000000000..c1fe6ebbba6 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderTest.java @@ -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(); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java b/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java index 3c79e9dfc99..9eb3e3893dd 100644 --- a/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java +++ b/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java @@ -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); + } + } } + diff --git a/sonar-db/src/main/java/org/sonar/db/rule/RuleMapper.java b/sonar-db/src/main/java/org/sonar/db/rule/RuleMapper.java index 6471993d00c..f2bc49ffb0c 100644 --- a/sonar-db/src/main/java/org/sonar/db/rule/RuleMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/rule/RuleMapper.java @@ -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); diff --git a/sonar-db/src/main/resources/org/sonar/db/rule/RuleMapper.xml b/sonar-db/src/main/resources/org/sonar/db/rule/RuleMapper.xml index d34b00c4fe7..3673dc55619 100644 --- a/sonar-db/src/main/resources/org/sonar/db/rule/RuleMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/rule/RuleMapper.xml @@ -67,12 +67,13 @@ 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> @@ -112,6 +113,25 @@ 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}, @@ -217,6 +237,17 @@ 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"/> diff --git a/sonar-db/src/test/java/org/sonar/db/rule/RuleDaoTest.java b/sonar-db/src/test/java/org/sonar/db/rule/RuleDaoTest.java index 4a09e16219a..28208807e43 100644 --- a/sonar-db/src/test/java/org/sonar/db/rule/RuleDaoTest.java +++ b/sonar-db/src/test/java/org/sonar/db/rule/RuleDaoTest.java @@ -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; @@ -77,6 +80,17 @@ public class RuleDaoTest { } @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() @@ -304,6 +331,19 @@ public class RuleDaoTest { } @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"); RuleDto rule1 = underTest.selectOrFailByKey(dbTester.getSession(), RuleKey.of("plugin", "NewRuleKey")); diff --git a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/shared.xml index ff4211adfce..94c54d47437 100644 --- a/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/shared.xml +++ b/sonar-db/src/test/resources/org/sonar/db/rule/RuleDaoTest/shared.xml @@ -15,4 +15,13 @@ 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> |