From 242f0c5e340735c62d50873f7cac33866a3b0651 Mon Sep 17 00:00:00 2001 From: Stephane Gamard Date: Thu, 22 May 2014 18:31:48 +0200 Subject: [PATCH] SONAR-5237 - Added Char & SubChar filtering --- .../sonar/server/rule2/index/RuleIndex.java | 20 +++++- .../org/sonar/server/search/BaseIndex.java | 16 +++++ .../rule2/index/RuleIndexMediumTest.java | 64 ++++++++++++++++++- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/index/RuleIndex.java b/sonar-server/src/main/java/org/sonar/server/rule2/index/RuleIndex.java index 4ca8faf2b69..5e62870815b 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/index/RuleIndex.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/index/RuleIndex.java @@ -141,10 +141,19 @@ public class RuleIndex extends BaseIndex { addMatchField(mapping, RuleNormalizer.RuleField.REPOSITORY.key(), "string"); addMatchField(mapping, RuleNormalizer.RuleField.SEVERITY.key(), "string"); - addMatchField(mapping, RuleNormalizer.RuleField.STATUS.key(), "string"); - + addMatchField(mapping, RuleNormalizer.RuleField.STATUS.key(), "string");; addMatchField(mapping, RuleNormalizer.RuleField.LANGUAGE.key(), "string"); + mapping.startObject(RuleNormalizer.RuleField.CHARACTERISTIC.key()) + .field("type", "string") + .field("analyzer", "whitespace") + .endObject(); + + mapping.startObject(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.key()) + .field("type", "string") + .field("analyzer", "whitespace") + .endObject(); + mapping.startObject(RuleNormalizer.RuleField._TAGS.key()) .field("type", "string") .field("analyzer", "whitespace") @@ -279,6 +288,8 @@ public class RuleIndex extends BaseIndex { RuleNormalizer.RuleField.KEY.key(), RuleNormalizer.RuleField.KEY.key() + ".search", RuleNormalizer.RuleField.LANGUAGE.key(), + RuleNormalizer.RuleField.CHARACTERISTIC.key(), + RuleNormalizer.RuleField.SUB_CHARACTERISTIC.key(), RuleNormalizer.RuleField._TAGS.key()); } else { qb = QueryBuilders.matchAllQuery(); @@ -288,7 +299,11 @@ public class RuleIndex extends BaseIndex { /* Build main filter (match based) */ protected FilterBuilder getFilter(RuleQuery query, QueryOptions options) { + BoolFilterBuilder fb = FilterBuilders.boolFilter(); + this.addMultiFieldTermFilter(query.getDebtCharacteristics(), fb, + RuleNormalizer.RuleField.SUB_CHARACTERISTIC.key(), + RuleNormalizer.RuleField.CHARACTERISTIC.key()); this.addTermFilter(RuleNormalizer.RuleField.LANGUAGE.key(), query.getLanguages(), fb); this.addTermFilter(RuleNormalizer.RuleField.REPOSITORY.key(), query.getRepositories(), fb); this.addTermFilter(RuleNormalizer.RuleField.SEVERITY.key(), query.getSeverities(), fb); @@ -333,6 +348,7 @@ public class RuleIndex extends BaseIndex { (query.getTags() != null && !query.getTags().isEmpty()) || (query.getStatuses() != null && !query.getStatuses().isEmpty()) || (query.getKey() != null && !query.getKey().isEmpty()) || + (query.getDebtCharacteristics() != null && !query.getDebtCharacteristics().isEmpty()) || (query.getActivation() != null && !query.getActivation().isEmpty())) { return fb; } else { diff --git a/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java b/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java index 7a68cd2cdd7..19a7d3f4995 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java +++ b/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java @@ -39,6 +39,7 @@ import org.sonar.server.es.ESNode; import java.io.IOException; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -278,6 +279,21 @@ public abstract class BaseIndex, K extends Serializable> .endObject(); } + protected BoolFilterBuilder addMultiFieldTermFilter(Collection values, BoolFilterBuilder filter, String... fields) { + if (values != null && !values.isEmpty()) { + BoolFilterBuilder valuesFilter = FilterBuilders.boolFilter(); + for (String value : values) { + Collection filterBuilders = new ArrayList(); + for (String field : fields) { + filterBuilders.add(FilterBuilders.termFilter(field, value)); + } + valuesFilter.should(FilterBuilders.orFilter(filterBuilders.toArray(new FilterBuilder[filterBuilders.size()]))); + } + filter.must(valuesFilter); + } + return filter; + } + protected BoolFilterBuilder addTermFilter(String field, Collection values, BoolFilterBuilder filter) { if (values != null && !values.isEmpty()) { diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/index/RuleIndexMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/index/RuleIndexMediumTest.java index 9baa5f01688..cbafce55bc5 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule2/index/RuleIndexMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule2/index/RuleIndexMediumTest.java @@ -36,6 +36,7 @@ import org.sonar.core.persistence.MyBatis; import org.sonar.core.qualityprofile.db.ActiveRuleDto; import org.sonar.core.qualityprofile.db.QualityProfileDto; import org.sonar.core.rule.RuleDto; +import org.sonar.core.technicaldebt.db.CharacteristicDto; import org.sonar.server.db.DbClient; import org.sonar.server.rule2.Rule; import org.sonar.server.rule2.persistence.RuleDao; @@ -258,7 +259,7 @@ public class RuleIndexMediumTest { } @Test - public void search_by_any_of_languages() throws InterruptedException { + public void search_by_any_of_languages() throws InterruptedException { dao.insert(newRuleDto(RuleKey.of("java", "S001")).setLanguage("java"), dbSession); dao.insert(newRuleDto(RuleKey.of("javascript", "S002")).setLanguage("js"), dbSession); dbSession.commit(); @@ -283,6 +284,67 @@ public class RuleIndexMediumTest { assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2); } + + @Test + public void search_by_characteristics() throws InterruptedException { + + CharacteristicDto char1 = new CharacteristicDto().setName("char1") + .setKey("char1") + .setEnabled(true); + dbClient.debtCharacteristicDao().insert(char1, dbSession); + dbSession.commit(); + + CharacteristicDto char11 = new CharacteristicDto().setName("char11") + .setKey("char11") + .setEnabled(true) + .setParentId(char1.getId()); + dbClient.debtCharacteristicDao().insert(char11, dbSession); + dbSession.commit(); + + dao.insert(newRuleDto(RuleKey.of("java", "S001")) + .setSubCharacteristicId(char11.getId()), dbSession); + + dao.insert(newRuleDto(RuleKey.of("javascript", "S002")), dbSession); + + dbSession.commit(); + + + RuleQuery query; + Result results; + + // 0. we have 2 rules in index + results = index.search(new RuleQuery(), new QueryOptions()); + assertThat(results.getHits()).hasSize(2); + + // filter by non-subChar + query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of("toto")); + assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty(); + + // filter by subChar + query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey())); + assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1); + + // filter by Char + query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char1.getKey())); + assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1); + + // filter by Char and SubChar + query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey(), char1.getKey())); + assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1); + + // search by Char + query = new RuleQuery().setQueryText(char1.getKey()); + assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1); + + // search by SubChar + query = new RuleQuery().setQueryText(char11.getKey()); + assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1); + + // search by SubChar & Char + query = new RuleQuery().setQueryText(char11.getKey()+" "+char1.getKey()); + assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1); + } + @Test public void search_by_any_of_severities() throws InterruptedException { dao.insert(newRuleDto(RuleKey.of("java", "S001")).setSeverity(Severity.BLOCKER), dbSession); -- 2.39.5