From ad51f7df0b924edcc927f271edfa3d2ad78997f1 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Mon, 20 Jan 2014 10:58:14 +0100 Subject: [PATCH] SONAR-4326 Add field to search for rules based on selected tags --- .../resources/org/sonar/l10n/core.properties | 1 + .../org/sonar/server/platform/Platform.java | 1 + .../server/qualityprofile/QProfiles.java | 9 +++- .../org/sonar/server/rule/ESRuleTags.java | 8 ++++ .../sonar/server/rule/ProfileRuleQuery.java | 4 ++ .../org/sonar/server/rule/ProfileRules.java | 7 ++++ .../org/sonar/server/rule/RuleTagLookup.java | 37 ++++++++++++++++ .../rules_configuration_controller.rb | 5 ++- .../views/rules_configuration/index.html.erb | 8 ++++ .../server/qualityprofile/QProfilesTest.java | 8 +++- .../org/sonar/server/rule/ESRuleTagsTest.java | 3 +- .../server/rule/ProfileRuleQueryTest.java | 24 +++++++++++ .../sonar/server/rule/RuleTagLookupTest.java | 42 +++++++++++++++++++ 13 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 sonar-server/src/main/java/org/sonar/server/rule/RuleTagLookup.java create mode 100644 sonar-server/src/test/java/org/sonar/server/rule/RuleTagLookupTest.java diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties index d2e176d7992..09a67b5752d 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties @@ -1664,6 +1664,7 @@ rules_configuration.original_value=Original value rules_configuration.original_severity=Original severity rules_configuration.repository=Repository rules_configuration.status_filters=Status +rules_configuration.tags_filters=Tags rules_configuration.sort_by=Sort by: rules_configuration.rule_name=Rule name rules_configuration.creation_date=Creation date diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index b09d07d3b8f..a87fb802b12 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -332,6 +332,7 @@ public final class Platform { // rules servicesContainer.addSingleton(RuleRegistry.class); servicesContainer.addSingleton(ESRuleTags.class); + servicesContainer.addSingleton(RuleTagLookup.class); servicesContainer.addSingleton(RubyRuleService.class); servicesContainer.addSingleton(RuleRepositories.class); diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java index 5366ea15bdb..8abc1dd1ef4 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java @@ -37,12 +37,14 @@ import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.rule.ProfileRuleQuery; import org.sonar.server.rule.ProfileRules; +import org.sonar.server.rule.RuleTagLookup; import org.sonar.server.user.UserSession; import org.sonar.server.util.Validation; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import java.util.Collection; import java.util.List; import java.util.Map; @@ -69,11 +71,12 @@ public class QProfiles implements ServerComponent { private final QProfileActiveRuleOperations activeRuleOperations; private final QProfileRuleOperations ruleOperations; private final ProfileRules rules; + private final RuleTagLookup ruleTagLookup; public QProfiles(QualityProfileDao qualityProfileDao, ActiveRuleDao activeRuleDao, RuleDao ruleDao, ResourceDao resourceDao, QProfileProjectOperations projectOperations, QProfileProjectLookup projectLookup, QProfileBackup backup, QProfilePluginExporter exporter, QProfileLookup profileLookup, QProfileOperations operations, QProfileActiveRuleOperations activeRuleOperations, QProfileRuleOperations ruleOperations, - ProfileRules rules) { + ProfileRules rules, RuleTagLookup ruleTagLookup) { this.qualityProfileDao = qualityProfileDao; this.activeRuleDao = activeRuleDao; this.ruleDao = ruleDao; @@ -87,6 +90,7 @@ public class QProfiles implements ServerComponent { this.activeRuleOperations = activeRuleOperations; this.ruleOperations = ruleOperations; this.rules = rules; + this.ruleTagLookup = ruleTagLookup; } public List allProfiles() { @@ -367,6 +371,9 @@ public class QProfiles implements ServerComponent { return activeRuleDao.selectByRuleId(rule.id()).size(); } + public Collection listAllTags() { + return ruleTagLookup.listAllTags(); + } // // Quality profile validation diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ESRuleTags.java b/sonar-server/src/main/java/org/sonar/server/rule/ESRuleTags.java index fb2f911fe2b..b8313bb7f6c 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ESRuleTags.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ESRuleTags.java @@ -23,6 +23,7 @@ import org.elasticsearch.common.io.BytesStream; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.query.FilterBuilders; import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.sort.SortOrder; import org.sonar.core.rule.RuleTagDto; import org.sonar.server.es.ESIndex; @@ -70,4 +71,11 @@ public class ESRuleTags { throw new IllegalStateException("Unable to index tags", ioException); } } + + public Collection searchAllTags() { + final int scrollSize = 50; + return index.findDocumentIds(index.client().prepareSearch(RuleRegistry.INDEX_RULES) + .setTypes(TYPE_TAG) + .addSort(RuleTagDocument.FIELD_VALUE, SortOrder.ASC), scrollSize); + } } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ProfileRuleQuery.java b/sonar-server/src/main/java/org/sonar/server/rule/ProfileRuleQuery.java index 4d3f5dc669c..463959bc1a0 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ProfileRuleQuery.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ProfileRuleQuery.java @@ -52,6 +52,7 @@ public class ProfileRuleQuery { private static final String PARAM_REPOSITORY_KEYS = "repositoryKeys"; private static final String PARAM_SEVERITIES = "severities"; private static final String PARAM_STATUSES = "statuses"; + private static final String PARAM_TAGS = "tags"; private static final String PARAM_INHERITANCE = "inheritance"; private static final String PARAM_SORT = "sort_by"; private static final String PARAM_ASC = "asc"; @@ -101,6 +102,9 @@ public class ProfileRuleQuery { if (params.get(PARAM_STATUSES) != null) { result.addStatuses(optionalVarargs(params.get(PARAM_STATUSES))); } + if (params.get(PARAM_TAGS) != null) { + result.addTags(optionalVarargs(params.get(PARAM_TAGS))); + } if (params.containsKey(PARAM_INHERITANCE)) { String inheritance = (String) params.get(PARAM_INHERITANCE); diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ProfileRules.java b/sonar-server/src/main/java/org/sonar/server/rule/ProfileRules.java index c5c7a70ce9a..0330564ec2a 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ProfileRules.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ProfileRules.java @@ -276,6 +276,13 @@ public class ProfileRules implements ServerExtension { BoolFilterBuilder filter = ruleFilterForActiveRuleSearch(query) .mustNot(hasChildFilter(TYPE_ACTIVE_RULE, termFilter(ActiveRuleDocument.FIELD_PROFILE_ID, query.profileId()))); addMustTermOrTerms(filter, RuleDocument.FIELD_SEVERITY, query.severities()); + + for (String tag: query.tags()) { + filter.must( + queryFilter( + multiMatchQuery(tag, RuleDocument.FIELD_ADMIN_TAGS, RuleDocument.FIELD_SYSTEM_TAGS))); + } + return filter; } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleTagLookup.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleTagLookup.java new file mode 100644 index 00000000000..473eadea345 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleTagLookup.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 org.sonar.api.ServerComponent; + +import java.util.Collection; + +public class RuleTagLookup implements ServerComponent { + + private final ESRuleTags esRuleTags; + + public RuleTagLookup(ESRuleTags esRuleTags) { + this.esRuleTags = esRuleTags; + } + + public Collection listAllTags() { + return esRuleTags.searchAllTags(); + } +} diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb index 1f482f46e6a..c9e13128425 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb @@ -76,6 +76,7 @@ class RulesConfigurationController < ApplicationController [message('rules.status.deprecated'), Rule::STATUS_DEPRECATED], [message('rules.status.ready'), Rule::STATUS_READY]] @select_sort_by = [[message('rules_configuration.rule_name'), Rule::SORT_BY_RULE_NAME], [message('rules_configuration.creation_date'), Rule::SORT_BY_CREATION_DATE]] + @select_tags = ANY_SELECTION + Internal.quality_profiles.listAllTags().sort end end @@ -346,6 +347,7 @@ class RulesConfigurationController < ApplicationController @activation = params[:rule_activation] || STATUS_ACTIVE @inheritance = params[:inheritance] || 'any' @status = params[:status] + @tags = filter_any(params[:tags]) || [''] @sort_by = !params[:sort_by].blank? ? params[:sort_by] : Rule::SORT_BY_RULE_NAME @searchtext = params[:searchtext] end @@ -359,7 +361,8 @@ class RulesConfigurationController < ApplicationController def init_criteria() {"profileId" => @profile.id.to_i, "activation" => @activation, "severities" => @priorities, "inheritance" => @inheritance, "statuses" => @status, - "repositoryKeys" => @repositories, "nameOrKey" => @searchtext, "include_parameters_and_notes" => true, "language" => @profile.language, "sort_by" => @sort_by} + "repositoryKeys" => @repositories, "nameOrKey" => @searchtext, "include_parameters_and_notes" => true, "language" => @profile.language, "tags" => @tags, + "sort_by" => @sort_by} end def criteria_params diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/index.html.erb index 2488e4f9f90..8b914250251 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/index.html.erb @@ -85,6 +85,14 @@ }, {:id => 'search_inheritance'} -%> <% end %> +